81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
|
|
import { test } from 'node:test';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import { createStore } from 'jotai';
|
||
|
|
import { callEmbedAtom } from './callEmbed';
|
||
|
|
import { CallEmbed } from '../plugins/call';
|
||
|
|
|
||
|
|
// callEmbedAtom holds the current CallEmbed in an unexported baseAtom. The setter:
|
||
|
|
// - identity no-op guard: setting the same reference does nothing
|
||
|
|
// - when replacing a previous embed, calls prevCallEmbed.dispose()
|
||
|
|
// We substitute a stub embed exposing a dispose() spy (the real CallEmbed needs a
|
||
|
|
// MatrixClient + DOM). `as unknown as CallEmbed` keeps eslint/prettier quiet.
|
||
|
|
|
||
|
|
type StubEmbed = { dispose: () => void; disposed: number };
|
||
|
|
|
||
|
|
const makeEmbed = (): StubEmbed => {
|
||
|
|
const stub: StubEmbed = {
|
||
|
|
disposed: 0,
|
||
|
|
dispose() {
|
||
|
|
stub.disposed += 1;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
return stub;
|
||
|
|
};
|
||
|
|
|
||
|
|
const asEmbed = (e: StubEmbed): CallEmbed => e as unknown as CallEmbed;
|
||
|
|
|
||
|
|
test('starts undefined', () => {
|
||
|
|
const store = createStore();
|
||
|
|
assert.equal(store.get(callEmbedAtom), undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('sets a call embed', () => {
|
||
|
|
const store = createStore();
|
||
|
|
const embed = makeEmbed();
|
||
|
|
store.set(callEmbedAtom, asEmbed(embed));
|
||
|
|
assert.equal(store.get(callEmbedAtom), asEmbed(embed));
|
||
|
|
assert.equal(embed.disposed, 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('replacing an embed disposes the previous one', () => {
|
||
|
|
const store = createStore();
|
||
|
|
const first = makeEmbed();
|
||
|
|
const second = makeEmbed();
|
||
|
|
|
||
|
|
store.set(callEmbedAtom, asEmbed(first));
|
||
|
|
store.set(callEmbedAtom, asEmbed(second));
|
||
|
|
|
||
|
|
assert.equal(first.disposed, 1);
|
||
|
|
assert.equal(second.disposed, 0);
|
||
|
|
assert.equal(store.get(callEmbedAtom), asEmbed(second));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('setting the same embed reference is a no-op (no dispose)', () => {
|
||
|
|
const store = createStore();
|
||
|
|
const embed = makeEmbed();
|
||
|
|
|
||
|
|
store.set(callEmbedAtom, asEmbed(embed));
|
||
|
|
store.set(callEmbedAtom, asEmbed(embed));
|
||
|
|
|
||
|
|
assert.equal(embed.disposed, 0);
|
||
|
|
assert.equal(store.get(callEmbedAtom), asEmbed(embed));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('clearing to undefined disposes the previous embed', () => {
|
||
|
|
const store = createStore();
|
||
|
|
const embed = makeEmbed();
|
||
|
|
|
||
|
|
store.set(callEmbedAtom, asEmbed(embed));
|
||
|
|
store.set(callEmbedAtom, undefined);
|
||
|
|
|
||
|
|
assert.equal(embed.disposed, 1);
|
||
|
|
assert.equal(store.get(callEmbedAtom), undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('setting undefined when already undefined is a no-op', () => {
|
||
|
|
const store = createStore();
|
||
|
|
// No previous embed: the identity guard (undefined === undefined) returns early.
|
||
|
|
store.set(callEmbedAtom, undefined);
|
||
|
|
assert.equal(store.get(callEmbedAtom), undefined);
|
||
|
|
});
|