@checksum-ai/runtime 1.0.3 → 1.0.4
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/README.md +1 -0
- package/checksum-root/checksum.config.ts +56 -0
- package/checksum-root/login.ts +19 -0
- package/checksum-root/playwright.config.ts +32 -0
- package/cli.ts +225 -0
- package/index.js +22 -22
- package/package.json +1 -1
- package/cli.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Checksum readme
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RunMode, getChecksumConfig } from "@checksum-ai/runtime";
|
|
2
|
+
|
|
3
|
+
export default getChecksumConfig({
|
|
4
|
+
/**
|
|
5
|
+
* Checksum runtime running mode -
|
|
6
|
+
* normal - tests run normally
|
|
7
|
+
* heal - checksum will attempt to heal tests that failed using fallback
|
|
8
|
+
* refactor - checksum will attempt to refactor and improve your tests
|
|
9
|
+
*/
|
|
10
|
+
runMode: RunMode.Normal,
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Insert here your Checksum API key
|
|
14
|
+
*/
|
|
15
|
+
apiKey: "<API key>",
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This is the base URL of the tested app
|
|
19
|
+
*/
|
|
20
|
+
baseURL: "<base URL>",
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Insert the account's username that will be used
|
|
24
|
+
* to login into your testing environment
|
|
25
|
+
*/
|
|
26
|
+
username: "<username>",
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Insert the account's password that will be used
|
|
30
|
+
* to login into your testing environment
|
|
31
|
+
*/
|
|
32
|
+
password: "<password>",
|
|
33
|
+
|
|
34
|
+
options: {
|
|
35
|
+
/**
|
|
36
|
+
* Whether to fallback to ESRA if the action selector is not found
|
|
37
|
+
*/
|
|
38
|
+
actionsESRAfallback: true,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Whether to use LLM fallback if action selector is not found
|
|
42
|
+
*/
|
|
43
|
+
actionsLLMFallback: true,
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether to use mock API data when running your tests
|
|
47
|
+
*/
|
|
48
|
+
useMockData: false,
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Print runtime logs.
|
|
52
|
+
* Use for debug only
|
|
53
|
+
*/
|
|
54
|
+
printLogs: false,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChecksumConfig, IChecksumPage } from "@checksum-ai/runtime";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Login method
|
|
5
|
+
*/
|
|
6
|
+
export default async function login(
|
|
7
|
+
page: IChecksumPage,
|
|
8
|
+
config: ChecksumConfig
|
|
9
|
+
) {
|
|
10
|
+
/**
|
|
11
|
+
* Update this function to login to your application
|
|
12
|
+
* i.e.:
|
|
13
|
+
* await page.goto('/login');
|
|
14
|
+
* await page.getByPlaceholder("Email...").fill(config.username);
|
|
15
|
+
* await page.getByPlaceholder("Password...").fill(config.password);
|
|
16
|
+
* await page.getByText("Continue").click();
|
|
17
|
+
* await page.waitForURL("/main");
|
|
18
|
+
*/
|
|
19
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
timeout: 120000,
|
|
5
|
+
testMatch: [/.*.[.]checksum.spec.ts/],
|
|
6
|
+
testDir: ".",
|
|
7
|
+
/* disable parallel test runs */
|
|
8
|
+
workers: 1,
|
|
9
|
+
/* Run tests in files in parallel */
|
|
10
|
+
fullyParallel: false,
|
|
11
|
+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
12
|
+
reporter: "html",
|
|
13
|
+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
14
|
+
use: {
|
|
15
|
+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
16
|
+
trace: "on",
|
|
17
|
+
video: "on",
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
/* Configure projects for major browsers */
|
|
21
|
+
projects: [
|
|
22
|
+
{
|
|
23
|
+
name: "chromium",
|
|
24
|
+
use: { ...devices["Desktop Chrome"] },
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "checksumpage",
|
|
28
|
+
use: { ...devices["Desktop Chrome"] },
|
|
29
|
+
testDir: "./src/lib/runtime",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
});
|
package/cli.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import * as childProcess from "child_process";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
5
|
+
const ROOT_DIR_NAME = "checksum";
|
|
6
|
+
|
|
7
|
+
class ChecksumCLI {
|
|
8
|
+
checksumConfig = undefined;
|
|
9
|
+
|
|
10
|
+
constructor() {}
|
|
11
|
+
|
|
12
|
+
async execute() {
|
|
13
|
+
switch (process.argv[2]) {
|
|
14
|
+
case "install":
|
|
15
|
+
this.install();
|
|
16
|
+
break;
|
|
17
|
+
case "run":
|
|
18
|
+
if (process.argv?.[3] === "--help") {
|
|
19
|
+
await this.printHelp("run");
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
await this.run(process.argv.slice(3));
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
await this.printHelp();
|
|
26
|
+
}
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async execCmd(cmdString) {
|
|
31
|
+
const child = await childProcess.spawn(cmdString, {
|
|
32
|
+
shell: true,
|
|
33
|
+
stdio: "inherit",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const exitPromise = new Promise((resolve, reject) => {
|
|
37
|
+
child.on("exit", (code) => {
|
|
38
|
+
if (code === 0) {
|
|
39
|
+
resolve(true);
|
|
40
|
+
} else {
|
|
41
|
+
reject(
|
|
42
|
+
new Error(
|
|
43
|
+
`Checsum failed execution with code: ${code} for command: "${cmdString}`
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return exitPromise;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getCmdOutput(cmdString): Promise<string> {
|
|
54
|
+
return new Promise<string>(function (resolve, reject) {
|
|
55
|
+
childProcess.exec(cmdString, (error, stdout, stderr) => {
|
|
56
|
+
if (error) {
|
|
57
|
+
reject(`Error executing command: ${error.message}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
resolve(stdout);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// return promise;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async printHelp(command?: string) {
|
|
69
|
+
switch (command) {
|
|
70
|
+
default:
|
|
71
|
+
console.log(`
|
|
72
|
+
Checksum CLI
|
|
73
|
+
Usage: checksum [command] [options]
|
|
74
|
+
|
|
75
|
+
Commands:
|
|
76
|
+
install installs checksum files and folders
|
|
77
|
+
run runs checksum tests
|
|
78
|
+
help prints this help message
|
|
79
|
+
`);
|
|
80
|
+
break;
|
|
81
|
+
case "run":
|
|
82
|
+
try {
|
|
83
|
+
const cmd = `npx playwright test --help`;
|
|
84
|
+
const testHelp: string = await this.getCmdOutput(cmd);
|
|
85
|
+
console.log(
|
|
86
|
+
testHelp.replace(/npx playwright test/g, "yarn checksum run")
|
|
87
|
+
);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.log("Error", e.message);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async run(args: string[]) {
|
|
97
|
+
args = this.getChecksumConfig(args);
|
|
98
|
+
// run shell command and pipe output rhe response to console
|
|
99
|
+
const cmd = `npx playwright test --config ${join(
|
|
100
|
+
this.getRootDirPath(),
|
|
101
|
+
"playwright.config.ts"
|
|
102
|
+
)} ${args.join(" ")}`;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
this.buildVolatileConfig();
|
|
106
|
+
return this.execCmd(cmd);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.log("Error", e.message);
|
|
109
|
+
} finally {
|
|
110
|
+
this.cleanup();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
buildVolatileConfig() {
|
|
115
|
+
if (!this.checksumConfig) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const configPath = this.getVolatileConfigPath();
|
|
120
|
+
const configString = `
|
|
121
|
+
import { RunMode, getChecksumConfig } from "@checksum-ai/runtime";
|
|
122
|
+
|
|
123
|
+
export default getChecksumConfig(${JSON.stringify(
|
|
124
|
+
this.checksumConfig,
|
|
125
|
+
null,
|
|
126
|
+
2
|
|
127
|
+
)});
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
writeFileSync(configPath, configString);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
cleanup() {
|
|
134
|
+
const configPath = this.getVolatileConfigPath();
|
|
135
|
+
if (existsSync(configPath)) {
|
|
136
|
+
rmSync(configPath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getVolatileConfigPath() {
|
|
141
|
+
return join(this.getRootDirPath(), "checksum.config.tmp.ts");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getChecksumConfig(args) {
|
|
145
|
+
for (const arg of args) {
|
|
146
|
+
if (arg.startsWith("--checksum-config")) {
|
|
147
|
+
try {
|
|
148
|
+
this.checksumConfig = JSON.parse(arg.split("=")[1]);
|
|
149
|
+
return args.filter((a) => a !== arg);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.log("Error parsing checksum config", e.message);
|
|
152
|
+
this.checksumConfig = undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return args;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
install() {
|
|
161
|
+
console.log(
|
|
162
|
+
"Creating Checksum directory and necessary files to run your tests"
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const checksumRoot = this.getRootDirPath();
|
|
166
|
+
|
|
167
|
+
if (!existsSync(this.getRootDirPath())) {
|
|
168
|
+
mkdirSync(checksumRoot);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!existsSync(this.getChecksumRootOrigin())) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
"Could not find checksum root directory, please install @checksum-ai/runtime package"
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// automatically install?
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// copy sources
|
|
180
|
+
[
|
|
181
|
+
"checksum.config.ts",
|
|
182
|
+
"playwright.config.ts",
|
|
183
|
+
"login.ts",
|
|
184
|
+
"README.md",
|
|
185
|
+
].forEach((file) => {
|
|
186
|
+
copyFileSync(
|
|
187
|
+
join(this.getChecksumRootOrigin(), file),
|
|
188
|
+
join(checksumRoot, file)
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// create tests folder
|
|
193
|
+
mkdirSync(join(checksumRoot, "tests"), {
|
|
194
|
+
recursive: true,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// create test data directories
|
|
198
|
+
["esra", "har", "trace", "log"].forEach((folder) => {
|
|
199
|
+
mkdirSync(join(checksumRoot, "test-data", folder), {
|
|
200
|
+
recursive: true,
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
getRootDirPath() {
|
|
206
|
+
return join(process.cwd(), ROOT_DIR_NAME);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
getChecksumRootOrigin() {
|
|
210
|
+
return join(
|
|
211
|
+
process.cwd(),
|
|
212
|
+
"node_modules",
|
|
213
|
+
"@checksum-ai",
|
|
214
|
+
"runtime",
|
|
215
|
+
"checksum-root"
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Trigger the main function
|
|
222
|
+
*/
|
|
223
|
+
(async () => {
|
|
224
|
+
await new ChecksumCLI().execute();
|
|
225
|
+
})();
|