mirror of
https://github.com/balzack/databag.git
synced 2025-03-13 00:50:03 +00:00
testing web access view
This commit is contained in:
parent
0cf94193a2
commit
eb96fe2664
@ -11,7 +11,7 @@
|
||||
"**/test/**"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
|
||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/fileMock.js",
|
||||
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
|
||||
}
|
||||
},
|
||||
|
@ -1,7 +1,4 @@
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { ViewportContext } from 'context/ViewportContext';
|
||||
import { useAccess } from './useAccess.hook';
|
||||
import { AccessWrapper } from './Access.styled';
|
||||
import { Login } from './login/Login';
|
||||
import { CreateAccount } from './createAccount/CreateAccount';
|
||||
@ -10,26 +7,16 @@ import login from 'images/login.png'
|
||||
|
||||
export function Access({ mode }) {
|
||||
|
||||
const navigate = useNavigate();
|
||||
const app = useContext(AppContext);
|
||||
const viewport = useContext(ViewportContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (app.state) {
|
||||
if (app.state.access) {
|
||||
navigate('/session');
|
||||
}
|
||||
}
|
||||
}, [app, navigate]);
|
||||
const { state } = useAccess();
|
||||
|
||||
return (
|
||||
<AccessWrapper>
|
||||
{ (viewport.state.display === 'large' || viewport.state.display === 'xlarge') && (
|
||||
<div class="split-layout">
|
||||
<div class="left">
|
||||
<img class="splash" src={login} alt="Databag Splash" />
|
||||
{ (state.display === 'large' || state.display === 'xlarge') && (
|
||||
<div className="split-layout">
|
||||
<div className="left">
|
||||
<img className="splash" src={login} alt="Databag Splash" />
|
||||
</div>
|
||||
<div class="right">
|
||||
<div className="right">
|
||||
{ mode === 'login' && (
|
||||
<Login />
|
||||
)}
|
||||
@ -39,9 +26,9 @@ export function Access({ mode }) {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{ (viewport.state.display === 'medium' || viewport.state.display === 'small') && (
|
||||
<div class="full-layout">
|
||||
<div class="center">
|
||||
{ (state.display === 'medium' || state.display === 'small') && (
|
||||
<div className="full-layout">
|
||||
<div className="center">
|
||||
{ mode === 'login' && (
|
||||
<Login />
|
||||
)}
|
||||
|
@ -27,35 +27,35 @@ export function CreateAccount() {
|
||||
|
||||
return (
|
||||
<CreateAccountWrapper>
|
||||
<div class="app-title">
|
||||
<div className="app-title">
|
||||
<span>Databag</span>
|
||||
<div class="settings" onClick={() => actions.onSettings()}>
|
||||
<div className="settings" onClick={() => actions.onSettings()}>
|
||||
<SettingOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-title">Create Account</div>
|
||||
<div class="form-form">
|
||||
<div className="form-title">Create Account</div>
|
||||
<div className="form-form">
|
||||
<Form name="basic" wrapperCol={{ span: 24, }}>
|
||||
|
||||
<Form.Item name="username" validateStatus={state.validateStatus} help={state.help}>
|
||||
<Input placeholder="Username" spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
autocomplete="username" autocapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div class="form-space"></div>
|
||||
<div className="form-space"></div>
|
||||
|
||||
<Form.Item name="password">
|
||||
<Input.Password placeholder="Password" spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
autocomplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="confirm">
|
||||
<Input.Password placeholder="Confirm Password" spellCheck="false" onChange={(e) => actions.setConfirm(e.target.value)}
|
||||
autocomplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
autoComplete="new-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div class="form-button">
|
||||
<div class="form-create">
|
||||
<div className="form-button">
|
||||
<div className="form-create">
|
||||
<Button type="primary" block onClick={create} disabled={ actions.isDisabled()}
|
||||
loading={state.busy} size="middle">
|
||||
Create Account
|
||||
@ -63,8 +63,8 @@ export function CreateAccount() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-button">
|
||||
<div class="form-login">
|
||||
<div className="form-button">
|
||||
<div className="form-login">
|
||||
<Button type="link" block onClick={(e) => actions.onLogin()}>
|
||||
Account Login
|
||||
</Button>
|
||||
|
@ -38,7 +38,6 @@ export const CreateAccountWrapper = styled.div`
|
||||
|
||||
.form-form {
|
||||
flex: 2;
|
||||
flex-grow: 1;
|
||||
|
||||
.form-space {
|
||||
height: 8px;
|
||||
|
@ -27,28 +27,28 @@ export function Login() {
|
||||
|
||||
return (
|
||||
<LoginWrapper>
|
||||
<div class="app-title">
|
||||
<div className="app-title">
|
||||
<span>Databag</span>
|
||||
<div class="settings" onClick={() => actions.onSettings()}>
|
||||
<div className="settings" onClick={() => actions.onSettings()}>
|
||||
<SettingOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-title">Login</div>
|
||||
<div class="form-form">
|
||||
<div className="form-title">Login</div>
|
||||
<div className="form-form">
|
||||
<Form name="basic" wrapperCol={{ span: 24, }}>
|
||||
|
||||
<Form.Item name="username">
|
||||
<Input placeholder="Username" spellCheck="false" onChange={(e) => actions.setUsername(e.target.value)}
|
||||
autocomplete="username" autocapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
autoComplete="username" autoCapitalize="none" onKeyDown={(e) => keyDown(e)} prefix={<UserOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="password">
|
||||
<Input.Password placeholder="Password" spellCheck="false" onChange={(e) => actions.setPassword(e.target.value)}
|
||||
autocomplete="current-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
autoComplete="current-password" onKeyDown={(e) => keyDown(e)} prefix={<LockOutlined />} size="large" />
|
||||
</Form.Item>
|
||||
|
||||
<div class="form-button">
|
||||
<div class="form-login">
|
||||
<div className="form-button">
|
||||
<div className="form-login">
|
||||
<Button type="primary" block onClick={login} disabled={ actions.isDisabled()}
|
||||
size="middle" loading={state.busy}>
|
||||
Login
|
||||
@ -56,7 +56,7 @@ export function Login() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-button">
|
||||
<div className="form-button">
|
||||
<Button type="link" block disabled={ !state.available } onClick={(e) => actions.onCreate()}>
|
||||
Create Account
|
||||
</Button>
|
||||
|
@ -77,6 +77,10 @@ export function useLogin() {
|
||||
access();
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [app.state, navigate, search]);
|
||||
|
||||
useEffect(() => {
|
||||
const count = async () => {
|
||||
try {
|
||||
const available = await getAvailable()
|
||||
@ -88,7 +92,7 @@ export function useLogin() {
|
||||
}
|
||||
count();
|
||||
// eslint-disable-next-line
|
||||
}, [app.state, navigate, search])
|
||||
}, [])
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
35
net/web/src/access/useAccess.hook.js
Normal file
35
net/web/src/access/useAccess.hook.js
Normal file
@ -0,0 +1,35 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { ViewportContext } from 'context/ViewportContext';
|
||||
|
||||
export function useAccess() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
display: null,
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
const app = useContext(AppContext);
|
||||
const viewport = useContext(ViewportContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (app.state.status) {
|
||||
navigate('/session');
|
||||
}
|
||||
}, [app.state, navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
const { display } = viewport.state;
|
||||
updateState({ display });
|
||||
}, [viewport.state]);
|
||||
|
||||
const actions = {};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
65
net/web/test/AccessView.test.js
Normal file
65
net/web/test/AccessView.test.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import {render, act, screen, waitFor, fireEvent} from '@testing-library/react'
|
||||
import { HashRouter as Router, Routes, Route } from "react-router-dom";
|
||||
import { ViewportContextProvider } from 'context/ViewportContext';
|
||||
import { AppContextProvider } from 'context/AppContext';
|
||||
import { Access } from 'access/Access';
|
||||
import * as fetchUtil from 'api/fetchUtil';
|
||||
|
||||
function AccessTestApp() {
|
||||
return (
|
||||
<ViewportContextProvider>
|
||||
<AppContextProvider>
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path="/" element={ <Access mode="login" /> } />
|
||||
<Route path="/login" element={ <Access mode="login" /> } />
|
||||
<Route path="/create" element={ <Access mode="create" /> } />
|
||||
</Routes>
|
||||
</Router>
|
||||
</AppContextProvider>
|
||||
</ViewportContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
Object.defineProperty(window, "matchMedia", {
|
||||
writable: true,
|
||||
value: jest.fn().mockImplementation(query => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: jest.fn(), // Deprecated
|
||||
removeListener: jest.fn(), // Deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
}))
|
||||
});
|
||||
});
|
||||
|
||||
const realFetchWithTimeout = fetchUtil.fetchWithTimeout;
|
||||
const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
|
||||
beforeEach(() => {
|
||||
const mockFetch = jest.fn().mockImplementation((url, options) => {
|
||||
return Promise.resolve({
|
||||
json: () => Promise.resolve([])
|
||||
});
|
||||
});
|
||||
fetchUtil.fetchWithTimeout = mockFetch;
|
||||
fetchUtil.fetchWithCustomTimeout = mockFetch;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchUtil.fetchWithTimeout = realFetchWithTimeout;
|
||||
fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout;
|
||||
});
|
||||
|
||||
test('login and create', async () => {
|
||||
await act(async () => {
|
||||
render(<AccessTestApp />);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
2
net/web/test/fileMock.js
Normal file
2
net/web/test/fileMock.js
Normal file
@ -0,0 +1,2 @@
|
||||
module.exports = '';
|
||||
|
Loading…
Reference in New Issue
Block a user