rxjs-reboot/src/__tests__/Subscription.spec.ts
2023-07-05 10:35:48 +02:00

161 lines
4.3 KiB
TypeScript

import 'jest-extended';
import * as Rx from 'rxjs';
import { SubscriptionConstructor, Subscription } from '../Subscription';
const testSubscription = (SubscriptionClass: SubscriptionConstructor) => () => {
it('[constructor] should not throw when created', () => {
expect(() => new SubscriptionClass()).not.toThrow();
});
it('[closed] should be false on creation', () => {
expect(new SubscriptionClass().closed).toBe(false);
});
it('[closed] should be true after unsubscribe', () => {
const sub = new SubscriptionClass();
sub.unsubscribe();
expect(sub.closed).toBe(true);
});
it('[unsubscribe] should call the given teardown', () => {
const teardown = jest.fn();
const sub = new SubscriptionClass(teardown);
sub.unsubscribe();
expect(teardown).toBeCalledTimes(1);
expect(sub.closed).toBe(true);
});
it('[unsubscribe] should call the given teardonwn once', () => {
const teardown = jest.fn();
const sub = new SubscriptionClass(teardown);
sub.unsubscribe();
sub.unsubscribe();
expect(teardown).toBeCalledTimes(1);
});
it('[add] should execute added teardowns when subscription is closed', () => {
const initialTeardown = jest.fn();
const additionalTeardown = jest.fn();
const sub = new SubscriptionClass(initialTeardown);
sub.add(additionalTeardown);
sub.unsubscribe();
expect(initialTeardown).toBeCalledTimes(1);
expect(additionalTeardown).toBeCalledTimes(1);
});
it('[add] should be able to unsubscribe partially using child subscription', () => {
const parentTeardown = jest.fn();
const childTeardown = jest.fn();
const childSub = new SubscriptionClass(childTeardown);
const parentSub = new SubscriptionClass(parentTeardown);
parentSub.add(childSub);
childSub.unsubscribe();
// childSub.unsubscribe();
expect(childTeardown).toBeCalledTimes(1);
expect(parentTeardown).not.toBeCalled();
parentSub.unsubscribe();
expect(childTeardown).toBeCalledTimes(1);
expect(parentTeardown).toBeCalledTimes(1);
});
it('[add] should add several teardowns', () => {
const teardownA = jest.fn();
const teardownB = jest.fn();
const teardownC = jest.fn();
const sub = new SubscriptionClass();
sub.add(teardownA);
sub.add(teardownB);
sub.add(teardownC);
sub.unsubscribe();
expect(teardownA).toBeCalledTimes(1);
expect(teardownB).toBeCalledTimes(1);
expect(teardownC).toBeCalledTimes(1);
});
it('[add] should call a child teardown twice', () => {
const teardown = jest.fn();
const subA = new SubscriptionClass();
const subB = new SubscriptionClass();
subA.add(teardown);
subB.add(teardown);
subA.unsubscribe();
subB.unsubscribe();
expect(teardown).toBeCalledTimes(2);
});
it('[add] should call a child subscription once', () => {
const teardown = jest.fn();
const teardownSub = new SubscriptionClass(teardown);
const subA = new SubscriptionClass();
const subB = new SubscriptionClass();
subA.add(teardownSub);
subB.add(teardownSub);
subA.unsubscribe();
subB.unsubscribe();
expect(teardown).toBeCalledTimes(1);
});
it('[add] should call a new added teardown when already unsubscribed', () => {
const initialTeardown = jest.fn();
const sub = new SubscriptionClass(initialTeardown);
sub.unsubscribe();
expect(initialTeardown).toBeCalledTimes(1);
const additionalTeardown = jest.fn();
sub.add(additionalTeardown);
expect(additionalTeardown).toBeCalledTimes(1);
});
it('[remove] should be able to remove a child subscription', () => {
const parentTeardown = jest.fn();
const childTeardown = jest.fn();
const childSub = new SubscriptionClass(childTeardown);
const parentSub = new SubscriptionClass(parentTeardown);
parentSub.add(childSub);
parentSub.remove(childSub);
parentSub.unsubscribe();
expect(childTeardown).not.toBeCalled();
expect(parentTeardown).toBeCalledTimes(1);
childSub.unsubscribe();
expect(childTeardown).toBeCalledTimes(1);
expect(parentTeardown).toBeCalledTimes(1);
});
};
describe('RX', () => {
describe('Subscription', testSubscription(Rx.Subscription as unknown as SubscriptionConstructor));
});
describe('Custom implementation', () => {
describe('Subscription', testSubscription(Subscription));
});