Files
kontrans.pagedev.pl/node_modules/playwriter/dist/executor.unit.test.js
2026-03-03 23:49:13 +01:00

115 lines
5.8 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { shouldAutoReturn, wrapCode } from './executor.js';
describe('shouldAutoReturn', () => {
it('returns true for simple expressions', () => {
expect(shouldAutoReturn('1 + 2')).toBe(true);
expect(shouldAutoReturn('page.title()')).toBe(true);
expect(shouldAutoReturn('await page.title()')).toBe(true);
expect(shouldAutoReturn('snapshot({ page })')).toBe(true);
expect(shouldAutoReturn('accessibilitySnapshot({ page })')).toBe(true);
expect(shouldAutoReturn('context.pages().map(p => p.url())')).toBe(true);
});
it('returns true for awaited expressions', () => {
expect(shouldAutoReturn('await Promise.resolve(42)')).toBe(true);
expect(shouldAutoReturn('await page.goto("https://example.com")')).toBe(true);
});
it('returns false for assignment expressions', () => {
expect(shouldAutoReturn('state.page = await context.newPage()')).toBe(false);
expect(shouldAutoReturn('const x = 1')).toBe(false);
expect(shouldAutoReturn('let y = 2')).toBe(false);
expect(shouldAutoReturn('x = 5')).toBe(false);
});
it('returns false for update expressions', () => {
expect(shouldAutoReturn('x++')).toBe(false);
expect(shouldAutoReturn('++x')).toBe(false);
expect(shouldAutoReturn('x--')).toBe(false);
expect(shouldAutoReturn('--x')).toBe(false);
});
it('returns false for delete expressions', () => {
expect(shouldAutoReturn('delete obj.prop')).toBe(false);
});
it('returns false for multiple statements', () => {
expect(shouldAutoReturn('const x = 1; x + 1')).toBe(false);
expect(shouldAutoReturn('await page.click("button"); await page.title()')).toBe(false);
expect(shouldAutoReturn('const a = 1\nconst b = 2')).toBe(false);
});
it('returns false for return statements', () => {
expect(shouldAutoReturn('return 5')).toBe(false);
expect(shouldAutoReturn('return await page.title()')).toBe(false);
});
it('returns false for non-expression statements', () => {
expect(shouldAutoReturn('if (true) { x }')).toBe(false);
expect(shouldAutoReturn('for (let i = 0; i < 10; i++) {}')).toBe(false);
expect(shouldAutoReturn('function foo() {}')).toBe(false);
expect(shouldAutoReturn('class Foo {}')).toBe(false);
});
it('returns false for invalid syntax', () => {
expect(shouldAutoReturn('const')).toBe(false);
expect(shouldAutoReturn('{')).toBe(false);
expect(shouldAutoReturn('await')).toBe(false);
});
it('handles edge cases', () => {
// Empty string
expect(shouldAutoReturn('')).toBe(false);
// Just whitespace
expect(shouldAutoReturn(' ')).toBe(false);
// Object literal (parsed as block)
expect(shouldAutoReturn('{ foo: 1 }')).toBe(false);
// Parenthesized object literal (expression)
expect(shouldAutoReturn('({ foo: 1 })')).toBe(true);
// Array literal
expect(shouldAutoReturn('[1, 2, 3]')).toBe(true);
});
it('handles sequence expressions with assignments', () => {
// Sequence with assignment should not auto-return
expect(shouldAutoReturn('(x = 1, x + 1)')).toBe(false);
// Sequence without assignment should auto-return
expect(shouldAutoReturn('(1, 2, 3)')).toBe(true);
});
it('handles comments in code', () => {
expect(shouldAutoReturn('// comment\npage.title()')).toBe(true);
expect(shouldAutoReturn('page.title() // comment')).toBe(true);
expect(shouldAutoReturn('/* block */ 42')).toBe(true);
});
it('handles template literals', () => {
expect(shouldAutoReturn('`hello`')).toBe(true);
expect(shouldAutoReturn('`hello ${name}`')).toBe(true);
});
it('returns true for expressions with trailing semicolons', () => {
expect(shouldAutoReturn('await page.title();')).toBe(true);
expect(shouldAutoReturn('page.title();')).toBe(true);
expect(shouldAutoReturn('snapshot({ page });')).toBe(true);
expect(shouldAutoReturn('await screenshotWithAccessibilityLabels({ page });')).toBe(true);
// trailing whitespace after semicolon
expect(shouldAutoReturn('await foo(); ')).toBe(true);
// comment after semicolon
expect(shouldAutoReturn('await foo(); // comment')).toBe(true);
// double semicolons are two statements, not auto-return
expect(shouldAutoReturn('await foo();;')).toBe(false);
});
});
describe('wrapCode', () => {
it('wraps single expressions with return await', () => {
expect(wrapCode('await page.title()')).toBe('(async () => { return await (await page.title()) })()');
});
it('strips trailing semicolons to avoid SyntaxError (#58)', () => {
// The bug: trailing semicolons inside return await (...;) produce invalid JS
const wrapped = wrapCode('await screenshotWithAccessibilityLabels({ page });');
expect(wrapped).toBe('(async () => { return await (await screenshotWithAccessibilityLabels({ page })) })()');
// Verify it's valid JS by parsing it
expect(() => new Function(wrapped)).not.toThrow();
});
it('produces valid JS for trailing semicolons on simple calls', () => {
const wrapped = wrapCode('page.title();');
expect(wrapped).toBe('(async () => { return await (page.title()) })()');
expect(() => new Function(wrapped)).not.toThrow();
});
it('wraps multi-statement code without return', () => {
const wrapped = wrapCode('const x = 1; console.log(x);');
expect(wrapped).toBe('(async () => { const x = 1; console.log(x); })()');
});
it('wraps assignment expressions without return', () => {
expect(wrapCode('x = 5')).toBe('(async () => { x = 5 })()');
});
});
//# sourceMappingURL=executor.unit.test.js.map