Skip to content

Commit

Permalink
fix(tests,linting): resolve test hanging and eslint warnings in useSSE
Browse files Browse the repository at this point in the history
  • Loading branch information
MeetinaXD committed Jun 12, 2024
1 parent b4db9c5 commit d041144
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 33 deletions.
43 changes: 24 additions & 19 deletions packages/scene-react/test/useSSE.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { undefinedValue } from '@/helper/variables';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { Alova, createAlova } from 'alova';
import { createAlova } from 'alova';
import GlobalFetch from 'alova/GlobalFetch';
import ReactHook from 'alova/react';
import ES from 'eventsource';
import { AddressInfo } from 'net';
import React, { ReactElement } from 'react';
import { IntervalEventName, IntervalMessage, TriggerEventName, server, send as serverSend } from '~/test/sseServer';
import { getAlovaInstance, untilCbCalled } from '~/test/utils';
import { FetchRequestInit } from '~/typings/general';
import { ReactState, useSSE } from '..';
import { useSSE } from '..';
import { AlovaSSEMessageEvent, SSEHookReadyState } from '../typings/general';
Object.defineProperty(global, 'EventSource', { value: ES, writable: false });

let alovaInst: Alova<ReactState<any>, unknown, FetchRequestInit, any, any>;

afterEach(() => {
server.close();
});
Expand All @@ -28,29 +25,28 @@ type AnyMessageType<T = any> = AlovaSSEMessageEvent<T, any, any, any, any, any,
const prepareAlova = async () => {
await server.listen();
const { port } = server.address() as AddressInfo;
alovaInst = createAlova({
return createAlova({
baseURL: `http://127.0.0.1:${port}`,
statesHook: ReactHook,
requestAdapter: GlobalFetch(),
cacheLogger: false
}) as any;
});
};

