@testspectra/cli 1.0.7 → 1.0.10

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.
Files changed (66) hide show
  1. package/dist/commands/init.js +58 -398
  2. package/dist/commands/run.js +18 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.js +1 -1
  5. package/package.json +8 -1
  6. package/templates/default/actions/applyDiscount/mobile.action.ts +6 -0
  7. package/templates/default/actions/applyDiscount/web.action.ts +6 -0
  8. package/templates/default/actions/verifyOtp/mobile.action.ts +6 -0
  9. package/templates/default/actions/verifyOtp/web.action.ts +6 -0
  10. package/templates/default/fixtures/couponCode.json +1 -0
  11. package/templates/default/fixtures/searchQuery.json +1 -0
  12. package/templates/default/fixtures/userData.json +1 -0
  13. package/templates/default/global-hooks/before.web.hook.ts +4 -0
  14. package/templates/default/package.json +18 -0
  15. package/templates/default/page-objects/LoginPage/mobile.ts +32 -0
  16. package/templates/default/page-objects/LoginPage/web.ts +32 -0
  17. package/templates/default/page-objects/ProductPage/mobile.ts +39 -0
  18. package/templates/default/page-objects/ProductPage/web.ts +38 -0
  19. package/templates/default/page-objects/SettingsPage/common.ts +26 -0
  20. package/templates/default/spectra.config.ts +61 -0
  21. package/templates/default/steps/loginUser/mobile.step.ts +4 -0
  22. package/templates/default/steps/loginUser/web.step.ts +4 -0
  23. package/templates/default/steps/searchProduct/mobile.step.ts +5 -0
  24. package/templates/default/steps/searchProduct/web.step.ts +5 -0
  25. package/templates/default/suites/Auth/TC-AUTH-01/android.test.ts +6 -0
  26. package/templates/default/suites/Auth/TC-AUTH-01/ios.test.ts +6 -0
  27. package/templates/default/suites/Auth/TC-AUTH-01/web.test.ts +13 -0
  28. package/templates/default/suites/Auth/TC-AUTH-02/android.test.ts +5 -0
  29. package/templates/default/suites/Auth/TC-AUTH-02/web.test.ts +5 -0
  30. package/templates/default/suites/Auth/hooks/before.android.hook.ts +3 -0
  31. package/templates/default/suites/Auth/hooks/before.ios.hook.ts +3 -0
  32. package/templates/default/suites/Auth/hooks/before.web.hook.ts +3 -0
  33. package/templates/default/suites/Product/TC-PROD-01/mobile.test.ts +8 -0
  34. package/templates/default/suites/Product/TC-PROD-01/web.test.ts +8 -0
  35. package/templates/default/suites/Product/TC-PROD-02/mobile.test.ts +6 -0
  36. package/templates/default/suites/Product/TC-PROD-02/web.test.ts +6 -0
  37. package/templates/default/suites/Product/hooks/before.web.hook.ts +3 -0
  38. package/templates/default/suites/Settings/TC-SET-01/common.test.ts +8 -0
  39. package/templates/default/tsconfig.android.json +39 -0
  40. package/templates/default/tsconfig.ios.json +39 -0
  41. package/templates/default/tsconfig.json +20 -0
  42. package/templates/default/tsconfig.web.json +45 -0
  43. package/CLI_IMPLEMENTATION_PLAN.md +0 -369
  44. package/src/commands/devices.ts +0 -41
  45. package/src/commands/doctor.ts +0 -57
  46. package/src/commands/init.ts +0 -470
  47. package/src/commands/run.ts +0 -102
  48. package/src/config/loader.ts +0 -82
  49. package/src/config/schema.ts +0 -489
  50. package/src/index.ts +0 -56
  51. package/src/plugin.ts +0 -81
  52. package/src/runner/bridge.ts +0 -146
  53. package/src/runner/reporter.ts +0 -64
  54. package/src/step/index.ts +0 -6
  55. package/src/step/matchers.ts +0 -131
  56. package/src/step/proto.ts +0 -163
  57. package/src/step/runner/collection.ts +0 -73
  58. package/src/step/runner/single.ts +0 -166
  59. package/src/step/spectra.ts +0 -185
  60. package/src/step/types.ts +0 -113
  61. package/src/types/generator.ts +0 -240
  62. package/src/types/webdriverio.d.ts +0 -46
  63. package/testspectra-cli-1.0.5.tgz +0 -0
  64. package/testspectra-cli-1.0.6.tgz +0 -0
  65. package/testspectra-cli-1.0.7.tgz +0 -0
  66. package/tsconfig.json +0 -17
