/ clis / amazon / discussion.test.js
discussion.test.js
  1  import { describe, expect, it, vi } from 'vitest';
  2  import { AuthRequiredError } from '@jackwener/opencli/errors';
  3  import { getRegistry } from '@jackwener/opencli/registry';
  4  import { __test__ } from './discussion.js';
  5  import './discussion.js';
  6  
  7  function createPageMock(evaluateResults) {
  8    const evaluate = vi.fn();
  9    for (const result of evaluateResults) {
 10      evaluate.mockResolvedValueOnce(result);
 11    }
 12    return {
 13      goto: vi.fn().mockResolvedValue(undefined),
 14      wait: vi.fn().mockResolvedValue(undefined),
 15      evaluate,
 16      snapshot: vi.fn().mockResolvedValue(undefined),
 17      click: vi.fn().mockResolvedValue(undefined),
 18      typeText: vi.fn().mockResolvedValue(undefined),
 19      pressKey: vi.fn().mockResolvedValue(undefined),
 20      scrollTo: vi.fn().mockResolvedValue(undefined),
 21      getFormState: vi.fn().mockResolvedValue({ forms: [], orphanFields: [] }),
 22      tabs: vi.fn().mockResolvedValue([]),
 23      selectTab: vi.fn().mockResolvedValue(undefined),
 24      networkRequests: vi.fn().mockResolvedValue([]),
 25      consoleMessages: vi.fn().mockResolvedValue([]),
 26      scroll: vi.fn().mockResolvedValue(undefined),
 27      autoScroll: vi.fn().mockResolvedValue(undefined),
 28      installInterceptor: vi.fn().mockResolvedValue(undefined),
 29      getInterceptedRequests: vi.fn().mockResolvedValue([]),
 30      getCookies: vi.fn().mockResolvedValue([]),
 31      screenshot: vi.fn().mockResolvedValue(''),
 32      waitForCapture: vi.fn().mockResolvedValue(undefined),
 33    };
 34  }
 35  
 36  describe('amazon discussion normalization', () => {
 37    it('normalizes review summary and sample reviews', () => {
 38      const result = __test__.normalizeDiscussionPayload({
 39        href: 'https://www.amazon.com/product-reviews/B0FJS72893',
 40        average_rating_text: '3.9 out of 5',
 41        total_review_count_text: '27 global ratings',
 42        qa_links: [],
 43        review_samples: [
 44          {
 45            title: '5.0 out of 5 stars Great value and quality',
 46            rating_text: '5.0 out of 5 stars',
 47            author: 'GTreader2',
 48            date_text: 'Reviewed in the United States on February 21, 2026',
 49            body: 'Small but mighty.',
 50            verified: true,
 51          },
 52        ],
 53      });
 54  
 55      expect(result.asin).toBe('B0FJS72893');
 56      expect(result.average_rating_value).toBe(3.9);
 57      expect(result.total_review_count).toBe(27);
 58      expect(result.review_samples).toEqual([
 59        {
 60          title: 'Great value and quality',
 61          rating_text: '5.0 out of 5 stars',
 62          rating_value: 5,
 63          author: 'GTreader2',
 64          date_text: 'Reviewed in the United States on February 21, 2026',
 65          body: 'Small but mighty.',
 66          verified_purchase: true,
 67        },
 68      ]);
 69    });
 70  
 71    it('falls back to the product page when the review page redirects to sign-in', async () => {
 72      const command = getRegistry().get('amazon/discussion');
 73      const page = createPageMock([
 74        {
 75          href: 'https://www.amazon.com/ap/signin?openid.return_to=https%3A%2F%2Fwww.amazon.com%2Fproduct-reviews%2FB09HKN2ZRT',
 76          title: 'Amazon Sign-In',
 77          body_text: 'Sign in Create account',
 78        },
 79        {
 80          href: 'https://www.amazon.com/ap/signin?openid.return_to=https%3A%2F%2Fwww.amazon.com%2Fproduct-reviews%2FB09HKN2ZRT',
 81          average_rating_text: '',
 82          total_review_count_text: '',
 83          review_samples: [],
 84        },
 85        {
 86          href: 'https://www.amazon.com/dp/B09HKN2ZRT',
 87          title: 'Amazon.com: Example product',
 88          body_text: 'Hello, zejia-wu Reviews',
 89        },
 90        {
 91          href: 'https://www.amazon.com/dp/B09HKN2ZRT',
 92          average_rating_text: '4.4 out of 5',
 93          total_review_count_text: '349 global ratings',
 94          review_samples: [
 95            {
 96              title: '5.0 out of 5 stars Perfect for the office',
 97              rating_text: '5.0 out of 5 stars',
 98              author: 'Ken',
 99              date_text: 'Reviewed in the United States on March 19, 2026',
100              body: 'Good for the office, no complaints.',
101              verified: true,
102            },
103          ],
104        },
105      ]);
106  
107      const result = await command.func(page, { input: 'B09HKN2ZRT', limit: 1 });
108  
109      expect(page.goto.mock.calls.map((call) => call[0])).toEqual([
110        'https://www.amazon.com/product-reviews/B09HKN2ZRT',
111        'https://www.amazon.com/dp/B09HKN2ZRT',
112      ]);
113      expect(result).toEqual([
114        expect.objectContaining({
115          asin: 'B09HKN2ZRT',
116          discussion_url: 'https://www.amazon.com/dp/B09HKN2ZRT',
117          average_rating_value: 4.4,
118          total_review_count: 349,
119        }),
120      ]);
121    });
122  
123    it('throws AuthRequiredError when both review and product pages are gated', async () => {
124      const command = getRegistry().get('amazon/discussion');
125      const authState = {
126        href: 'https://www.amazon.com/ap/signin?openid.return_to=https%3A%2F%2Fwww.amazon.com%2Fproduct-reviews%2FB09HKN2ZRT',
127        title: 'Amazon Sign-In',
128        body_text: 'Sign in Create account',
129      };
130      const page = createPageMock([
131        authState,
132        {
133          href: authState.href,
134          average_rating_text: '',
135          total_review_count_text: '',
136          review_samples: [],
137        },
138        authState,
139      ]);
140  
141      await expect(command.func(page, { input: 'B09HKN2ZRT', limit: 1 })).rejects.toBeInstanceOf(AuthRequiredError);
142    });
143  
144    it('does not treat a public product page with sign-in copy as a gated page', () => {
145      expect(__test__.isSignInState({
146        href: 'https://www.amazon.com/dp/B09HKN2ZRT',
147        title: 'Amazon.com: Example product',
148        body_text: 'Hello, sign in Account & Lists Create account',
149      })).toBe(false);
150    });
151  });