container-superposition 0.1.1
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/README.md +843 -0
- package/dist/scripts/init.d.ts +3 -0
- package/dist/scripts/init.d.ts.map +1 -0
- package/dist/scripts/init.js +1190 -0
- package/dist/scripts/init.js.map +1 -0
- package/dist/scripts/migrate-to-manifests.d.ts +12 -0
- package/dist/scripts/migrate-to-manifests.d.ts.map +1 -0
- package/dist/scripts/migrate-to-manifests.js +230 -0
- package/dist/scripts/migrate-to-manifests.js.map +1 -0
- package/dist/tool/questionnaire/composer.d.ts +6 -0
- package/dist/tool/questionnaire/composer.d.ts.map +1 -0
- package/dist/tool/questionnaire/composer.js +1232 -0
- package/dist/tool/questionnaire/composer.js.map +1 -0
- package/dist/tool/readme/markdown-parser.d.ts +30 -0
- package/dist/tool/readme/markdown-parser.d.ts.map +1 -0
- package/dist/tool/readme/markdown-parser.js +139 -0
- package/dist/tool/readme/markdown-parser.js.map +1 -0
- package/dist/tool/readme/readme-generator.d.ts +9 -0
- package/dist/tool/readme/readme-generator.d.ts.map +1 -0
- package/dist/tool/readme/readme-generator.js +422 -0
- package/dist/tool/readme/readme-generator.js.map +1 -0
- package/dist/tool/schema/custom-loader.d.ts +17 -0
- package/dist/tool/schema/custom-loader.d.ts.map +1 -0
- package/dist/tool/schema/custom-loader.js +149 -0
- package/dist/tool/schema/custom-loader.js.map +1 -0
- package/dist/tool/schema/overlay-loader.d.ts +47 -0
- package/dist/tool/schema/overlay-loader.d.ts.map +1 -0
- package/dist/tool/schema/overlay-loader.js +252 -0
- package/dist/tool/schema/overlay-loader.js.map +1 -0
- package/dist/tool/schema/types.d.ts +212 -0
- package/dist/tool/schema/types.d.ts.map +1 -0
- package/dist/tool/schema/types.js +5 -0
- package/dist/tool/schema/types.js.map +1 -0
- package/docs/README.md +308 -0
- package/docs/architecture.md +233 -0
- package/docs/creating-overlays.md +549 -0
- package/docs/custom-patches.md +540 -0
- package/docs/dependencies.md +279 -0
- package/docs/examples/custom-patches-example.md +85 -0
- package/docs/examples.md +576 -0
- package/docs/messaging-comparison.md +265 -0
- package/docs/messaging-quick-start.md +385 -0
- package/docs/observability-workflow.md +537 -0
- package/docs/overlay-manifest-refactoring.md +214 -0
- package/docs/overlay-metadata-archive.md +54 -0
- package/docs/overlays.md +523 -0
- package/docs/presets-architecture.md +498 -0
- package/docs/presets.md +366 -0
- package/docs/publishing.md +476 -0
- package/docs/quick-reference.md +326 -0
- package/docs/ux.md +170 -0
- package/features/README.md +85 -0
- package/features/cross-distro-packages/README.md +146 -0
- package/features/cross-distro-packages/devcontainer-feature.json +20 -0
- package/features/cross-distro-packages/install.sh +58 -0
- package/features/local-secrets-manager/devcontainer-feature.json +18 -0
- package/features/local-secrets-manager/install.sh +127 -0
- package/features/project-scaffolder/devcontainer-feature.json +24 -0
- package/features/project-scaffolder/install.sh +100 -0
- package/features/team-conventions/devcontainer-feature.json +24 -0
- package/features/team-conventions/install.sh +93 -0
- package/overlays/.registry/README.md +14 -0
- package/overlays/.registry/base-images.yml +26 -0
- package/overlays/.registry/base-templates.yml +7 -0
- package/overlays/README.md +155 -0
- package/overlays/alertmanager/.env.example +5 -0
- package/overlays/alertmanager/README.md +465 -0
- package/overlays/alertmanager/alert-rules.yml +56 -0
- package/overlays/alertmanager/alertmanager.yml +42 -0
- package/overlays/alertmanager/devcontainer.patch.json +12 -0
- package/overlays/alertmanager/docker-compose.yml +20 -0
- package/overlays/alertmanager/overlay.yml +17 -0
- package/overlays/alertmanager/setup.sh +53 -0
- package/overlays/alertmanager/verify.sh +31 -0
- package/overlays/aws-cli/README.md +473 -0
- package/overlays/aws-cli/devcontainer.patch.json +13 -0
- package/overlays/aws-cli/overlay.yml +13 -0
- package/overlays/azure-cli/README.md +551 -0
- package/overlays/azure-cli/devcontainer.patch.json +8 -0
- package/overlays/azure-cli/overlay.yml +13 -0
- package/overlays/bun/README.md +312 -0
- package/overlays/bun/devcontainer.patch.json +41 -0
- package/overlays/bun/overlay.yml +16 -0
- package/overlays/bun/setup.sh +79 -0
- package/overlays/bun/verify.sh +30 -0
- package/overlays/codex/README.md +128 -0
- package/overlays/codex/devcontainer.patch.json +3 -0
- package/overlays/codex/overlay.yml +14 -0
- package/overlays/codex/setup.sh +24 -0
- package/overlays/codex/verify.sh +30 -0
- package/overlays/commitlint/README.md +333 -0
- package/overlays/commitlint/devcontainer.patch.json +8 -0
- package/overlays/commitlint/overlay.yml +16 -0
- package/overlays/commitlint/setup.sh +234 -0
- package/overlays/direnv/README.md +504 -0
- package/overlays/direnv/devcontainer.patch.json +6 -0
- package/overlays/direnv/overlay.yml +13 -0
- package/overlays/direnv/setup.sh +139 -0
- package/overlays/docker-in-docker/README.md +534 -0
- package/overlays/docker-in-docker/devcontainer.patch.json +10 -0
- package/overlays/docker-in-docker/overlay.yml +13 -0
- package/overlays/docker-sock/README.md +256 -0
- package/overlays/docker-sock/devcontainer.patch.json +9 -0
- package/overlays/docker-sock/docker-compose.yml +8 -0
- package/overlays/docker-sock/overlay.yml +13 -0
- package/overlays/dotnet/README.md +147 -0
- package/overlays/dotnet/devcontainer.patch.json +51 -0
- package/overlays/dotnet/global-tools.txt +24 -0
- package/overlays/dotnet/overlay.yml +13 -0
- package/overlays/dotnet/setup.sh +51 -0
- package/overlays/dotnet/verify.sh +26 -0
- package/overlays/gcloud/README.md +269 -0
- package/overlays/gcloud/devcontainer.patch.json +14 -0
- package/overlays/gcloud/overlay.yml +14 -0
- package/overlays/gcloud/verify.sh +52 -0
- package/overlays/git-helpers/README.md +168 -0
- package/overlays/git-helpers/devcontainer.patch.json +33 -0
- package/overlays/git-helpers/overlay.yml +15 -0
- package/overlays/git-helpers/setup.sh +91 -0
- package/overlays/go/README.md +293 -0
- package/overlays/go/devcontainer.patch.json +43 -0
- package/overlays/go/overlay.yml +15 -0
- package/overlays/go/setup.sh +33 -0
- package/overlays/go/verify.sh +40 -0
- package/overlays/grafana/.env.example +9 -0
- package/overlays/grafana/README.md +462 -0
- package/overlays/grafana/dashboard-provider.yml +11 -0
- package/overlays/grafana/dashboards/observability-overview.json +263 -0
- package/overlays/grafana/devcontainer.patch.json +12 -0
- package/overlays/grafana/docker-compose.yml +27 -0
- package/overlays/grafana/grafana-datasources.yml +57 -0
- package/overlays/grafana/overlay.yml +21 -0
- package/overlays/grafana/verify.sh +34 -0
- package/overlays/jaeger/.env.example +7 -0
- package/overlays/jaeger/README.md +867 -0
- package/overlays/jaeger/devcontainer.patch.json +12 -0
- package/overlays/jaeger/docker-compose.yml +17 -0
- package/overlays/jaeger/overlay.yml +19 -0
- package/overlays/java/README.md +267 -0
- package/overlays/java/devcontainer.patch.json +44 -0
- package/overlays/java/overlay.yml +16 -0
- package/overlays/java/setup.sh +41 -0
- package/overlays/java/verify.sh +42 -0
- package/overlays/just/README.md +443 -0
- package/overlays/just/devcontainer.patch.json +3 -0
- package/overlays/just/overlay.yml +13 -0
- package/overlays/just/setup.sh +182 -0
- package/overlays/kubectl-helm/README.md +660 -0
- package/overlays/kubectl-helm/devcontainer.patch.json +10 -0
- package/overlays/kubectl-helm/overlay.yml +13 -0
- package/overlays/loki/.env.example +5 -0
- package/overlays/loki/README.md +1156 -0
- package/overlays/loki/devcontainer.patch.json +12 -0
- package/overlays/loki/docker-compose.yml +18 -0
- package/overlays/loki/loki-config.yaml +45 -0
- package/overlays/loki/overlay.yml +17 -0
- package/overlays/minio/.env.example +9 -0
- package/overlays/minio/README.md +639 -0
- package/overlays/minio/devcontainer.patch.json +30 -0
- package/overlays/minio/docker-compose.yml +28 -0
- package/overlays/minio/overlay.yml +18 -0
- package/overlays/minio/setup.sh +61 -0
- package/overlays/minio/verify.sh +64 -0
- package/overlays/mkdocs/README.md +309 -0
- package/overlays/mkdocs/devcontainer.patch.json +24 -0
- package/overlays/mkdocs/overlay.yml +15 -0
- package/overlays/modern-cli-tools/README.md +556 -0
- package/overlays/modern-cli-tools/devcontainer.patch.json +3 -0
- package/overlays/modern-cli-tools/overlay.yml +13 -0
- package/overlays/modern-cli-tools/setup.sh +153 -0
- package/overlays/mongodb/.env.example +9 -0
- package/overlays/mongodb/README.md +481 -0
- package/overlays/mongodb/devcontainer.patch.json +32 -0
- package/overlays/mongodb/docker-compose.yml +44 -0
- package/overlays/mongodb/overlay.yml +17 -0
- package/overlays/mongodb/verify.sh +48 -0
- package/overlays/mysql/.env.example +11 -0
- package/overlays/mysql/README.md +542 -0
- package/overlays/mysql/devcontainer.patch.json +34 -0
- package/overlays/mysql/docker-compose.yml +55 -0
- package/overlays/mysql/overlay.yml +16 -0
- package/overlays/mysql/verify.sh +48 -0
- package/overlays/nats/.env.example +5 -0
- package/overlays/nats/README.md +762 -0
- package/overlays/nats/devcontainer.patch.json +24 -0
- package/overlays/nats/docker-compose.yml +31 -0
- package/overlays/nats/overlay.yml +18 -0
- package/overlays/nats/verify.sh +50 -0
- package/overlays/ngrok/README.md +503 -0
- package/overlays/ngrok/devcontainer.patch.json +3 -0
- package/overlays/ngrok/overlay.yml +14 -0
- package/overlays/ngrok/setup.sh +125 -0
- package/overlays/nodejs/README.md +192 -0
- package/overlays/nodejs/devcontainer.patch.json +49 -0
- package/overlays/nodejs/global-packages.txt +16 -0
- package/overlays/nodejs/overlay.yml +14 -0
- package/overlays/nodejs/setup.sh +46 -0
- package/overlays/nodejs/verify.sh +32 -0
- package/overlays/otel-collector/.env.example +9 -0
- package/overlays/otel-collector/README.md +1257 -0
- package/overlays/otel-collector/devcontainer.patch.json +28 -0
- package/overlays/otel-collector/docker-compose.yml +22 -0
- package/overlays/otel-collector/otel-collector-config.yaml +68 -0
- package/overlays/otel-collector/overlay.yml +21 -0
- package/overlays/otel-collector/setup.sh +49 -0
- package/overlays/otel-demo-nodejs/.env.example +2 -0
- package/overlays/otel-demo-nodejs/Dockerfile-otel-demo-nodejs +17 -0
- package/overlays/otel-demo-nodejs/README.md +409 -0
- package/overlays/otel-demo-nodejs/devcontainer.patch.json +12 -0
- package/overlays/otel-demo-nodejs/docker-compose.yml +19 -0
- package/overlays/otel-demo-nodejs/overlay.yml +23 -0
- package/overlays/otel-demo-nodejs/package-otel-demo-nodejs.json +20 -0
- package/overlays/otel-demo-nodejs/server-otel-demo-nodejs.js +259 -0
- package/overlays/otel-demo-nodejs/tracing-otel-demo-nodejs.js +57 -0
- package/overlays/otel-demo-nodejs/verify.sh +31 -0
- package/overlays/otel-demo-python/.env.example +2 -0
- package/overlays/otel-demo-python/Dockerfile-otel-demo-python +16 -0
- package/overlays/otel-demo-python/README.md +82 -0
- package/overlays/otel-demo-python/app-otel-demo-python.py +208 -0
- package/overlays/otel-demo-python/devcontainer.patch.json +12 -0
- package/overlays/otel-demo-python/docker-compose.yml +19 -0
- package/overlays/otel-demo-python/overlay.yml +23 -0
- package/overlays/otel-demo-python/requirements-otel-demo-python.txt +4 -0
- package/overlays/otel-demo-python/verify.sh +31 -0
- package/overlays/playwright/README.md +629 -0
- package/overlays/playwright/devcontainer.patch.json +9 -0
- package/overlays/playwright/overlay.yml +13 -0
- package/overlays/postgres/.env.example +6 -0
- package/overlays/postgres/README.md +602 -0
- package/overlays/postgres/devcontainer.patch.json +21 -0
- package/overlays/postgres/docker-compose.yml +22 -0
- package/overlays/postgres/overlay.yml +15 -0
- package/overlays/postgres/verify.sh +45 -0
- package/overlays/powershell/README.md +314 -0
- package/overlays/powershell/devcontainer.patch.json +22 -0
- package/overlays/powershell/overlay.yml +13 -0
- package/overlays/powershell/setup.sh +29 -0
- package/overlays/powershell/verify.sh +38 -0
- package/overlays/pre-commit/README.md +263 -0
- package/overlays/pre-commit/devcontainer.patch.json +9 -0
- package/overlays/pre-commit/overlay.yml +16 -0
- package/overlays/pre-commit/setup.sh +129 -0
- package/overlays/presets/docs-site.yml +118 -0
- package/overlays/presets/fullstack.yml +181 -0
- package/overlays/presets/microservice.yml +118 -0
- package/overlays/presets/web-api.yml +109 -0
- package/overlays/prometheus/.env.example +5 -0
- package/overlays/prometheus/README.md +1246 -0
- package/overlays/prometheus/devcontainer.patch.json +12 -0
- package/overlays/prometheus/docker-compose.yml +22 -0
- package/overlays/prometheus/overlay.yml +17 -0
- package/overlays/prometheus/prometheus.yml +12 -0
- package/overlays/prometheus/verify.sh +34 -0
- package/overlays/promtail/.env.example +2 -0
- package/overlays/promtail/README.md +357 -0
- package/overlays/promtail/devcontainer.patch.json +5 -0
- package/overlays/promtail/docker-compose.yml +16 -0
- package/overlays/promtail/overlay.yml +17 -0
- package/overlays/promtail/promtail-config.yaml +60 -0
- package/overlays/promtail/verify.sh +31 -0
- package/overlays/pulumi/README.md +472 -0
- package/overlays/pulumi/devcontainer.patch.json +13 -0
- package/overlays/pulumi/overlay.yml +14 -0
- package/overlays/pulumi/verify.sh +31 -0
- package/overlays/python/README.md +919 -0
- package/overlays/python/devcontainer.patch.json +41 -0
- package/overlays/python/overlay.yml +12 -0
- package/overlays/python/requirements-overlay.txt +13 -0
- package/overlays/python/setup.sh +47 -0
- package/overlays/python/verify.sh +32 -0
- package/overlays/rabbitmq/.env.example +7 -0
- package/overlays/rabbitmq/README.md +680 -0
- package/overlays/rabbitmq/devcontainer.patch.json +28 -0
- package/overlays/rabbitmq/docker-compose.yml +30 -0
- package/overlays/rabbitmq/overlay.yml +18 -0
- package/overlays/rabbitmq/verify.sh +41 -0
- package/overlays/redis/.env.example +4 -0
- package/overlays/redis/README.md +776 -0
- package/overlays/redis/devcontainer.patch.json +21 -0
- package/overlays/redis/docker-compose.yml +21 -0
- package/overlays/redis/overlay.yml +15 -0
- package/overlays/redis/verify.sh +41 -0
- package/overlays/redpanda/.env.example +10 -0
- package/overlays/redpanda/README.md +703 -0
- package/overlays/redpanda/devcontainer.patch.json +37 -0
- package/overlays/redpanda/docker-compose.yml +67 -0
- package/overlays/redpanda/overlay.yml +21 -0
- package/overlays/redpanda/verify.sh +48 -0
- package/overlays/rust/README.md +299 -0
- package/overlays/rust/devcontainer.patch.json +39 -0
- package/overlays/rust/overlay.yml +15 -0
- package/overlays/rust/setup.sh +36 -0
- package/overlays/rust/verify.sh +51 -0
- package/overlays/sqlite/README.md +584 -0
- package/overlays/sqlite/devcontainer.patch.json +14 -0
- package/overlays/sqlite/overlay.yml +15 -0
- package/overlays/sqlite/setup.sh +27 -0
- package/overlays/sqlite/verify.sh +43 -0
- package/overlays/sqlserver/.env.example +6 -0
- package/overlays/sqlserver/README.md +592 -0
- package/overlays/sqlserver/devcontainer.patch.json +22 -0
- package/overlays/sqlserver/docker-compose.yml +32 -0
- package/overlays/sqlserver/overlay.yml +17 -0
- package/overlays/sqlserver/verify.sh +30 -0
- package/overlays/tempo/.env.example +5 -0
- package/overlays/tempo/README.md +273 -0
- package/overlays/tempo/devcontainer.patch.json +12 -0
- package/overlays/tempo/docker-compose.yml +20 -0
- package/overlays/tempo/overlay.yml +20 -0
- package/overlays/tempo/tempo-config.yaml +32 -0
- package/overlays/tempo/verify.sh +31 -0
- package/overlays/terraform/README.md +389 -0
- package/overlays/terraform/devcontainer.patch.json +15 -0
- package/overlays/terraform/overlay.yml +14 -0
- package/overlays/terraform/verify.sh +63 -0
- package/package.json +74 -0
- package/templates/README.md +285 -0
- package/templates/compose/.devcontainer/devcontainer.json +46 -0
- package/templates/compose/.devcontainer/docker-compose.yml +12 -0
- package/templates/compose/README.md +20 -0
- package/templates/plain/.devcontainer/devcontainer.json +35 -0
- package/templates/plain/README.md +21 -0
- package/tool/README.md +281 -0
- package/tool/schema/base-images.schema.json +43 -0
- package/tool/schema/base-templates.schema.json +34 -0
- package/tool/schema/config.schema.json +71 -0
- package/tool/schema/overlay-manifest.schema.json +86 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: otel-demo-python
|
|
2
|
+
name: OTel Demo (Python)
|
|
3
|
+
description: Sample Python Flask app with OpenTelemetry instrumentation
|
|
4
|
+
category: observability
|
|
5
|
+
supports:
|
|
6
|
+
- compose
|
|
7
|
+
requires:
|
|
8
|
+
- otel-collector
|
|
9
|
+
suggests:
|
|
10
|
+
- jaeger
|
|
11
|
+
- tempo
|
|
12
|
+
- prometheus
|
|
13
|
+
- loki
|
|
14
|
+
- grafana
|
|
15
|
+
conflicts: []
|
|
16
|
+
tags:
|
|
17
|
+
- observability
|
|
18
|
+
- demo
|
|
19
|
+
- python
|
|
20
|
+
- opentelemetry
|
|
21
|
+
ports:
|
|
22
|
+
- 8081
|
|
23
|
+
order: 4
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# OTel Demo Python verification script
|
|
3
|
+
|
|
4
|
+
echo "🔍 Verifying OTel Demo (Python) installation..."
|
|
5
|
+
|
|
6
|
+
# Track overall success
|
|
7
|
+
ALL_CHECKS_PASSED=true
|
|
8
|
+
|
|
9
|
+
# Check if service is running
|
|
10
|
+
if docker ps --format '{{.Names}}' | grep -q otel-demo-python; then
|
|
11
|
+
echo "✓ OTel Demo (Python) service is running"
|
|
12
|
+
else
|
|
13
|
+
echo "✗ OTel Demo (Python) service is not running"
|
|
14
|
+
ALL_CHECKS_PASSED=false
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Check if HTTP endpoint is accessible
|
|
18
|
+
if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-python:8081/health 2>/dev/null | grep -q "200"; then
|
|
19
|
+
echo "✓ Demo app HTTP endpoint is accessible"
|
|
20
|
+
else
|
|
21
|
+
echo "⚠️ Demo app HTTP endpoint not responding yet (may still be starting)"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Final result
|
|
25
|
+
if [ "$ALL_CHECKS_PASSED" = true ]; then
|
|
26
|
+
echo "✓ All critical checks passed"
|
|
27
|
+
exit 0
|
|
28
|
+
else
|
|
29
|
+
echo "✗ Some checks failed"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
# Playwright Overlay
|
|
2
|
+
|
|
3
|
+
Browser automation and end-to-end testing framework with support for Chromium, Firefox, and WebKit.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-browser support** - Chromium, Firefox, and WebKit (Safari)
|
|
8
|
+
- **Headless and headed modes** - Run with or without visible browser
|
|
9
|
+
- **Auto-wait** - Automatically waits for elements to be ready
|
|
10
|
+
- **Network interception** - Mock API responses and intercept requests
|
|
11
|
+
- **Screenshots and videos** - Capture test execution
|
|
12
|
+
- **Mobile emulation** - Test responsive designs
|
|
13
|
+
- **Parallel execution** - Run tests concurrently
|
|
14
|
+
- **Codegen** - Generate tests by recording browser interactions
|
|
15
|
+
- **VS Code Extension:** Playwright Test for VS Code (ms-playwright.playwright)
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
Playwright is typically used with a programming language. Select appropriate overlay:
|
|
20
|
+
|
|
21
|
+
- **nodejs** - For JavaScript/TypeScript (most common)
|
|
22
|
+
- **python** - For Python
|
|
23
|
+
- **dotnet** - For C#
|
|
24
|
+
|
|
25
|
+
### Installation
|
|
26
|
+
|
|
27
|
+
#### JavaScript/TypeScript (requires nodejs overlay)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Install Playwright
|
|
31
|
+
npm init playwright@latest
|
|
32
|
+
|
|
33
|
+
# Or add to existing project
|
|
34
|
+
npm install -D @playwright/test
|
|
35
|
+
npx playwright install --with-deps
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Python (requires python overlay)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Install Playwright
|
|
42
|
+
pip install playwright
|
|
43
|
+
|
|
44
|
+
# Install browsers
|
|
45
|
+
playwright install --with-deps
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### .NET (requires dotnet overlay)
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Create test project
|
|
52
|
+
dotnet new nunit -n PlaywrightTests
|
|
53
|
+
cd PlaywrightTests
|
|
54
|
+
|
|
55
|
+
# Install Playwright
|
|
56
|
+
dotnet add package Microsoft.Playwright.NUnit
|
|
57
|
+
dotnet build
|
|
58
|
+
|
|
59
|
+
# Install browsers
|
|
60
|
+
pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Common Commands
|
|
64
|
+
|
|
65
|
+
### Running Tests (JavaScript/TypeScript)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Run all tests
|
|
69
|
+
npx playwright test
|
|
70
|
+
|
|
71
|
+
# Run tests in headed mode
|
|
72
|
+
npx playwright test --headed
|
|
73
|
+
|
|
74
|
+
# Run specific test file
|
|
75
|
+
npx playwright test tests/login.spec.ts
|
|
76
|
+
|
|
77
|
+
# Run tests in specific browser
|
|
78
|
+
npx playwright test --project=chromium
|
|
79
|
+
npx playwright test --project=firefox
|
|
80
|
+
npx playwright test --project=webkit
|
|
81
|
+
|
|
82
|
+
# Run tests in debug mode
|
|
83
|
+
npx playwright test --debug
|
|
84
|
+
|
|
85
|
+
# Run with UI mode (interactive)
|
|
86
|
+
npx playwright test --ui
|
|
87
|
+
|
|
88
|
+
# Run specific test by name
|
|
89
|
+
npx playwright test -g "should login"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Code Generation (Codegen)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Generate test by recording interactions
|
|
96
|
+
npx playwright codegen
|
|
97
|
+
|
|
98
|
+
# Generate test for specific URL
|
|
99
|
+
npx playwright codegen https://example.com
|
|
100
|
+
|
|
101
|
+
# Generate with specific browser
|
|
102
|
+
npx playwright codegen --browser=firefox https://example.com
|
|
103
|
+
|
|
104
|
+
# Generate with mobile emulation
|
|
105
|
+
npx playwright codegen --device="iPhone 13" https://example.com
|
|
106
|
+
|
|
107
|
+
# Generate with authentication
|
|
108
|
+
npx playwright codegen --save-storage=auth.json https://example.com
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Debugging
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Debug tests with Playwright Inspector
|
|
115
|
+
npx playwright test --debug
|
|
116
|
+
|
|
117
|
+
# Debug specific test
|
|
118
|
+
npx playwright test tests/login.spec.ts --debug
|
|
119
|
+
|
|
120
|
+
# Show browser while running
|
|
121
|
+
npx playwright test --headed --slow-mo=1000
|
|
122
|
+
|
|
123
|
+
# Pause test execution
|
|
124
|
+
# Add await page.pause() in your test code
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Reports
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Show last test report
|
|
131
|
+
npx playwright show-report
|
|
132
|
+
|
|
133
|
+
# Generate HTML report
|
|
134
|
+
npx playwright test --reporter=html
|
|
135
|
+
|
|
136
|
+
# Generate JUnit XML report
|
|
137
|
+
npx playwright test --reporter=junit
|
|
138
|
+
|
|
139
|
+
# Multiple reporters
|
|
140
|
+
npx playwright test --reporter=list,html,json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Browser Management
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Install all browsers
|
|
147
|
+
npx playwright install
|
|
148
|
+
|
|
149
|
+
# Install with system dependencies
|
|
150
|
+
npx playwright install --with-deps
|
|
151
|
+
|
|
152
|
+
# Install specific browser
|
|
153
|
+
npx playwright install chromium
|
|
154
|
+
npx playwright install firefox
|
|
155
|
+
npx playwright install webkit
|
|
156
|
+
|
|
157
|
+
# Update browsers
|
|
158
|
+
npx playwright install
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Writing Tests
|
|
162
|
+
|
|
163
|
+
### Basic Test (JavaScript/TypeScript)
|
|
164
|
+
|
|
165
|
+
**tests/example.spec.ts:**
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { test, expect } from '@playwright/test';
|
|
169
|
+
|
|
170
|
+
test('homepage has title', async ({ page }) => {
|
|
171
|
+
// Navigate to URL
|
|
172
|
+
await page.goto('https://playwright.dev/');
|
|
173
|
+
|
|
174
|
+
// Assert title contains text
|
|
175
|
+
await expect(page).toHaveTitle(/Playwright/);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('get started link works', async ({ page }) => {
|
|
179
|
+
await page.goto('https://playwright.dev/');
|
|
180
|
+
|
|
181
|
+
// Click the get started link
|
|
182
|
+
await page.getByRole('link', { name: 'Get started' }).click();
|
|
183
|
+
|
|
184
|
+
// Verify URL
|
|
185
|
+
await expect(page).toHaveURL(/.*intro/);
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Interacting with Elements
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { test, expect } from '@playwright/test';
|
|
193
|
+
|
|
194
|
+
test('form submission', async ({ page }) => {
|
|
195
|
+
await page.goto('https://example.com/form');
|
|
196
|
+
|
|
197
|
+
// Fill input fields
|
|
198
|
+
await page.fill('#username', 'john.doe');
|
|
199
|
+
await page.fill('#password', 'secret123');
|
|
200
|
+
|
|
201
|
+
// Click button
|
|
202
|
+
await page.click('button[type="submit"]');
|
|
203
|
+
|
|
204
|
+
// Wait for navigation
|
|
205
|
+
await page.waitForURL('**/dashboard');
|
|
206
|
+
|
|
207
|
+
// Assert success message
|
|
208
|
+
await expect(page.locator('.success-message')).toBeVisible();
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### API Testing
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { test, expect } from '@playwright/test';
|
|
216
|
+
|
|
217
|
+
test('API test', async ({ request }) => {
|
|
218
|
+
// GET request
|
|
219
|
+
const response = await request.get('https://api.example.com/users');
|
|
220
|
+
expect(response.ok()).toBeTruthy();
|
|
221
|
+
expect(response.status()).toBe(200);
|
|
222
|
+
|
|
223
|
+
const users = await response.json();
|
|
224
|
+
expect(users).toHaveLength(10);
|
|
225
|
+
|
|
226
|
+
// POST request
|
|
227
|
+
const newUser = await request.post('https://api.example.com/users', {
|
|
228
|
+
data: {
|
|
229
|
+
name: 'John Doe',
|
|
230
|
+
email: 'john@example.com',
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
expect(newUser.status()).toBe(201);
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Screenshots and Videos
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
test('take screenshot', async ({ page }) => {
|
|
241
|
+
await page.goto('https://example.com');
|
|
242
|
+
|
|
243
|
+
// Screenshot full page
|
|
244
|
+
await page.screenshot({ path: 'screenshot.png', fullPage: true });
|
|
245
|
+
|
|
246
|
+
// Screenshot element
|
|
247
|
+
const element = page.locator('.hero');
|
|
248
|
+
await element.screenshot({ path: 'element.png' });
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Enable video recording in playwright.config.ts:**
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
export default defineConfig({
|
|
256
|
+
use: {
|
|
257
|
+
video: 'on', // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'
|
|
258
|
+
screenshot: 'only-on-failure',
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Network Interception
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
test('mock API response', async ({ page }) => {
|
|
267
|
+
// Intercept API call
|
|
268
|
+
await page.route('**/api/users', (route) => {
|
|
269
|
+
route.fulfill({
|
|
270
|
+
status: 200,
|
|
271
|
+
contentType: 'application/json',
|
|
272
|
+
body: JSON.stringify([{ id: 1, name: 'Mocked User' }]),
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
await page.goto('https://example.com');
|
|
277
|
+
// Page will receive mocked data instead of real API
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test('block images', async ({ page }) => {
|
|
281
|
+
// Block all image requests
|
|
282
|
+
await page.route('**/*.{png,jpg,jpeg,gif}', (route) => route.abort());
|
|
283
|
+
|
|
284
|
+
await page.goto('https://example.com');
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Mobile Emulation
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { test, devices } from '@playwright/test';
|
|
292
|
+
|
|
293
|
+
test.use({
|
|
294
|
+
...devices['iPhone 13'],
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('mobile test', async ({ page }) => {
|
|
298
|
+
await page.goto('https://example.com');
|
|
299
|
+
|
|
300
|
+
// Test is running in iPhone 13 viewport
|
|
301
|
+
const isMobile = await page.evaluate(() => window.innerWidth < 768);
|
|
302
|
+
expect(isMobile).toBeTruthy();
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Configuration
|
|
307
|
+
|
|
308
|
+
### playwright.config.ts
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
312
|
+
|
|
313
|
+
export default defineConfig({
|
|
314
|
+
// Test directory
|
|
315
|
+
testDir: './tests',
|
|
316
|
+
|
|
317
|
+
// Maximum time one test can run
|
|
318
|
+
timeout: 30 * 1000,
|
|
319
|
+
|
|
320
|
+
// Run tests in parallel
|
|
321
|
+
fullyParallel: true,
|
|
322
|
+
|
|
323
|
+
// Fail the build on CI if you accidentally left test.only
|
|
324
|
+
forbidOnly: !!process.env.CI,
|
|
325
|
+
|
|
326
|
+
// Retry on CI only
|
|
327
|
+
retries: process.env.CI ? 2 : 0,
|
|
328
|
+
|
|
329
|
+
// Workers for parallel execution
|
|
330
|
+
workers: process.env.CI ? 1 : undefined,
|
|
331
|
+
|
|
332
|
+
// Reporter
|
|
333
|
+
reporter: 'html',
|
|
334
|
+
|
|
335
|
+
// Shared settings for all projects
|
|
336
|
+
use: {
|
|
337
|
+
// Base URL
|
|
338
|
+
baseURL: 'http://localhost:3000',
|
|
339
|
+
|
|
340
|
+
// Collect trace on failure
|
|
341
|
+
trace: 'on-first-retry',
|
|
342
|
+
|
|
343
|
+
// Screenshot on failure
|
|
344
|
+
screenshot: 'only-on-failure',
|
|
345
|
+
|
|
346
|
+
// Video on failure
|
|
347
|
+
video: 'retain-on-failure',
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
// Configure projects for major browsers
|
|
351
|
+
projects: [
|
|
352
|
+
{
|
|
353
|
+
name: 'chromium',
|
|
354
|
+
use: { ...devices['Desktop Chrome'] },
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: 'firefox',
|
|
358
|
+
use: { ...devices['Desktop Firefox'] },
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: 'webkit',
|
|
362
|
+
use: { ...devices['Desktop Safari'] },
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: 'Mobile Chrome',
|
|
366
|
+
use: { ...devices['Pixel 5'] },
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
name: 'Mobile Safari',
|
|
370
|
+
use: { ...devices['iPhone 13'] },
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
|
|
374
|
+
// Run local dev server before tests
|
|
375
|
+
webServer: {
|
|
376
|
+
command: 'npm run start',
|
|
377
|
+
url: 'http://localhost:3000',
|
|
378
|
+
reuseExistingServer: !process.env.CI,
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Use Cases
|
|
384
|
+
|
|
385
|
+
### End-to-End Testing
|
|
386
|
+
|
|
387
|
+
- Test complete user workflows
|
|
388
|
+
- Verify critical paths work correctly
|
|
389
|
+
- Regression testing
|
|
390
|
+
|
|
391
|
+
### Cross-Browser Testing
|
|
392
|
+
|
|
393
|
+
- Test on Chromium, Firefox, and WebKit
|
|
394
|
+
- Ensure consistent behavior across browsers
|
|
395
|
+
- Mobile and desktop testing
|
|
396
|
+
|
|
397
|
+
### Visual Regression Testing
|
|
398
|
+
|
|
399
|
+
- Compare screenshots against baselines
|
|
400
|
+
- Detect unintended UI changes
|
|
401
|
+
- Pixel-perfect validation
|
|
402
|
+
|
|
403
|
+
### API Testing
|
|
404
|
+
|
|
405
|
+
- Test REST APIs without UI
|
|
406
|
+
- Validate response structures
|
|
407
|
+
- Mock external services
|
|
408
|
+
|
|
409
|
+
### Performance Testing
|
|
410
|
+
|
|
411
|
+
- Measure page load times
|
|
412
|
+
- Track network requests
|
|
413
|
+
- Monitor resource usage
|
|
414
|
+
|
|
415
|
+
## Authentication
|
|
416
|
+
|
|
417
|
+
### Reusing Authentication State
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// global-setup.ts
|
|
421
|
+
import { chromium, FullConfig } from '@playwright/test';
|
|
422
|
+
|
|
423
|
+
async function globalSetup(config: FullConfig) {
|
|
424
|
+
const browser = await chromium.launch();
|
|
425
|
+
const page = await browser.newPage();
|
|
426
|
+
|
|
427
|
+
// Login
|
|
428
|
+
await page.goto('https://example.com/login');
|
|
429
|
+
await page.fill('#username', 'admin');
|
|
430
|
+
await page.fill('#password', 'password');
|
|
431
|
+
await page.click('button[type="submit"]');
|
|
432
|
+
await page.waitForURL('**/dashboard');
|
|
433
|
+
|
|
434
|
+
// Save storage state
|
|
435
|
+
await page.context().storageState({ path: 'auth.json' });
|
|
436
|
+
await browser.close();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export default globalSetup;
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
**Use in tests:**
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { test } from '@playwright/test';
|
|
446
|
+
|
|
447
|
+
test.use({ storageState: 'auth.json' });
|
|
448
|
+
|
|
449
|
+
test('authenticated test', async ({ page }) => {
|
|
450
|
+
// Already logged in
|
|
451
|
+
await page.goto('https://example.com/dashboard');
|
|
452
|
+
});
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Visual Comparison
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
# Install visual comparison plugin
|
|
459
|
+
npm install -D @playwright/test
|
|
460
|
+
|
|
461
|
+
# Take baseline screenshots
|
|
462
|
+
npx playwright test --update-snapshots
|
|
463
|
+
|
|
464
|
+
# Run visual tests
|
|
465
|
+
npx playwright test
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
test('visual regression', async ({ page }) => {
|
|
470
|
+
await page.goto('https://example.com');
|
|
471
|
+
|
|
472
|
+
// Compare screenshot with baseline
|
|
473
|
+
await expect(page).toHaveScreenshot('homepage.png');
|
|
474
|
+
|
|
475
|
+
// Compare element
|
|
476
|
+
await expect(page.locator('.header')).toHaveScreenshot('header.png');
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## CI/CD Integration
|
|
481
|
+
|
|
482
|
+
### GitHub Actions
|
|
483
|
+
|
|
484
|
+
```yaml
|
|
485
|
+
name: Playwright Tests
|
|
486
|
+
on:
|
|
487
|
+
push:
|
|
488
|
+
branches: [main]
|
|
489
|
+
pull_request:
|
|
490
|
+
branches: [main]
|
|
491
|
+
|
|
492
|
+
jobs:
|
|
493
|
+
test:
|
|
494
|
+
runs-on: ubuntu-latest
|
|
495
|
+
steps:
|
|
496
|
+
- uses: actions/checkout@v4
|
|
497
|
+
- uses: actions/setup-node@v4
|
|
498
|
+
with:
|
|
499
|
+
node-version: 20
|
|
500
|
+
|
|
501
|
+
- name: Install dependencies
|
|
502
|
+
run: npm ci
|
|
503
|
+
|
|
504
|
+
- name: Install Playwright Browsers
|
|
505
|
+
run: npx playwright install --with-deps
|
|
506
|
+
|
|
507
|
+
- name: Run Playwright tests
|
|
508
|
+
run: npx playwright test
|
|
509
|
+
|
|
510
|
+
- name: Upload test results
|
|
511
|
+
if: always()
|
|
512
|
+
uses: actions/upload-artifact@v4
|
|
513
|
+
with:
|
|
514
|
+
name: playwright-report
|
|
515
|
+
path: playwright-report/
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## Troubleshooting
|
|
519
|
+
|
|
520
|
+
### Browser installation fails
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
# Install with system dependencies
|
|
524
|
+
npx playwright install --with-deps
|
|
525
|
+
|
|
526
|
+
# Install specific browser
|
|
527
|
+
npx playwright install chromium
|
|
528
|
+
|
|
529
|
+
# Clear cache and reinstall
|
|
530
|
+
rm -rf ~/.cache/ms-playwright
|
|
531
|
+
npx playwright install
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Tests timeout
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
// Increase timeout in config
|
|
538
|
+
export default defineConfig({
|
|
539
|
+
timeout: 60 * 1000, // 60 seconds
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
// Or per test
|
|
543
|
+
test('slow test', async ({ page }) => {
|
|
544
|
+
test.setTimeout(60000);
|
|
545
|
+
await page.goto('https://slow-site.com');
|
|
546
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Element not found
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
// Wait for element
|
|
553
|
+
await page.waitForSelector('.my-element');
|
|
554
|
+
|
|
555
|
+
// Use auto-waiting locators
|
|
556
|
+
await page.locator('.my-element').click();
|
|
557
|
+
|
|
558
|
+
// Check if element exists
|
|
559
|
+
const exists = (await page.locator('.my-element').count()) > 0;
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### Screenshots not working in headless mode
|
|
563
|
+
|
|
564
|
+
Headless mode is the default and supports screenshots. If issues occur:
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
// Run in headed mode for debugging
|
|
568
|
+
npx playwright test --headed
|
|
569
|
+
|
|
570
|
+
// Ensure screenshot directory exists
|
|
571
|
+
await page.screenshot({ path: 'screenshots/test.png' });
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
## Best Practices
|
|
575
|
+
|
|
576
|
+
1. **Use auto-waiting locators** - Prefer `page.locator()` over `page.$`
|
|
577
|
+
2. **Avoid sleeps** - Use `waitForSelector` instead of fixed delays
|
|
578
|
+
3. **Use meaningful assertions** - Make tests easy to understand
|
|
579
|
+
4. **Keep tests independent** - Each test should run in isolation
|
|
580
|
+
5. **Use Page Object Model** - Organize selectors and actions
|
|
581
|
+
6. **Parallelize tests** - Speed up execution with workers
|
|
582
|
+
7. **Use test fixtures** - Share setup/teardown code
|
|
583
|
+
8. **Record failures** - Enable video/screenshots on failure
|
|
584
|
+
9. **Mock external services** - Keep tests fast and reliable
|
|
585
|
+
10. **Version control test data** - Use fixtures for consistent data
|
|
586
|
+
|
|
587
|
+
## Page Object Model Example
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
// pages/login-page.ts
|
|
591
|
+
export class LoginPage {
|
|
592
|
+
constructor(private page: Page) {}
|
|
593
|
+
|
|
594
|
+
async goto() {
|
|
595
|
+
await this.page.goto('/login');
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
async login(username: string, password: string) {
|
|
599
|
+
await this.page.fill('#username', username);
|
|
600
|
+
await this.page.fill('#password', password);
|
|
601
|
+
await this.page.click('button[type="submit"]');
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// tests/login.spec.ts
|
|
606
|
+
import { test } from '@playwright/test';
|
|
607
|
+
import { LoginPage } from '../pages/login-page';
|
|
608
|
+
|
|
609
|
+
test('login', async ({ page }) => {
|
|
610
|
+
const loginPage = new LoginPage(page);
|
|
611
|
+
await loginPage.goto();
|
|
612
|
+
await loginPage.login('admin', 'password');
|
|
613
|
+
});
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
## Related Overlays
|
|
617
|
+
|
|
618
|
+
- **nodejs** - Required for JavaScript/TypeScript Playwright
|
|
619
|
+
- **python** - Required for Python Playwright
|
|
620
|
+
- **dotnet** - Required for C# Playwright
|
|
621
|
+
- **docker-sock/docker-in-docker** - For testing containerized apps
|
|
622
|
+
|
|
623
|
+
## Additional Resources
|
|
624
|
+
|
|
625
|
+
- [Playwright Documentation](https://playwright.dev/docs/intro)
|
|
626
|
+
- [Playwright API Reference](https://playwright.dev/docs/api/class-playwright)
|
|
627
|
+
- [Playwright Best Practices](https://playwright.dev/docs/best-practices)
|
|
628
|
+
- [Playwright GitHub Repository](https://github.com/microsoft/playwright)
|
|
629
|
+
- [Example Projects](https://playwright.dev/docs/examples)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
|
|
3
|
+
"features": {
|
|
4
|
+
"ghcr.io/devcontainers/features/node:1": {
|
|
5
|
+
"version": "lts"
|
|
6
|
+
}
|
|
7
|
+
},
|
|
8
|
+
"postCreateCommand": "npx -y playwright install --with-deps chromium"
|
|
9
|
+
}
|