Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

66 lines
3.1 KiB
JavaScript

import { describe, it, expect, vi } from 'vitest';
import { getRegistry } from '@jackwener/opencli/registry';
import './channel-join.js';
import './channel-leave.js';
import './channel-archive.js';
import './channel-unarchive.js';
function makePage(result = { kind: 'ok', rows: { ok: true } }) {
return { goto: vi.fn(), evaluate: vi.fn().mockResolvedValue(result) };
}
const CASES = [
['channel-join', 'join', 'joined'],
['channel-leave', 'leave', 'left'],
['channel-archive', 'archive', 'archived'],
['channel-unarchive', 'unarchive', 'unarchived'],
];
describe('slock channel-action factory', () => {
for (const [name, verb, label] of CASES) {
const command = getRegistry().get(`slock/${name}`);
it(`${name}: resolves #name and POSTs /channels/:id/${verb}`, async () => {
const page = makePage();
const rows = await command.func(page, { channel: '#general' });
const script = page.evaluate.mock.calls[0][0];
expect(script).toContain('"general"'); // channel-name resolution
expect(script).toContain(`"/${verb}"`); // verb path suffix
expect(rows[0]).toMatchObject({ channel: '#general', result: label });
});
}
it('archive surfaces archivedAt from the updated channel', async () => {
const command = getRegistry().get('slock/channel-archive');
const page = makePage({ kind: 'ok', rows: { id: 'c1', archivedAt: '2026-06-07T00:00:00Z' } });
const rows = await command.func(page, { channel: '#general' });
expect(rows[0]).toMatchObject({ id: 'c1', archivedAt: '2026-06-07T00:00:00Z', result: 'archived' });
});
// F7 — qatester live-flagged: archived channels are excluded from the
// channelResolveFragment lookup (which lists active channels only), so
// `channel-unarchive #name` always errored with "no channel matches".
// Unarchive opts into a hint that points the user at the UUID escape hatch.
it('[F7] channel-unarchive rewrites "no channel matches" into an actionable archived-channel hint', async () => {
const command = getRegistry().get('slock/channel-unarchive');
const page = makePage({ kind: 'unresolvable', detail: 'no channel matches "old-channel"' });
await expect(command.func(page, { channel: '#old-channel' }))
.rejects.toThrow(/Archived channels are excluded.*UUID/);
});
// Sister verbs (join / leave / archive) should NOT get the unarchive hint
// — they fail loud with the bare "no channel matches" because the user can
// see and #name a non-archived channel.
it('[F7] non-unarchive sister verbs do NOT inject the archived hint', async () => {
for (const name of ['channel-join', 'channel-leave', 'channel-archive']) {
const command = getRegistry().get(`slock/${name}`);
const page = makePage({ kind: 'unresolvable', detail: 'no channel matches "nope"' });
await expect(command.func(page, { channel: '#nope' }))
.rejects.toThrow(/no channel matches/);
// Verify the hint text is absent from the thrown message.
await expect(command.func(page, { channel: '#nope' }))
.rejects.not.toThrow(/Archived channels are excluded/);
}
});
});