@@ -1,240 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
-
4
- export type PlatformTarget = "web" | "android" | "ios" | "mobile" | "common";
5
-
6
- const PLATFORM_HIERARCHY: Record<PlatformTarget, string[]> = {
7
- web: ["web", "common"],
8
- ios: ["ios", "mobile", "common"],
9
- android: ["android", "mobile", "common"],
10
- mobile: ["mobile", "common"],
11
- common: ["common"],
12
- };
13
-
14
- export class TypeGenerator {
15
- static getPageObjectsDir(cwd: string): string {
16
- const p1 = path.join(cwd, "page-objects");
17
- if (fs.existsSync(p1)) return p1;
18
- return path.join(cwd, "pageobjects");
19
- }
20
-
21
- static generateAmbientDeclarations(cwd: string): Record<string, string> {
22
- const poDir = this.getPageObjectsDir(cwd);
23
- const actionsDir = path.join(cwd, "actions");
24
- const stepsDir = path.join(cwd, "steps");
25
- const fixturesDir = path.join(cwd, "fixtures");
26
-
27
- const platforms: PlatformTarget[] = ["web", "android", "ios", "mobile", "common"];
28
- const results: Record<string, string> = {};
29
-
30
- for (const platform of platforms) {
31
- const hierarchy = PLATFORM_HIERARCHY[platform];
32
- let content = `// Auto-generated ambient declarations for TestSpectra [${platform.toUpperCase()}]\n`;
33
- content += `// Do not edit manually. Run 'spectra watch' or let the Language Service manage this.\n\n`;
34
- content += `/// <reference types="@wdio/globals/types" />\n`;
35
- content += `/// <reference types="@wdio/mocha-framework" />\n`;
36
- content += `/// <reference path="./fixtures.d.ts" />\n\n`;
37
-
38
- content += `declare namespace WebdriverIO {\n`;
39
- content += ` export interface InterceptFixtureOptions {\n`;
40
- content += ` statusCode?: number;\n`;
41
- content += ` headers?: Record<string, string>;\n`;
42
- content += ` }\n`;
43
- content += ` export interface InterceptFixtureObject<TData = unknown> {\n`;
44
- content += ` statusCode?: number;\n`;
45
- content += ` body: TData;\n`;
46
- content += ` headers?: Record<string, string>;\n`;
47
- content += ` }\n`;
48
- content += ` export type InterceptInput<TData = unknown> = InterceptFixtureObject<TData> | TData | string;\n`;
49
- content += ` interface Mock {\n`;
50
- content += ` respondWith<TData = unknown>(fixture: InterceptInput<TData>, options?: InterceptFixtureOptions): Promise<void>;\n`;
51
- content += ` }\n`;
52
- content += ` interface Browser {\n`;
53
- content += ` intercept<TData = unknown>(path: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH', fixture?: InterceptInput<TData>, options?: InterceptFixtureOptions): Promise<Mock>;\n`;
54
- content += ` shouldHaveUrl(expectedUrl: string): Promise<void>;\n`;
55
- content += ` shouldContainUrl(expectedUrl: string): Promise<void>;\n`;
56
- content += ` shouldHaveTitle(expectedTitle: string): Promise<void>;\n`;
57
- content += ` shouldContainTitle(expectedTitle: string): Promise<void>;\n`;
58
- content += ` }\n`;
59
- content += ` interface Element {\n`;
60
- content += ` shouldBeVisible(): Promise<Element>;\n`;
61
- content += ` shouldNotBeVisible(): Promise<Element>;\n`;
62
- content += ` shouldExist(): Promise<Element>;\n`;
63
- content += ` shouldNotExist(): Promise<Element>;\n`;
64
- content += ` shouldBeEnabled(): Promise<Element>;\n`;
65
- content += ` shouldBeDisabled(): Promise<Element>;\n`;
66
- content += ` shouldBeSelected(): Promise<Element>;\n`;
67
- content += ` shouldBeChecked(): Promise<Element>;\n`;
68
- content += ` shouldHaveValue(expectedValue: string): Promise<Element>;\n`;
69
- content += ` shouldContainValue(expectedValue: string): Promise<Element>;\n`;
70
- content += ` shouldHaveText(expectedText: string): Promise<Element>;\n`;
71
- content += ` shouldContainText(expectedText: string): Promise<Element>;\n`;
72
- content += ` shouldHaveClass(className: string): Promise<Element>;\n`;
73
- content += ` shouldHaveAttribute(attributeName: string, expectedValue?: string): Promise<Element>;\n`;
74
- content += ` }\n`;
75
- content += `}\n\n`;
76
- content += `interface Promise<T> {\n`;
77
- content += ` shouldBeVisible(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
78
- content += ` shouldNotBeVisible(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
79
- content += ` shouldExist(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
80
- content += ` shouldNotExist(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
81
- content += ` shouldBeEnabled(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
82
- content += ` shouldBeDisabled(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
83
- content += ` shouldBeSelected(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
84
- content += ` shouldBeChecked(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;\n`;
85
- content += ` shouldHaveValue(this: Promise<WebdriverIO.Element>, expectedValue: string): Promise<WebdriverIO.Element>;\n`;
86
- content += ` shouldContainValue(this: Promise<WebdriverIO.Element>, expectedValue: string): Promise<WebdriverIO.Element>;\n`;
87
- content += ` shouldHaveText(this: Promise<WebdriverIO.Element>, expectedText: string): Promise<WebdriverIO.Element>;\n`;
88
- content += ` shouldContainText(this: Promise<WebdriverIO.Element>, expectedText: string): Promise<WebdriverIO.Element>;\n`;
89
- content += ` shouldHaveClass(this: Promise<WebdriverIO.Element>, className: string): Promise<WebdriverIO.Element>;\n`;
90
- content += ` shouldHaveAttribute(this: Promise<WebdriverIO.Element>, attributeName: string, expectedValue?: string): Promise<WebdriverIO.Element>;\n`;
91
- content += `}\n\n`;
92
-
93
- // 1. Page Objects Global Declarations (Hierarchical)
94
-
95
- // 2. Page Objects Global Declarations (Hierarchical)
96
- if (fs.existsSync(poDir)) {
97
- const poEntries = fs.readdirSync(poDir, { withFileTypes: true });
98
- for (const entry of poEntries) {
99
- if (entry.name.startsWith(".")) continue;
100
- if (entry.isDirectory()) {
101
- const className = entry.name;
102
- const classFolder = path.join(poDir, className);
103
- // Search hierarchy
104
- let matchedFile: string | null = null;
105
- for (const stem of hierarchy) {
106
- const cand = path.join(classFolder, `${stem}.ts`);
107
- if (fs.existsSync(cand)) {
108
- matchedFile = `../../page-objects/${className}/${stem}.js`;
109
- break;
110
- }
111
- }
112
- if (matchedFile) {
113
- content += `declare const ${className}: typeof import('${matchedFile}').default;\n`;
114
- }
115
- } else if (entry.isFile() && entry.name.endsWith(".ts")) {
116
- const className = entry.name.split(".")[0];
117
- content += `declare const ${className}: typeof import('../../page-objects/${entry.name.replace(".ts", ".js")}').default;\n`;
118
- }
119
- }
120
- }
121
-
122
- // 3. Actions Global Interface (Extends built-in @testspectra/cli Spectra)
123
- content += `\ninterface TestSpectraActions extends Omit<typeof import('@testspectra/cli').Spectra, ''> {\n`;
124
- if (fs.existsSync(actionsDir)) {
125
- const actionEntries = fs.readdirSync(actionsDir, { withFileTypes: true });
126
- for (const entry of actionEntries) {
127
- if (entry.name.startsWith(".")) continue;
128
- if (entry.isDirectory()) {
129
- const actionName = entry.name;
130
- const actionFolder = path.join(actionsDir, actionName);
131
- let matchedFile: string | null = null;
132
- for (const stem of hierarchy) {
133
- const cand1 = path.join(actionFolder, `${stem}.action.ts`);
134
- const cand2 = path.join(actionFolder, `${stem}.ts`);
135
- if (fs.existsSync(cand1)) {
136
- matchedFile = `../../actions/${actionName}/${stem}.action.js`;
137
- break;
138
- } else if (fs.existsSync(cand2)) {
139
- matchedFile = `../../actions/${actionName}/${stem}.js`;
140
- break;
141
- }
142
- }
143
- if (matchedFile) {
144
- content += ` ${actionName}: (typeof import('${matchedFile}') extends { default: infer T } ? T : typeof import('${matchedFile}'));\n`;
145
- } else {
146
- content += ` ${actionName}: (...args: any[]) => Promise<any>;\n`;
147
- }
148
- } else if (entry.isFile() && entry.name.endsWith(".ts")) {
149
- const actionName = entry.name.split(".")[0];
150
- const modPath = `../../actions/${entry.name.replace(".ts", ".js")}`;
151
- content += ` ${actionName}: (typeof import('${modPath}') extends { default: infer T } ? T : typeof import('${modPath}'));\n`;
152
- }
153
- }
154
- }
155
- content += `}\n`;
156
- content += `declare const Spectra: TestSpectraActions;\n\n`;
157
-
158
- // 4. Shared Steps Global Interface
159
- content += `interface TestSpectraSteps {\n`;
160
- if (fs.existsSync(stepsDir)) {
161
- const stepEntries = fs.readdirSync(stepsDir, { withFileTypes: true });
162
- for (const entry of stepEntries) {
163
- if (entry.name.startsWith(".")) continue;
164
- if (entry.isDirectory()) {
165
- const stepName = entry.name;
166
- const stepFolder = path.join(stepsDir, stepName);
167
- let matchedFile: string | null = null;
168
- for (const stem of hierarchy) {
169
- const cand1 = path.join(stepFolder, `${stem}.step.ts`);
170
- const cand2 = path.join(stepFolder, `${stem}.ts`);
171
- if (fs.existsSync(cand1)) {
172
- matchedFile = `../../steps/${stepName}/${stem}.step.js`;
173
- break;
174
- } else if (fs.existsSync(cand2)) {
175
- matchedFile = `../../steps/${stepName}/${stem}.js`;
176
- break;
177
- }
178
- }
179
- if (matchedFile) {
180
- content += ` ${stepName}: (typeof import('${matchedFile}') extends { default: infer T } ? T : typeof import('${matchedFile}'));\n`;
181
- } else {
182
- content += ` ${stepName}: (...args: any[]) => Promise<any>;\n`;
183
- }
184
- } else if (entry.isFile() && entry.name.endsWith(".ts")) {
185
- const stepName = entry.name.split(".")[0];
186
- const modPath = `../../steps/${entry.name.replace(".ts", ".js")}`;
187
- content += ` ${stepName}: (typeof import('${modPath}') extends { default: infer T } ? T : typeof import('${modPath}'));\n`;
188
- }
189
- }
190
- }
191
- content += `}\n`;
192
- content += `declare const Step: TestSpectraSteps;\n\n`;
193
-
194
- results[platform] = content;
195
- }
196
-
197
- return results;
198
- }
199
-
200
- static generateFixturesDeclaration(cwd: string): string {
201
- const fixturesDir = path.join(cwd, "fixtures");
202
- let content = `// Auto-generated ambient fixture declarations for TestSpectra\n`;
203
- content += `// Do not edit manually. Run 'spectra watch' or let the Language Service manage this.\n\n`;
204
- content += `interface TestSpectraFixtures {\n`;
205
- if (fs.existsSync(fixturesDir)) {
206
- const fixtureFiles = fs.readdirSync(fixturesDir);
207
- for (const file of fixtureFiles) {
208
- if (file.startsWith(".")) continue;
209
- const parsed = path.parse(file);
210
- const varName = parsed.name.replace(/[^a-zA-Z0-9_$]/g, "_");
211
- content += ` readonly ${varName}: string;\n`;
212
- }
213
- }
214
- content += `}\n`;
215
- content += `declare const Fixture: TestSpectraFixtures;\n`;
216
- return content;
217
- }
218
-
219
- static writeDeclarationFiles(cwd: string): void {
220
- const typesDir = path.join(cwd, ".testspectra", "types");
221
- if (!fs.existsSync(typesDir)) {
222
- fs.mkdirSync(typesDir, { recursive: true });
223
- }
224
-
225
- // 1. Write single platform-agnostic fixtures.d.ts
226
- const fixturesContent = this.generateFixturesDeclaration(cwd);
227
- fs.writeFileSync(path.join(typesDir, "fixtures.d.ts"), fixturesContent, "utf-8");
228
-
229
- // 2. Write per-platform ambient types
230
- const declarations = this.generateAmbientDeclarations(cwd);
231
- for (const [platform, content] of Object.entries(declarations)) {
232
- const filePath = path.join(typesDir, `${platform}.d.ts`);
233
- fs.writeFileSync(filePath, content, "utf-8");
234
- }
235
-
236
- // Also write a universal ambient index
237
- const universalPath = path.join(typesDir, "index.d.ts");
238
- fs.writeFileSync(universalPath, `/// <reference path="./common.d.ts" />\n`, "utf-8");
239
- }
240
- }
@@ -1,46 +0,0 @@
1
- declare global {
2
- namespace WebdriverIO {
3
- export interface InterceptFixtureOptions {
4
- statusCode?: number;
5
- headers?: Record<string, string>;
6
- }
7
-
8
- export interface InterceptFixtureObject<TData = unknown> {
9
- statusCode?: number;
10
- body: TData;
11
- headers?: Record<string, string>;
12
- }
13
-
14
- export type InterceptInput<TData = unknown> =
15
- | InterceptFixtureObject<TData>
16
- | TData
17
- | string;
18
-
19
- interface Mock {
20
- /**
21
- * Dynamically set or change the fixture response for this mock instance.
22
- * Supports Fixture paths, `{ statusCode, body, headers }` objects, or raw payloads.
23
- */
24
- respondWith<TData = unknown>(
25
- fixture: InterceptInput<TData>,
26
- options?: InterceptFixtureOptions,
27
- ): Promise<void>;
28
- }
29
-
30
- interface Browser {
31
- /**
32
- * Clean & strongly-typed API interceptor for WebdriverIO.
33
- * Automatically resolves relative path against browser.options.baseUrl.
34
- * Integrated directly with TestSpectra Fixtures.
35
- */
36
- intercept<TData = unknown>(
37
- path: string,
38
- method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH',
39
- fixture?: InterceptInput<TData>,
40
- options?: InterceptFixtureOptions,
41
- ): Promise<Mock>;
42
- }
43
- }
44
- }
45
-
46
- export {};
Binary file
Binary file
Binary file
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "declaration": true,
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "types": ["node", "@wdio/globals/types", "@wdio/mocha-framework"],
13
- "forceConsistentCasingInFileNames": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules", "dist"]
17
- }