delete.test.js
1 import { describe, expect, it, vi } from 'vitest'; 2 import { CommandExecutionError } from '@jackwener/opencli/errors'; 3 import { getRegistry } from '@jackwener/opencli/registry'; 4 import { __test__ } from './delete.js'; 5 import './delete.js'; 6 describe('twitter delete command', () => { 7 it('extracts tweet ids from both user and i/status URLs', () => { 8 expect(__test__.extractTweetId('https://x.com/alice/status/2040254679301718161?s=20')).toBe('2040254679301718161'); 9 expect(__test__.extractTweetId('https://x.com/i/status/2040318731105313143')).toBe('2040318731105313143'); 10 }); 11 it('targets the matched tweet article instead of the first More button on the page', async () => { 12 const cmd = getRegistry().get('twitter/delete'); 13 expect(cmd?.func).toBeTypeOf('function'); 14 const page = { 15 goto: vi.fn().mockResolvedValue(undefined), 16 wait: vi.fn().mockResolvedValue(undefined), 17 evaluate: vi.fn().mockResolvedValue({ ok: true, message: 'Tweet successfully deleted.' }), 18 }; 19 const result = await cmd.func(page, { 20 url: 'https://x.com/alice/status/2040254679301718161?s=20', 21 }); 22 expect(page.goto).toHaveBeenCalledWith('https://x.com/alice/status/2040254679301718161?s=20'); 23 expect(page.wait).toHaveBeenNthCalledWith(1, { selector: '[data-testid="primaryColumn"]' }); 24 expect(page.wait).toHaveBeenNthCalledWith(2, 2); 25 const script = page.evaluate.mock.calls[0][0]; 26 expect(script).toContain("document.querySelectorAll('article')"); 27 expect(script).toContain("'/status/' + tweetId"); 28 expect(script).toContain("targetArticle.querySelectorAll('button,[role=\"button\"]')"); 29 expect(result).toEqual([ 30 { 31 status: 'success', 32 message: 'Tweet successfully deleted.', 33 }, 34 ]); 35 }); 36 it('passes through matched-tweet lookup failures', async () => { 37 const cmd = getRegistry().get('twitter/delete'); 38 expect(cmd?.func).toBeTypeOf('function'); 39 const page = { 40 goto: vi.fn().mockResolvedValue(undefined), 41 wait: vi.fn().mockResolvedValue(undefined), 42 evaluate: vi.fn().mockResolvedValue({ 43 ok: false, 44 message: 'Could not find the tweet card matching the requested URL.', 45 }), 46 }; 47 const result = await cmd.func(page, { 48 url: 'https://x.com/alice/status/2040254679301718161', 49 }); 50 expect(result).toEqual([ 51 { 52 status: 'failed', 53 message: 'Could not find the tweet card matching the requested URL.', 54 }, 55 ]); 56 expect(page.wait).toHaveBeenCalledTimes(1); 57 }); 58 it('normalizes invalid tweet URLs into CommandExecutionError', async () => { 59 const cmd = getRegistry().get('twitter/delete'); 60 expect(cmd?.func).toBeTypeOf('function'); 61 const page = { 62 goto: vi.fn(), 63 wait: vi.fn(), 64 evaluate: vi.fn(), 65 }; 66 await expect(cmd.func(page, { 67 url: 'https://x.com/alice/home', 68 })).rejects.toThrow(CommandExecutionError); 69 expect(page.goto).not.toHaveBeenCalled(); 70 expect(page.wait).not.toHaveBeenCalled(); 71 expect(page.evaluate).not.toHaveBeenCalled(); 72 }); 73 });