mirror of
				https://gitlab.nic.cz/turris/reforis/foris-js.git
				synced 2025-11-03 23:00:31 +01:00 
			
		
		
		
	Set tests.
This commit is contained in:
		@@ -8,20 +8,20 @@
 | 
			
		||||
// https://jestjs.io/docs/en/configuration.html
 | 
			
		||||
module.exports = {
 | 
			
		||||
    moduleDirectories: [
 | 
			
		||||
        'node_modules',
 | 
			
		||||
        '<rootDir>/src/testUtils',
 | 
			
		||||
        '<rootDir>/src/',
 | 
			
		||||
        "node_modules",
 | 
			
		||||
        "<rootDir>/src/testUtils",
 | 
			
		||||
        "<rootDir>/src/",
 | 
			
		||||
    ],
 | 
			
		||||
    clearMocks: true,
 | 
			
		||||
    collectCoverageFrom: ['src/**/*.{js,jsx}'],
 | 
			
		||||
    coverageDirectory: 'coverage',
 | 
			
		||||
    testPathIgnorePatterns: ['/node_modules/', '/__fixtures__/'],
 | 
			
		||||
    collectCoverageFrom: ["src/**/*.{js,jsx}"],
 | 
			
		||||
    coverageDirectory: "coverage",
 | 
			
		||||
    testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/"],
 | 
			
		||||
    verbose: false,
 | 
			
		||||
    setupFilesAfterEnv: [
 | 
			
		||||
        '@testing-library/react/cleanup-after-each',
 | 
			
		||||
        '<rootDir>/src/testUtils/setupTest',
 | 
			
		||||
        "@testing-library/react/cleanup-after-each",
 | 
			
		||||
        "<rootDir>/src/testUtils/setup",
 | 
			
		||||
    ],
 | 
			
		||||
    globals: {
 | 
			
		||||
        TZ: 'utc',
 | 
			
		||||
        TZ: "utc",
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
import axios from "axios";
 | 
			
		||||
import { useCallback, useReducer } from "react";
 | 
			
		||||
 | 
			
		||||
import { ForisUrls } from "forisUrls";
 | 
			
		||||
import { ForisURLs } from "forisUrls";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const POST_HEADERS = {
 | 
			
		||||
@@ -57,7 +57,7 @@ const APIGetReducer = (state, action) => {
 | 
			
		||||
            data: action.payload,
 | 
			
		||||
        };
 | 
			
		||||
    case API_ACTIONS.FAILURE:
 | 
			
		||||
        if (action.status === 403) window.location.assign(ForisUrls.login);
 | 
			
		||||
        if (action.status === 403) window.location.assign(ForisURLs.login);
 | 
			
		||||
        return {
 | 
			
		||||
            ...state,
 | 
			
		||||
            isLoading: false,
 | 
			
		||||
@@ -69,18 +69,12 @@ const APIGetReducer = (state, action) => {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This function adds one to its input.
 | 
			
		||||
 * @returns {number} that number, plus one.
 | 
			
		||||
 * @param url
 | 
			
		||||
 */
 | 
			
		||||
export function useAPIGet(url) {
 | 
			
		||||
    const [state, dispatch] = useReducer(APIGetReducer, {
 | 
			
		||||
        isLoading: false,
 | 
			
		||||
        isError: false,
 | 
			
		||||
        data: null,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const get = useCallback(async () => {
 | 
			
		||||
        dispatch({ type: API_ACTIONS.INIT });
 | 
			
		||||
        try {
 | 
			
		||||
@@ -118,7 +112,7 @@ const APIPostReducer = (state, action) => {
 | 
			
		||||
            data: action.payload,
 | 
			
		||||
        };
 | 
			
		||||
    case API_ACTIONS.FAILURE:
 | 
			
		||||
        if (action.status === 403) window.location.assign(ForisUrls.login);
 | 
			
		||||
        if (action.status === 403) window.location.assign(ForisURLs.login);
 | 
			
		||||
        return {
 | 
			
		||||
            ...state,
 | 
			
		||||
            isSending: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,11 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import {useUID} from 'react-uid';
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
import { useUID } from "react-uid";
 | 
			
		||||
 | 
			
		||||
import {formFieldsSize} from './constants';
 | 
			
		||||
import { formFieldsSize } from "./constants";
 | 
			
		||||
 | 
			
		||||
CheckBox.propTypes = {
 | 
			
		||||
    /** Label message */
 | 
			
		||||
@@ -19,28 +19,32 @@ CheckBox.propTypes = {
 | 
			
		||||
    /** Apply default size (full-width) */
 | 
			
		||||
    useDefaultSize: PropTypes.bool,
 | 
			
		||||
    /** Control if checkbox is clickable */
 | 
			
		||||
    disabled: PropTypes.bool
 | 
			
		||||
    disabled: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CheckBox.defaultProps = {
 | 
			
		||||
    useDefaultSize: true,
 | 
			
		||||
    disabled: false
 | 
			
		||||
    disabled: false,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function CheckBox({label, helpText, useDefaultSize, disabled, ...props}) {
 | 
			
		||||
export function CheckBox({
 | 
			
		||||
    label, helpText, useDefaultSize, disabled, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    const uid = useUID();
 | 
			
		||||
    return <div className={useDefaultSize ? formFieldsSize : ""} style={{marginBottom: '1rem'}}>
 | 
			
		||||
        <div className='custom-control custom-checkbox' style={{marginBottom: '0'}}>
 | 
			
		||||
            <input
 | 
			
		||||
                className='custom-control-input'
 | 
			
		||||
                type='checkbox'
 | 
			
		||||
                id={uid}
 | 
			
		||||
                disabled={disabled}
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={useDefaultSize ? formFieldsSize : ""} style={{ marginBottom: "1rem" }}>
 | 
			
		||||
            <div className="custom-control custom-checkbox" style={{ marginBottom: "0" }}>
 | 
			
		||||
                <input
 | 
			
		||||
                    className="custom-control-input"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    id={uid}
 | 
			
		||||
                    disabled={disabled}
 | 
			
		||||
 | 
			
		||||
                {...props}
 | 
			
		||||
            />
 | 
			
		||||
            <label className='custom-control-label' htmlFor={uid} style={helpText ? {marginBottom: '0'} : null}>{label}</label>
 | 
			
		||||
                    {...props}
 | 
			
		||||
                />
 | 
			
		||||
                <label className="custom-control-label" htmlFor={uid} style={helpText ? { marginBottom: "0" } : null}>{label}</label>
 | 
			
		||||
            </div>
 | 
			
		||||
            {helpText ? <small className="form-text text-muted">{helpText}</small> : null}
 | 
			
		||||
        </div>
 | 
			
		||||
        {helpText ? <small className="form-text text-muted">{helpText}</small> : null}
 | 
			
		||||
    </div>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,36 +5,42 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
Spinner.propTypes = {
 | 
			
		||||
    /** Children components put into `div` with "spinner-text" class. */
 | 
			
		||||
    children: PropTypes.oneOfType([
 | 
			
		||||
        PropTypes.arrayOf(PropTypes.node),
 | 
			
		||||
        PropTypes.node
 | 
			
		||||
        PropTypes.node,
 | 
			
		||||
    ]),
 | 
			
		||||
    /** Render component with full-screen mode (using apropriate `.css` styles) */
 | 
			
		||||
    fullScreen: PropTypes.bool.isRequired,
 | 
			
		||||
    className: PropTypes.string
 | 
			
		||||
    className: PropTypes.string,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Spinner.defaultProps = {
 | 
			
		||||
    fullScreen: false,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function Spinner({fullScreen, children, className, ...props}) {
 | 
			
		||||
export function Spinner({
 | 
			
		||||
    fullScreen, children, className, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    if (!fullScreen) {
 | 
			
		||||
        return <div className={'spinner-wrapper ' + (className ? className : '')} {...props}>
 | 
			
		||||
            <SpinnerElement>{children}</SpinnerElement>
 | 
			
		||||
        </div>;
 | 
			
		||||
        return (
 | 
			
		||||
            <div className={`spinner-wrapper ${className || ""}`} {...props}>
 | 
			
		||||
                <SpinnerElement>{children}</SpinnerElement>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return <div className="spinner-fs-wrapper" {...props}>
 | 
			
		||||
        <div className="spinner-fs-background">
 | 
			
		||||
            <SpinnerElement>{children}</SpinnerElement>
 | 
			
		||||
    return (
 | 
			
		||||
        <div className="spinner-fs-wrapper" {...props}>
 | 
			
		||||
            <div className="spinner-fs-background">
 | 
			
		||||
                <SpinnerElement>{children}</SpinnerElement>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SpinnerElement.propTypes = {
 | 
			
		||||
@@ -43,15 +49,17 @@ SpinnerElement.propTypes = {
 | 
			
		||||
    /** Children components */
 | 
			
		||||
    children: PropTypes.oneOfType([
 | 
			
		||||
        PropTypes.arrayOf(PropTypes.node),
 | 
			
		||||
        PropTypes.node
 | 
			
		||||
        PropTypes.node,
 | 
			
		||||
    ]),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function SpinnerElement({small, children}) {
 | 
			
		||||
    return <>
 | 
			
		||||
        <div className={'spinner-border ' + (small ? 'spinner-border-sm' : '')} role="status">
 | 
			
		||||
            <span className="sr-only"/>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="spinner-text">{children}</div>
 | 
			
		||||
    </>
 | 
			
		||||
export function SpinnerElement({ small, children }) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <div className={`spinner-border ${small ? "spinner-border-sm" : ""}`} role="status">
 | 
			
		||||
                <span className="sr-only" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="spinner-text">{children}</div>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import Button from '../Button'
 | 
			
		||||
import {Button} from '../Button'
 | 
			
		||||
 | 
			
		||||
describe('<Button />', () => {
 | 
			
		||||
    it('Render button correctly', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,12 +9,12 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import Checkbox from '../Checkbox'
 | 
			
		||||
import {CheckBox} from '../Checkbox'
 | 
			
		||||
 | 
			
		||||
describe('<Checkbox/>', () => {
 | 
			
		||||
    it('Render checkbox', () => {
 | 
			
		||||
        const {container} = render(
 | 
			
		||||
            <Checkbox
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                checked
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
@@ -26,7 +26,7 @@ describe('<Checkbox/>', () => {
 | 
			
		||||
 | 
			
		||||
    it('Render uncheked checkbox', () => {
 | 
			
		||||
        const {container} = render(
 | 
			
		||||
            <Checkbox
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
            />
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import NumberInput from '../NumberInput';
 | 
			
		||||
import {NumberInput} from '../NumberInput';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('<NumberInput/>', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import PasswordInput from '../PasswordInput';
 | 
			
		||||
import {PasswordInput} from '../PasswordInput';
 | 
			
		||||
 | 
			
		||||
describe('<PasswordInput/>', () => {
 | 
			
		||||
    it('Render password input', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import RadioSet from '../RadioSet';
 | 
			
		||||
import {RadioSet} from '../RadioSet';
 | 
			
		||||
 | 
			
		||||
const TEST_CHOICES = [
 | 
			
		||||
    {label: 'label', value: 'value'},
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {fireEvent, getByDisplayValue, getByText, render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import Select from '../Select';
 | 
			
		||||
import {Select} from '../Select';
 | 
			
		||||
 | 
			
		||||
const TEST_CHOICES = {
 | 
			
		||||
    '1': 'one',
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import TextInput from '../TextInput';
 | 
			
		||||
import {TextInput} from '../TextInput';
 | 
			
		||||
 | 
			
		||||
describe('<TextInput/>', () => {
 | 
			
		||||
    it('Render text input', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import {render} from 'customTestRender';
 | 
			
		||||
 | 
			
		||||
import SubmitButton, {STATES} from '../components/SubmitButton';
 | 
			
		||||
import {STATES, SubmitButton} from '../components/SubmitButton';
 | 
			
		||||
 | 
			
		||||
describe('<SubmitButton/>', () => {
 | 
			
		||||
    it('Render ready', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,15 +5,12 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// TODO: rewrite this test
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import {fireEvent, render, waitForElement} from 'customTestRender';
 | 
			
		||||
import {act, fireEvent, render, waitForElement} from 'customTestRender';
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
 | 
			
		||||
import ForisForm from '../components/ForisForm';
 | 
			
		||||
import API_URLs from 'common/API';
 | 
			
		||||
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.
 | 
			
		||||
@@ -47,8 +44,8 @@ describe('useForm hook.', () => {
 | 
			
		||||
                ws={mockWebSockets}
 | 
			
		||||
                // Just some module which exists...
 | 
			
		||||
                forisConfig={{
 | 
			
		||||
                    endpoint: API_URLs.wan,
 | 
			
		||||
                    wsModule: 'wan'
 | 
			
		||||
                    endpoint: 'testEndpoint',
 | 
			
		||||
                    wsModule: 'testWSModule'
 | 
			
		||||
                }}
 | 
			
		||||
                prepData={mockPrepData}
 | 
			
		||||
                prepDataToSubmit={mockPrepDataToSubmit}
 | 
			
		||||
@@ -70,46 +67,48 @@ describe('useForm hook.', () => {
 | 
			
		||||
        expect(Child).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formErrors).toMatchObject({});
 | 
			
		||||
 | 
			
		||||
        fireEvent.change(input, {target: {value: 'invalidValue', type: 'text'}});
 | 
			
		||||
        act(() => {
 | 
			
		||||
            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'});
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    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 checkbox value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {checked: true, type: 'checkbox'}})
 | 
			
		||||
        expect(input.checked).toBe(true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Fetch data.', () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledWith('/api/wan', expect.anything());
 | 
			
		||||
        expect(mockPrepData).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formData).toMatchObject({field: 'preparedData'});
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Submit.', () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(0);
 | 
			
		||||
 | 
			
		||||
        fireEvent.submit(form);
 | 
			
		||||
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(
 | 
			
		||||
            '/api/wan',
 | 
			
		||||
            {'field': 'preparedDataToSubmit'},
 | 
			
		||||
            expect.anything(),
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    // 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 checkbox value.', () => {
 | 
			
		||||
    //     fireEvent.change(input, {target: {checked: true, type: 'checkbox'}})
 | 
			
		||||
    //     expect(input.checked).toBe(true);
 | 
			
		||||
    // });
 | 
			
		||||
    //
 | 
			
		||||
    // it('Fetch data.', () => {
 | 
			
		||||
    //     expect(mockAxios.get).toHaveBeenCalledWith('/api/wan', expect.anything());
 | 
			
		||||
    //     expect(mockPrepData).toHaveBeenCalledTimes(1);
 | 
			
		||||
    //     expect(Child.mock.calls[0][0].formData).toMatchObject({field: 'preparedData'});
 | 
			
		||||
    // });
 | 
			
		||||
    //
 | 
			
		||||
    // it('Submit.', () => {
 | 
			
		||||
    //     expect(mockAxios.get).toHaveBeenCalledTimes(1);
 | 
			
		||||
    //     expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(0);
 | 
			
		||||
    //
 | 
			
		||||
    //     fireEvent.submit(form);
 | 
			
		||||
    //
 | 
			
		||||
    //     expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(1);
 | 
			
		||||
    //     expect(mockAxios.post).toHaveBeenCalledTimes(1);
 | 
			
		||||
    //     expect(mockAxios.post).toHaveBeenCalledWith(
 | 
			
		||||
    //         '/api/wan',
 | 
			
		||||
    //         {'field': 'preparedDataToSubmit'},
 | 
			
		||||
    //         expect.anything(),
 | 
			
		||||
    //     );
 | 
			
		||||
    // });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,10 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import {Button} from 'bootstrap/Button';
 | 
			
		||||
import { Button } from "bootstrap/Button";
 | 
			
		||||
 | 
			
		||||
export const STATES = {
 | 
			
		||||
    READY: 1,
 | 
			
		||||
@@ -18,32 +18,34 @@ export const STATES = {
 | 
			
		||||
 | 
			
		||||
SubmitButton.propTypes = {
 | 
			
		||||
    disabled: PropTypes.bool,
 | 
			
		||||
    state: PropTypes.oneOf(Object.keys(STATES).map(key => STATES[key]))
 | 
			
		||||
    state: PropTypes.oneOf(Object.keys(STATES).map((key) => STATES[key])),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function SubmitButton({disabled, state, ...props}) {
 | 
			
		||||
export function SubmitButton({ disabled, state, ...props }) {
 | 
			
		||||
    const disableSubmitButton = disabled || state !== STATES.READY;
 | 
			
		||||
    const loadingSubmitButton = state !== STATES.READY;
 | 
			
		||||
 | 
			
		||||
    let labelSubmitButton;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case STATES.SAVING:
 | 
			
		||||
            labelSubmitButton = _('Updating');
 | 
			
		||||
            break;
 | 
			
		||||
        case STATES.LOAD:
 | 
			
		||||
            labelSubmitButton = _('Load settings');
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            labelSubmitButton = _('Save');
 | 
			
		||||
    case STATES.SAVING:
 | 
			
		||||
        labelSubmitButton = _("Updating");
 | 
			
		||||
        break;
 | 
			
		||||
    case STATES.LOAD:
 | 
			
		||||
        labelSubmitButton = _("Load settings");
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        labelSubmitButton = _("Save");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return <Button
 | 
			
		||||
        loading={loadingSubmitButton}
 | 
			
		||||
        disabled={disableSubmitButton}
 | 
			
		||||
        forisFormSize
 | 
			
		||||
    return (
 | 
			
		||||
        <Button
 | 
			
		||||
            loading={loadingSubmitButton}
 | 
			
		||||
            disabled={disableSubmitButton}
 | 
			
		||||
            forisFormSize
 | 
			
		||||
 | 
			
		||||
        {...props}
 | 
			
		||||
    >
 | 
			
		||||
        {labelSubmitButton}
 | 
			
		||||
    </Button>;
 | 
			
		||||
            {...props}
 | 
			
		||||
        >
 | 
			
		||||
            {labelSubmitButton}
 | 
			
		||||
        </Button>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,87 +5,86 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import {useCallback, useEffect, useReducer} from 'react';
 | 
			
		||||
import update from 'immutability-helper';
 | 
			
		||||
import { useCallback, useEffect, useReducer } from "react";
 | 
			
		||||
import update from "immutability-helper";
 | 
			
		||||
 | 
			
		||||
import {useAPIGet} from 'api/hooks';
 | 
			
		||||
import {useWSForisModule} from 'webSockets/hooks';
 | 
			
		||||
import { useAPIGet } from "api/hooks";
 | 
			
		||||
import { useWSForisModule } from "webSockets/hooks";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function useForm(validator, prepData) {
 | 
			
		||||
    const [state, dispatch] = useReducer(formReducer, {
 | 
			
		||||
        data: null,
 | 
			
		||||
        initialData: null,
 | 
			
		||||
        errors: {},
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onFormReload = useCallback(data => {
 | 
			
		||||
        dispatch({
 | 
			
		||||
            type: FORM_ACTIONS.resetData,
 | 
			
		||||
            data: data,
 | 
			
		||||
            prepData: prepData,
 | 
			
		||||
            validator: validator,
 | 
			
		||||
        });
 | 
			
		||||
    }, [prepData, validator]);
 | 
			
		||||
 | 
			
		||||
    const onFormChangeHandler = useCallback(updateRule =>
 | 
			
		||||
        event => {
 | 
			
		||||
            dispatch({
 | 
			
		||||
                type: FORM_ACTIONS.updateValue,
 | 
			
		||||
                value: getChangedValue(event.target),
 | 
			
		||||
                updateRule: updateRule,
 | 
			
		||||
                validator: validator,
 | 
			
		||||
            })
 | 
			
		||||
        }, [validator]);
 | 
			
		||||
 | 
			
		||||
    return [
 | 
			
		||||
        state,
 | 
			
		||||
        onFormChangeHandler,
 | 
			
		||||
        onFormReload,
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FORM_ACTIONS = {
 | 
			
		||||
    updateValue: 1,
 | 
			
		||||
    resetData: 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function useForm(validator, prepData) {
 | 
			
		||||
 | 
			
		||||
    const [state, dispatch] = useReducer(formReducer, {
 | 
			
		||||
        data: null,
 | 
			
		||||
        initialData: null,
 | 
			
		||||
        errors: {},
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onFormReload = useCallback((data) => {
 | 
			
		||||
        dispatch({
 | 
			
		||||
            type: FORM_ACTIONS.resetData,
 | 
			
		||||
            data,
 | 
			
		||||
            prepData,
 | 
			
		||||
            validator,
 | 
			
		||||
        });
 | 
			
		||||
    }, [prepData, validator]);
 | 
			
		||||
 | 
			
		||||
    const onFormChangeHandler = useCallback((updateRule) => (event) => {
 | 
			
		||||
        dispatch({
 | 
			
		||||
            type: FORM_ACTIONS.updateValue,
 | 
			
		||||
            value: getChangedValue(event.target),
 | 
			
		||||
            updateRule,
 | 
			
		||||
            validator,
 | 
			
		||||
        });
 | 
			
		||||
    }, [validator]);
 | 
			
		||||
    return [
 | 
			
		||||
        state,
 | 
			
		||||
        onFormChangeHandler,
 | 
			
		||||
        onFormReload,
 | 
			
		||||
    ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function formReducer(state, action) {
 | 
			
		||||
    switch (action.type) {
 | 
			
		||||
        case FORM_ACTIONS.updateValue: {
 | 
			
		||||
            const newData = update(state.data, action.updateRule(action.value));
 | 
			
		||||
            const errors = action.validator(newData);
 | 
			
		||||
            return {
 | 
			
		||||
                ...state,
 | 
			
		||||
                data: newData,
 | 
			
		||||
                errors: errors
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case FORM_ACTIONS.resetData: {
 | 
			
		||||
            if (!action.data)
 | 
			
		||||
                return {...state, initialData: state.data};
 | 
			
		||||
            const prepData = action.prepData ? action.prepData(action.data) : action.data;
 | 
			
		||||
            return {
 | 
			
		||||
                data: prepData,
 | 
			
		||||
                initialData: prepData,
 | 
			
		||||
                errors: action.data ? action.validator(prepData) : undefined,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            throw new Error();
 | 
			
		||||
        }
 | 
			
		||||
    case FORM_ACTIONS.updateValue: {
 | 
			
		||||
        const newData = update(state.data, action.updateRule(action.value));
 | 
			
		||||
        const errors = action.validator(newData);
 | 
			
		||||
        return {
 | 
			
		||||
            ...state,
 | 
			
		||||
            data: newData,
 | 
			
		||||
            errors,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    case FORM_ACTIONS.resetData: {
 | 
			
		||||
        if (!action.data) return { ...state, initialData: state.data };
 | 
			
		||||
        const prepData = action.prepData ? action.prepData(action.data) : action.data;
 | 
			
		||||
        return {
 | 
			
		||||
            data: prepData,
 | 
			
		||||
            initialData: prepData,
 | 
			
		||||
            errors: action.data ? action.validator(prepData) : undefined,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
        throw new Error();
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getChangedValue(target) {
 | 
			
		||||
    let value = target.value;
 | 
			
		||||
    if (target.type === 'checkbox') {
 | 
			
		||||
    let { value } = target;
 | 
			
		||||
    if (target.type === "checkbox") {
 | 
			
		||||
        value = target.checked;
 | 
			
		||||
    } else if (target.type === 'number') {
 | 
			
		||||
    } else if (target.type === "number") {
 | 
			
		||||
        const parsedValue = parseInt(value);
 | 
			
		||||
        value = isNaN(parsedValue) ? value : parsedValue;
 | 
			
		||||
    }
 | 
			
		||||
    return value
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useForisModule(ws, config) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								src/testUtils/__mocks__/axios.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/testUtils/__mocks__/axios.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 mockAxios from "jest-mock-axios";
 | 
			
		||||
export default mockAxios;
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import {UIDReset} from 'react-uid';
 | 
			
		||||
import {StaticRouter} from 'react-router';
 | 
			
		||||
import {render} from '@testing-library/react'
 | 
			
		||||
 | 
			
		||||
Wrapper.propTypes = {
 | 
			
		||||
@@ -20,9 +21,11 @@ Wrapper.propTypes = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Wrapper({children}) {
 | 
			
		||||
    return <UIDReset>
 | 
			
		||||
        {children}
 | 
			
		||||
    </UIDReset>
 | 
			
		||||
    return <StaticRouter>
 | 
			
		||||
        <UIDReset>
 | 
			
		||||
            {children}
 | 
			
		||||
        </UIDReset>
 | 
			
		||||
    </StaticRouter>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const customTestRender = (ui, options) => render(ui, {wrapper: Wrapper, ...options});
 | 
			
		||||
 
 | 
			
		||||
@@ -28,5 +28,3 @@ jest.doMock('moment', () => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Date.now = jest.fn(() => new Date(Date.UTC(2019, 1, 1, 12, 13, 14)).valueOf());
 | 
			
		||||
 | 
			
		||||
jest.doMock("utils/vfs_fonts", () => ({}));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user