mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added web account context test
This commit is contained in:
parent
e068273487
commit
132d7cc003
@ -7,14 +7,16 @@ import { StoreContext } from './StoreContext';
|
||||
|
||||
export function useAccountContext() {
|
||||
const [state, setState] = useState({
|
||||
init: false,
|
||||
offsync: false,
|
||||
status: null,
|
||||
seal: null,
|
||||
sealPrivate: null,
|
||||
sealKey: null,
|
||||
});
|
||||
const access = useRef(null);
|
||||
const revision = useRef(null);
|
||||
const next = useRef(null);
|
||||
const setRevision = useRef(null);
|
||||
const curRevision = useRef(null);
|
||||
const syncing = useRef(false);
|
||||
const force = useRef(false);
|
||||
|
||||
const storeContext = useContext(StoreContext);
|
||||
|
||||
@ -24,37 +26,48 @@ export function useAccountContext() {
|
||||
|
||||
useEffect(() => {
|
||||
updateState({ sealKey: storeContext.state.sealKey });
|
||||
}, [storeContext.state.sealKey]);
|
||||
}, [storeContext.state]);
|
||||
|
||||
const setStatus = async (rev) => {
|
||||
if (next.current == null) {
|
||||
if (revision.current !== rev) {
|
||||
let status = await getAccountStatus(access.current);
|
||||
updateState({ init: true, status, seal: status.seal });
|
||||
revision.current = rev;
|
||||
const sync = async () => {
|
||||
if (!syncing.current && (setRevision.current !== curRevision.current || force.current)) {
|
||||
syncing.current = true;
|
||||
force.current = false;
|
||||
|
||||
try {
|
||||
const token = access.current;
|
||||
const revision = curRevision.current;
|
||||
const status = await getAccountStatus(token);
|
||||
setRevision.current = revision;
|
||||
updateState({ offsync: false, status, seal: status.seal });
|
||||
}
|
||||
if (next.current != null) {
|
||||
let r = next.current;
|
||||
next.current = null;
|
||||
setStatus(r);
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
syncing.current = false;
|
||||
updateState({ offsync: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
next.current = rev;
|
||||
|
||||
syncing.current = false;
|
||||
await sync();
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setToken: (token) => {
|
||||
if (access.current || syncing.current) {
|
||||
throw new Error("invalid account session state");
|
||||
}
|
||||
access.current = token;
|
||||
curRevision.current = null;
|
||||
setRevision.current = null;
|
||||
setState({ offsync: false, status: null, seal: null, sealKey: null });
|
||||
},
|
||||
clearToken: () => {
|
||||
access.current = null;
|
||||
revision.current = 0;
|
||||
setState({ init: false, seal: {}, sealKey: {} });
|
||||
},
|
||||
setRevision: async (rev) => {
|
||||
setStatus(rev);
|
||||
curRevision.current = rev;
|
||||
await sync();
|
||||
},
|
||||
setSearchable: async (flag) => {
|
||||
await setAccountSearchable(access.current, flag);
|
||||
@ -74,6 +87,10 @@ export function useAccountContext() {
|
||||
setLogin: async (username, password) => {
|
||||
await setAccountLogin(access.current, username, password);
|
||||
},
|
||||
resync: async () => {
|
||||
force.current = true;
|
||||
await sync();
|
||||
},
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -38,10 +38,19 @@ export function useAppContext(websocket) {
|
||||
const cardContext = useContext(CardContext);
|
||||
|
||||
const setSession = (token) => {
|
||||
try {
|
||||
accountContext.actions.setToken(token);
|
||||
profileContext.actions.setToken(token);
|
||||
cardContext.actions.setToken(token);
|
||||
channelContext.actions.setToken(token);
|
||||
}
|
||||
catch (err) {
|
||||
accountContext.actions.clearToken();
|
||||
profileContext.actions.clearToken();
|
||||
cardContext.actions.clearToken();
|
||||
channelContext.actions.clearToken();
|
||||
throw err;
|
||||
}
|
||||
setWebsocket(token);
|
||||
}
|
||||
|
||||
|
112
net/web/test/Account.test.js
Normal file
112
net/web/test/Account.test.js
Normal file
@ -0,0 +1,112 @@
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import {render, act, screen, waitFor, fireEvent} from '@testing-library/react'
|
||||
import { AccountContextProvider, AccountContext } from 'context/AccountContext';
|
||||
import { StoreContextProvider } from 'context/StoreContext';
|
||||
import * as fetchUtil from 'api/fetchUtil';
|
||||
|
||||
let accountContext = null;
|
||||
function AccountView() {
|
||||
const [renderCount, setRenderCount] = useState(0);
|
||||
const account = useContext(AccountContext);
|
||||
accountContext = account;
|
||||
|
||||
useEffect(() => {
|
||||
setRenderCount(renderCount + 1);
|
||||
}, [account.state]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span data-testid="count">{ renderCount }</span>
|
||||
<span data-testid="seal">{ account.state.seal }</span>
|
||||
<span data-testid="sealKey">{ account.state.sealKey }</span>
|
||||
<span data-testid="searchable">{ account.state.status?.searchable.toString() }</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountTestApp() {
|
||||
return (
|
||||
<StoreContextProvider>
|
||||
<AccountContextProvider>
|
||||
<AccountView />
|
||||
</AccountContextProvider>
|
||||
</StoreContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const realFetchWithTimeout = fetchUtil.fetchWithTimeout;
|
||||
const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
|
||||
let fetchStatus;
|
||||
let sealSet;
|
||||
|
||||
beforeEach(() => {
|
||||
fetchStatus = {};
|
||||
sealSet = false;
|
||||
|
||||
const mockFetch = jest.fn().mockImplementation((url, options) => {
|
||||
if (url === '/account/seal?agent=abc123') {
|
||||
sealSet = true;
|
||||
return Promise.resolve({
|
||||
json: () => Promise.resolve({})
|
||||
});
|
||||
}
|
||||
else if (url === '/account/status?agent=abc123') {
|
||||
return Promise.resolve({
|
||||
json: () => Promise.resolve(fetchStatus)
|
||||
});
|
||||
}
|
||||
else {
|
||||
return Promise.resolve({
|
||||
json: () => Promise.resolve({})
|
||||
});
|
||||
}
|
||||
});
|
||||
fetchUtil.fetchWithTimeout = mockFetch;
|
||||
fetchUtil.fetchWithCustomTimeout = mockFetch;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchUtil.fetchWithTimeout = realFetchWithTimeout;
|
||||
fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout;
|
||||
});
|
||||
|
||||
test('testing account sync', async () => {
|
||||
render(<AccountTestApp />);
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(accountContext).not.toBe(null);
|
||||
});
|
||||
|
||||
fetchStatus = { disabled: false, storageUsed: 1, searchable: true, pushEnabled: false, sealable: true };
|
||||
|
||||
await act(async () => {
|
||||
accountContext.actions.setToken('abc123');
|
||||
await accountContext.actions.setRevision(1);
|
||||
});
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(screen.getByTestId('searchable').textContent).toBe('true');
|
||||
expect(screen.getByTestId('seal').textContent).toBe('');
|
||||
expect(screen.getByTestId('sealKey').textContent).toBe('');
|
||||
expect(sealSet).toBe(false);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await accountContext.actions.setSeal('testeal', 'testsealkey');
|
||||
});
|
||||
|
||||
fetchStatus = { disabled: false, storageUsed: 1, searchable: true, pushEnabled: false, sealable: true, seal: 'testseal' };
|
||||
|
||||
await act(async () => {
|
||||
await accountContext.actions.setRevision(2);
|
||||
});
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(sealSet).toBe(true);
|
||||
expect(screen.getByTestId('seal').textContent).toBe('testseal');
|
||||
expect(screen.getByTestId('sealKey').textContent).toBe('testsealkey');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -68,8 +68,6 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
const mockFetch = jest.fn().mockImplementation((url, options) => {
|
||||
|
||||
console.log(url, options);
|
||||
const params = url.split('/');
|
||||
if (params[1] === 'account' && options.method === 'POST') {
|
||||
return Promise.resolve({
|
||||
@ -119,7 +117,7 @@ test('testing app sync', async () => {
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
mockWebsocket.onclose();
|
||||
mockWebsocket.onclose('test close');
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
});
|
||||
|
||||
|
@ -96,8 +96,6 @@ beforeEach(() => {
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log(params, options);
|
||||
|
||||
return Promise.resolve({
|
||||
url: 'endpoint',
|
||||
status: 200,
|
||||
|
@ -131,7 +131,6 @@ beforeEach(() => {
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log(params, options);
|
||||
return Promise.resolve({
|
||||
url: 'endpoint',
|
||||
status: 200,
|
||||
|
Loading…
Reference in New Issue
Block a user