testing web app context

This commit is contained in:
balzack 2023-01-11 21:54:26 -08:00
parent 28940671d9
commit a371bbbc1d
2 changed files with 60 additions and 62 deletions

View File

@ -15,7 +15,7 @@ import { createWebsocket } from 'api/fetchUtil';
export function useAppContext(websocket) {
const [state, setState] = useState({
disconnected: true,
status: 'disconnected',
});
const [appRevision, setAppRevision] = useState();
@ -23,8 +23,8 @@ export function useAppContext(websocket) {
const appVersion = "1.0.0";
const userAgent = window.navigator.userAgent;
const access = useRef(null);
const ws = useRef(null);
const revision = useRef(null);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }))
@ -37,21 +37,28 @@ export function useAppContext(websocket) {
const channelContext = useContext(ChannelContext);
const cardContext = useContext(CardContext);
const resetData = () => {
revision.current = null;
const setSession = (token) => {
accountContext.actions.setToken(token);
profileContext.actions.setToken(token);
cardContext.actions.setToken(token);
channelContext.actions.setToken(token);
setWebsocket(token);
}
const clearSession = () => {
uploadContext.actions.clear();
storeContext.actions.clear();
accountContext.actions.clearToken();
profileContext.actions.clearToken();
cardContext.actions.clearToken();
channelContext.actions.clearToken();
setState({});
clearWebsocket();
}
const actions = {
logout: () => {
appLogout();
storeContext.actions.clear();
uploadContext.actions.clear();
resetData();
logout: async () => {
await appLogout();
},
access: async (token) => {
await appAccess(token)
@ -62,21 +69,14 @@ export function useAppContext(websocket) {
create: async (username, password, token) => {
await appCreate(username, password, token)
},
username: getUsername,
available: getAvailable,
}
const appCreate = async (username, password, token) => {
await addAccount(username, password, token);
let access = await setLogin(username, password, appName, appVersion, userAgent)
updateState({ access: access.appToken });
const access = await setLogin(username, password, appName, appVersion, userAgent);
storeContext.actions.setValue('login:timestamp', access.created);
accountContext.actions.setToken(access.appToken);
profileContext.actions.setToken(access.appToken);
cardContext.actions.setToken(access.appToken);
channelContext.actions.setToken(access.appToken);
setSession(access.appToken);
setWebsocket(access.appToken)
localStorage.setItem("session", JSON.stringify({
access: access.appToken,
timestamp: access.created,
@ -85,15 +85,10 @@ export function useAppContext(websocket) {
}
const appLogin = async (username, password) => {
let access = await setLogin(username, password, appName, appVersion, userAgent)
updateState({ access: access.appToken });
const access = await setLogin(username, password, appName, appVersion, userAgent);
storeContext.actions.setValue('login:timestamp', access.created);
accountContext.actions.setToken(access.appToken);
profileContext.actions.setToken(access.appToken);
cardContext.actions.setToken(access.appToken);
channelContext.actions.setToken(access.appToken);
setSession(access.appToken);
setWebsocket(access.appToken)
localStorage.setItem("session", JSON.stringify({
access: access.appToken,
timestamp: access.created,
@ -102,15 +97,10 @@ export function useAppContext(websocket) {
}
const appAccess = async (token) => {
let access = await setAccountAccess(token, appName, appVersion, userAgent)
updateState({ access: access.appToken });
const access = await setAccountAccess(token, appName, appVersion, userAgent);
storeContext.actions.setValue('login:timestamp', access.created);
accountContext.actions.setToken(access.appToken);
profileContext.actions.setToken(access.appToken);
cardContext.actions.setToken(access.appToken);
channelContext.actions.setToken(access.appToken);
setSession(access.appToken);
setWebsocket(access.appToken)
localStorage.setItem("session", JSON.stringify({
access: access.appToken,
timestamp: access.created,
@ -119,21 +109,15 @@ export function useAppContext(websocket) {
}
const appLogout = async () => {
clearSession();
try {
await clearLogin(state.access);
await clearLogin(access.current);
}
catch (err) {
console.log(err);
}
updateState({ access: null });
accountContext.actions.clearToken();
profileContext.actions.clearToken();
cardContext.actions.clearToken();
channelContext.actions.clearToken();
clearWebsocket()
localStorage.removeItem("session");
}
};
useEffect(() => {
if (appRevision) {
@ -154,20 +138,22 @@ export function useAppContext(websocket) {
protocol = 'wss://';
}
updateState({ status: 'connecting' });
ws.current = createWebsocket(protocol + window.location.host + "/status");
ws.current.onmessage = (ev) => {
try {
let rev = JSON.parse(ev.data);
updateState({ status: 'connected' });
setAppRevision(rev);
updateState({ disconnected: false });
}
catch (err) {
console.log(err);
ws.current.close();
}
}
ws.current.onclose = (e) => {
updateState({ disconnected: true });
console.log(e)
updateState({ status: 'disconnected' });
setTimeout(() => {
if (ws.current != null) {
ws.current.onmessage = () => {}
@ -176,14 +162,15 @@ export function useAppContext(websocket) {
ws.current.onerror = () => {}
setWebsocket(token);
}
}, 1000)
}, 1000);
}
ws.current.onopen = () => {
ws.current.send(JSON.stringify({ AppToken: token }))
}
ws.current.error = (e) => {
updateState({ disconnected: true });
console.log(e)
ws.current.close();
updateState({ status: 'disconnected' });
}
}
@ -191,6 +178,7 @@ export function useAppContext(websocket) {
ws.current.onclose = () => {}
ws.current.close()
ws.current = null
updateState({ status: 'disconnected' });
}
useEffect(() => {
@ -199,25 +187,16 @@ export function useAppContext(websocket) {
try {
const session = JSON.parse(storage)
if (session?.access) {
setState({ access: session.access })
setWebsocket(session.access);
} else {
setState({})
setSession(session.access);
}
}
catch(err) {
console.log(err)
setState({})
}
} else {
setState({})
}
// eslint-disable-next-line
}, []);
if (state == null) {
return {};
}
return { state, actions }
}

View File

@ -12,10 +12,9 @@ import { UploadContextProvider } from 'context/UploadContext';
import { ViewportContextProvider } from 'context/ViewportContext';
import { ConversationContextProvider } from 'context/ConversationContext';
let mockWebsocket;
function MockWebsocket(url) {
setTimeout(() => {
this.onmessage({ data: JSON.stringify({ account: 1, profile: 1, card: 1, channel: 1 }) });
});
this.url = url;
};
let appContext = null;
@ -31,7 +30,7 @@ function AppView() {
return (
<div>
<span data-testid="count">{ renderCount }</span>
<span data-testid="disconnected">{ app.state.disconnected ? 'true' : 'false' }</span>
<span data-testid="status">{ app.state.status }</span>
</div>
);
}
@ -64,7 +63,8 @@ const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
beforeEach(() => {
const mockCreateWebsocket = jest.fn().mockImplementation((url) => {
return new MockWebsocket(url);
mockWebsocket = new MockWebsocket(url);
return mockWebsocket;
});
const mockFetch = jest.fn().mockImplementation((url, options) => {
@ -102,10 +102,29 @@ test('testing app sync', async () => {
await act(async () => {
appContext.actions.login('testlogin', 'testpassword');
expect(mockWebsocket?.onmessage).not.toBe(null);
expect(mockWebsocket?.onclose).not.toBe(null);
});
await waitFor(async () => {
expect(screen.getByTestId('disconnected').textContent).toBe('false');
expect(screen.getByTestId('status').textContent).toBe('connecting');
});
await act(async () => {
mockWebsocket.onmessage({ data: JSON.stringify({ account: 1, profile: 1, card: 1, channel: 1 }) });
});
await waitFor(async () => {
expect(screen.getByTestId('status').textContent).toBe('connected');
});
await act(async () => {
mockWebsocket.onclose();
await new Promise(r => setTimeout(r, 1000));
});
await waitFor(async () => {
expect(screen.getByTestId('status').textContent).toBe('connecting');
});
});