describe('react => useSSE', () => {
// ! 无初始数据,不立即发送请求
test('should default not request immediately', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${IntervalEventName}`, data);

let recv = undefinedValue;
const mockOpenFn = jest.fn();
const mockOnFn = jest.fn((event: AnyMessageType) => {
recv = event.data;
});
// const mockOpenFn = jest.fn();

const Page = () => {
const { on, onOpen, data, readyState, send } = useSSE(poster);
const { on, onOpen, data, readyState, send, close } = useSSE(poster);
on(IntervalEventName, mockOnFn);
onOpen(mockOpenFn);

Expand All @@ -69,6 +65,11 @@ describe('react => useSSE', () => {
onClick={send}>
send request
</button>
<button
role="close-btn"
onClick={close}>
close
</button>
</div>
);
};
Expand All @@ -94,11 +95,15 @@ describe('react => useSSE', () => {
},
{ timeout: 4000 }
);

fireEvent.click(screen.getByRole('close-btn'));
await untilCbCalled(setTimeout, 200);
expect(screen.getByRole('status')).toHaveTextContent('closed');
});

// ! 有初始数据,不立即发送请求
test('should get the initial data and NOT send request immediately', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${TriggerEventName}`, data);
const initialData = 'initial-data';
const testDataA = 'test-data-1';
Expand Down Expand Up @@ -178,7 +183,7 @@ describe('react => useSSE', () => {

// ! 有初始数据,立即发送请求
test('should get the initial data and send request immediately', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${TriggerEventName}`, data);
const initialData = 'initial-data';
const testDataA = 'test-data-1';
Expand Down Expand Up @@ -230,7 +235,7 @@ describe('react => useSSE', () => {

// ! 测试关闭后重新连接
test('should not trigger handler after close', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${TriggerEventName}`, data);
const testDataA = 'test-data-1';
const testDataB = 'test-data-2';
Expand Down Expand Up @@ -327,7 +332,7 @@ describe('react => useSSE', () => {

// ! 打开失败应该报错,立即发送请求
test('should throw error then try to connect a not exist url', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get('/not-exist-path', data);

let recv = undefinedValue;
Expand Down Expand Up @@ -359,7 +364,7 @@ describe('react => useSSE', () => {

render((<Page />) as ReactElement<any, any>);

await untilCbCalled(setTimeout, 500);
await untilCbCalled(setTimeout, 1500);
await screen.findByText(/closed/);

expect(screen.getByRole('data')).toBeEmptyDOMElement();
Expand All @@ -371,7 +376,7 @@ describe('react => useSSE', () => {

// ! 打开失败应该报错,不立即发送请求
test('should throw error then try to connect a not exist url (immediate: false)', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get('/not-exist-path', data);

let recv = undefinedValue;
Expand Down Expand Up @@ -399,7 +404,7 @@ describe('react => useSSE', () => {
<span role="data">{data}</span>
<button
role="send"
onClick={send}>
onClick={() => send()}>
send request
</button>
</div>
Expand Down Expand Up @@ -441,7 +446,7 @@ describe('react => useSSE', () => {
const mockResponseErrorFn = jest.fn();
const mockResponseCompleteFn = jest.fn();

alovaInst = getAlovaInstance(ReactHook, {
const alovaInst = getAlovaInstance(ReactHook, {
baseURL: `http://localhost:${port}`,
responseExpect: data => {
mockResponseFn();
Expand Down Expand Up @@ -600,7 +605,7 @@ describe('react => useSSE', () => {
const mockResponseErrorFn = jest.fn();
const mockResponseCompleteFn = jest.fn();

alovaInst = getAlovaInstance(ReactHook, {
const alovaInst = getAlovaInstance(ReactHook, {
baseURL: `http://localhost:${port}`,
responseExpect: () => {
mockResponseFn();
Expand Down
33 changes: 20 additions & 13 deletions packages/scene-vue/test/useSSE.spec.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { usePromise } from '@/helper';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/vue';
import { Alova, createAlova } from 'alova';
import { createAlova } from 'alova';
import GlobalFetch from 'alova/GlobalFetch';
import VueHook from 'alova/vue';
import ES from 'eventsource';
import { AddressInfo } from 'net';
import { Ref } from 'vue';
import { IntervalEventName, IntervalMessage, TriggerEventName, server, send as serverSend } from '~/test/sseServer';
import { untilCbCalled } from '~/test/utils';
import { AnyFn, FetchRequestInit, SSEHookReadyState } from '~/typings/general';
import { AnyFn, SSEHookReadyState } from '~/typings/general';
import { useSSE } from '..';
import { AlovaSSEMessageEvent } from '../typings/general';
import CompUseSSEGlobalResponse from './components/use-sse-global-response.vue';
import CompUseSSE from './components/use-sse.vue';

Object.defineProperty(global, 'EventSource', { value: ES, writable: false });

let alovaInst: Alova<Ref<unknown>, Ref<unknown>, FetchRequestInit, Response, Headers>;

afterEach(() => {
server.close();
const { promise, resolve } = usePromise();
if (server.listening) {
server.close(resolve);
return promise;
}
});

type AnyMessageType<T = any> = AlovaSSEMessageEvent<T, any, any, any, any, any, any, any>;
Expand All @@ -30,7 +32,7 @@ type AnyMessageType<T = any> = AlovaSSEMessageEvent<T, any, any, any, any, any,
const prepareAlova = async () => {
await server.listen();
const { port } = server.address() as AddressInfo;
alovaInst = createAlova({
return createAlova({
baseURL: `http://127.0.0.1:${port}`,
statesHook: VueHook,
requestAdapter: GlobalFetch(),
Expand All @@ -41,9 +43,9 @@ const prepareAlova = async () => {
describe('vue => useSSE', () => {
// ! 无初始数据,不立即发送请求
test('should default NOT request immediately', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${IntervalEventName}`, data);
const { on, onOpen, data, readyState, send } = useSSE(poster);
const { on, onOpen, data, readyState, send, close } = useSSE(poster);
const cb = jest.fn();
const openCb = jest.fn();
on(IntervalEventName, cb);
Expand All @@ -67,25 +69,26 @@ describe('vue => useSSE', () => {
await untilCbCalled(setTimeout, 100);
expect(openCb).toHaveBeenCalled();

const { data: recvData } = (await untilCbCalled(onIntervalCb)) as AnyMessageType<string>;
const { data: recvData } = (await untilCbCalled(onIntervalCb)) as AnyMessageType;

expect(readyState.value).toStrictEqual(SSEHookReadyState.OPEN);
expect(cb).toHaveBeenCalled();

expect(recvData).toEqual(IntervalMessage);
expect(data.value).toStrictEqual(IntervalMessage);
close();
}, 3000);

// ! 有初始数据,不立即发送请求
test('should get the initial data and NOT send request immediately', async () => {
await prepareAlova();
const alovaInst = await prepareAlova();
const poster = (data: any) => alovaInst.Get(`/${TriggerEventName}`, data);
const initialData = {
id: 9527,
name: 'Tom',
age: 18
};
const { onMessage, onOpen, data, readyState, send } = useSSE(poster, { initialData });
const { onMessage, onOpen, data, readyState, send, close } = useSSE(poster, { initialData });

const testDataA = 'test-data-1';
const testDataB = 'test-data-2';
Expand Down Expand Up @@ -117,13 +120,14 @@ describe('vue => useSSE', () => {
await send();
serverSend(testDataB);

const { data: recvData } = (await untilCbCalled(onMessage)) as AnyMessageType<string>;
const { data: recvData } = (await untilCbCalled(onMessage)) as AnyMessageType;

expect(readyState.value).toStrictEqual(SSEHookReadyState.OPEN);
expect(cb).toHaveBeenCalled();

expect(recvData).toEqual(testDataB);
expect(data.value).toStrictEqual(testDataB);
close();
});

// ! 有初始数据,立即发送请求
Expand All @@ -145,6 +149,7 @@ describe('vue => useSSE', () => {
expect(screen.getByRole('data')).toHaveTextContent(initialData);

await screen.findByText(/opened/);
await untilCbCalled(setTimeout, 100);

expect(screen.getByRole('onopen').innerHTML).toStrictEqual('1');

Expand Down Expand Up @@ -291,6 +296,7 @@ describe('vue => useSSE', () => {
expect(screen.getByRole('data')).toHaveTextContent(initialData);

await screen.findByText(/opened/);
await untilCbCalled(setTimeout, 100);

expect(screen.getByRole('onopen').innerHTML).toStrictEqual('1');
expect(screen.getByRole('on-response').innerHTML).toStrictEqual('0');
Expand Down Expand Up @@ -375,6 +381,7 @@ describe('vue => useSSE', () => {
expect(screen.getByRole('data')).toHaveTextContent(initialData);

await screen.findByText(/opened/);
await untilCbCalled(setTimeout, 100);

expect(screen.getByRole('onopen').innerHTML).toStrictEqual('1');
expect(screen.getByRole('on-response').innerHTML).toStrictEqual('0');
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useSSE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export default <Data, S, E, R, T, RC, RE, RH>(
*/
const createSSEEvent = async (eventFrom: keyof EventSourceEventMap, dataOrError: Promise<any>) => {
assert(!!eventSource.current, 'EventSource is not initialized');
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const es = eventSource.current!;

const ev = (type: AlovaHookEventType, data?: any, error?: Error) => {
Expand Down Expand Up @@ -362,7 +363,7 @@ export default <Data, S, E, R, T, RC, RE, RH>(
});
});

return promiseObj!.promise;
return promiseObj.promise;
});

onUnmounted$(() => {
Expand Down

0 comments on commit d041144

Please sign in to comment.