Fixed tests for redux
This commit is contained in:
parent
0805d9d4d0
commit
76d10ba431
14 changed files with 64 additions and 59 deletions
|
@ -1,2 +1 @@
|
||||||
# frontend
|
# frontend
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,16 @@ import { render } from "@testing-library/react";
|
||||||
import { Router } from "react-router";
|
import { Router } from "react-router";
|
||||||
import { createMemoryHistory } from "history";
|
import { createMemoryHistory } from "history";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
import smartHutStore from "./store";
|
||||||
|
|
||||||
test("redirects to homepage", () => {
|
test("redirects to homepage", () => {
|
||||||
const history = createMemoryHistory();
|
const history = createMemoryHistory();
|
||||||
render(
|
render(
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<App />
|
<Provider store={smartHutStore}>
|
||||||
|
<App />
|
||||||
|
</Provider>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
expect(history.location.pathname).toBe("/");
|
expect(history.location.pathname).toBe("/");
|
||||||
|
|
|
@ -48,7 +48,9 @@ const mapStateToProps = (state, _) => ({
|
||||||
if (state.active.activeRoom === -1) {
|
if (state.active.activeRoom === -1) {
|
||||||
return Object.values(state.devices);
|
return Object.values(state.devices);
|
||||||
} else {
|
} else {
|
||||||
const deviceArray = [...state.rooms[state.active.activeRoom].devices].sort();
|
const deviceArray = [
|
||||||
|
...state.rooms[state.active.activeRoom].devices,
|
||||||
|
].sort();
|
||||||
return deviceArray.map((id) => state.devices[id]);
|
return deviceArray.map((id) => state.devices[id]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,19 +56,21 @@ class Device extends React.Component {
|
||||||
return (
|
return (
|
||||||
<Segment>
|
<Segment>
|
||||||
<Grid columns={2}>
|
<Grid columns={2}>
|
||||||
<Grid.Column>
|
<Grid.Column>{this.renderDeviceComponent()}</Grid.Column>
|
||||||
{this.renderDeviceComponent()}
|
<Grid.Column textAlign="center">
|
||||||
</Grid.Column>
|
<Header as="h3">{this.props.device.name}</Header>
|
||||||
<Grid.Column textAlign='center'>
|
<Button color="blue" icon onClick={this.edit} labelPosition="left">
|
||||||
<Header as='h3'>{this.props.device.name}</Header>
|
<Icon name="pencil" />
|
||||||
<Button color='blue' icon onClick={this.edit} labelPosition='left'>
|
|
||||||
<Icon name='pencil' />
|
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
{this.props.device.kind === "smartPlug" ? (
|
{this.props.device.kind === "smartPlug" ? (
|
||||||
<Button color='orange' icon onClick={this.resetSmartPlug}
|
<Button
|
||||||
labelPosition='left'>
|
color="orange"
|
||||||
<Icon name='undo' />
|
icon
|
||||||
|
onClick={this.resetSmartPlug}
|
||||||
|
labelPosition="left"
|
||||||
|
>
|
||||||
|
<Icon name="undo" />
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -65,7 +65,7 @@ export class KnobDimmerComponent extends Component {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
intensity: this.props.device.intensity || 0,
|
intensity: this.props.device.intensity || 0,
|
||||||
timeout: null
|
timeout: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.saveIntensity = this.saveIntensity.bind(this);
|
this.saveIntensity = this.saveIntensity.bind(this);
|
||||||
|
@ -74,20 +74,20 @@ export class KnobDimmerComponent extends Component {
|
||||||
|
|
||||||
setIntensity(intensity) {
|
setIntensity(intensity) {
|
||||||
intensity *= 100;
|
intensity *= 100;
|
||||||
|
|
||||||
if (this.state.timeout) {
|
if (this.state.timeout) {
|
||||||
clearTimeout(this.state.timeout);
|
clearTimeout(this.state.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
intensity,
|
intensity,
|
||||||
timeout: setTimeout(() => {
|
timeout: setTimeout(() => {
|
||||||
this.saveIntensity();
|
this.saveIntensity();
|
||||||
this.setState({
|
this.setState({
|
||||||
intensity: this.state.intensity,
|
intensity: this.state.intensity,
|
||||||
timeout: null
|
timeout: null,
|
||||||
});
|
});
|
||||||
}, 100)
|
}, 100),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ export class KnobDimmerComponent extends Component {
|
||||||
this.props
|
this.props
|
||||||
.knobDimmerDimTo(this.props.id, val)
|
.knobDimmerDimTo(this.props.id, val)
|
||||||
.catch((err) => console.error("knob dimmer set intensity error", err));
|
.catch((err) => console.error("knob dimmer set intensity error", err));
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -65,20 +65,20 @@ class Light extends Component {
|
||||||
|
|
||||||
setIntensity(intensity) {
|
setIntensity(intensity) {
|
||||||
intensity *= 100;
|
intensity *= 100;
|
||||||
|
|
||||||
if (this.state.timeout) {
|
if (this.state.timeout) {
|
||||||
clearTimeout(this.state.timeout);
|
clearTimeout(this.state.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
intensity,
|
intensity,
|
||||||
timeout: setTimeout(() => {
|
timeout: setTimeout(() => {
|
||||||
this.saveIntensity();
|
this.saveIntensity();
|
||||||
this.setState({
|
this.setState({
|
||||||
intensity: this.state.intensity,
|
intensity: this.state.intensity,
|
||||||
timeout: null
|
timeout: null,
|
||||||
});
|
});
|
||||||
}, 100)
|
}, 100),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,7 @@
|
||||||
The user can reset this value.
|
The user can reset this value.
|
||||||
**/
|
**/
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import {
|
import { BottomPanel, StyledDiv } from "./styleComponents";
|
||||||
BottomPanel,
|
|
||||||
StyledDiv
|
|
||||||
} from "./styleComponents";
|
|
||||||
import { Image } from "semantic-ui-react";
|
import { Image } from "semantic-ui-react";
|
||||||
import {
|
import {
|
||||||
energyConsumedStyle,
|
energyConsumedStyle,
|
||||||
|
@ -36,8 +33,9 @@ class SmartPlug extends Component {
|
||||||
|
|
||||||
onClickDevice = () => {
|
onClickDevice = () => {
|
||||||
const on = !this.turnedOn;
|
const on = !this.turnedOn;
|
||||||
this.props.saveDevice({ ...this.props.device, on })
|
this.props
|
||||||
.catch((err) => console.error('smart plug update error', err));
|
.saveDevice({ ...this.props.device, on })
|
||||||
|
.catch((err) => console.error("smart plug update error", err));
|
||||||
};
|
};
|
||||||
|
|
||||||
getIcon = () => {
|
getIcon = () => {
|
||||||
|
@ -48,9 +46,7 @@ class SmartPlug extends Component {
|
||||||
return (
|
return (
|
||||||
<StyledDiv onClick={this.onClickDevice}>
|
<StyledDiv onClick={this.onClickDevice}>
|
||||||
<Image src={this.getIcon()} style={imageStyle} />
|
<Image src={this.getIcon()} style={imageStyle} />
|
||||||
<span style={nameStyle}>
|
<span style={nameStyle}>Smart Plug</span>
|
||||||
Smart Plug
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<BottomPanel
|
<BottomPanel
|
||||||
style={
|
style={
|
||||||
|
|
|
@ -30,17 +30,16 @@ class Switch extends Component {
|
||||||
onClickDevice = () => {
|
onClickDevice = () => {
|
||||||
const newOn = !this.turnedOn;
|
const newOn = !this.turnedOn;
|
||||||
const type = newOn ? "ON" : "OFF";
|
const type = newOn ? "ON" : "OFF";
|
||||||
this.props.switchOperate(this.props.id, type)
|
this.props
|
||||||
.catch(err => console.error('switch operate failed', err))
|
.switchOperate(this.props.id, type)
|
||||||
|
.catch((err) => console.error("switch operate failed", err));
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<StyledDiv onClick={this.onClickDevice}>
|
<StyledDiv onClick={this.onClickDevice}>
|
||||||
<Image src={this.getIcon()} style={imageStyle} />
|
<Image src={this.getIcon()} style={imageStyle} />
|
||||||
<span style={nameStyle}>
|
<span style={nameStyle}>Switch</span>
|
||||||
Switch
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<BottomPanel
|
<BottomPanel
|
||||||
style={
|
style={
|
||||||
|
@ -49,9 +48,7 @@ class Switch extends Component {
|
||||||
: { backgroundColor: "#1a2849" }
|
: { backgroundColor: "#1a2849" }
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span style={turnedOnStyle}>
|
<span style={turnedOnStyle}>{this.turnedOn ? "ON" : "OFF"}</span>
|
||||||
{this.turnedOn ? "ON" : "OFF"}
|
|
||||||
</span>
|
|
||||||
</BottomPanel>
|
</BottomPanel>
|
||||||
</StyledDiv>
|
</StyledDiv>
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,7 +14,6 @@ export function socketURL(token) {
|
||||||
const protocol = isSecure ? "wss:" : "ws:";
|
const protocol = isSecure ? "wss:" : "ws:";
|
||||||
const port = httpURL.port || (isSecure ? 443 : 80);
|
const port = httpURL.port || (isSecure ? 443 : 80);
|
||||||
const url = `${protocol}//${httpURL.hostname}:${port}/sensor-socket?token=${token}`;
|
const url = `${protocol}//${httpURL.hostname}:${port}/sensor-socket?token=${token}`;
|
||||||
console.log('socket url: ', url);
|
console.log("socket url: ", url);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import axios from "axios";
|
||||||
import { endpointURL, socketURL } from "./endpoint";
|
import { endpointURL, socketURL } from "./endpoint";
|
||||||
import { connect, disconnect } from "@giantmachines/redux-websocket";
|
import { connect, disconnect } from "@giantmachines/redux-websocket";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object returned by promise rejections in remoteservice
|
* An object returned by promise rejections in remoteservice
|
||||||
* @typedef {Error} RemoteError
|
* @typedef {Error} RemoteError
|
||||||
|
@ -170,8 +169,8 @@ export const RemoteService = {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
return Endpoint.login(usernameOrEmail, password)
|
return Endpoint.login(usernameOrEmail, password)
|
||||||
.then((token) => {
|
.then((token) => {
|
||||||
dispatch(actions.loginSuccess(token))
|
dispatch(actions.loginSuccess(token));
|
||||||
dispatch(connect(socketURL(token)))
|
dispatch(connect(socketURL(token)));
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.warn("login error", err);
|
console.warn("login error", err);
|
||||||
|
@ -190,8 +189,8 @@ export const RemoteService = {
|
||||||
logout: () => {
|
logout: () => {
|
||||||
return (dispatch) =>
|
return (dispatch) =>
|
||||||
Endpoint.logout().then(() => {
|
Endpoint.logout().then(() => {
|
||||||
dispatch(disconnect())
|
dispatch(disconnect());
|
||||||
dispatch(actions.logout())
|
dispatch(actions.logout());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -237,14 +237,14 @@ function reducer(previousState, action) {
|
||||||
newState = reducer(previousState, {
|
newState = reducer(previousState, {
|
||||||
type: "DEVICES_UPDATE",
|
type: "DEVICES_UPDATE",
|
||||||
partial: true,
|
partial: true,
|
||||||
devices
|
devices,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn(`Action type ${action.type} unknown`, action);
|
console.warn(`Action type ${action.type} unknown`, action);
|
||||||
return previousState;
|
return previousState;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,10 +284,11 @@ function createSmartHutStore() {
|
||||||
initialState.login.token = null;
|
initialState.login.token = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = createStore(reducer, initialState,
|
const store = createStore(
|
||||||
compose(
|
reducer,
|
||||||
applyMiddleware(thunk),
|
initialState,
|
||||||
applyMiddleware(reduxWebSocket())));
|
compose(applyMiddleware(thunk), applyMiddleware(reduxWebSocket()))
|
||||||
|
);
|
||||||
if (initialState.login.loggedIn) {
|
if (initialState.login.loggedIn) {
|
||||||
store.dispatch(connect(socketURL(token)));
|
store.dispatch(connect(socketURL(token)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,11 @@ export default class ChangePass extends Component {
|
||||||
|
|
||||||
Forms.submitResetPassword(this.props.query.token, this.state.password)
|
Forms.submitResetPassword(this.props.query.token, this.state.password)
|
||||||
.then(() => this.setState({ success: true }))
|
.then(() => this.setState({ success: true }))
|
||||||
.catch((err) => this.setState({ error:
|
.catch((err) =>
|
||||||
{ state: true, message: err.messages.join(' - ') }}));
|
this.setState({
|
||||||
|
error: { state: true, message: err.messages.join(" - ") },
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -35,7 +35,9 @@ export default class ForgotPass extends Component {
|
||||||
|
|
||||||
Forms.submitInitResetPassword(this.state.user)
|
Forms.submitInitResetPassword(this.state.user)
|
||||||
.then(() => this.setState({ success: true }))
|
.then(() => this.setState({ success: true }))
|
||||||
.catch((err) => this.setState({ error: { state: true, message: err.messages }}));
|
.catch((err) =>
|
||||||
|
this.setState({ error: { state: true, message: err.messages } })
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -34,10 +34,11 @@ export default class Signup extends Component {
|
||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
};
|
};
|
||||||
|
|
||||||
Forms
|
Forms.submitRegistration(params)
|
||||||
.submitRegistration(params)
|
|
||||||
.then(() => this.setState({ success: true }))
|
.then(() => this.setState({ success: true }))
|
||||||
.catch((err) => this.setState({ error: { state: true, message: err.messages }}));
|
.catch((err) =>
|
||||||
|
this.setState({ error: { state: true, message: err.messages } })
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onChangeHandler = (event) => {
|
onChangeHandler = (event) => {
|
||||||
|
|
Loading…
Reference in a new issue