mirror of
				https://gitlab.nic.cz/turris/reforis/foris-js.git
				synced 2025-11-03 23:00:31 +01:00 
			
		
		
		
	Wi-Fi settings form
This commit is contained in:
		@@ -6,7 +6,9 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render, getByText, queryByText, fireEvent } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    render, getByText, queryByText, fireEvent,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { useAlert, AlertContextProvider } from "../AlertContext";
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +22,7 @@ function AlertTest() {
 | 
			
		||||
            <button onClick={dismissAlert}>Dismiss alert</button>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
describe("AlertContext", () => {
 | 
			
		||||
    let componentContainer;
 | 
			
		||||
@@ -29,7 +31,7 @@ describe("AlertContext", () => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <AlertContextProvider>
 | 
			
		||||
                <AlertTest />
 | 
			
		||||
            </AlertContextProvider>
 | 
			
		||||
            </AlertContextProvider>,
 | 
			
		||||
        );
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ describe("<Button />", () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Render button with spinner", () => {
 | 
			
		||||
        const { container } = render(<Button loading={true}>Test Button</Button>);
 | 
			
		||||
        const { container } = render(<Button loading>Test Button</Button>);
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<Checkbox/>", () => {
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
@@ -31,7 +31,7 @@ describe("<Checkbox/>", () => {
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { render, fireEvent, getByLabelText, wait } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    render, fireEvent, getByLabelText, wait,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { NumberInput } from "../NumberInput";
 | 
			
		||||
 | 
			
		||||
@@ -22,7 +24,7 @@ describe("<NumberInput/>", () => {
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                value={1}
 | 
			
		||||
                onChange={onChangeMock}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
@@ -34,12 +36,12 @@ describe("<NumberInput/>", () => {
 | 
			
		||||
    it("Increase number with button", async () => {
 | 
			
		||||
        const increaseButton = getByLabelText(componentContainer, "Increase");
 | 
			
		||||
        fireEvent.mouseDown(increaseButton);
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 2}}));
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({ target: { value: 2 } }));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Decrease number with button", async () => {
 | 
			
		||||
        const decreaseButton = getByLabelText(componentContainer, "Decrease");
 | 
			
		||||
        fireEvent.mouseDown(decreaseButton);
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 0}}));
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({ target: { value: 0 } }));
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<PasswordInput/>", () => {
 | 
			
		||||
                value="Some password"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,30 +14,30 @@ import { RadioSet } from "../RadioSet";
 | 
			
		||||
const TEST_CHOICES = [
 | 
			
		||||
    {
 | 
			
		||||
        label: "label",
 | 
			
		||||
        value: "value"
 | 
			
		||||
        value: "value",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        label: "another label",
 | 
			
		||||
        value: "another value"
 | 
			
		||||
        value: "another value",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        label: "another one  label",
 | 
			
		||||
        value: "another on value"
 | 
			
		||||
    }
 | 
			
		||||
        value: "another on value",
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
describe("<RadioSet/>", () => {
 | 
			
		||||
    it("Render radio set", () => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <RadioSet
 | 
			
		||||
                name={"test_name"}
 | 
			
		||||
                label='Radios set label'
 | 
			
		||||
                value='value'
 | 
			
		||||
                name="test_name"
 | 
			
		||||
                label="Radios set label"
 | 
			
		||||
                value="value"
 | 
			
		||||
                choices={TEST_CHOICES}
 | 
			
		||||
                helpText={"Some help text"}
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,29 +7,31 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, getByDisplayValue, getByText, render } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    fireEvent, getByDisplayValue, getByText, render,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { Select } from "../Select";
 | 
			
		||||
 | 
			
		||||
const TEST_CHOICES = {
 | 
			
		||||
    "1": "one",
 | 
			
		||||
    "2": "two",
 | 
			
		||||
    "3": "three",
 | 
			
		||||
    1: "one",
 | 
			
		||||
    2: "two",
 | 
			
		||||
    3: "three",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe("<Select/>", () => {
 | 
			
		||||
    var selectContainer;
 | 
			
		||||
    let selectContainer;
 | 
			
		||||
    const onChangeHandler = jest.fn();
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <Select
 | 
			
		||||
                label='Test label'
 | 
			
		||||
                value='1'
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                value="1"
 | 
			
		||||
                choices={TEST_CHOICES}
 | 
			
		||||
                helpText='Help text'
 | 
			
		||||
                helpText="Help text"
 | 
			
		||||
 | 
			
		||||
                onChange={onChangeHandler}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        selectContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<TextInput/>", () => {
 | 
			
		||||
                value="Some text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								src/common/WiFiSettings/ResetWiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/common/WiFiSettings/ResetWiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { Button } from "../../bootstrap/Button";
 | 
			
		||||
import { useAlert } from "../../alertContext/AlertContext";
 | 
			
		||||
import { ALERT_TYPES } from "../../bootstrap/Alert";
 | 
			
		||||
import { useAPIPost } from "../../api/hooks";
 | 
			
		||||
import { API_STATE } from "../../api/utils";
 | 
			
		||||
import { formFieldsSize } from "../../bootstrap/constants";
 | 
			
		||||
 | 
			
		||||
ResetWiFiSettings.propTypes = {
 | 
			
		||||
    ws: PropTypes.object.isRequired,
 | 
			
		||||
    endpoint: PropTypes.string.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function ResetWiFiSettings({ ws, endpoint }) {
 | 
			
		||||
    const [isLoading, setIsLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        const module = "wifi";
 | 
			
		||||
        ws.subscribe(module)
 | 
			
		||||
            .bind(module, "reset", () => {
 | 
			
		||||
                setIsLoading(true);
 | 
			
		||||
                // eslint-disable-next-line no-restricted-globals
 | 
			
		||||
                setTimeout(() => location.reload(), 1000);
 | 
			
		||||
            });
 | 
			
		||||
    }, [ws]);
 | 
			
		||||
 | 
			
		||||
    const [postResetResponse, postReset] = useAPIPost(endpoint);
 | 
			
		||||
    const [setAlert, dismissAlert] = useAlert();
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (postResetResponse.state === API_STATE.ERROR) {
 | 
			
		||||
            setAlert(_("An error occurred during resetting Wi-Fi settings."));
 | 
			
		||||
        } else if (postResetResponse.state === API_STATE.SUCCESS) {
 | 
			
		||||
            setAlert(_("Wi-Fi settings are set to defaults."), ALERT_TYPES.SUCCESS);
 | 
			
		||||
        }
 | 
			
		||||
    }, [postResetResponse, setAlert]);
 | 
			
		||||
 | 
			
		||||
    function onReset() {
 | 
			
		||||
        dismissAlert();
 | 
			
		||||
        postReset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <h4>{_("Reset Wi-Fi Settings")}</h4>
 | 
			
		||||
            <p>
 | 
			
		||||
                {_(`
 | 
			
		||||
If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the
 | 
			
		||||
current Wi-Fi configuration and restore the default values.
 | 
			
		||||
        `)}
 | 
			
		||||
            </p>
 | 
			
		||||
            <div className={`${formFieldsSize} text-right`}>
 | 
			
		||||
                <Button
 | 
			
		||||
                    className="btn-warning"
 | 
			
		||||
                    forisFormSize
 | 
			
		||||
                    loading={isLoading}
 | 
			
		||||
                    disabled={isLoading}
 | 
			
		||||
 | 
			
		||||
                    onClick={onReset}
 | 
			
		||||
                >
 | 
			
		||||
                    {_("Reset Wi-Fi Settings")}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										250
									
								
								src/common/WiFiSettings/WiFiForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/common/WiFiSettings/WiFiForm.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { CheckBox } from "../../bootstrap/CheckBox";
 | 
			
		||||
import { PasswordInput } from "../../bootstrap/PasswordInput";
 | 
			
		||||
import { RadioSet } from "../../bootstrap/RadioSet";
 | 
			
		||||
import { Select } from "../../bootstrap/Select";
 | 
			
		||||
import { TextInput } from "../../bootstrap/TextInput";
 | 
			
		||||
import WiFiQRCode from "./WiFiQRCode";
 | 
			
		||||
import WifiGuestForm from "./WiFiGuestForm";
 | 
			
		||||
import { HELP_TEXTS, HTMODES, HWMODES } from "./constants";
 | 
			
		||||
 | 
			
		||||
WiFiForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape(
 | 
			
		||||
        { devices: PropTypes.arrayOf(PropTypes.object) },
 | 
			
		||||
    ).isRequired,
 | 
			
		||||
    formErrors: PropTypes.oneOfType([
 | 
			
		||||
        PropTypes.object,
 | 
			
		||||
        PropTypes.array,
 | 
			
		||||
    ]),
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
WiFiForm.defaultProps = {
 | 
			
		||||
    formData: { devices: [] },
 | 
			
		||||
    setFormValue: () => {},
 | 
			
		||||
    hasGuestNetwork: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function WiFiForm({
 | 
			
		||||
    formData, formErrors, setFormValue, hasGuestNetwork, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    return formData.devices.map((device) => (
 | 
			
		||||
        <DeviceForm
 | 
			
		||||
            key={device.id}
 | 
			
		||||
            formData={device}
 | 
			
		||||
            formErrors={(formErrors || [])[device.id]}
 | 
			
		||||
            setFormValue={setFormValue}
 | 
			
		||||
            hasGuestNetwork={hasGuestNetwork}
 | 
			
		||||
 | 
			
		||||
            {...props}
 | 
			
		||||
        />
 | 
			
		||||
    ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeviceForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape({
 | 
			
		||||
        id: PropTypes.number.isRequired,
 | 
			
		||||
        enabled: PropTypes.bool.isRequired,
 | 
			
		||||
        SSID: PropTypes.string.isRequired,
 | 
			
		||||
        password: PropTypes.string.isRequired,
 | 
			
		||||
        hidden: PropTypes.bool.isRequired,
 | 
			
		||||
        hwmode: PropTypes.string.isRequired,
 | 
			
		||||
        htmode: PropTypes.string.isRequired,
 | 
			
		||||
        channel: PropTypes.string.isRequired,
 | 
			
		||||
        guest_wifi: PropTypes.object.isRequired,
 | 
			
		||||
    }),
 | 
			
		||||
    formErrors: PropTypes.object.isRequired,
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DeviceForm.defaultProps = {
 | 
			
		||||
    formErrors: {},
 | 
			
		||||
    hasGuestNetwork: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DeviceForm({
 | 
			
		||||
    formData, formErrors, setFormValue, hasGuestNetwork, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    const deviceID = formData.id;
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <h3>{_(`Wi-Fi ${deviceID + 1}`)}</h3>
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label={_("Enable")}
 | 
			
		||||
                checked={formData.enabled}
 | 
			
		||||
 | 
			
		||||
                onChange={setFormValue(
 | 
			
		||||
                    (value) => ({ devices: { [deviceID]: { enabled: { $set: value } } } }),
 | 
			
		||||
                )}
 | 
			
		||||
 | 
			
		||||
                {...props}
 | 
			
		||||
            />
 | 
			
		||||
            {formData.enabled
 | 
			
		||||
                ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                        <TextInput
 | 
			
		||||
                            label="SSID"
 | 
			
		||||
                            value={formData.SSID}
 | 
			
		||||
                            error={formErrors.SSID || null}
 | 
			
		||||
                            required
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({ devices: { [deviceID]: { SSID: { $set: value } } } }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        >
 | 
			
		||||
                            <div className="input-group-append">
 | 
			
		||||
                                <WiFiQRCode
 | 
			
		||||
                                    SSID={formData.SSID}
 | 
			
		||||
                                    password={formData.password}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </TextInput>
 | 
			
		||||
 | 
			
		||||
                        <PasswordInput
 | 
			
		||||
                            withEye
 | 
			
		||||
                            label="Password"
 | 
			
		||||
                            value={formData.password}
 | 
			
		||||
                            error={formErrors.password}
 | 
			
		||||
                            helpText={HELP_TEXTS.password}
 | 
			
		||||
                            required
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { password: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <CheckBox
 | 
			
		||||
                            label="Hide SSID"
 | 
			
		||||
                            helpText={HELP_TEXTS.hidden}
 | 
			
		||||
                            checked={formData.hidden}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { hidden: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <RadioSet
 | 
			
		||||
                            name={`hwmode-${deviceID}`}
 | 
			
		||||
                            label="GHz"
 | 
			
		||||
                            choices={getHwmodeChoices(formData)}
 | 
			
		||||
                            value={formData.hwmode}
 | 
			
		||||
                            helpText={HELP_TEXTS.hwmode}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [deviceID]: {
 | 
			
		||||
                                            hwmode: { $set: value },
 | 
			
		||||
                                            channel: { $set: "0" },
 | 
			
		||||
                                        },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <Select
 | 
			
		||||
                            label="802.11n/ac mode"
 | 
			
		||||
                            choices={getHtmodeChoices(formData)}
 | 
			
		||||
                            value={formData.htmode}
 | 
			
		||||
                            helpText={HELP_TEXTS.htmode}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { htmode: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <Select
 | 
			
		||||
                            label="Channel"
 | 
			
		||||
                            choices={getChannelChoices(formData)}
 | 
			
		||||
                            value={formData.channel}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { channel: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        {hasGuestNetwork && (
 | 
			
		||||
                            <WifiGuestForm
 | 
			
		||||
                                formData={{ id: deviceID, ...formData.guest_wifi }}
 | 
			
		||||
                                formErrors={formErrors.guest_wifi || {}}
 | 
			
		||||
 | 
			
		||||
                                setFormValue={setFormValue}
 | 
			
		||||
 | 
			
		||||
                                {...props}
 | 
			
		||||
                            />
 | 
			
		||||
                        )}
 | 
			
		||||
                    </>
 | 
			
		||||
                )
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getChannelChoices(device) {
 | 
			
		||||
    const channelChoices = {
 | 
			
		||||
        0: _("auto"),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    device.available_bands.forEach((availableBand) => {
 | 
			
		||||
        if (availableBand.hwmode !== device.hwmode) return;
 | 
			
		||||
 | 
			
		||||
        availableBand.available_channels.forEach((availableChannel) => {
 | 
			
		||||
            channelChoices[availableChannel.number.toString()] = `
 | 
			
		||||
                        ${availableChannel.number}
 | 
			
		||||
                        (${availableChannel.frequency} MHz ${availableChannel.radar ? " ,DFS" : ""})
 | 
			
		||||
                    `;
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return channelChoices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHtmodeChoices(device) {
 | 
			
		||||
    const htmodeChoices = {};
 | 
			
		||||
 | 
			
		||||
    device.available_bands.forEach((availableBand) => {
 | 
			
		||||
        if (availableBand.hwmode !== device.hwmode) return;
 | 
			
		||||
 | 
			
		||||
        availableBand.available_htmodes.forEach((availableHtmod) => {
 | 
			
		||||
            htmodeChoices[availableHtmod] = HTMODES[availableHtmod];
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return htmodeChoices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHwmodeChoices(device) {
 | 
			
		||||
    return device.available_bands.map((availableBand) => ({
 | 
			
		||||
        label: HWMODES[availableBand.hwmode],
 | 
			
		||||
        value: availableBand.hwmode,
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								src/common/WiFiSettings/WiFiGuestForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/common/WiFiSettings/WiFiGuestForm.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { CheckBox } from "../../bootstrap/CheckBox";
 | 
			
		||||
import { TextInput } from "../../bootstrap/TextInput";
 | 
			
		||||
import { PasswordInput } from "../../bootstrap/PasswordInput";
 | 
			
		||||
import WiFiQRCode from "./WiFiQRCode";
 | 
			
		||||
import { HELP_TEXTS } from "./constants";
 | 
			
		||||
 | 
			
		||||
WifiGuestForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape({
 | 
			
		||||
        id: PropTypes.number.isRequired,
 | 
			
		||||
        SSID: PropTypes.string.isRequired,
 | 
			
		||||
        password: PropTypes.string.isRequired,
 | 
			
		||||
        enabled: PropTypes.bool.isRequired,
 | 
			
		||||
    }),
 | 
			
		||||
    formErrors: PropTypes.shape({
 | 
			
		||||
        SSID: PropTypes.string,
 | 
			
		||||
        password: PropTypes.string,
 | 
			
		||||
    }),
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function WifiGuestForm({
 | 
			
		||||
    formData, formErrors, setFormValue, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label={_("Enable Guest Wifi")}
 | 
			
		||||
                checked={formData.enabled}
 | 
			
		||||
                helpText={HELP_TEXTS.guest_wifi_enabled}
 | 
			
		||||
 | 
			
		||||
                onChange={setFormValue(
 | 
			
		||||
                    (value) => (
 | 
			
		||||
                        { devices: { [formData.id]: { guest_wifi: { enabled: { $set: value } } } } }
 | 
			
		||||
                    ),
 | 
			
		||||
                )}
 | 
			
		||||
 | 
			
		||||
                {...props}
 | 
			
		||||
            />
 | 
			
		||||
            {formData.enabled
 | 
			
		||||
                ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                        <TextInput
 | 
			
		||||
                            label="SSID"
 | 
			
		||||
                            value={formData.SSID}
 | 
			
		||||
                            error={formErrors.SSID}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [formData.id]: { guest_wifi: { SSID: { $set: value } } },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        >
 | 
			
		||||
                            <div className="input-group-append">
 | 
			
		||||
                                <WiFiQRCode
 | 
			
		||||
                                    SSID={formData.SSID}
 | 
			
		||||
                                    password={formData.password}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </TextInput>
 | 
			
		||||
 | 
			
		||||
                        <PasswordInput
 | 
			
		||||
                            withEye
 | 
			
		||||
                            label={_("Password")}
 | 
			
		||||
                            value={formData.password}
 | 
			
		||||
                            helpText={HELP_TEXTS.password}
 | 
			
		||||
                            error={formErrors.password}
 | 
			
		||||
                            required
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [formData.id]: {
 | 
			
		||||
                                            guest_wifi: { password: { $set: value } },
 | 
			
		||||
                                        },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
                    </>
 | 
			
		||||
                )
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								src/common/WiFiSettings/WiFiQRCode.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/common/WiFiSettings/WiFiQRCode.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import QRCode from "qrcode.react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { ForisURLs } from "../../forisUrls";
 | 
			
		||||
import { Button } from "../../bootstrap/Button";
 | 
			
		||||
import {
 | 
			
		||||
    Modal, ModalBody, ModalFooter, ModalHeader,
 | 
			
		||||
} from "../../bootstrap/Modal";
 | 
			
		||||
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers";
 | 
			
		||||
 | 
			
		||||
WiFiQRCode.propTypes = {
 | 
			
		||||
    SSID: PropTypes.string.isRequired,
 | 
			
		||||
    password: PropTypes.string.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const QR_ICON_PATH = `${ForisURLs.static}/imgs/QR_icon.svg`;
 | 
			
		||||
 | 
			
		||||
export default function WiFiQRCode({ SSID, password }) {
 | 
			
		||||
    const [modal, setModal] = useState(false);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <button
 | 
			
		||||
                type="button"
 | 
			
		||||
                className="input-group-text"
 | 
			
		||||
                onClick={(e) => {
 | 
			
		||||
                    e.preventDefault();
 | 
			
		||||
                    setModal(true);
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <img width="20" src={QR_ICON_PATH} alt="QR" style={{ opacity: 0.67 }} />
 | 
			
		||||
            </button>
 | 
			
		||||
            {modal
 | 
			
		||||
                ? <QRCodeModal setShown={setModal} shown={modal} SSID={SSID} password={password} />
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QRCodeModal.propTypes = {
 | 
			
		||||
    SSID: PropTypes.string.isRequired,
 | 
			
		||||
    password: PropTypes.string.isRequired,
 | 
			
		||||
    shown: PropTypes.bool.isRequired,
 | 
			
		||||
    setShown: PropTypes.func.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function QRCodeModal({
 | 
			
		||||
    shown, setShown, SSID, password,
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal setShown={setShown} shown={shown}>
 | 
			
		||||
            <ModalHeader setShown={setShown} title={_("Wi-Fi QR Code")} />
 | 
			
		||||
            <ModalBody>
 | 
			
		||||
                <QRCode
 | 
			
		||||
                    renderAs="svg"
 | 
			
		||||
                    value={toQRCodeContent(SSID, password)}
 | 
			
		||||
                    level="M"
 | 
			
		||||
                    size={350}
 | 
			
		||||
                    includeMargin
 | 
			
		||||
                    style={{ display: "block", margin: "auto" }}
 | 
			
		||||
                />
 | 
			
		||||
            </ModalBody>
 | 
			
		||||
            <ModalFooter>
 | 
			
		||||
                <Button
 | 
			
		||||
                    className="btn-outline-primary"
 | 
			
		||||
                    onClick={(e) => {
 | 
			
		||||
                        e.preventDefault();
 | 
			
		||||
                        createAndDownloadPdf(SSID, password);
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                    <i className="fas fa-arrow-down mr-2" />
 | 
			
		||||
                    {_("Download PDF")}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </ModalFooter>
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								src/common/WiFiSettings/WiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/common/WiFiSettings/WiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { ForisForm } from "../../form/components/ForisForm";
 | 
			
		||||
import WiFiForm from "./WiFiForm";
 | 
			
		||||
import ResetWiFiSettings from "./ResetWiFiSettings";
 | 
			
		||||
 | 
			
		||||
WiFiSettings.propTypes = {
 | 
			
		||||
    ws: PropTypes.object.isRequired,
 | 
			
		||||
    endpoint: PropTypes.string.isRequired,
 | 
			
		||||
    resetEndpoint: PropTypes.string.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function WiFiSettings({
 | 
			
		||||
    ws, endpoint, resetEndpoint, hasGuestNetwork,
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <ForisForm
 | 
			
		||||
                ws={ws}
 | 
			
		||||
                forisConfig={{
 | 
			
		||||
                    endpoint,
 | 
			
		||||
                    wsModule: "wifi",
 | 
			
		||||
                }}
 | 
			
		||||
                prepData={prepData}
 | 
			
		||||
                prepDataToSubmit={prepDataToSubmit}
 | 
			
		||||
                validator={validator}
 | 
			
		||||
            >
 | 
			
		||||
                <WiFiForm hasGuestNetwork={hasGuestNetwork} />
 | 
			
		||||
            </ForisForm>
 | 
			
		||||
            <ResetWiFiSettings ws={ws} endpoint={resetEndpoint} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prepData(formData) {
 | 
			
		||||
    formData.devices.forEach((device, idx) => {
 | 
			
		||||
        formData.devices[idx].channel = device.channel.toString();
 | 
			
		||||
    });
 | 
			
		||||
    return formData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prepDataToSubmit(formData) {
 | 
			
		||||
    formData.devices.forEach((device, idx) => {
 | 
			
		||||
        delete device.available_bands;
 | 
			
		||||
 | 
			
		||||
        formData.devices[idx].channel = parseInt(device.channel);
 | 
			
		||||
 | 
			
		||||
        if (!device.enabled) {
 | 
			
		||||
            formData.devices[idx] = { id: device.id, enabled: false };
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!device.guest_wifi.enabled) formData.devices[idx].guest_wifi = { enabled: false };
 | 
			
		||||
    });
 | 
			
		||||
    return formData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function validator(formData) {
 | 
			
		||||
    const formErrors = formData.devices.map(
 | 
			
		||||
        (device) => {
 | 
			
		||||
            if (!device.enabled) return {};
 | 
			
		||||
 | 
			
		||||
            const errors = {};
 | 
			
		||||
            if (device.SSID.length > 32) errors.SSID = _("SSID can't be longer than 32 symbols");
 | 
			
		||||
            if (device.SSID.length === 0) errors.SSID = _("SSID can't be empty");
 | 
			
		||||
 | 
			
		||||
            if (device.password.length < 8) errors.password = _("Password must contain at least 8 symbols");
 | 
			
		||||
 | 
			
		||||
            if (!device.guest_wifi.enabled) return errors;
 | 
			
		||||
 | 
			
		||||
            const guest_wifi_errors = {};
 | 
			
		||||
            if (device.guest_wifi.SSID.length > 32) guest_wifi_errors.SSID = _("SSID can't be longer than 32 symbols");
 | 
			
		||||
            if (device.guest_wifi.SSID.length === 0) guest_wifi_errors.SSID = _("SSID can't be empty");
 | 
			
		||||
 | 
			
		||||
            if (device.guest_wifi.password.length < 8) guest_wifi_errors.password = _("Password must contain at least 8 symbols");
 | 
			
		||||
 | 
			
		||||
            if (guest_wifi_errors.SSID || guest_wifi_errors.password) {
 | 
			
		||||
                errors.guest_wifi = guest_wifi_errors;
 | 
			
		||||
            }
 | 
			
		||||
            return errors;
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
    return JSON.stringify(formErrors) === "[{},{}]" ? null : formErrors;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/common/WiFiSettings/__tests__/ResetWiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/common/WiFiSettings/__tests__/ResetWiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render, fireEvent, wait } from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
import { mockSetAlert } from "testUtils/alertContextMock";
 | 
			
		||||
import { ALERT_TYPES } from "../../../bootstrap/Alert";
 | 
			
		||||
 | 
			
		||||
import ResetWiFiSettings from "../ResetWiFiSettings";
 | 
			
		||||
 | 
			
		||||
describe("<ResetWiFiSettings/>", () => {
 | 
			
		||||
    const webSockets = new WebSockets();
 | 
			
		||||
    const endpoint = "/reforis/api/wifi-reset";
 | 
			
		||||
    let getAllByText;
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        ({ getAllByText } = render(<ResetWiFiSettings ws={webSockets} endpoint={endpoint} />));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should display alert on open ports - success", async () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Reset Wi-Fi Settings")[1]);
 | 
			
		||||
        expect(mockAxios.post).toBeCalledWith(endpoint, undefined, expect.anything());
 | 
			
		||||
        mockAxios.mockResponse({ data: { foo: "bar" } });
 | 
			
		||||
        await wait(() => expect(mockSetAlert).toBeCalledWith("Wi-Fi settings are set to defaults.", ALERT_TYPES.SUCCESS));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should display alert on open ports - failure", async () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Reset Wi-Fi Settings")[1]);
 | 
			
		||||
        mockJSONError();
 | 
			
		||||
        await wait(() => expect(mockSetAlert).toBeCalledWith("An error occurred during resetting Wi-Fi settings."));
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										161
									
								
								src/common/WiFiSettings/__tests__/WiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/common/WiFiSettings/__tests__/WiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import diffSnapshot from "snapshot-diff";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, render, wait } from "customTestRender";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
 | 
			
		||||
import { wifiSettingsFixture } from "./__fixtures__/wifiSettings";
 | 
			
		||||
import { WiFiSettings } from "../WiFiSettings";
 | 
			
		||||
 | 
			
		||||
describe("<WiFiSettings/>", () => {
 | 
			
		||||
    let firstRender;
 | 
			
		||||
    let getAllByText;
 | 
			
		||||
    let getAllByLabelText;
 | 
			
		||||
    let getByText;
 | 
			
		||||
    let asFragment;
 | 
			
		||||
    const endpoint = "/reforis/api/wifi";
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        const webSockets = new WebSockets();
 | 
			
		||||
        const renderRes = render(<WiFiSettings ws={webSockets} endpoint={endpoint} resetEndpoint="foo" />);
 | 
			
		||||
        asFragment = renderRes.asFragment;
 | 
			
		||||
        getAllByText = renderRes.getAllByText;
 | 
			
		||||
        getAllByLabelText = renderRes.getAllByLabelText;
 | 
			
		||||
        getByText = renderRes.getByText;
 | 
			
		||||
        mockAxios.mockResponse({ data: wifiSettingsFixture() });
 | 
			
		||||
        await wait(() => renderRes.getByText("Wi-Fi 1"));
 | 
			
		||||
        firstRender = renderRes.asFragment();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should handle error", async () => {
 | 
			
		||||
        const webSockets = new WebSockets();
 | 
			
		||||
        const { getByText } = render(<WiFiSettings ws={webSockets} ws={webSockets} endpoint={endpoint} resetEndpoint="foo" />);
 | 
			
		||||
        mockJSONError();
 | 
			
		||||
        await wait(() => {
 | 
			
		||||
            expect(getByText("An error occurred while fetching data.")).toBeTruthy();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot both modules disabled.", () => {
 | 
			
		||||
        expect(firstRender).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot one module enabled.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        expect(diffSnapshot(firstRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot 2.4 GHz", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        const enabledRender = asFragment();
 | 
			
		||||
        fireEvent.click(getAllByText("2.4")[0]);
 | 
			
		||||
        expect(diffSnapshot(enabledRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot guest network.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        const enabledRender = asFragment();
 | 
			
		||||
        fireEvent.click(getAllByText("Enable Guest Wifi")[0]);
 | 
			
		||||
        expect(diffSnapshot(enabledRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: both modules disabled.", () => {
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                { enabled: false, id: 0 },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: one module enabled.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 60,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: { enabled: false },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11a",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: 2.4 GHz", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        fireEvent.click(getAllByText("2.4")[0]);
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 0,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: { enabled: false },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11g",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: guest network.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        fireEvent.click(getAllByText("Enable Guest Wifi")[0]);
 | 
			
		||||
        fireEvent.change(getAllByLabelText("Password")[1], { target: { value: "test_password" } });
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 60,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: {
 | 
			
		||||
                        SSID: "TestGuestSSID",
 | 
			
		||||
                        enabled: true,
 | 
			
		||||
                        password: "test_password",
 | 
			
		||||
                    },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11a",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										318
									
								
								src/common/WiFiSettings/__tests__/__fixtures__/wifiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								src/common/WiFiSettings/__tests__/__fixtures__/wifiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,318 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export function wifiSettingsFixture() {
 | 
			
		||||
    return {
 | 
			
		||||
        devices: [
 | 
			
		||||
            {
 | 
			
		||||
                SSID: "TestSSID1",
 | 
			
		||||
                available_bands: [
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2412,
 | 
			
		||||
                                number: 1,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2417,
 | 
			
		||||
                                number: 2,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2422,
 | 
			
		||||
                                number: 3,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2427,
 | 
			
		||||
                                number: 4,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2432,
 | 
			
		||||
                                number: 5,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2437,
 | 
			
		||||
                                number: 6,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2442,
 | 
			
		||||
                                number: 7,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2447,
 | 
			
		||||
                                number: 8,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2452,
 | 
			
		||||
                                number: 9,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2457,
 | 
			
		||||
                                number: 10,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2462,
 | 
			
		||||
                                number: 11,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                            "VHT20",
 | 
			
		||||
                            "VHT40",
 | 
			
		||||
                            "VHT80",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11g",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5180,
 | 
			
		||||
                                number: 36,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5200,
 | 
			
		||||
                                number: 40,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5220,
 | 
			
		||||
                                number: 44,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5240,
 | 
			
		||||
                                number: 48,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5260,
 | 
			
		||||
                                number: 52,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5280,
 | 
			
		||||
                                number: 56,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5300,
 | 
			
		||||
                                number: 60,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5320,
 | 
			
		||||
                                number: 64,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5500,
 | 
			
		||||
                                number: 100,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5520,
 | 
			
		||||
                                number: 104,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5540,
 | 
			
		||||
                                number: 108,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5560,
 | 
			
		||||
                                number: 112,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5580,
 | 
			
		||||
                                number: 116,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5600,
 | 
			
		||||
                                number: 120,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5620,
 | 
			
		||||
                                number: 124,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5640,
 | 
			
		||||
                                number: 128,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5660,
 | 
			
		||||
                                number: 132,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5680,
 | 
			
		||||
                                number: 136,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5700,
 | 
			
		||||
                                number: 140,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5720,
 | 
			
		||||
                                number: 144,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5745,
 | 
			
		||||
                                number: 149,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5765,
 | 
			
		||||
                                number: 153,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5785,
 | 
			
		||||
                                number: 157,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5805,
 | 
			
		||||
                                number: 161,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5825,
 | 
			
		||||
                                number: 165,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                            "VHT20",
 | 
			
		||||
                            "VHT40",
 | 
			
		||||
                            "VHT80",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11a",
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                channel: 60,
 | 
			
		||||
                enabled: false,
 | 
			
		||||
                guest_wifi: {
 | 
			
		||||
                    SSID: "TestGuestSSID",
 | 
			
		||||
                    enabled: false,
 | 
			
		||||
                    password: "",
 | 
			
		||||
                },
 | 
			
		||||
                hidden: false,
 | 
			
		||||
                htmode: "HT40",
 | 
			
		||||
                hwmode: "11a",
 | 
			
		||||
                id: 0,
 | 
			
		||||
                password: "TestPass",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                SSID: "Turris",
 | 
			
		||||
                available_bands: [
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2412,
 | 
			
		||||
                                number: 1,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2417,
 | 
			
		||||
                                number: 2,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2422,
 | 
			
		||||
                                number: 3,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2427,
 | 
			
		||||
                                number: 4,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2432,
 | 
			
		||||
                                number: 5,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2437,
 | 
			
		||||
                                number: 6,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2442,
 | 
			
		||||
                                number: 7,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2447,
 | 
			
		||||
                                number: 8,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2452,
 | 
			
		||||
                                number: 9,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2457,
 | 
			
		||||
                                number: 10,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2462,
 | 
			
		||||
                                number: 11,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11g",
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                channel: 11,
 | 
			
		||||
                enabled: false,
 | 
			
		||||
                guest_wifi: {
 | 
			
		||||
                    SSID: "TestSSID",
 | 
			
		||||
                    enabled: false,
 | 
			
		||||
                    password: "",
 | 
			
		||||
                },
 | 
			
		||||
                hidden: false,
 | 
			
		||||
                htmode: "HT40",
 | 
			
		||||
                hwmode: "11g",
 | 
			
		||||
                id: 1,
 | 
			
		||||
                password: "TestPass",
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,912 @@
 | 
			
		||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -246,207 +246,95 @@
 | 
			
		||||
              value=\\"0\\"
 | 
			
		||||
            >
 | 
			
		||||
              auto
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"36\\"
 | 
			
		||||
+             value=\\"1\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         36
 | 
			
		||||
-                         (5180 MHz )
 | 
			
		||||
+                         1
 | 
			
		||||
+                         (2412 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"40\\"
 | 
			
		||||
+             value=\\"2\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         40
 | 
			
		||||
-                         (5200 MHz )
 | 
			
		||||
+                         2
 | 
			
		||||
+                         (2417 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"44\\"
 | 
			
		||||
+             value=\\"3\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         44
 | 
			
		||||
-                         (5220 MHz )
 | 
			
		||||
+                         3
 | 
			
		||||
+                         (2422 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"48\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         48
 | 
			
		||||
-                         (5240 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"52\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         52
 | 
			
		||||
-                         (5260 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"56\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         56
 | 
			
		||||
-                         (5280 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"60\\"
 | 
			
		||||
+             value=\\"4\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         60
 | 
			
		||||
-                         (5300 MHz  ,DFS)
 | 
			
		||||
+                         4
 | 
			
		||||
+                         (2427 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"64\\"
 | 
			
		||||
+             value=\\"5\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         64
 | 
			
		||||
-                         (5320 MHz  ,DFS)
 | 
			
		||||
+                         5
 | 
			
		||||
+                         (2432 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"100\\"
 | 
			
		||||
+             value=\\"6\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         100
 | 
			
		||||
-                         (5500 MHz  ,DFS)
 | 
			
		||||
+                         6
 | 
			
		||||
+                         (2437 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"104\\"
 | 
			
		||||
+             value=\\"7\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         104
 | 
			
		||||
-                         (5520 MHz  ,DFS)
 | 
			
		||||
+                         7
 | 
			
		||||
+                         (2442 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"108\\"
 | 
			
		||||
+             value=\\"8\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         108
 | 
			
		||||
-                         (5540 MHz  ,DFS)
 | 
			
		||||
+                         8
 | 
			
		||||
+                         (2447 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"112\\"
 | 
			
		||||
+             value=\\"9\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         112
 | 
			
		||||
-                         (5560 MHz  ,DFS)
 | 
			
		||||
+                         9
 | 
			
		||||
+                         (2452 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"116\\"
 | 
			
		||||
+             value=\\"10\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         116
 | 
			
		||||
-                         (5580 MHz  ,DFS)
 | 
			
		||||
+                         10
 | 
			
		||||
+                         (2457 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"120\\"
 | 
			
		||||
+             value=\\"11\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         120
 | 
			
		||||
-                         (5600 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"124\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         124
 | 
			
		||||
-                         (5620 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"128\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         128
 | 
			
		||||
-                         (5640 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"132\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         132
 | 
			
		||||
-                         (5660 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"136\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         136
 | 
			
		||||
-                         (5680 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"140\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         140
 | 
			
		||||
-                         (5700 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"144\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         144
 | 
			
		||||
-                         (5720 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"149\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         149
 | 
			
		||||
-                         (5745 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"153\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         153
 | 
			
		||||
-                         (5765 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"157\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         157
 | 
			
		||||
-                         (5785 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"161\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         161
 | 
			
		||||
-                         (5805 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"165\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         165
 | 
			
		||||
-                         (5825 MHz )
 | 
			
		||||
+                         11
 | 
			
		||||
+                         (2462 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
          </select>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div"
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot both modules disabled. 1`] = `
 | 
			
		||||
<DocumentFragment>
 | 
			
		||||
  <div
 | 
			
		||||
    class="col-sm-12 offset-lg-1 col-lg-10 p-0 mb-3"
 | 
			
		||||
  >
 | 
			
		||||
    <form>
 | 
			
		||||
      <h3>
 | 
			
		||||
        Wi-Fi 1
 | 
			
		||||
      </h3>
 | 
			
		||||
      <div
 | 
			
		||||
        class="form-group"
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          class="custom-control custom-checkbox "
 | 
			
		||||
        >
 | 
			
		||||
          <input
 | 
			
		||||
            class="custom-control-input"
 | 
			
		||||
            id="1"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
          />
 | 
			
		||||
          <label
 | 
			
		||||
            class="custom-control-label"
 | 
			
		||||
            for="1"
 | 
			
		||||
          >
 | 
			
		||||
            Enable
 | 
			
		||||
          </label>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <h3>
 | 
			
		||||
        Wi-Fi 2
 | 
			
		||||
      </h3>
 | 
			
		||||
      <div
 | 
			
		||||
        class="form-group"
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          class="custom-control custom-checkbox "
 | 
			
		||||
        >
 | 
			
		||||
          <input
 | 
			
		||||
            class="custom-control-input"
 | 
			
		||||
            id="2"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
          />
 | 
			
		||||
          <label
 | 
			
		||||
            class="custom-control-label"
 | 
			
		||||
            for="2"
 | 
			
		||||
          >
 | 
			
		||||
            Enable
 | 
			
		||||
          </label>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        class="text-right"
 | 
			
		||||
      >
 | 
			
		||||
        <button
 | 
			
		||||
          class="btn btn-primary  col-sm-12 col-lg-3"
 | 
			
		||||
          type="submit"
 | 
			
		||||
        >
 | 
			
		||||
            Save
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
  </div>
 | 
			
		||||
  <h4>
 | 
			
		||||
    Reset Wi-Fi Settings
 | 
			
		||||
  </h4>
 | 
			
		||||
  <p>
 | 
			
		||||
    
 | 
			
		||||
If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the
 | 
			
		||||
current Wi-Fi configuration and restore the default values.
 | 
			
		||||
        
 | 
			
		||||
  </p>
 | 
			
		||||
  <div
 | 
			
		||||
    class="col-sm-12 offset-lg-1 col-lg-10 p-0 mb-3 text-right"
 | 
			
		||||
  >
 | 
			
		||||
    <button
 | 
			
		||||
      class="btn btn-warning col-sm-12 col-lg-3"
 | 
			
		||||
      type="button"
 | 
			
		||||
    >
 | 
			
		||||
        Reset Wi-Fi Settings
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
</DocumentFragment>
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot guest network. 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -475,10 +475,89 @@
 | 
			
		||||
          
 | 
			
		||||
              </small>
 | 
			
		||||
            </label>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"20\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           SSID
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"20\\"
 | 
			
		||||
+             type=\\"text\\"
 | 
			
		||||
+             value=\\"TestGuestSSID\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <img
 | 
			
		||||
+                 alt=\\"QR\\"
 | 
			
		||||
+                 src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\"
 | 
			
		||||
+                 style=\\"opacity: 0.67;\\"
 | 
			
		||||
+                 width=\\"20\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"21\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             autocomplete=\\"new-password\\"
 | 
			
		||||
+             class=\\"form-control  is-invalid\\"
 | 
			
		||||
+             id=\\"21\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"password\\"
 | 
			
		||||
+             value=\\"\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <i
 | 
			
		||||
+                 class=\\"fa fa-eye\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"invalid-feedback\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password must contain at least 8 symbols
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
        <h3>
 | 
			
		||||
          Wi-Fi 2
 | 
			
		||||
        </h3>
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"form-group\\"
 | 
			
		||||
@@ -502,10 +581,11 @@
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"text-right\\"
 | 
			
		||||
        >
 | 
			
		||||
          <button
 | 
			
		||||
            class=\\"btn btn-primary  col-sm-12 col-lg-3\\"
 | 
			
		||||
+           disabled=\\"\\"
 | 
			
		||||
            type=\\"submit\\"
 | 
			
		||||
          >
 | 
			
		||||
              Save
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>"
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -23,10 +23,462 @@
 | 
			
		||||
            >
 | 
			
		||||
              Enable
 | 
			
		||||
            </label>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"4\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           SSID
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"4\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"text\\"
 | 
			
		||||
+             value=\\"TestSSID1\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <img
 | 
			
		||||
+                 alt=\\"QR\\"
 | 
			
		||||
+                 src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\"
 | 
			
		||||
+                 style=\\"opacity: 0.67;\\"
 | 
			
		||||
+                 width=\\"20\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"5\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             autocomplete=\\"new-password\\"
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"5\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"password\\"
 | 
			
		||||
+             value=\\"TestPass\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <i
 | 
			
		||||
+                 class=\\"fa fa-eye\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-checkbox \\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"6\\"
 | 
			
		||||
+             type=\\"checkbox\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"6\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Hide SSID
 | 
			
		||||
+             <small
 | 
			
		||||
+               class=\\"form-text text-muted\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               If set, network is not visible when scanning for available networks.
 | 
			
		||||
+             </small>
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           class=\\"d-block\\"
 | 
			
		||||
+           for=\\"7\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           GHz
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-radio custom-control-inline\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"hwmode-0-0\\"
 | 
			
		||||
+             name=\\"hwmode-0\\"
 | 
			
		||||
+             type=\\"radio\\"
 | 
			
		||||
+             value=\\"11g\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"hwmode-0-0\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             2.4
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-radio custom-control-inline\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             checked=\\"\\"
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"hwmode-0-1\\"
 | 
			
		||||
+             name=\\"hwmode-0\\"
 | 
			
		||||
+             type=\\"radio\\"
 | 
			
		||||
+             value=\\"11a\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"hwmode-0-1\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             5
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a
 | 
			
		||||
+         newer standard and may not be supported by all your devices. It usually has less interference, but the signal
 | 
			
		||||
+         does not carry so well indoors.
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"8\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           802.11n/ac mode
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <select
 | 
			
		||||
+           class=\\"custom-select\\"
 | 
			
		||||
+           id=\\"8\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"NOHT\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Disabled
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"HT20\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11n - 20 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"HT40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11n - 40 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT20\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 20 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 40 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT80\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 80 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+         </select>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         Change this to adjust 802.11n/ac mode of operation. 802.11n with 40 MHz wide channels can yield higher
 | 
			
		||||
+         throughput but can cause more interference in the network. If you don't know what to choose, use the default
 | 
			
		||||
+         option with 20 MHz wide channel.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"9\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Channel
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <select
 | 
			
		||||
+           class=\\"custom-select\\"
 | 
			
		||||
+           id=\\"9\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"0\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             auto
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"36\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         36
 | 
			
		||||
+                         (5180 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         40
 | 
			
		||||
+                         (5200 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"44\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         44
 | 
			
		||||
+                         (5220 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"48\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         48
 | 
			
		||||
+                         (5240 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"52\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         52
 | 
			
		||||
+                         (5260 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"56\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         56
 | 
			
		||||
+                         (5280 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"60\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         60
 | 
			
		||||
+                         (5300 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"64\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         64
 | 
			
		||||
+                         (5320 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"100\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         100
 | 
			
		||||
+                         (5500 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"104\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         104
 | 
			
		||||
+                         (5520 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"108\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         108
 | 
			
		||||
+                         (5540 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"112\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         112
 | 
			
		||||
+                         (5560 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"116\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         116
 | 
			
		||||
+                         (5580 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"120\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         120
 | 
			
		||||
+                         (5600 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"124\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         124
 | 
			
		||||
+                         (5620 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"128\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         128
 | 
			
		||||
+                         (5640 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"132\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         132
 | 
			
		||||
+                         (5660 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"136\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         136
 | 
			
		||||
+                         (5680 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"140\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         140
 | 
			
		||||
+                         (5700 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"144\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         144
 | 
			
		||||
+                         (5720 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"149\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         149
 | 
			
		||||
+                         (5745 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"153\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         153
 | 
			
		||||
+                         (5765 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"157\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         157
 | 
			
		||||
+                         (5785 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"161\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         161
 | 
			
		||||
+                         (5805 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"165\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         165
 | 
			
		||||
+                         (5825 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+         </select>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-checkbox \\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"10\\"
 | 
			
		||||
+             type=\\"checkbox\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"10\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Enable Guest Wifi
 | 
			
		||||
+             <small
 | 
			
		||||
+               class=\\"form-text text-muted\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               
 | 
			
		||||
+         Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to
 | 
			
		||||
+         access the internet, but aren't allowed to access other devices and the configuration interface of the router.
 | 
			
		||||
+         Parameters of the guest network can be set in the Guest network tab.
 | 
			
		||||
+         
 | 
			
		||||
+             </small>
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
        <h3>
 | 
			
		||||
          Wi-Fi 2
 | 
			
		||||
        </h3>
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"form-group\\""
 | 
			
		||||
`;
 | 
			
		||||
							
								
								
									
										39
									
								
								src/common/WiFiSettings/constants.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/common/WiFiSettings/constants.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const HTMODES = {
 | 
			
		||||
    NOHT: _("Disabled"),
 | 
			
		||||
    HT20: _("802.11n - 20 MHz wide channel"),
 | 
			
		||||
    HT40: _("802.11n - 40 MHz wide channel"),
 | 
			
		||||
    VHT20: _("802.11ac - 20 MHz wide channel"),
 | 
			
		||||
    VHT40: _("802.11ac - 40 MHz wide channel"),
 | 
			
		||||
    VHT80: _("802.11ac - 80 MHz wide channel"),
 | 
			
		||||
};
 | 
			
		||||
export const HWMODES = {
 | 
			
		||||
    "11g": "2.4",
 | 
			
		||||
    "11a": "5",
 | 
			
		||||
};
 | 
			
		||||
export const HELP_TEXTS = {
 | 
			
		||||
    password: _(`
 | 
			
		||||
        WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
    `),
 | 
			
		||||
    hidden: _("If set, network is not visible when scanning for available networks."),
 | 
			
		||||
    hwmode: _(`
 | 
			
		||||
        The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a
 | 
			
		||||
        newer standard and may not be supported by all your devices. It usually has less interference, but the signal
 | 
			
		||||
        does not carry so well indoors.`),
 | 
			
		||||
    htmode: _(`
 | 
			
		||||
        Change this to adjust 802.11n/ac mode of operation. 802.11n with 40 MHz wide channels can yield higher
 | 
			
		||||
        throughput but can cause more interference in the network. If you don't know what to choose, use the default
 | 
			
		||||
        option with 20 MHz wide channel.
 | 
			
		||||
    `),
 | 
			
		||||
    guest_wifi_enabled: _(`
 | 
			
		||||
        Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to
 | 
			
		||||
        access the internet, but aren't allowed to access other devices and the configuration interface of the router.
 | 
			
		||||
        Parameters of the guest network can be set in the Guest network tab.
 | 
			
		||||
        `),
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										28
									
								
								src/common/WiFiSettings/qrCodeHelpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/common/WiFiSettings/qrCodeHelpers.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import pdfMake from "pdfmake";
 | 
			
		||||
 | 
			
		||||
export function createAndDownloadPdf(SSID, password) {
 | 
			
		||||
    const docDefinition = {
 | 
			
		||||
        content: [
 | 
			
		||||
            {
 | 
			
		||||
                text: "Wi-Fi", style: "header", fontSize: 55, alignment: "center",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                qr: toQRCodeContent(SSID, password), fit: "350", margin: [0, 80], alignment: "center",
 | 
			
		||||
            },
 | 
			
		||||
            { text: `SSID: ${SSID}`, fontSize: 25, alignment: "center" },
 | 
			
		||||
            { text: `Password: ${password}`, fontSize: 25, alignment: "center" },
 | 
			
		||||
        ],
 | 
			
		||||
    };
 | 
			
		||||
    pdfMake.createPdf(docDefinition).download("wifi.pdf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function toQRCodeContent(SSID, password) {
 | 
			
		||||
    return `WIFI:S:${SSID};T:WPA2;P:${password};;`;
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, getByText, queryByText, render, wait } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    fireEvent, getByText, queryByText, render, wait,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
import { mockSetAlert } from "testUtils/alertContextMock";
 | 
			
		||||
@@ -18,8 +20,8 @@ describe("<RebootButton/>", () => {
 | 
			
		||||
    let componentContainer;
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        const { container } = render(<>
 | 
			
		||||
            <div id="modal-container"/>
 | 
			
		||||
            <RebootButton/>
 | 
			
		||||
            <div id="modal-container" />
 | 
			
		||||
            <RebootButton />
 | 
			
		||||
        </>);
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
@@ -51,5 +53,4 @@ describe("<RebootButton/>", () => {
 | 
			
		||||
        await wait(() => expect(mockSetAlert)
 | 
			
		||||
            .toBeCalledWith("Reboot request failed."));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -12,17 +12,17 @@ import { STATES, SubmitButton } from "../components/SubmitButton";
 | 
			
		||||
 | 
			
		||||
describe("<SubmitButton/>", () => {
 | 
			
		||||
    it("Render ready", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.READY}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.READY} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
    it("Render saving", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.SAVING}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.SAVING} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
    it("Render load", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.LOAD}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.LOAD} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,99 +5,98 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { act, fireEvent, render, waitForElement } from 'customTestRender';
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import { ForisForm } from "../components/ForisForm";
 | 
			
		||||
import {
 | 
			
		||||
    act, fireEvent, render, waitForElement,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
 | 
			
		||||
import { ForisForm } from "../components/ForisForm";
 | 
			
		||||
 | 
			
		||||
// It's possible to unittest each hooks via react-hooks-testing-library.
 | 
			
		||||
// But it's better and easier to test it by test components which uses this hooks.
 | 
			
		||||
 | 
			
		||||
const TestForm = ({formData, formErrors, setFormValue}) => {
 | 
			
		||||
    return <>
 | 
			
		||||
const TestForm = ({ formData, formErrors, setFormValue }) => (
 | 
			
		||||
    <>
 | 
			
		||||
        <input
 | 
			
		||||
            data-testid='test-input'
 | 
			
		||||
            data-testid="test-input"
 | 
			
		||||
            value={formData.field}
 | 
			
		||||
            onChange={setFormValue(value => ({field: {$set: value}}))}
 | 
			
		||||
            onChange={setFormValue((value) => ({ field: { $set: value } }))}
 | 
			
		||||
        />
 | 
			
		||||
        <p>{formErrors.field}</p>
 | 
			
		||||
    </>
 | 
			
		||||
};
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
describe('useForm hook.', () => {
 | 
			
		||||
describe("useForm hook.", () => {
 | 
			
		||||
    let mockValidator;
 | 
			
		||||
    let mockPrepData;
 | 
			
		||||
    let mockPrepDataToSubmit;
 | 
			
		||||
    let input;
 | 
			
		||||
    let form;
 | 
			
		||||
    const Child = jest.fn(props => <TestForm {...props}/>);
 | 
			
		||||
    const Child = jest.fn((props) => <TestForm {...props} />);
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        mockPrepData = jest.fn(() => ({field: 'preparedData'}));
 | 
			
		||||
        mockPrepDataToSubmit = jest.fn(() => ({field: 'preparedDataToSubmit'}));
 | 
			
		||||
        mockValidator = jest.fn(data => data.field === 'invalidValue' ? {field: 'Error'} : {});
 | 
			
		||||
        const {getByTestId, container} = render(
 | 
			
		||||
        mockPrepData = jest.fn(() => ({ field: "preparedData" }));
 | 
			
		||||
        mockPrepDataToSubmit = jest.fn(() => ({ field: "preparedDataToSubmit" }));
 | 
			
		||||
        mockValidator = jest.fn((data) => (data.field === "invalidValue" ? { field: "Error" } : {}));
 | 
			
		||||
        const { getByTestId, container } = render(
 | 
			
		||||
            <ForisForm
 | 
			
		||||
                ws={new WebSockets()}
 | 
			
		||||
                // Just some module which exists...
 | 
			
		||||
                forisConfig={{
 | 
			
		||||
                    endpoint: 'testEndpoint',
 | 
			
		||||
                    wsModule: 'testWSModule'
 | 
			
		||||
                    endpoint: "testEndpoint",
 | 
			
		||||
                    wsModule: "testWSModule",
 | 
			
		||||
                }}
 | 
			
		||||
                prepData={mockPrepData}
 | 
			
		||||
                prepDataToSubmit={mockPrepDataToSubmit}
 | 
			
		||||
                validator={mockValidator}
 | 
			
		||||
            >
 | 
			
		||||
                <Child/>
 | 
			
		||||
            </ForisForm>
 | 
			
		||||
                <Child />
 | 
			
		||||
            </ForisForm>,
 | 
			
		||||
        );
 | 
			
		||||
        mockAxios.mockResponse({field: 'fetchedData'});
 | 
			
		||||
        mockAxios.mockResponse({ field: "fetchedData" });
 | 
			
		||||
 | 
			
		||||
        input = await waitForElement(() =>
 | 
			
		||||
            getByTestId('test-input')
 | 
			
		||||
        );
 | 
			
		||||
        input = await waitForElement(() => getByTestId("test-input"));
 | 
			
		||||
        form = container.firstChild.firstChild;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Validation on changing.', () => {
 | 
			
		||||
    it("Validation on changing.", () => {
 | 
			
		||||
        expect(mockValidator).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formErrors).toMatchObject({});
 | 
			
		||||
 | 
			
		||||
        act(() => {
 | 
			
		||||
            fireEvent.change(input, {target: {value: 'invalidValue', type: 'text'}});
 | 
			
		||||
            fireEvent.change(input, { target: { value: "invalidValue", type: "text" } });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        expect(Child).toHaveBeenCalledTimes(2);
 | 
			
		||||
        expect(mockValidator).toHaveBeenCalledTimes(2);
 | 
			
		||||
        expect(Child.mock.calls[1][0].formErrors).toMatchObject({field: 'Error'});
 | 
			
		||||
        expect(Child.mock.calls[1][0].formErrors).toMatchObject({ field: "Error" });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update text value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {value: 'newValue', type: 'text'}})
 | 
			
		||||
        expect(input.value).toBe('newValue');
 | 
			
		||||
    it("Update text value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { value: "newValue", type: "text" } });
 | 
			
		||||
        expect(input.value).toBe("newValue");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update text value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {value: 123, type: 'number'}})
 | 
			
		||||
        expect(input.value).toBe('123');
 | 
			
		||||
    it("Update text value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { value: 123, type: "number" } });
 | 
			
		||||
        expect(input.value).toBe("123");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update checkbox value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {checked: true, type: 'checkbox'}})
 | 
			
		||||
    it("Update checkbox value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { checked: true, type: "checkbox" } });
 | 
			
		||||
        expect(input.checked).toBe(true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Fetch data.', () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledWith('testEndpoint', expect.anything());
 | 
			
		||||
    it("Fetch data.", () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledWith("testEndpoint", expect.anything());
 | 
			
		||||
        expect(mockPrepData).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formData).toMatchObject({field: 'preparedData'});
 | 
			
		||||
        expect(Child.mock.calls[0][0].formData).toMatchObject({ field: "preparedData" });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Submit.', () => {
 | 
			
		||||
    it("Submit.", () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(0);
 | 
			
		||||
 | 
			
		||||
@@ -106,8 +105,8 @@ describe('useForm hook.', () => {
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(
 | 
			
		||||
            'testEndpoint',
 | 
			
		||||
            {'field': 'preparedDataToSubmit'},
 | 
			
		||||
            "testEndpoint",
 | 
			
		||||
            { field: "preparedDataToSubmit" },
 | 
			
		||||
            expect.anything(),
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import {
 | 
			
		||||
    validateIPv4Address,
 | 
			
		||||
    validateIPv6Address,
 | 
			
		||||
    validateIPv6Prefix,
 | 
			
		||||
    validateMAC
 | 
			
		||||
    validateMAC,
 | 
			
		||||
} from "validations";
 | 
			
		||||
 | 
			
		||||
describe("Validation functions", () => {
 | 
			
		||||
@@ -50,7 +50,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
        expect(validateIPv6Address("::"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
    it("validateIPv6Address invalid", () => {
 | 
			
		||||
        expect(validateIPv6Address("invalid"))
 | 
			
		||||
@@ -85,7 +84,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    it("validateDomain valid", () => {
 | 
			
		||||
        expect(validateDomain("example.com"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
@@ -108,7 +106,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
        expect(validateDUID("ABCDEF12AB"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
    it("validateDUID invalid", () => {
 | 
			
		||||
        expect(validateDUID("gggggggg"))
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ export {
 | 
			
		||||
 | 
			
		||||
// Common
 | 
			
		||||
export { RebootButton } from "./common/RebootButton";
 | 
			
		||||
export { WiFiSettings } from "./common/WiFiSettings/WiFiSettings";
 | 
			
		||||
 | 
			
		||||
// Form
 | 
			
		||||
export { ForisForm } from "./form/components/ForisForm";
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ window.AlertContext = React.createContext();
 | 
			
		||||
function AlertContextMock({ children }) {
 | 
			
		||||
    return (
 | 
			
		||||
        <AlertContext.Provider value={[mockSetAlert, mockDismissAlert]}>
 | 
			
		||||
                { children }
 | 
			
		||||
            { children }
 | 
			
		||||
        </AlertContext.Provider>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
 | 
			
		||||
export function mockJSONError(data) {
 | 
			
		||||
    mockAxios.mockError({ response: { data, headers: { "content-type": "application/json" } } });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import moment from 'moment-timezone';
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import moment from "moment-timezone";
 | 
			
		||||
 | 
			
		||||
// Setup axios cleanup
 | 
			
		||||
global.afterEach(() => {
 | 
			
		||||
@@ -14,9 +14,9 @@ global.afterEach(() => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Mock babel (gettext)
 | 
			
		||||
global._ = str => str;
 | 
			
		||||
global.ngettext = str => str;
 | 
			
		||||
global.babel = {format: (str) => str};
 | 
			
		||||
global._ = (str) => str;
 | 
			
		||||
global.ngettext = (str) => str;
 | 
			
		||||
global.babel = { format: (str) => str };
 | 
			
		||||
global.ForisTranslations = {};
 | 
			
		||||
 | 
			
		||||
// Mock web sockets
 | 
			
		||||
@@ -25,9 +25,9 @@ window.WebSocket = jest.fn();
 | 
			
		||||
// Mock scrollIntoView
 | 
			
		||||
global.HTMLElement.prototype.scrollIntoView = () => {};
 | 
			
		||||
 | 
			
		||||
jest.doMock('moment', () => {
 | 
			
		||||
    moment.tz.setDefault('UTC');
 | 
			
		||||
// Mock timezone utilities
 | 
			
		||||
jest.doMock("moment", () => {
 | 
			
		||||
    moment.tz.setDefault("UTC");
 | 
			
		||||
    return moment;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Date.now = jest.fn(() => new Date(Date.UTC(2019, 1, 1, 12, 13, 14)).valueOf());
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,10 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render } from "customTestRender";
 | 
			
		||||
import { API_STATE } from "api/utils";
 | 
			
		||||
import {
 | 
			
		||||
    withEither, withSpinner, withSending, withSpinnerOnSending, withError, withErrorMessage,
 | 
			
		||||
} from "../conditionalHOCs";
 | 
			
		||||
import { API_STATE } from "api/utils";
 | 
			
		||||
 | 
			
		||||
describe("conditional HOCs", () => {
 | 
			
		||||
    const First = () => <p>First</p>;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user