@pwtap/create 0.1.0
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/core-manifest.json +50 -0
- package/dist/commands/add.d.ts +8 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +9 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/create.d.ts +12 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +114 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/remove.d.ts +7 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +9 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/injectors/assets.d.ts +6 -0
- package/dist/injectors/assets.d.ts.map +1 -0
- package/dist/injectors/assets.js +53 -0
- package/dist/injectors/assets.js.map +1 -0
- package/dist/injectors/envJson.d.ts +6 -0
- package/dist/injectors/envJson.d.ts.map +1 -0
- package/dist/injectors/envJson.js +39 -0
- package/dist/injectors/envJson.js.map +1 -0
- package/dist/injectors/fixturesBarrel.d.ts +11 -0
- package/dist/injectors/fixturesBarrel.d.ts.map +1 -0
- package/dist/injectors/fixturesBarrel.js +66 -0
- package/dist/injectors/fixturesBarrel.js.map +1 -0
- package/dist/injectors/packageJson.d.ts +6 -0
- package/dist/injectors/packageJson.d.ts.map +1 -0
- package/dist/injectors/packageJson.js +25 -0
- package/dist/injectors/packageJson.js.map +1 -0
- package/dist/injectors/pwConfig.d.ts +10 -0
- package/dist/injectors/pwConfig.d.ts.map +1 -0
- package/dist/injectors/pwConfig.js +40 -0
- package/dist/injectors/pwConfig.js.map +1 -0
- package/dist/manifest.d.ts +65 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +22 -0
- package/dist/manifest.js.map +1 -0
- package/dist/plugin-apply.d.ts +13 -0
- package/dist/plugin-apply.d.ts.map +1 -0
- package/dist/plugin-apply.js +89 -0
- package/dist/plugin-apply.js.map +1 -0
- package/dist/prompts.d.ts +22 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +65 -0
- package/dist/prompts.js.map +1 -0
- package/dist/registry.d.ts +26 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +34 -0
- package/dist/registry.js.map +1 -0
- package/dist/util/fs.d.ts +13 -0
- package/dist/util/fs.d.ts.map +1 -0
- package/dist/util/fs.js +32 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/log.d.ts +8 -0
- package/dist/util/log.d.ts.map +1 -0
- package/dist/util/log.js +9 -0
- package/dist/util/log.js.map +1 -0
- package/dist/util/markers.d.ts +20 -0
- package/dist/util/markers.d.ts.map +1 -0
- package/dist/util/markers.js +51 -0
- package/dist/util/markers.js.map +1 -0
- package/dist/util/run.d.ts +8 -0
- package/dist/util/run.d.ts.map +1 -0
- package/dist/util/run.js +27 -0
- package/dist/util/run.js.map +1 -0
- package/package.json +31 -0
- package/template/.commitlintrc.json +3 -0
- package/template/.prettierrc +17 -0
- package/template/api/core/ApiClient.ts +99 -0
- package/template/api/core/types.ts +29 -0
- package/template/api/index.ts +4 -0
- package/template/api/models/pet.ts +24 -0
- package/template/api/services/PetService.ts +67 -0
- package/template/config/envUtils.ts +70 -0
- package/template/config/index.ts +2 -0
- package/template/config/loadEnv.ts +110 -0
- package/template/env/environments.example.json +20 -0
- package/template/eslint.config.js +74 -0
- package/template/fixtures/api.ts +46 -0
- package/template/fixtures/auth.ts +150 -0
- package/template/fixtures/index.ts +38 -0
- package/template/fixtures/ui.ts +112 -0
- package/template/pages/BasePage.ts +225 -0
- package/template/pages/LoginPage.ts +50 -0
- package/template/pages/index.ts +2 -0
- package/template/playwright.config.ts +71 -0
- package/template/templates/gitignore +19 -0
- package/template/testData/users.example.json +17 -0
- package/template/tests/api/pet.api.ts +60 -0
- package/template/tests/example/authSession.spec.ts +34 -0
- package/template/tests/example/login.spec.ts +50 -0
- package/template/tsconfig.json +33 -0
- package/template/utils/apiUtils.ts +224 -0
- package/template/utils/dateUtils.ts +158 -0
- package/template/utils/index.ts +15 -0
- package/template/utils/stringUtils.ts +192 -0
- package/template/utils/uiUtils.ts +236 -0
- package/template/utils/validationUtils.ts +190 -0
- package/template/utils/waitUtils.ts +207 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wait and Retry Utility Functions
|
|
5
|
+
* Provides wait helpers and retry logic
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class WaitUtils {
|
|
9
|
+
/**
|
|
10
|
+
* Wait for specific amount of time
|
|
11
|
+
*/
|
|
12
|
+
static async wait(milliseconds: number): Promise<void> {
|
|
13
|
+
await new Promise(resolve => setTimeout(resolve, milliseconds));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Wait for condition to be true
|
|
18
|
+
*/
|
|
19
|
+
static async waitForCondition(
|
|
20
|
+
condition: () => boolean | Promise<boolean>,
|
|
21
|
+
options?: {
|
|
22
|
+
timeout?: number;
|
|
23
|
+
interval?: number;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
},
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
const timeout = options?.timeout || 30000;
|
|
28
|
+
const interval = options?.interval || 500;
|
|
29
|
+
const errorMessage = options?.errorMessage || 'Condition not met within timeout';
|
|
30
|
+
const startTime = Date.now();
|
|
31
|
+
|
|
32
|
+
while (Date.now() - startTime < timeout) {
|
|
33
|
+
if (await condition()) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
await this.wait(interval);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
throw new Error(errorMessage);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Wait for element count to match expected value
|
|
44
|
+
*/
|
|
45
|
+
static async waitForElementCount(
|
|
46
|
+
elements: Locator,
|
|
47
|
+
expectedCount: number,
|
|
48
|
+
timeout: number = 30000,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
await this.waitForCondition(async () => (await elements.count()) === expectedCount, {
|
|
51
|
+
timeout,
|
|
52
|
+
errorMessage: `Expected ${expectedCount} elements, but got different count`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Wait for text to appear in element
|
|
58
|
+
*/
|
|
59
|
+
static async waitForText(element: Locator, text: string, timeout: number = 30000): Promise<void> {
|
|
60
|
+
await element.waitFor({ state: 'visible', timeout });
|
|
61
|
+
await this.waitForCondition(
|
|
62
|
+
async () => {
|
|
63
|
+
const content = await element.textContent();
|
|
64
|
+
return content?.includes(text) || false;
|
|
65
|
+
},
|
|
66
|
+
{ timeout, errorMessage: `Text "${text}" did not appear in element` },
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Wait for text to disappear from element
|
|
72
|
+
*/
|
|
73
|
+
static async waitForTextToDisappear(
|
|
74
|
+
element: Locator,
|
|
75
|
+
text: string,
|
|
76
|
+
timeout: number = 30000,
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
await this.waitForCondition(
|
|
79
|
+
async () => {
|
|
80
|
+
const content = await element.textContent();
|
|
81
|
+
return !content?.includes(text);
|
|
82
|
+
},
|
|
83
|
+
{ timeout, errorMessage: `Text "${text}" did not disappear from element` },
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Wait for URL to match pattern
|
|
89
|
+
*/
|
|
90
|
+
static async waitForURL(
|
|
91
|
+
page: Page,
|
|
92
|
+
urlPattern: string | RegExp,
|
|
93
|
+
timeout: number = 30000,
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
await page.waitForURL(urlPattern, { timeout });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Wait for URL to contain text
|
|
100
|
+
*/
|
|
101
|
+
static async waitForURLContains(
|
|
102
|
+
page: Page,
|
|
103
|
+
text: string,
|
|
104
|
+
timeout: number = 30000,
|
|
105
|
+
): Promise<void> {
|
|
106
|
+
await this.waitForCondition(() => page.url().includes(text), {
|
|
107
|
+
timeout,
|
|
108
|
+
errorMessage: `URL does not contain "${text}"`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Wait for page to be fully loaded
|
|
114
|
+
*/
|
|
115
|
+
static async waitForPageLoad(
|
|
116
|
+
page: Page,
|
|
117
|
+
state: 'load' | 'domcontentloaded' | 'networkidle' = 'load',
|
|
118
|
+
timeout: number = 30000,
|
|
119
|
+
): Promise<void> {
|
|
120
|
+
await page.waitForLoadState(state, { timeout });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Wait for navigation to complete
|
|
125
|
+
*/
|
|
126
|
+
static async waitForNavigation(
|
|
127
|
+
page: Page,
|
|
128
|
+
action: () => Promise<void>,
|
|
129
|
+
timeout: number = 30000,
|
|
130
|
+
): Promise<void> {
|
|
131
|
+
await Promise.all([page.waitForNavigation({ timeout }), action()]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Wait for selector with custom timeout
|
|
136
|
+
*/
|
|
137
|
+
static async waitForSelector(
|
|
138
|
+
page: Page,
|
|
139
|
+
selector: string,
|
|
140
|
+
options?: {
|
|
141
|
+
timeout?: number;
|
|
142
|
+
state?: 'attached' | 'detached' | 'visible' | 'hidden';
|
|
143
|
+
},
|
|
144
|
+
): Promise<void> {
|
|
145
|
+
await page.locator(selector).waitFor({
|
|
146
|
+
timeout: options?.timeout || 30000,
|
|
147
|
+
state: options?.state || 'visible',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Retry function with exponential backoff
|
|
153
|
+
*/
|
|
154
|
+
static async retry<T>(
|
|
155
|
+
fn: () => Promise<T>,
|
|
156
|
+
options?: {
|
|
157
|
+
maxRetries?: number;
|
|
158
|
+
initialDelay?: number;
|
|
159
|
+
maxDelay?: number;
|
|
160
|
+
factor?: number;
|
|
161
|
+
},
|
|
162
|
+
): Promise<T> {
|
|
163
|
+
const { maxRetries = 3, initialDelay = 1000, maxDelay = 10000, factor = 2 } = options || {};
|
|
164
|
+
|
|
165
|
+
let lastError: Error;
|
|
166
|
+
let delay = initialDelay;
|
|
167
|
+
|
|
168
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
169
|
+
try {
|
|
170
|
+
return await fn();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
lastError = error as Error;
|
|
173
|
+
if (attempt < maxRetries) {
|
|
174
|
+
await this.wait(Math.min(delay, maxDelay));
|
|
175
|
+
delay *= factor;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
throw lastError!;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Poll until condition is met or timeout
|
|
185
|
+
*/
|
|
186
|
+
static async poll<T>(
|
|
187
|
+
fn: () => Promise<T | null | undefined>,
|
|
188
|
+
options?: {
|
|
189
|
+
timeout?: number;
|
|
190
|
+
interval?: number;
|
|
191
|
+
},
|
|
192
|
+
): Promise<T> {
|
|
193
|
+
const timeout = options?.timeout || 30000;
|
|
194
|
+
const interval = options?.interval || 1000;
|
|
195
|
+
const startTime = Date.now();
|
|
196
|
+
|
|
197
|
+
while (Date.now() - startTime < timeout) {
|
|
198
|
+
const result = await fn();
|
|
199
|
+
if (result !== null && result !== undefined) {
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
await this.wait(interval);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
throw new Error('Polling timed out');
|
|
206
|
+
}
|
|
207
|
+
}
|