mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 07:41:58 +08:00
225 lines
7.3 KiB
TypeScript
225 lines
7.3 KiB
TypeScript
import type { ChannelTransport, Listener } from '.';
|
|
import { Channel } from '.';
|
|
|
|
jest.useFakeTimers();
|
|
|
|
describe('Channel', () => {
|
|
let transport: ChannelTransport;
|
|
let channel: Channel;
|
|
|
|
beforeEach(() => {
|
|
transport = { setHandler: jest.fn(), send: jest.fn() };
|
|
channel = new Channel({ transport });
|
|
});
|
|
|
|
describe('constructor', () => {
|
|
it('should set the handler if handler is preset', () => {
|
|
channel = new Channel({ transport });
|
|
expect(transport.setHandler).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not set transport if not passed as an argument', () => {
|
|
channel = new Channel();
|
|
expect(channel.hasTransport).toBeFalsy();
|
|
});
|
|
|
|
it('should set transport if passed as an argument', () => {
|
|
channel = new Channel({ transport });
|
|
expect(channel.hasTransport).toBeTruthy();
|
|
});
|
|
|
|
it('should set isAsync to false as default value', () => {
|
|
channel = new Channel();
|
|
expect(channel.isAsync).toBeFalsy();
|
|
});
|
|
|
|
it('should set isAsync to true if passed as an argument', () => {
|
|
channel = new Channel({ async: true });
|
|
expect(channel.isAsync).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('method:addListener', () => {
|
|
it('should create one listener', () => {
|
|
const eventName = 'event1';
|
|
|
|
channel.addListener(eventName, jest.fn());
|
|
expect(channel.listeners(eventName).length).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('method:on', () => {
|
|
it('should do the same as addListener', () => {
|
|
const eventName = 'event1';
|
|
|
|
channel.on(eventName, jest.fn());
|
|
expect(channel.listeners(eventName).length).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('method:off', () => {
|
|
it('should remove listeners', () => {
|
|
const eventName = 'event1';
|
|
const fn = jest.fn();
|
|
|
|
channel.on(eventName, fn);
|
|
expect(channel.listeners(eventName).length).toBe(1);
|
|
channel.off(eventName, fn);
|
|
expect(channel.listeners(eventName).length).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('method:emit', () => {
|
|
it('should execute the callback fn of a listener', () => {
|
|
const eventName = 'event1';
|
|
const listenerInputData = ['string1', 'string2', 'string3'];
|
|
let listenerOutputData: string[] = null;
|
|
const mockListener: Listener = (data) => {
|
|
listenerOutputData = data;
|
|
};
|
|
|
|
channel.addListener(eventName, mockListener);
|
|
channel.emit(eventName, listenerInputData);
|
|
expect(listenerOutputData).toBe(listenerInputData);
|
|
});
|
|
|
|
it('should be callable with a spread operator as event arguments', () => {
|
|
const eventName = 'event1';
|
|
const listenerInputData = ['string1', 'string2', 'string3'];
|
|
let listenerOutputData: string[] = null;
|
|
|
|
channel.addListener(eventName, (...data) => {
|
|
listenerOutputData = data;
|
|
});
|
|
channel.emit(eventName, ...listenerInputData);
|
|
expect(listenerOutputData).toEqual(listenerInputData);
|
|
});
|
|
|
|
it('should be callable with options on the event', () => {
|
|
const eventName = 'event1';
|
|
const listenerInputData = [{ event: {}, options: { depth: 1 } }];
|
|
let listenerOutputData: any = null;
|
|
|
|
channel.addListener(eventName, (...data) => {
|
|
listenerOutputData = data;
|
|
});
|
|
const sendSpy = jest.fn();
|
|
// @ts-expect-error (Converted from ts-ignore)
|
|
channel.transport.send = sendSpy;
|
|
channel.emit(eventName, ...listenerInputData);
|
|
expect(listenerOutputData).toEqual(listenerInputData);
|
|
expect(sendSpy.mock.calls[0][1]).toEqual({ depth: 1 });
|
|
});
|
|
|
|
it('should use setImmediate if async is true', () => {
|
|
channel = new Channel({ async: true, transport });
|
|
channel.addListener('event1', jest.fn());
|
|
});
|
|
});
|
|
|
|
describe('method:eventNames', () => {
|
|
it('should return a list of all registered events', () => {
|
|
const eventNames = ['event1', 'event2', 'event3'];
|
|
eventNames.forEach((eventName) => channel.addListener(eventName, jest.fn()));
|
|
|
|
expect(channel.eventNames()).toEqual(eventNames);
|
|
});
|
|
});
|
|
|
|
describe('method:listenerCount', () => {
|
|
it('should return a list of all registered events', () => {
|
|
const events = [
|
|
{ eventName: 'event1', listeners: [jest.fn(), jest.fn(), jest.fn()], listenerCount: 0 },
|
|
{ eventName: 'event2', listeners: [jest.fn()], listenerCount: 0 },
|
|
];
|
|
events.forEach((event) => {
|
|
event.listeners.forEach((listener) => {
|
|
channel.addListener(event.eventName, listener);
|
|
// eslint-disable-next-line no-plusplus, no-param-reassign
|
|
event.listenerCount++;
|
|
});
|
|
});
|
|
|
|
events.forEach((event) => {
|
|
expect(channel.listenerCount(event.eventName)).toBe(event.listenerCount);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('method:once', () => {
|
|
it('should execute a listener once and remove it afterwards', () => {
|
|
const eventName = 'event1';
|
|
channel.once(eventName, jest.fn());
|
|
channel.emit(eventName);
|
|
|
|
expect(channel.listenerCount(eventName)).toBe(0);
|
|
});
|
|
|
|
it('should pass all event arguments correctly to the listener', () => {
|
|
const eventName = 'event1';
|
|
const listenerInputData = ['string1', 'string2', 'string3'];
|
|
let listenerOutputData = null;
|
|
const mockListener: Listener = (data: string[]) => {
|
|
listenerOutputData = data;
|
|
};
|
|
|
|
channel.once(eventName, (args) => mockListener(args));
|
|
channel.emit(eventName, listenerInputData);
|
|
|
|
expect(listenerOutputData).toEqual(listenerInputData);
|
|
});
|
|
|
|
it('should be removable', () => {
|
|
const eventName = 'event1';
|
|
const listenerToBeRemoved = jest.fn();
|
|
|
|
channel.once(eventName, listenerToBeRemoved);
|
|
channel.removeListener(eventName, listenerToBeRemoved);
|
|
});
|
|
});
|
|
|
|
describe('method:removeAllListeners', () => {
|
|
it('should remove all listeners', () => {
|
|
const eventName1 = 'event1';
|
|
const eventName2 = 'event2';
|
|
const listeners1 = [jest.fn(), jest.fn(), jest.fn()];
|
|
const listeners2 = [jest.fn()];
|
|
|
|
listeners1.forEach((fn) => channel.addListener(eventName1, fn));
|
|
listeners2.forEach((fn) => channel.addListener(eventName2, fn));
|
|
channel.removeAllListeners();
|
|
|
|
expect(channel.listenerCount(eventName1)).toBe(0);
|
|
expect(channel.listenerCount(eventName2)).toBe(0);
|
|
});
|
|
|
|
it('should remove all listeners of a certain event', () => {
|
|
const eventName = 'event1';
|
|
const listeners = [jest.fn(), jest.fn(), jest.fn()];
|
|
|
|
listeners.forEach((fn) => channel.addListener(eventName, fn));
|
|
expect(channel.listenerCount(eventName)).toBe(listeners.length);
|
|
|
|
channel.removeAllListeners(eventName);
|
|
expect(channel.listenerCount(eventName)).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('method:removeListener', () => {
|
|
it('should remove one listener', () => {
|
|
const eventName = 'event1';
|
|
const listenerToBeRemoved = jest.fn();
|
|
const listeners = [jest.fn(), jest.fn()];
|
|
const findListener = (listener: Listener) =>
|
|
channel.listeners(eventName).find((_listener) => _listener === listener);
|
|
|
|
listeners.forEach((fn) => channel.addListener(eventName, fn));
|
|
channel.addListener(eventName, listenerToBeRemoved);
|
|
expect(findListener(listenerToBeRemoved)).toBe(listenerToBeRemoved);
|
|
|
|
channel.removeListener(eventName, listenerToBeRemoved);
|
|
expect(findListener(listenerToBeRemoved)).toBeUndefined();
|
|
});
|
|
});
|
|
});
|