playwriter 0.0.30 → 0.0.33

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/dist/resource.md DELETED
@@ -1,436 +0,0 @@
1
-
2
-
3
- You can also find `getByRole` to get elements on the page.
4
-
5
- ```javascript
6
- // Then use the information from the snapshot to click elements
7
- // For example, if snapshot shows: { "role": "button", "name": "Sign In" }
8
- await page.getByRole('button', { name: 'Sign In' }).click()
9
-
10
- // For a link with { "role": "link", "name": "About" }
11
- await page.getByRole('link', { name: 'About' }).click()
12
-
13
- // For a textbox with { "role": "textbox", "name": "Email" }
14
- await page.getByRole('textbox', { name: 'Email' }).fill('user@example.com')
15
-
16
- // For a heading with { "role": "heading", "name": "Welcome to Example.com" }
17
- const headingText = await page
18
- .getByRole('heading', { name: 'Welcome to Example.com' })
19
- .textContent()
20
- console.log('Heading text:', headingText)
21
- ```
22
-
23
- ### Complete Example: Find and Click Elements
24
-
25
- ```javascript
26
- await page.getByRole('button', { name: 'Submit Form' }).click()
27
- console.log('Clicked submit button')
28
-
29
- await page.waitForLoadState('networkidle')
30
- console.log('Form submitted successfully')
31
- ```
32
-
33
- ## Core Concepts
34
-
35
- ### Page and Context
36
-
37
- In Playwright, automation happens through a `page` object (representing a browser tab) and `context` (representing a browser session with cookies, storage, etc.).
38
-
39
- ```javascript
40
- // Assuming you have page and context already available
41
- const page = await context.newPage()
42
- ```
43
-
44
- ### Element Selection
45
-
46
- Playwright uses locators to find elements. The examples below show various selection methods:
47
-
48
- ```javascript
49
- // By role (recommended)
50
- await page.getByRole('button', { name: 'Submit' })
51
-
52
- // By text
53
- await page.getByText('Welcome')
54
-
55
- // By placeholder
56
- await page.getByPlaceholder('Enter email')
57
-
58
- // By label
59
- await page.getByLabel('Username')
60
-
61
- // By test id
62
- await page.getByTestId('submit-button')
63
-
64
- // By CSS selector
65
- await page.locator('.my-class')
66
-
67
- // By XPath
68
- await page.locator('//div[@class="content"]')
69
- ```
70
-
71
- ## Navigation
72
-
73
- ### Navigate to URL
74
-
75
- ```javascript
76
- await page.goto('https://example.com')
77
- // Wait for network idle (no requests for 500ms)
78
- await page.goto('https://example.com', { waitUntil: 'networkidle' })
79
- ```
80
-
81
- ### Navigate Back/Forward
82
-
83
- ```javascript
84
- // Go back to previous page
85
- await page.goBack()
86
-
87
- // Go forward to next page
88
- await page.goForward()
89
- ```
90
-
91
- ## Screenshots
92
-
93
- ### Take Screenshot
94
-
95
- ```javascript
96
- // Screenshot of viewport
97
- await page.screenshot({ path: 'screenshot.png' })
98
-
99
- // Full page screenshot
100
- await page.screenshot({ path: 'fullpage.png', fullPage: true })
101
-
102
- // Screenshot of specific element
103
- const element = await page.getByRole('button', { name: 'Submit' })
104
- await element.screenshot({ path: 'button.png' })
105
-
106
- // Screenshot with custom dimensions
107
- await page.setViewportSize({ width: 1280, height: 720 })
108
- await page.screenshot({ path: 'custom-size.png' })
109
- ```
110
-
111
- ## Mouse Interactions
112
-
113
- ### Click Elements
114
-
115
- ```javascript
116
- // Click by role
117
- await page.getByRole('button', { name: 'Submit' }).click()
118
-
119
- // Click at coordinates
120
- await page.mouse.click(100, 200)
121
-
122
- // Double click
123
- await page.getByText('Double click me').dblclick()
124
-
125
- // Right click
126
- await page.getByText('Right click me').click({ button: 'right' })
127
-
128
- // Click with modifiers
129
- await page.getByText('Ctrl click me').click({ modifiers: ['Control'] })
130
- ```
131
-
132
- ### Hover
133
-
134
- ```javascript
135
- // Hover over element
136
- await page.getByText('Hover me').hover()
137
-
138
- // Hover at coordinates
139
- await page.mouse.move(100, 200)
140
- ```
141
-
142
- ## Keyboard Input
143
-
144
- ### Type Text
145
-
146
- ```javascript
147
- // Type into input field
148
- await page.getByLabel('Email').fill('user@example.com')
149
-
150
- // Type character by character (simulates real typing)
151
- await page.getByLabel('Email').type('user@example.com', { delay: 100 })
152
-
153
- // Clear and type
154
- await page.getByLabel('Email').clear()
155
- await page.getByLabel('Email').fill('new@example.com')
156
- ```
157
-
158
- ### Press Keys
159
-
160
- ```javascript
161
- // Press single key
162
- await page.keyboard.press('Enter')
163
-
164
- // Press key combination
165
- await page.keyboard.press('Control+A')
166
-
167
- // Press sequence of keys
168
- await page.keyboard.press('Tab')
169
- await page.keyboard.press('Tab')
170
- await page.keyboard.press('Space')
171
-
172
- // Common key shortcuts
173
- await page.keyboard.press('Control+C') // Copy
174
- await page.keyboard.press('Control+V') // Paste
175
- await page.keyboard.press('Control+Z') // Undo
176
- ```
177
-
178
- ## Form Interactions
179
-
180
- ### Select Dropdown Options
181
-
182
- ```javascript
183
- // Select by value
184
- await page.selectOption('select#country', 'us')
185
-
186
- // Select by label
187
- await page.selectOption('select#country', { label: 'United States' })
188
-
189
- // Select multiple options
190
- await page.selectOption('select#colors', ['red', 'blue', 'green'])
191
-
192
- // Get selected option
193
- const selectedValue = await page.$eval('select#country', (el) => el.value)
194
- ```
195
-
196
- ### Checkboxes and Radio Buttons
197
-
198
- ```javascript
199
- // Check checkbox
200
- await page.getByLabel('I agree').check()
201
-
202
- // Uncheck checkbox
203
- await page.getByLabel('Subscribe').uncheck()
204
-
205
- // Check if checked
206
- const isChecked = await page.getByLabel('I agree').isChecked()
207
-
208
- // Select radio button
209
- await page.getByLabel('Option A').check()
210
- ```
211
-
212
- ## JavaScript Evaluation
213
-
214
- ### Execute JavaScript in Page Context
215
-
216
- ```javascript
217
- // Evaluate simple expression
218
- const result = await page.evaluate(() => 2 + 2)
219
-
220
- // Access page variables
221
- const pageTitle = await page.evaluate(() => document.title)
222
-
223
- // Modify page
224
- await page.evaluate(() => {
225
- document.body.style.backgroundColor = 'red'
226
- })
227
-
228
- // Pass arguments to page context
229
- const sum = await page.evaluate(([a, b]) => a + b, [5, 3])
230
-
231
- // Work with elements
232
- const elementText = await page.evaluate(
233
- (el) => el.textContent,
234
- await page.getByRole('heading'),
235
- )
236
- ```
237
-
238
- ### Execute JavaScript on Element
239
-
240
- ```javascript
241
- // Get element property
242
- const href = await page.getByRole('link').evaluate((el) => el.href)
243
-
244
- // Modify element
245
- await page.getByRole('button').evaluate((el) => {
246
- el.style.backgroundColor = 'green'
247
- el.disabled = true
248
- })
249
-
250
- // Scroll element into view
251
- await page.getByText('Section').evaluate((el) => el.scrollIntoView())
252
- ```
253
-
254
- ## File Handling
255
-
256
- ### File Upload
257
-
258
- ```javascript
259
- // Upload single file
260
- await page.getByLabel('Upload file').setInputFiles('/path/to/file.pdf')
261
-
262
- // Upload multiple files
263
- await page
264
- .getByLabel('Upload files')
265
- .setInputFiles(['/path/to/file1.pdf', '/path/to/file2.pdf'])
266
-
267
- // Clear file input
268
- await page.getByLabel('Upload file').setInputFiles([])
269
-
270
- // For file inputs, use setInputFiles directly on the input element
271
- // Find the file input element (often hidden)
272
- await page.locator('input[type="file"]').setInputFiles('/path/to/file.pdf')
273
- ```
274
-
275
- ## Network Monitoring
276
-
277
- ### Check Network Activity
278
-
279
- ```javascript
280
- // Wait for a specific request to complete and get its response
281
- const response = await page.waitForResponse(
282
- (response) =>
283
- response.url().includes('/api/user') && response.status() === 200,
284
- )
285
-
286
- // Get response data
287
- const responseBody = await response.json()
288
- console.log('API response:', responseBody)
289
-
290
- // Wait for specific request
291
- const request = await page.waitForRequest('**/api/data')
292
- console.log('Request URL:', request.url())
293
- console.log('Request method:', request.method())
294
-
295
- // Get all resources loaded by the page
296
- const resources = await page.evaluate(() =>
297
- performance.getEntriesByType('resource').map((r) => ({
298
- name: r.name,
299
- duration: r.duration,
300
- size: r.transferSize,
301
- })),
302
- )
303
- console.log('Page resources:', resources)
304
- ```
305
-
306
- ## Console Messages
307
-
308
- ### Capture Console Output
309
-
310
- ```javascript
311
- // Console messages are automatically captured by the MCP implementation
312
- // Use the console_logs tool to retrieve them
313
-
314
- // To trigger console messages from the page:
315
- await page.evaluate(() => {
316
- console.log('This message will be captured')
317
- console.error('This error will be captured')
318
- console.warn('This warning will be captured')
319
- })
320
-
321
- // Then use the console_logs MCP tool to retrieve all captured messages
322
- // The tool provides filtering by type and pagination
323
- ```
324
-
325
- ## Waiting
326
-
327
- ### Wait for Conditions
328
-
329
- ```javascript
330
- // Wait for element to appear
331
- await page.waitForSelector('.success-message')
332
-
333
- // Wait for element to disappear
334
- await page.waitForSelector('.loading', { state: 'hidden' })
335
-
336
- await page.waitForURL(/github\.com.*\/pull/)
337
- await page.waitForURL(/\/new-org/)
338
-
339
- // Wait for text to appear
340
- await page.waitForFunction(
341
- (text) => document.body.textContent.includes(text),
342
- 'Success!',
343
- )
344
-
345
- // Wait for navigation
346
- await page.waitForURL('**/success')
347
-
348
- // Wait for page load
349
- await page.waitForLoadState('networkidle')
350
-
351
- // Wait for specific condition
352
- await page.waitForFunction(
353
- (text) => document.querySelector('.status')?.textContent === text,
354
- 'Ready',
355
- )
356
- ```
357
-
358
- ### Wait for Text to Appear or Disappear
359
-
360
- ```javascript
361
- // Wait for specific text to appear on the page
362
- await page.getByText('Loading complete').first().waitFor({ state: 'visible' })
363
- console.log('Loading complete text is now visible')
364
-
365
- // Wait for text to disappear from the page
366
- await page.getByText('Loading...').first().waitFor({ state: 'hidden' })
367
- console.log('Loading text has disappeared')
368
-
369
- // Wait for multiple conditions sequentially
370
- // First wait for loading to disappear, then wait for success message
371
- await page.getByText('Processing...').first().waitFor({ state: 'hidden' })
372
- await page.getByText('Success!').first().waitFor({ state: 'visible' })
373
- console.log('Processing finished and success message appeared')
374
-
375
- // Example: Wait for error message to disappear before proceeding
376
- await page
377
- .getByText('Error: Please try again')
378
- .first()
379
- .waitFor({ state: 'hidden' })
380
- await page.getByRole('button', { name: 'Submit' }).click()
381
-
382
- // Example: Wait for confirmation text after form submission
383
- await page.getByRole('button', { name: 'Save' }).click()
384
- await page
385
- .getByText('Your changes have been saved')
386
- .first()
387
- .waitFor({ state: 'visible' })
388
- console.log('Save confirmed')
389
-
390
- // Example: Wait for dynamic content to load
391
- await page.getByRole('button', { name: 'Load More' }).click()
392
- await page
393
- .getByText('Loading more items...')
394
- .first()
395
- .waitFor({ state: 'visible' })
396
- await page
397
- .getByText('Loading more items...')
398
- .first()
399
- .waitFor({ state: 'hidden' })
400
- console.log('Additional items loaded')
401
- ```
402
-
403
- ### Work with Frames
404
-
405
- ```javascript
406
- // Get frame by name
407
- const frame = page.frame('frameName')
408
-
409
- // Get frame by URL
410
- const frame = page.frame({ url: /frame\.html/ })
411
-
412
- // Interact with frame content
413
- await frame.getByText('In Frame').click()
414
-
415
- // Get all frames
416
- const frames = page.frames()
417
- ```
418
-
419
- ## Best Practices
420
-
421
- ### Reliable Selectors
422
-
423
- ```javascript
424
- // Prefer user-facing attributes
425
- await page.getByRole('button', { name: 'Submit' })
426
- await page.getByLabel('Email')
427
- await page.getByPlaceholder('Search...')
428
- await page.getByText('Welcome')
429
-
430
- // Use test IDs for complex cases
431
- await page.getByTestId('complex-component')
432
-
433
- // Avoid brittle selectors
434
- // Bad: await page.locator('.btn-3842');
435
- // Good: await page.getByRole('button', { name: 'Submit' });
436
- ```