/ clis / twitter / delete.test.js
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  });