thaievisa commited on
Commit
6f8b81c
·
verified ·
1 Parent(s): fb00e00

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +691 -19
index.html CHANGED
@@ -1,19 +1,691 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Playwright Python showcase</title>
7
+
8
+ <!-- Import Phosphor Icons for modern iconography -->
9
+ <script src="https://unpkg.com/@phosphor-icons/web"></script>
10
+
11
+ <style>
12
+ /* --- CSS Variables & Reset --- */
13
+ :root {
14
+ --bg-body: #0f172a;
15
+ --bg-card: #1e293b;
16
+ --bg-code: #0d1117;
17
+ --primary: #22d3ee;
18
+ --secondary: #818cf8;
19
+ --accent: #2ea043;
20
+ --text-main: #f8fafc;
21
+ --text-muted: #94a3b8;
22
+ --border: #334155;
23
+ --font-main: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
24
+ --font-code: 'Fira Code', 'Courier New', monospace;
25
+ --radius: 12px;
26
+ --shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3);
27
+ }
28
+
29
+ * {
30
+ box-sizing: border-box;
31
+ margin: 0;
32
+ padding: 0;
33
+ }
34
+
35
+ html {
36
+ scroll-behavior: smooth;
37
+ }
38
+
39
+ body {
40
+ font-family: var(--font-main);
41
+ background-color: var(--bg-body);
42
+ color: var(--text-main);
43
+ line-height: 1.6;
44
+ overflow-x: hidden;
45
+ }
46
+
47
+ a {
48
+ text-decoration: none;
49
+ color: inherit;
50
+ transition: color 0.2s;
51
+ }
52
+
53
+ ul {
54
+ list-style: none;
55
+ }
56
+
57
+ /* --- Header --- */
58
+ header {
59
+ position: fixed;
60
+ top: 0;
61
+ width: 100%;
62
+ background: rgba(15, 23, 42, 0.85);
63
+ backdrop-filter: blur(10px);
64
+ border-bottom: 1px solid var(--border);
65
+ z-index: 1000;
66
+ padding: 1rem 0;
67
+ }
68
+
69
+ .container {
70
+ max-width: 1200px;
71
+ margin: 0 auto;
72
+ padding: 0 1.5rem;
73
+ }
74
+
75
+ .nav-wrapper {
76
+ display: flex;
77
+ justify-content: space-between;
78
+ align-items: center;
79
+ }
80
+
81
+ .logo {
82
+ font-size: 1.5rem;
83
+ font-weight: 700;
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 0.5rem;
87
+ color: var(--text-main);
88
+ }
89
+
90
+ .logo i {
91
+ color: var(--primary);
92
+ font-size: 1.8rem;
93
+ }
94
+
95
+ .brand-link {
96
+ font-size: 0.9rem;
97
+ color: var(--text-muted);
98
+ font-weight: 500;
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 0.4rem;
102
+ padding: 0.5rem 1rem;
103
+ border-radius: 20px;
104
+ background: rgba(255, 255, 255, 0.05);
105
+ border: 1px solid var(--border);
106
+ transition: all 0.3s ease;
107
+ }
108
+
109
+ .brand-link:hover {
110
+ background: rgba(34, 211, 238, 0.1);
111
+ color: var(--primary);
112
+ border-color: var(--primary);
113
+ }
114
+
115
+ /* --- Hero Section --- */
116
+ .hero {
117
+ padding: 8rem 0 4rem;
118
+ text-align: center;
119
+ position: relative;
120
+ }
121
+
122
+ .hero::before {
123
+ content: '';
124
+ position: absolute;
125
+ top: -100px;
126
+ left: 50%;
127
+ transform: translateX(-50%);
128
+ width: 600px;
129
+ height: 400px;
130
+ background: radial-gradient(circle, rgba(34, 211, 238, 0.15) 0%, rgba(15, 23, 42, 0) 70%);
131
+ z-index: -1;
132
+ pointer-events: none;
133
+ }
134
+
135
+ .hero h1 {
136
+ font-size: clamp(2.5rem, 5vw, 4rem);
137
+ font-weight: 800;
138
+ margin-bottom: 1.5rem;
139
+ background: linear-gradient(to right, var(--primary), var(--secondary));
140
+ -webkit-background-clip: text;
141
+ -webkit-text-fill-color: transparent;
142
+ letter-spacing: -0.02em;
143
+ }
144
+
145
+ .hero p {
146
+ font-size: 1.25rem;
147
+ color: var(--text-muted);
148
+ max-width: 700px;
149
+ margin: 0 auto 2.5rem;
150
+ }
151
+
152
+ .btn {
153
+ display: inline-flex;
154
+ align-items: center;
155
+ gap: 0.5rem;
156
+ padding: 0.75rem 2rem;
157
+ border-radius: 50px;
158
+ font-weight: 600;
159
+ transition: transform 0.2s, box-shadow 0.2s;
160
+ cursor: pointer;
161
+ }
162
+
163
+ .btn-primary {
164
+ background: var(--primary);
165
+ color: var(--bg-body);
166
+ box-shadow: 0 0 20px rgba(34, 211, 238, 0.3);
167
+ }
168
+
169
+ .btn-primary:hover {
170
+ transform: translateY(-2px);
171
+ box-shadow: 0 0 30px rgba(34, 211, 238, 0.5);
172
+ }
173
+
174
+ /* --- Features Grid --- */
175
+ .features {
176
+ padding: 4rem 0;
177
+ }
178
+
179
+ .grid {
180
+ display: grid;
181
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
182
+ gap: 2rem;
183
+ }
184
+
185
+ .card {
186
+ background: var(--bg-card);
187
+ border: 1px solid var(--border);
188
+ padding: 2rem;
189
+ border-radius: var(--radius);
190
+ transition: transform 0.3s ease, border-color 0.3s ease;
191
+ }
192
+
193
+ .card:hover {
194
+ transform: translateY(-5px);
195
+ border-color: var(--primary);
196
+ }
197
+
198
+ .card-icon {
199
+ font-size: 2rem;
200
+ color: var(--secondary);
201
+ margin-bottom: 1rem;
202
+ }
203
+
204
+ .card h3 {
205
+ font-size: 1.25rem;
206
+ margin-bottom: 0.75rem;
207
+ }
208
+
209
+ .card p {
210
+ color: var(--text-muted);
211
+ font-size: 0.95rem;
212
+ }
213
+
214
+ /* --- Code Showcase Section --- */
215
+ .showcase {
216
+ padding: 4rem 0;
217
+ }
218
+
219
+ .section-header {
220
+ text-align: center;
221
+ margin-bottom: 3rem;
222
+ }
223
+
224
+ .section-header h2 {
225
+ font-size: 2.5rem;
226
+ margin-bottom: 0.5rem;
227
+ }
228
+
229
+ /* Tab System */
230
+ .tabs-wrapper {
231
+ background: var(--bg-card);
232
+ border-radius: var(--radius);
233
+ border: 1px solid var(--border);
234
+ overflow: hidden;
235
+ box-shadow: var(--shadow);
236
+ }
237
+
238
+ .tabs-header {
239
+ display: flex;
240
+ background: rgba(0,0,0,0.2);
241
+ border-bottom: 1px solid var(--border);
242
+ overflow-x: auto;
243
+ }
244
+
245
+ .tab-btn {
246
+ background: transparent;
247
+ border: none;
248
+ color: var(--text-muted);
249
+ padding: 1rem 1.5rem;
250
+ font-size: 0.95rem;
251
+ font-weight: 600;
252
+ cursor: pointer;
253
+ border-bottom: 2px solid transparent;
254
+ transition: all 0.3s;
255
+ white-space: nowrap;
256
+ display: flex;
257
+ align-items: center;
258
+ gap: 0.5rem;
259
+ }
260
+
261
+ .tab-btn:hover {
262
+ color: var(--text-main);
263
+ background: rgba(255,255,255,0.03);
264
+ }
265
+
266
+ .tab-btn.active {
267
+ color: var(--primary);
268
+ border-bottom-color: var(--primary);
269
+ background: rgba(34, 211, 238, 0.05);
270
+ }
271
+
272
+ .tab-content {
273
+ display: none;
274
+ padding: 1.5rem;
275
+ position: relative;
276
+ }
277
+
278
+ .tab-content.active {
279
+ display: block;
280
+ animation: fadeIn 0.3s ease-in-out;
281
+ }
282
+
283
+ @keyframes fadeIn {
284
+ from { opacity: 0; transform: translateY(5px); }
285
+ to { opacity: 1; transform: translateY(0); }
286
+ }
287
+
288
+ /* Code Window Styling */
289
+ .code-window {
290
+ background: var(--bg-code);
291
+ border-radius: 8px;
292
+ border: 1px solid var(--border);
293
+ font-family: var(--font-code);
294
+ font-size: 0.9rem;
295
+ overflow: hidden;
296
+ position: relative;
297
+ }
298
+
299
+ .window-header {
300
+ background: rgba(255,255,255,0.05);
301
+ padding: 0.5rem 1rem;
302
+ display: flex;
303
+ justify-content: space-between;
304
+ align-items: center;
305
+ border-bottom: 1px solid var(--border);
306
+ }
307
+
308
+ .window-controls {
309
+ display: flex;
310
+ gap: 6px;
311
+ }
312
+
313
+ .control {
314
+ width: 10px;
315
+ height: 10px;
316
+ border-radius: 50%;
317
+ }
318
+
319
+ .red { background: #ff5f56; }
320
+ .yellow { background: #ffbd2e; }
321
+ .green { background: #27c93f; }
322
+
323
+ .filename {
324
+ color: var(--text-muted);
325
+ font-size: 0.8rem;
326
+ }
327
+
328
+ .copy-btn {
329
+ background: transparent;
330
+ border: 1px solid var(--border);
331
+ color: var(--text-muted);
332
+ padding: 4px 8px;
333
+ border-radius: 4px;
334
+ font-size: 0.75rem;
335
+ cursor: pointer;
336
+ transition: all 0.2s;
337
+ }
338
+
339
+ .copy-btn:hover {
340
+ color: var(--text-main);
341
+ border-color: var(--text-main);
342
+ }
343
+
344
+ .code-body {
345
+ padding: 1.5rem;
346
+ overflow-x: auto;
347
+ color: #e6edf3;
348
+ }
349
+
350
+ /* Syntax Highlighting Colors */
351
+ .k { color: #ff7b72; } /* Keyword */
352
+ .f { color: #d2a8ff; } /* Function */
353
+ .s { color: #a5d6ff; } /* String */
354
+ .c { color: #8b949e; font-style: italic; } /* Comment */
355
+ .n { color: #79c0ff; } /* Number/Class */
356
+ .o { color: #ff7b72; } /* Operator */
357
+
358
+ /* --- Installation Section --- */
359
+ .install {
360
+ padding: 4rem 0;
361
+ background: linear-gradient(to bottom, var(--bg-body), #0b1120);
362
+ }
363
+
364
+ .install-box {
365
+ background: var(--bg-card);
366
+ border: 1px solid var(--accent);
367
+ padding: 2rem;
368
+ border-radius: var(--radius);
369
+ text-align: center;
370
+ max-width: 600px;
371
+ margin: 0 auto;
372
+ }
373
+
374
+ .install-cmd {
375
+ display: inline-block;
376
+ background: rgba(0,0,0,0.3);
377
+ padding: 0.5rem 1rem;
378
+ border-radius: 6px;
379
+ font-family: var(--font-code);
380
+ color: var(--primary);
381
+ margin: 1rem 0;
382
+ border: 1px dashed var(--border);
383
+ }
384
+
385
+ /* --- Footer --- */
386
+ footer {
387
+ border-top: 1px solid var(--border);
388
+ padding: 2rem 0;
389
+ text-align: center;
390
+ color: var(--text-muted);
391
+ font-size: 0.9rem;
392
+ }
393
+
394
+ /* --- Responsive Tweaks --- */
395
+ @media (max-width: 768px) {
396
+ .hero h1 {
397
+ font-size: 2.5rem;
398
+ }
399
+ .nav-wrapper {
400
+ flex-direction: column;
401
+ gap: 1rem;
402
+ }
403
+ .tabs-header {
404
+ padding-bottom: 0.5rem;
405
+ }
406
+ }
407
+ </style>
408
+ </head>
409
+ <body>
410
+
411
+ <!-- Header -->
412
+ <header>
413
+ <div class="container nav-wrapper">
414
+ <div class="logo">
415
+ <i class="ph ph-play-circle"></i>
416
+ <span>Playwright<span style="color:var(--text-muted)">.Py</span></span>
417
+ </div>
418
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="brand-link">
419
+ Built with anycoder <i class="ph ph-arrow-square-out"></i>
420
+ </a>
421
+ </div>
422
+ </header>
423
+
424
+ <main>
425
+ <!-- Hero Section -->
426
+ <section class="hero container">
427
+ <h1>Fast, Reliable & Modern<br>Web Automation</h1>
428
+ <p>Playwright enables reliable end-to-end testing for modern web apps. This page demonstrates core capabilities using Python.</p>
429
+ <a href="#samples" class="btn btn-primary">
430
+ View Code Samples <i class="ph ph-code"></i>
431
+ </a>
432
+ </section>
433
+
434
+ <!-- Features Grid -->
435
+ <section class="features container">
436
+ <div class="grid">
437
+ <div class="card">
438
+ <div class="card-icon"><i class="ph ph-lightning"></i></div>
439
+ <h3>Fast Execution</h3>
440
+ <p>Parallelize tests with zero configuration. Playwright runs tests in parallel across all browsers.</p>
441
+ </div>
442
+ <div class="card">
443
+ <div class="card-icon"><i class="ph ph-crosshair"></i></div>
444
+ <h3>Auto-Waiting</h3>
445
+ <p>No more flaky tests. Playwright waits for elements to be actionable before executing actions.</p>
446
+ </div>
447
+ <div class="card">
448
+ <div class="card-icon"><i class="ph ph-browsers"></i></div>
449
+ <h3>Cross-Browser</h3>
450
+ <p>Test on Chromium, Firefox, and WebKit (Safari) with a single API on Windows, Linux, and macOS.</p>
451
+ </div>
452
+ </div>
453
+ </section>
454
+
455
+ <!-- Code Samples Section -->
456
+ <section id="samples" class="showcase container">
457
+ <div class="section-header">
458
+ <h2>Python Code Samples</h2>
459
+ <p style="color: var(--text-muted)">Click on the tabs to explore different Playwright capabilities.</p>
460
+ </div>
461
+
462
+ <div class="tabs-wrapper">
463
+ <!-- Tabs Header -->
464
+ <div class="tabs-header">
465
+ <button class="tab-btn active" onclick="openTab(event, 'basic')">
466
+ <i class="ph ph-file-code"></i> Basic Script
467
+ </button>
468
+ <button class="tab-btn" onclick="openTab(event, 'locators')">
469
+ <i class="ph ph-crosshair-simple"></i> Locators
470
+ </button>
471
+ <button class="tab-btn" onclick="openTab(event, 'assertions')">
472
+ <i class="ph ph-check-circle"></i> Assertions
473
+ </button>
474
+ <button class="tab-btn" onclick="openTab(event, 'trace-viewer')">
475
+ <i class="ph ph-film-strip"></i> Trace Viewer
476
+ </button>
477
+ </div>
478
+
479
+ <!-- Tab Content: Basic Script -->
480
+ <div id="basic" class="tab-content active">
481
+ <p style="margin-bottom: 1rem; color: var(--text-muted);">A simple synchronous script to launch a browser and take a screenshot.</p>
482
+ <div class="code-window">
483
+ <div class="window-header">
484
+ <div class="window-controls">
485
+ <div class="control red"></div>
486
+ <div class="control yellow"></div>
487
+ <div class="control green"></div>
488
+ </div>
489
+ <div class="filename">example_basic.py</div>
490
+ <button class="copy-btn" onclick="copyCode(this)">Copy</button>
491
+ </div>
492
+ <div class="code-body">
493
+ <pre><code><span class="k">from</span> playwright.sync_api <span class="k">import</span> sync_playwright
494
+
495
+ <span class="k">with</span> sync_playwright() <span class="k">as</span> p:
496
+ <span class="c"># Launch browser (headless=False to see UI)</span>
497
+ browser <span class="o">=</span> p.chromium.launch(headless<span class="o">=</span><span class="n">False</span>)
498
+ page <span class="o">=</span> browser.new_page()
499
+
500
+ <span class="c"># Navigate to URL</span>
501
+ page.<span class="f">goto</span>(<span class="s">"https://playwright.dev/python"</span>)
502
+
503
+ <span class="c"># Interact with page</span>
504
+ print(page.<span class="f">title</span>())
505
+
506
+ <span class="c"># Screenshot</span>
507
+ page.<span class="f">screenshot</span>(path<span class="o">=</span><span class="s">"example.png"</span>)
508
+
509
+ browser.<span class="f">close</span>()</code></pre>
510
+ </div>
511
+ </div>
512
+ </div>
513
+
514
+ <!-- Tab Content: Locators -->
515
+ <div id="locators" class="tab-content">
516
+ <p style="margin-bottom: 1rem; color: var(--text-muted);">Using robust Locators to find elements on the page.</p>
517
+ <div class="code-window">
518
+ <div class="window-header">
519
+ <div class="window-controls">
520
+ <div class="control red"></div>
521
+ <div class="control yellow"></div>
522
+ <div class="control green"></div>
523
+ </div>
524
+ <div class="filename">locators.py</div>
525
+ <button class="copy-btn" onclick="copyCode(this)">Copy</button>
526
+ </div>
527
+ <div class="code-body">
528
+ <pre><code><span class="k">from</span> playwright.sync_api <span class="k">import</span> sync_playwright
529
+
530
+ <span class="k">with</span> sync_playwright() <span class="k">as</span> p:
531
+ browser <span class="o">=</span> p.chromium.launch()
532
+ page <span class="o">=</span> browser.new_page()
533
+ page.<span class="f">goto</span>(<span class="s">"https://example.com"</span>)
534
+
535
+ <span class="c"># Get by role (most accessible)</span>
536
+ get_started <span class="o">=</span> page.<span class="f">get_by_role</span>(<span class="s">"link"</span>, name<span class="o">=</span><span class="s">"Get Started"</span>)
537
+
538
+ <span class="c"># Get by text content</span>
539
+ submit <span class="o">=</span> page.<span class="f">get_by_text</span>(<span class="s">"Submit"</span>)
540
+
541
+ <span class="c"># Get by test ID (recommended for CSS changes)</span>
542
+ submit <span class="o">=</span> page.<span class="f">get_by_test_id</span>(<span class="s">"auth-button"</span>)
543
+
544
+ <span class="c"># Chain locators</span>
545
+ product <span class="o">=</span> page.locator(<span class="s">".list"</span>).<span class="f">get_by_text</span>(<span class="s">"Playwright"</span>)
546
+
547
+ browser.<span class="f">close</span>()</code></pre>
548
+ </div>
549
+ </div>
550
+ </div>
551
+
552
+ <!-- Tab Content: Assertions -->
553
+ <div id="assertions" class="tab-content">
554
+ <p style="margin-bottom: 1rem; color: var(--text-muted);">Built-in assertions to wait for conditions automatically.</p>
555
+ <div class="code-window">
556
+ <div class="window-header">
557
+ <div class="window-controls">
558
+ <div class="control red"></div>
559
+ <div class="control yellow"></div>
560
+ <div class="control green"></div>
561
+ </div>
562
+ <div class="filename">assertions.py</div>
563
+ <button class="copy-btn" onclick="copyCode(this)">Copy</button>
564
+ </div>
565
+ <div class="code-body">
566
+ <pre><code><span class="k">from</span> playwright.sync_api <span class="k">import</span> expect
567
+
568
+ <span class="c"># Navigating and waiting for URL</span>
569
+ page.<span class="f">goto</span>(<span class="s">"https://example.com"</span>)
570
+ <span class="f">expect</span>(page).<span class="f">to_have_url</span>(<span class="s">"https://example.com/"</span>)
571
+
572
+ <span class="c"># Checking element visibility</span>
573
+ locator <span class="o">=</span> page.locator(<span class="s">".status-message"</span>)
574
+ <span class="f">expect</span>(locator).<span class="f">to_be_visible</span>()
575
+
576
+ <span class="c"># Checking text content</span>
577
+ <span class="f">expect</span>(locator).<span class="f">to_contain_text</span>(<span class="s">"Welcome"</span>)
578
+
579
+ <span class="c"># Checking attribute values</span>
580
+ button <span class="o">=</span> page.locator(<span class="s">"#submit"</span>)
581
+ <span class="f">expect</span>(button).<span class="f">to_have_attribute</span>(<span class="s">"type"</span>, <span class="s">"submit"</span>)</code></pre>
582
+ </div>
583
+ </div>
584
+ </div>
585
+
586
+ <!-- Tab Content: Trace Viewer -->
587
+ <div id="trace-viewer" class="tab-content">
588
+ <p style="margin-bottom: 1rem; color: var(--text-muted);">Capturing a trace to debug test failures visually.</p>
589
+ <div class="code-window">
590
+ <div class="window-header">
591
+ <div class="window-controls">
592
+ <div class="control red"></div>
593
+ <div class="control yellow"></div>
594
+ <div class="control green"></div>
595
+ </div>
596
+ <div class="filename">trace.py</div>
597
+ <button class="copy-btn" onclick="copyCode(this)">Copy</button>
598
+ </div>
599
+ <div class="code-body">
600
+ <pre><code><span class="c"># Start tracing before creating/running the browser</span>
601
+ context <span class="o">=</span> browser.new_context()
602
+ context.<span class="f">tracing</span>.<span class="f">start</span>(screenshots<span class="o">=</span><span class="n">True</span>, snapshots<span class="o">=</span><span class="n">True</span>)
603
+
604
+ page <span class="o">=</span> context.new_page()
605
+ page.<span class="f">goto</span>(<span class="s">"https://playwright.dev"</span>)
606
+
607
+ <span class="c"># ... perform actions ...</span>
608
+ page.<span class="f">click</span>(<span class="s">"text=Get Started"</span>)
609
+
610
+ <span class="c"># Stop tracing and save the file</span>
611
+ context.<span class="f">tracing</span>.<span class="f">stop</span>(path <span class="o">=</span> <span class="s">"trace.zip"</span>)
612
+
613
+ <span class="c"># View trace using CLI:</span>
614
+ <span class="c"># playwright show-trace trace.zip</span></code></pre>
615
+ </div>
616
+ </div>
617
+ </div>
618
+ </div>
619
+ </section>
620
+
621
+ <!-- Installation Section -->
622
+ <section id="install" class="install">
623
+ <div class="container">
624
+ <div class="install-box">
625
+ <h2 style="margin-bottom: 1rem;">Get Started Now</h2>
626
+ <p style="color: var(--text-muted);">Install Playwright via pip and install the required browsers.</p>
627
+
628
+ <div class="install-cmd">pip install playwright</div>
629
+ <div class="install-cmd">playwright install</div>
630
+
631
+ <a href="https://playwright.dev/python/docs/intro" target="_blank" class="btn btn-primary" style="background: var(--accent); margin-top: 1rem;">
632
+ Read Official Docs <i class="ph ph-book-open"></i>
633
+ </a>
634
+ </div>
635
+ </div>
636
+ </section>
637
+ </main>
638
+
639
+ <footer>
640
+ <div class="container">
641
+ <p>&copy; 2023 Playwright Python Showcase. Built for demonstration.</p>
642
+ </div>
643
+ </footer>
644
+
645
+ <script>
646
+ // Tab Functionality
647
+ function openTab(evt, tabName) {
648
+ // Hide all tab content
649
+ const tabContent = document.getElementsByClassName("tab-content");
650
+ for (let i = 0; i < tabContent.length; i++) {
651
+ tabContent[i].classList.remove("active");
652
+ }
653
+
654
+ // Remove active class from all buttons
655
+ const tabBtns = document.getElementsByClassName("tab-btn");
656
+ for (let i = 0; i < tabBtns.length; i++) {
657
+ tabBtns[i].classList.remove("active");
658
+ }
659
+
660
+ // Show current tab and add active class
661
+ document.getElementById(tabName).classList.add("active");
662
+ evt.currentTarget.classList.add("active");
663
+ }
664
+
665
+ // Copy Code Functionality
666
+ function copyCode(btnElement) {
667
+ // Find the code block within the same window
668
+ const codeWindow = btnElement.closest('.code-window');
669
+ const codeBlock = codeWindow.querySelector('code');
670
+ const textToCopy = codeBlock.innerText;
671
+
672
+ // Use Clipboard API
673
+ navigator.clipboard.writeText(textToCopy).then(() => {
674
+ // Visual feedback
675
+ const originalText = btnElement.innerText;
676
+ btnElement.innerText = "Copied!";
677
+ btnElement.style.color = "var(--accent)";
678
+ btnElement.style.borderColor = "var(--accent)";
679
+
680
+ setTimeout(() => {
681
+ btnElement.innerText = originalText;
682
+ btnElement.style.color = "";
683
+ btnElement.style.borderColor = "";
684
+ }, 2000);
685
+ }).catch(err => {
686
+ console.error('Failed to copy text: ', err);
687
+ });
688
+ }
689
+ </script>
690
+ </body>
691
+ </html>