@checksum-ai/runtime 1.0.2 → 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/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
+ })();
package/index.d.ts CHANGED
@@ -0,0 +1,87 @@
1
+ import { Page } from "@playwright/test";
2
+
3
+ export interface IChecksumPage extends Page {
4
+ initWithTest: (testInfo) => Promise<void>;
5
+ checksumId: (id: string) => IChecksumPage;
6
+ checksumStep: (thought: string, testFunction?: () => void) => IChecksumPage;
7
+ testId: (testId: string) => void;
8
+ }
9
+
10
+ export enum RunMode {
11
+ Normal = "normal",
12
+ Heal = "heal",
13
+ Refactor = "refactor",
14
+ }
15
+
16
+ export type RuntimeOptions = {
17
+ /**
18
+ * fallback to ESRA if the action selector is not found
19
+ */
20
+ actionsESRAfallback: boolean;
21
+ /**
22
+ * use LLM fallback if action selector is not found
23
+ */
24
+ actionsLLMFallback: boolean;
25
+ /**
26
+ * add new assertions
27
+ */
28
+ newAssertionsEnabled: boolean;
29
+ /**
30
+ * use mocked data
31
+ */
32
+ useMockData: boolean;
33
+ /**
34
+ * print logs to console
35
+ */
36
+ printLogs: boolean;
37
+ };
38
+
39
+ export type ChecksumConfig = {
40
+ /**
41
+ * Checksum runtime running mode -
42
+ * normal - tests run normally
43
+ * heal - checksum will attempt to heal tests that failed using fallback
44
+ * refactor - checksum will attempt to refactor and improve your tests
45
+ */
46
+ runMode: RunMode;
47
+ /**
48
+ * Checksum API key
49
+ */
50
+ apiKey: string;
51
+ /**
52
+ * Base URL of the tested app (i.e http://staging.example.com)
53
+ */
54
+ baseURL: string;
55
+
56
+ apiURL: string;
57
+ /**
58
+ * Account's username that will be used
59
+ * to login into your testing environment
60
+ */
61
+ username?: string;
62
+ /**
63
+ * Account's password that will be used
64
+ * to login into your testing environment
65
+ */
66
+ password?: string;
67
+ options?: Partial<RuntimeOptions>;
68
+ };
69
+
70
+ export function getLogin(): (page: Page) => Promise<void>;
71
+
72
+ export function getChecksumConfig(
73
+ config: Partial<ChecksumConfig>
74
+ ): ChecksumConfig;
75
+
76
+ export function init(
77
+ base: TestType<
78
+ PlaywrightTestArgs & PlaywrightTestOptions,
79
+ PlaywrightWorkerArgs & PlaywrightWorkerOptions
80
+ >
81
+ ): {
82
+ test: TestType<
83
+ PlaywrightTestArgs & PlaywrightTestOptions,
84
+ PlaywrightWorkerArgs & PlaywrightWorkerOptions
85
+ >;
86
+ login: ReturnType<typeof getLogin>;
87
+ };