docs: enterprise refactor plan with ralph specs

This commit is contained in:
debian
2026-03-04 16:17:03 -05:00
parent 4c92712d20
commit f8191133c8
204 changed files with 32722 additions and 422 deletions

View File

@@ -0,0 +1,109 @@
import { PlaywrightReproducer } from '../../src/plugins/reproducers/PlaywrightReproducer';
import { IAction } from '../../src/core/interfaces';
function makeAction(id: string, type: IAction['type'], overrides: Partial<IAction> = {}): IAction {
return {
id,
type,
selector: '#btn',
timestamp: 1000,
seed: 42,
stateId: 's1',
...overrides,
};
}
describe('PlaywrightReproducer', () => {
let reproducer: PlaywrightReproducer;
beforeEach(() => {
reproducer = new PlaywrightReproducer();
});
describe('serialize', () => {
it('serializes an action trace to valid JSON', () => {
const trace = [makeAction('a1', 'click'), makeAction('a2', 'fill', { value: 'test' })];
const json = reproducer.serialize(trace);
expect(() => JSON.parse(json)).not.toThrow();
});
it('round-trips through serialize/deserialize', () => {
const trace = [
makeAction('a1', 'navigate', { url: 'http://localhost/', selector: undefined }),
makeAction('a2', 'click'),
makeAction('a3', 'fill', { value: '' }),
];
const json = reproducer.serialize(trace);
const restored = reproducer.deserialize(json);
expect(restored).toHaveLength(3);
expect(restored[0].id).toBe('a1');
expect(restored[1].type).toBe('click');
expect(restored[2].value).toBe('');
});
it('serializes empty trace', () => {
expect(reproducer.serialize([])).toBe('[]');
});
});
describe('deserialize', () => {
it('throws on invalid JSON', () => {
expect(() => reproducer.deserialize('not-json')).toThrow();
});
it('throws when JSON is not an array', () => {
expect(() => reproducer.deserialize('{"id":"a1"}')).toThrow(
'PlaywrightReproducer.deserialize: expected a JSON array'
);
});
it('preserves all action fields', () => {
const action = makeAction('a1', 'fill', { value: 'hello', selector: 'input#email' });
const restored = reproducer.deserialize(reproducer.serialize([action]));
expect(restored[0]).toEqual(action);
});
});
describe('generateScript', () => {
it('generates a non-empty string', () => {
const trace = [makeAction('a1', 'click')];
const script = reproducer.generateScript(trace);
expect(typeof script).toBe('string');
expect(script.length).toBeGreaterThan(0);
});
it('includes playwright require', () => {
const script = reproducer.generateScript([makeAction('a1', 'click')]);
expect(script).toContain("require('playwright')");
});
it('generates navigate step', () => {
const action = makeAction('a1', 'navigate', { url: 'http://localhost:3000', selector: undefined });
const script = reproducer.generateScript([action]);
expect(script).toContain('page.goto');
expect(script).toContain('http://localhost:3000');
});
it('generates click step', () => {
const script = reproducer.generateScript([makeAction('a1', 'click', { selector: '#submit' })]);
expect(script).toContain('click()');
expect(script).toContain('#submit');
});
it('generates fill step with value', () => {
const script = reproducer.generateScript([makeAction('a1', 'fill', { selector: '#email', value: '' })]);
expect(script).toContain('fill');
expect(script).toContain('#email');
});
it('includes seed comment for reproducibility', () => {
const script = reproducer.generateScript([makeAction('a1', 'click')]);
expect(script).toContain('seed=42');
});
it('generates empty script for empty trace', () => {
const script = reproducer.generateScript([]);
expect(script).toContain('browser.close');
});
});
});