Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ test-results
# Demo recording output
recordings

# @humanjs/generator default exports (throwaway recordings)
humanjs-recording.ts
humanjs-recording.spec.ts

# Environment
.env
.env.local
Expand Down
87 changes: 87 additions & 0 deletions examples/generate-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* HumanJS generator demo — record a clean flow, then print the test the
* generator would produce.
*
* The visual generator (`npx @humanjs/generator <url>`) captures your clicks in
* a real browser and exports a humanized `@playwright/test` spec. This demo
* shows the engine behind that export, headless and offline: it records a short
* session, then runs the public codegen (`generatePlaywrightTest` /
* `generateHumanJS`) on the timeline and prints both a spec and a standalone
* script.
*
* Run with:
* pnpm demo:generate
* PERSONALITY=distracted pnpm demo:generate (changes the generated humanOptions)
*/

import {
chromium,
createHuman,
generateHumanJS,
generatePlaywrightTest,
} from '@humanjs/playwright';
import { parsePersonality } from './lib';

const DEMO_HTML = /* html */ `
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Sign in</title>
</head>
<body>
<h1>Sign in</h1>
<label>Email <input id="email" type="email" autocomplete="off" spellcheck="false" /></label>
<label>Password <input id="password" type="password" autocomplete="off" /></label>
<button type="button" id="continue">Continue</button>
</body>
</html>
`;

function banner(title: string): void {
const rule = '─'.repeat(64);
console.log(`\n${rule}\n ${title}\n${rule}`);
}

async function main() {
const personality = parsePersonality(process.env.PERSONALITY, 'careful', 'PERSONALITY');

// Headless — this demo is about the generated code, not a visible run.
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setContent(DEMO_HTML);
const human = await createHuman(page, { personality, seed: 'generate-demo' });

// Timeline-only recording (`video: false`) — no frame capture or ffmpeg.
// We only want the action log to feed the codegen, exactly like the
// generator's export does. Selectors are role-first, with a CSS fallback
// for the password field (password inputs expose no `textbox` role).
const rec = await human.record({ name: 'sign in', video: false }, async () => {
await human.type('role=textbox[name="Email"]', 'demo@humanjs.dev');
await human.type('#password', 'hunter2'); // password input → value is masked
await human.click('role=button[name="Continue"]');
});

// The same public codegen the generator runs on a curated timeline. The
// spec uses the `@humanjs/playwright/test` fixture (instant in CI); the
// standalone script drives a `createHuman` session directly.
banner('generatePlaywrightTest(timeline) → sign-in.spec.ts');
console.log(generatePlaywrightTest(rec.timeline));

banner('generateHumanJS(timeline) → sign-in.ts');
console.log(generateHumanJS(rec.timeline));

console.log(
`\nCaptured ${rec.timeline.events.length} actions — this is what "npx @humanjs/generator <url>" exports, minus the visual editor.`,
);
console.log('The password value is masked; edit the export to read it from process.env.');
} finally {
await browser.close();
}
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
34 changes: 0 additions & 34 deletions examples/humanjs-recording.ts

This file was deleted.

2 changes: 1 addition & 1 deletion examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"record-manual": "tsx record-manual-demo.ts",
"scroll": "tsx scroll-demo.ts",
"type": "tsx type-demo.ts",
"recorder": "tsx humanjs-recording.ts"
"generate": "tsx generate-demo.ts"
},
"dependencies": {
"@humanjs/playwright": "workspace:*",
Expand Down
26 changes: 0 additions & 26 deletions humanjs-recording.ts

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"demo:record-manual": "turbo run build --filter=@humanjs/playwright... && pnpm --filter @humanjs/examples record-manual",
"demo:scroll": "turbo run build --filter=@humanjs/playwright... && pnpm --filter @humanjs/examples scroll",
"demo:type": "turbo run build --filter=@humanjs/playwright... && pnpm --filter @humanjs/examples type",
"demo:recorder": "turbo run build --filter=@humanjs/playwright... && pnpm --filter @humanjs/examples recorder"
"demo:generate": "turbo run build --filter=@humanjs/playwright... && pnpm --filter @humanjs/examples generate"
},
"commitlint": {
"extends": [
Expand Down