@checksum-ai/runtime 1.0.23 → 1.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/checksum-root/playwright.config.ts +1 -1
- package/cli.js +5 -5
- package/index.d.ts +11 -3
- package/index.js +91 -83
- package/package.json +3 -2
- package/scripts/{headless.sh → patch.sh} +1 -1
- package/test-run-monitor.js +2 -0
- package/upload-agent.js +0 -20
|
@@ -3,7 +3,7 @@ import { defineConfig, devices } from "@playwright/test";
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
timeout: 120000,
|
|
5
5
|
testMatch: [/.*.[.]checksum.spec.ts/],
|
|
6
|
-
testDir: "
|
|
6
|
+
testDir: "..",
|
|
7
7
|
/* disable parallel test runs */
|
|
8
8
|
workers: 1,
|
|
9
9
|
/* Run tests in files in parallel */
|
package/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var m=Object.create;var u=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var C=Object.getPrototypeOf,w=Object.prototype.hasOwnProperty;var g=(n,t)=>u(n,"name",{value:t,configurable:!0});var y=(n,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of f(t))!w.call(n,o)&&o!==e&&u(n,o,{get:()=>t[o],enumerable:!(s=d(t,o))||s.enumerable});return n};var k=(n,t,e)=>(e=n!=null?m(C(n)):{},y(t||!n||!n.__esModule?u(e,"default",{value:n,enumerable:!0}):e,n));var i=require("fs"),l=k(require("child_process")),r=require("path");var p="checksum";var h=class{constructor(){this.TEST_RUN_MONITOR_PATH=(0,r.join)(__dirname,"test-run-monitor.js");this.CHECKSUM_API_URL="https://api.checksum.ai";this.didFail=!1;this.mock=!1;this.isolatedMode=!1;this.completeIndicators={upload:!1,tests:!1,report:!1};this.guardReturn=async(t,e=1e3,s="action hang guard timed out")=>{let o="guard-timed-out",a=g(async()=>(await this.awaitSleep(e+1e3),o),"guard"),c=await Promise.race([t,a()]);if(typeof c=="string"&&c===o)throw new Error(s);return c};this.awaitSleep=t=>new Promise(e=>setTimeout(e,t))}async execute(){switch(process.argv.find(t=>t==="--help"||t==="-h")&&(await this.printHelp(process.argv[2]),process.exit(0)),process.argv[2]){case"init":this.install();break;case"test":await this.test(process.argv.slice(3));break;case"show-report":this.showReport(process.argv.slice(3));break;default:await this.printHelp()}process.exit(0)}async execCmd(t){let e=await l.spawn(t,{shell:!0,stdio:"inherit"});return new Promise((o,a)=>{e.on("exit",c=>{c===0?o(!0):a(new Error(`Checsum failed execution with code: ${c} `))})})}async getCmdOutput(t){return new Promise(function(e,s){l.exec(t,(o,a,c)=>{if(o){s(`Error executing command: ${o.message}`);return}e(a)})})}async printHelp(t){switch(t){default:console.log(`
|
|
2
2
|
Checksum CLI
|
|
3
3
|
Usage: checksum [command] [options]
|
|
4
4
|
|
|
@@ -10,10 +10,10 @@ show-report [options] [report] show HTML report
|
|
|
10
10
|
`);break;case"test":try{let e="npx playwright test --help",s=(await this.getCmdOutput(e)).replace(/npx playwright/g,"yarn checksum").split(`
|
|
11
11
|
`);s.splice(5,0," --checksum-config=<config> Checksum configuration in JSON format").join(`
|
|
12
12
|
`),console.log(s.join(`
|
|
13
|
-
`))}catch(e){console.log("Error",e.message)}break;case"show-report":try{let e="npx playwright show-report --help",s=(await this.getCmdOutput(e)).replace(/npx playwright/g,"yarn checksum");console.log(s)}catch(e){console.log("Error",e.message)}break}}async showReport(t){let e=`npx playwright show-report ${t.join(" ")}`;try{await this.execCmd(e)}catch(s){console.log("Error showing report",s.message)}}async test(t){
|
|
14
|
-
* Checksum report URL: ${
|
|
15
|
-
*******************`);break
|
|
13
|
+
`))}catch(e){console.log("Error",e.message)}break;case"show-report":try{let e="npx playwright show-report --help",s=(await this.getCmdOutput(e)).replace(/npx playwright/g,"yarn checksum");console.log(s)}catch(e){console.log("Error",e.message)}break}}async showReport(t){let e=`npx playwright show-report ${t.join(" ")}`;try{await this.execCmd(e)}catch(s){console.log("Error showing report",s.message)}}async test(t){this.processChecksumArguments(t),this.setChecksumConfig(),await this.getSession();let e;try{e=await this.guardReturn(this.startTestRunMonitor(this.testSession),1e4,"test run monitor timeout")}catch{console.log("Error starting test run monitor. Test results will not be available on checksum.")}this.buildVolatileConfig();let s=`${e?`CHECKSUM_UPLOAD_AGENT_PORT=${e} `:""} PWDEBUG=console npx playwright test --config ${this.getPlaywrightConfigFile()} ${t.join(" ")}`;await this.patchPlaywright();try{await this.execCmd(s),console.log("Tests execution finished")}catch(o){this.didFail=!0,console.log("Error during test",o.message)}finally{let o=this.getPlaywrightReportPath();(0,i.existsSync)(o)?this.testRunMonitorProcess.stdin.write(`cli:report=${o}`):console.log(`Could not find report file at ${o}`),await this.patchPlaywright(!0),this.completeIndicators.tests=!0,await this.handleCompleteMessage()}}async patchPlaywright(t=!1){let e=`bash ${(0,r.join)(__dirname,"scripts/patch.sh")}${t?" off":""}`;try{await this.execCmd(e)}catch(s){console.log("Error patching playwright",s.message)}}getPlaywrightReportPath(){var o,a;let t=(0,r.join)(process.cwd(),"playwright-report"),e=require(this.getPlaywrightConfigFile()),{reporter:s}=e;return s instanceof Array&&s.length>1&&((o=s[1])!=null&&o.outputFolder)&&(t=(a=s[1])==null?void 0:a.outputFolder),process.env.PLAYWRIGHT_HTML_REPORT&&(t=process.env.PLAYWRIGHT_HTML_REPORT),(0,r.join)(t,"index.html")}getPlaywrightConfigFile(){return(0,r.join)(this.getRootDirPath(),"playwright.config.ts")}startTestRunMonitor(t){return new Promise(e=>{console.log("Starting test run monitor"),this.testRunMonitorProcess=l.spawn("node",[this.TEST_RUN_MONITOR_PATH,JSON.stringify({sessionId:t,checksumApiURL:this.CHECKSUM_API_URL,apiKey:this.config.apiKey}),...this.mock?["mock"]:[]]),this.testRunMonitorProcess.stdout.on("data",s=>{let o=s.toString().trim();if(!o.startsWith("monitor"))return;let[a,c]=o.substring(o.indexOf(":")+1).split("=");a==="port"?e(c):this.handleTestRunMonitorMessage(a,c)}),this.testRunMonitorProcess.on("exit",(s,o)=>{console.log(`test run monitor process exited with code ${s} and signal ${o}`)}),this.testRunMonitorProcess.on("error",s=>{console.error(`Error starting test run monitor: ${s.message}`)})})}async handleTestRunMonitorMessage(t,e){switch(t){case"complete":this.isolatedMode||console.log("Test artifacts uploaded successfully"),this.sendUploadsComplete().then(()=>{this.completeIndicators.upload=!0});break;case"report-uploaded":{this.isolatedMode||console.log("Report generated and uploaded to checksum");let s={};try{s=JSON.parse(e)}catch(a){console.log("Error parsing stats",a.message)}let o=await this.sendTestRunEnd(s);this.completeIndicators.report=!0,!this.isolatedMode&&o&&console.log(`*******************
|
|
14
|
+
* Checksum report URL: ${o}
|
|
15
|
+
*******************`);break}default:console.warn(`Unhandled test run monitor message: ${t}=${e}`)}}async handleCompleteMessage(){for(;;)Object.keys(this.completeIndicators).find(t=>!this.completeIndicators[t])?await this.awaitSleep(1e3):(console.log("Checksum test run complete"),this.shutdown(this.didFail?1:0))}shutdown(t=0){this.cleanup(),process.exit(t)}buildVolatileConfig(){if(!this.volatileChecksumConfig)return;let t=this.getVolatileConfigPath(),e=`
|
|
16
16
|
import { RunMode, getChecksumConfig } from "@checksum-ai/runtime";
|
|
17
17
|
|
|
18
18
|
export default getChecksumConfig(${JSON.stringify(this.config,null,2)});
|
|
19
|
-
`;(0,
|
|
19
|
+
`;(0,i.writeFileSync)(t,e)}cleanup(){this.deleteVolatileConfig(),this.testRunMonitorProcess.stdin.write("cli:shutdown"),this.testRunMonitorProcess.kill()}async getSession(){try{if(this.mock){this.testSession="mock-session";return}let t=this.config.apiKey;(!t||t==="<API key>")&&(console.error("No API key found in checksum config"),this.shutdown(1));let e=JSON.stringify(await this.getEnvInfo()),s=await fetch(`${this.CHECKSUM_API_URL}/client-api/test-runs`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",ChecksumAppCode:t},body:e});this.testSession=(await s.json()).uuid}catch{console.log("Error getting checksum test session, will run in isolation mode"),this.isolatedMode=!0,this.mock=!0,this.testSession="isolated-session"}}async sendTestRunEnd(t){try{if(this.mock)return"https://mock.report.url";let e=JSON.stringify({...t,endedAt:Date.now()}),{reportURL:s}=await this.updateTestRun(`${this.CHECKSUM_API_URL}/client-api/test-runs/${this.testSession}`,"PATCH",e);return s}catch(e){return console.log("Error sending test run end",e.message),null}}async sendUploadsComplete(){if(!this.mock)try{await this.updateTestRun(`${this.CHECKSUM_API_URL}/client-api/test-runs/${this.testSession}/uploads-completed`,"PATCH")}catch(t){console.log("Error sending test run uploads complete",t.message)}}async updateTestRun(t,e,s=void 0){return(await fetch(t,{method:e,headers:{Accept:"application/json","Content-Type":"application/json",ChecksumAppCode:this.config.apiKey},body:s})).json()}async getEnvInfo(){let t={commitHash:"",branch:"branch",environment:process.env.CI?"CI":"local",name:"name",startedAt:Date.now()};try{t.commitHash=(await this.getCmdOutput("git rev-parse HEAD")).toString().trim()}catch(e){console.log("Error getting git hash",e.message)}try{t.branch=(await this.getCmdOutput("git rev-parse --abbrev-ref HEAD")).toString().trim()}catch(e){console.log("Error getting branch name",e.message)}return t}getVolatileConfigPath(){return(0,r.join)(this.getRootDirPath(),"checksum.config.tmp.ts")}deleteVolatileConfig(){let t=this.getVolatileConfigPath();(0,i.existsSync)(t)&&(0,i.rmSync)(t)}setChecksumConfig(){this.config={...require((0,r.join)(this.getRootDirPath(),"checksum.config.ts")).default||{},...this.volatileChecksumConfig||{}},this.config.checksumApi&&(this.CHECKSUM_API_URL=this.config.checksumApi)}processChecksumArguments(t){this.deleteVolatileConfig();for(let e of t)if(e.startsWith("--checksum-config"))try{this.volatileChecksumConfig=JSON.parse(e.split("=")[1]),t=t.filter(s=>s!==e)}catch(s){console.log("Error parsing checksum config",s.message),this.volatileChecksumConfig=void 0}}install(){console.log("Creating Checksum directory and necessary files to run your tests");let t=this.getRootDirPath();if((0,i.existsSync)(this.getRootDirPath())||(0,i.mkdirSync)(t),!(0,i.existsSync)(this.getChecksumRootOrigin()))throw new Error("Could not find checksum root directory, please install @checksum-ai/runtime package");["checksum.config.ts","playwright.config.ts","login.ts","README.md"].forEach(e=>{(0,i.copyFileSync)((0,r.join)(this.getChecksumRootOrigin(),e),(0,r.join)(t,e))}),(0,i.mkdirSync)((0,r.join)(t,"tests"),{recursive:!0}),["esra","har","trace","log"].forEach(e=>{(0,i.mkdirSync)((0,r.join)(t,"test-data",e),{recursive:!0})})}getRootDirPath(){return(0,r.join)(process.cwd(),p)}getChecksumRootOrigin(){return(0,r.join)(process.cwd(),"node_modules","@checksum-ai","runtime","checksum-root")}};g(h,"ChecksumCLI");(async()=>await new h().execute())();
|
package/index.d.ts
CHANGED
|
@@ -23,17 +23,25 @@ export type RuntimeOptions = {
|
|
|
23
23
|
*/
|
|
24
24
|
useChecksumAI: boolean;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Add new assertions
|
|
27
27
|
*/
|
|
28
28
|
newAssertionsEnabled: boolean;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Use mocked data
|
|
31
31
|
*/
|
|
32
32
|
useMockData: boolean;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Print logs to console
|
|
35
35
|
*/
|
|
36
36
|
printLogs: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Save reports on checksum hosting servers
|
|
39
|
+
*/
|
|
40
|
+
hostReports?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Create a new PR for auto healed tests
|
|
43
|
+
*/
|
|
44
|
+
autoHealPRs?: boolean;
|
|
37
45
|
};
|
|
38
46
|
|
|
39
47
|
export type ChecksumConfig = {
|