├── .gitignore
├── LICENSE
├── README.md
├── browserless.dc.yaml
├── docker-compose.yaml
├── grafana
├── config
│ └── grafana.ini
├── dashboards
│ └── dashboard.yml
└── datasources
│ └── datasource.yml
├── k6
└── scripts
│ ├── ewoks.js
│ ├── example.js
│ └── meetup.js
├── playwright
├── README.md
├── package-lock.json
├── package.json
├── playwright.config.js
├── tests
│ ├── addObserver.js
│ ├── basic.spec.js
│ ├── bingLogo.png
│ ├── capabilities.spec.js
│ ├── fixtures.js
│ ├── googlelogo_light_color_272x92dp.png
│ ├── influxDemo.spec.js
│ ├── influxUtils.js
│ ├── old_capabilities.spec.js
│ ├── variability.spec.js
│ └── zeroed.perf.spec.js
└── trace.json
├── prometheus
└── prometheus.yml
└── xk6-browser
└── example.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 | grafana/grafana.db
106 | k6/scripts/copied-har.js
107 |
108 | playwright/test-results
109 | playwright/start.heapsnapshot
110 | .DS_Store
111 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 John Hill
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
js-perf-toolkit
6 |
7 |
8 | A collection of (Open Source) performance tools which allow a js developer to reliably model and monitor a webapp.
9 |
10 | Explore the docs »
11 |
12 |
13 | View Demo
14 | ·
15 | Report Bug
16 | ·
17 | Request Feature
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Table of Contents
26 |
27 | -
28 | About The Project
29 |
32 |
33 | -
34 | Getting Started
35 |
39 |
40 | - Usage
41 | - Roadmap
42 | - License
43 | - Contact
44 | - Acknowledgements
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## About The Project
52 |
53 | A collection of (Open Source) performance tools which allow a js developer to reliably model and monitor a webapp. At the moment, most of the focus is on the playwright component.
54 |
55 | ### Built With
56 |
57 | * [playwright](https://github.com/microsoft/playwright)
58 | * [k6](https://github.com/k6io/k6)
59 | * [browserless](https://github.com/browserless/chrome)
60 | * [grafana](https://github.com/grafana/grafana)
61 | * [prometheus](https://github.com/prometheus/prometheus)
62 | * [influxdb](https://github.com/influxdata/influxdb)
63 |
64 |
65 | ## Getting Started
66 |
67 | To get a local copy up and running follow these simple steps.
68 |
69 | ### Prerequisites
70 |
71 | This is an example of how to list things you need to use the software and how to install them.
72 | * [Docker](https://docs.docker.com/get-docker/)
73 | * [nodejs](https://github.com/nvm-sh/nvm/)
74 |
75 | ### Installation
76 |
77 | This installation is split into two components: the playwright local installation and the full stack of performance Infrastructure.
78 |
79 | #### playwright local
80 | 1. Clone this repo
81 | ```sh
82 | git clone https://github.com/unlikelyzero/js-perf-toolkit.git
83 | ```
84 | 2. Install nvm. https://github.com/nvm-sh/nvm/
85 | 3. npm install the `./playwright` repo
86 | ```sh
87 | cd playwright
88 | nvm use 14
89 | npm install
90 | ```
91 | 4. install playwright browsers
92 | ```sh
93 | npx playwright install
94 | ```
95 | 4. run a basic test
96 | ```sh
97 | npm run test:local:basic
98 | ```
99 |
100 | #### Docker Infrastructure
101 | 1. Clone the repo
102 | ```sh
103 | git clone https://github.com/unlikelyzero/js-perf-toolkit.git
104 | ```
105 | 1. Start the monitoring containers (except browserless)
106 | ```
107 | docker compose up -d
108 | ```
109 | 1. Verify that the following webservers are up:
110 | ```
111 | localhost:9090
112 | localhost:8086
113 | localhost:8089
114 | localhost:3006
115 | ```
116 | 1. Start the browserless container
117 | ```
118 | docker compose -f ./browserless.dc.yaml up -d browserless
119 | 1. Verify that the following webserver is up
120 | ```
121 | localhost:3003
122 | ```
123 |
124 |
125 |
126 | ## Roadmap
127 |
128 | See the [open issues](https://github.com/unlikelyzero/js-perf-toolkit/issues) for a list of proposed features (and known issues).
129 |
130 |
131 | ## License
132 |
133 | Distributed under the MIT License. See `LICENSE` for more information.
134 |
135 |
136 | ## Contact
137 |
138 | John Hill - [Email on https://github.com/unlikelyzero]
139 |
140 | Project Link: [https://github.com/unlikelyzero/js-perf-toolkit](https://github.com/unlikelyzero/js-perf-toolkit)
141 |
142 |
143 |
144 |
145 | ## Acknowledgements
146 |
147 | Sources
148 | - https://medium.com/swlh/beautiful-load-testing-with-k6-and-docker-compose-4454edb3a2e3
149 | - https://susi.dev/prometheus-grafana-loki-with-docker-compose
150 | - https://github.com/browserless/chrome/issues/52
151 | - https://michaljanaszek.com/blog/test-website-performance-with-puppeteer/
152 | - https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
153 | - https://automationrhapsody.com/performance-testing-in-the-browser/
154 | - https://github.com/llatinov/sample-performance-testing-in-browser
155 |
156 |
157 |
158 |
159 |
160 | [contributors-shield]: https://img.shields.io/github/contributors/unlikelyzero/repo.svg?style=for-the-badge
161 | [contributors-url]: https://github.com/unlikelyzero/repo/graphs/contributors
162 | [forks-shield]: https://img.shields.io/github/forks/unlikelyzero/repo.svg?style=for-the-badge
163 | [forks-url]: https://github.com/unlikelyzero/repo/network/members
164 | [stars-shield]: https://img.shields.io/github/stars/unlikelyzero/repo.svg?style=for-the-badge
165 | [stars-url]: https://github.com/unlikelyzero/repo/stargazers
166 | [issues-shield]: https://img.shields.io/github/issues/unlikelyzero/repo.svg?style=for-the-badge
167 | [issues-url]: https://github.com/unlikelyzero/repo/issues
168 | [license-shield]: https://img.shields.io/github/license/unlikelyzero/repo.svg?style=for-the-badge
169 | [license-url]: https://github.com/unlikelyzero/repo/blob/master/LICENSE.txt
170 | [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
171 | [linkedin-url]: https://linkedin.com/in/unlikelyzero
172 |
173 |
--------------------------------------------------------------------------------
/browserless.dc.yaml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | browserless:
4 | image: browserless/chrome:latest
5 | container_name: browserless
6 | cpus: 2.0
7 | mem_limit: 4g
8 | environment:
9 | - MAX_CONCURRENT_SESSIONS=1
10 | - CONNECTION_TIMEOUT=60000
11 | - PREBOOT_CHROME=true
12 | - DEFAULT_HEADLESS=false
13 | - ENABLE_DEBUGGER=true
14 | - DEFAULT_IGNORE_HTTPS_ERRORS=true
15 | - ENABLE_API_GET=true
16 | - DEFAULT_LAUNCH_ARGS=["--window-size=1200,900"]
17 | - ENABLE_HEAP_DUMP=true
18 | volumes:
19 | - browserless:/tmp/
20 | ports:
21 | - "3003:3000"
22 | expose:
23 | - 3003
24 | - 3000
25 | networks:
26 | - js-perf-toolkit_monitoring
27 | networks:
28 | js-perf-toolkit_monitoring:
29 | external: true
30 | volumes:
31 | browserless: {}
32 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 | services:
3 | mon_influxdb:
4 | image: influxdb:latest
5 | container_name: influxdb
6 | volumes:
7 | - mon_influxdb_data:/var/lib/influxdb
8 | environment:
9 | - INFLUXDB_DB=db0
10 | - INFLUXDB_ADMIN_USER=admin
11 | - INFLUXDB_ADMIN_PASSWORD=admin
12 | ports:
13 | - "8086:8086"
14 | expose:
15 | - 8086
16 | networks:
17 | - monitoring
18 | mon_prometheus_write:
19 | image: prom/prometheus:latest
20 | container_name: mon_prometheus
21 | command: --enable-feature=remote-write-receiver --config.file=/etc/prometheus/prometheus.yml
22 | volumes:
23 | - /etc/localtime:/etc/localtime:ro
24 | - /etc/timezone:/etc/timezone:ro
25 | - ${PWD}/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
26 | - mon_prometheus_data:/prometheus
27 | restart: always
28 | ports:
29 | - "9090:9090"
30 | networks:
31 | - monitoring
32 |
33 | # mon_node-exporter:
34 | # image: prom/node-exporter:latest
35 | # container_name: mon_node-exporter
36 | # restart: always
37 | # volumes:
38 | # - /etc/localtime:/etc/localtime:ro
39 | # - /etc/timezone:/etc/timezone:ro
40 | # - /proc:/host/proc:ro
41 | # - /sys:/host/sys:ro
42 | # - /:/rootfs:ro
43 | # command:
44 | # - '--path.procfs=/host/proc'
45 | # - '--path.sysfs=/host/sys'
46 | # - '--path.rootfs=/rootfs'
47 | # - '--collector.filesystem.ignored-mount-points="^(/rootfs|/host|)/(sys|proc|dev|host|etc)($$|/)"'
48 | # - '--collector.filesystem.ignored-fs-types="^(sys|proc|auto|cgroup|devpts|ns|au|fuse\.lxc|mqueue)(fs|)$$"'
49 | # networks:
50 | # - monitoring
51 |
52 | mon_cadvisor:
53 | image: gcr.io/cadvisor/cadvisor:latest
54 | container_name: mon_cadvisor
55 | restart: always
56 | volumes:
57 | - /etc/localtime:/etc/localtime:ro
58 | - /etc/timezone:/etc/timezone:ro
59 | - /:/rootfs:ro
60 | #- /var/run:/var/run:ro # linux
61 | - /var/run/docker.sock:/var/run/docker.sock:rw # Docker for Mac
62 | - /sys:/sys:ro
63 | - /var/lib/docker/:/var/lib/docker:ro
64 | - /dev/disk/:/dev/disk:ro
65 | ports:
66 | - "8089:8080"
67 | expose:
68 | - 8080
69 | - 8089
70 | networks:
71 | - monitoring
72 |
73 | mon_grafana:
74 | image: grafana/grafana:latest
75 | container_name: mon_grafana
76 | restart: unless-stopped
77 | volumes:
78 | - /etc/localtime:/etc/localtime:ro
79 | - /etc/timezone:/etc/timezone:ro
80 | - mon_grafana_data:/var/lib/grafana
81 | - ./grafana/datasources:/etc/grafana/datasources
82 | - ./grafana/dashboards:/etc/grafana/dashboards
83 | - ./grafana/config/grafana.ini:/etc/grafana/grafana.ini
84 | environment:
85 | - GF_SECURITY_ADMIN_USER=admin
86 | - GF_SECURITY_ADMIN_PASSWORD=admin
87 | - GF_USERS_ALLOW_SIGN_UP=false
88 | ports:
89 | - "3006:3000"
90 | expose:
91 | - 3006
92 | - 3000
93 | networks:
94 | - monitoring
95 |
96 | mon_toxiproxy:
97 | image: "ghcr.io/shopify/toxiproxy"
98 | container_name: mon_toxiproxy
99 | command:
100 | -runtime-metrics
101 | -proxy-metrics
102 | ports:
103 | - "8474:8474"
104 | - "8088:8080"
105 | - "3306:3306"
106 | - "6379:6379"
107 | - "16379:16379"
108 | expose:
109 | - 8088
110 | - 8474
111 | - 16379
112 | - 3306
113 | - 6379
114 | networks:
115 | - monitoring
116 |
117 | networks:
118 | monitoring:
119 | driver: bridge
120 |
121 | volumes:
122 | mon_grafana_data: {}
123 | mon_prometheus_data: {}
124 | mon_cadvisor_data: {}
125 | mon_influxdb_data: {}
126 |
--------------------------------------------------------------------------------
/grafana/config/grafana.ini:
--------------------------------------------------------------------------------
1 | [analytics]
2 | reporting_enabled = false
3 | [auth.anonymous]
4 | enabled = true
5 | org_role = Admin
6 | [explore]
7 | enabled = true
8 | [users]
9 | default_theme = dark
10 | [server]
11 | domain = grafana
12 | root_url = %(protocol)s://%(domain)s:%(http_port)s
13 | serve_from_sub_path = false
--------------------------------------------------------------------------------
/grafana/dashboards/dashboard.yml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | providers:
4 | - name: 'Prometheus'
5 | orgId: 1
6 | folder: ''
7 | type: file
8 | disableDeletion: false
9 | editable: true
10 | allowUiUpdates: true
11 | options:
12 | path: /etc/grafana/provisioning/dashboards
--------------------------------------------------------------------------------
/grafana/datasources/datasource.yml:
--------------------------------------------------------------------------------
1 |
2 |
3 | apiVersion: 1
4 |
5 | datasources:
6 | - name: Prometheus
7 | type: prometheus
8 | access: proxy
9 | orgId: 1
10 | url: http://prometheus:9090
11 | basicAuth: false
12 | isDefault: true
13 | editable: true
14 | - name: InfluxDB
15 | type: influxdb
16 | access: proxy
17 | database: db0
18 | user: admin
19 | password: admin
20 | url: http://influxdb:8086
21 | isDefault: true
22 | editable: true
--------------------------------------------------------------------------------
/k6/scripts/ewoks.js:
--------------------------------------------------------------------------------
1 | import http from 'k6/http';
2 | import { check } from "k6";
3 | export let options = {
4 | stages: [
5 | // Ramp-up from 1 to 5 VUs in 5s
6 | { duration: "5s", target: 5 },
7 | // Stay at rest on 5 VUs for 10s
8 | { duration: "10s", target: 5 },
9 | // Ramp-down from 5 to 0 VUs for 5s
10 | { duration: "5s", target: 0 }
11 | ]
12 | };
13 | export default function () {
14 | const response = http.get("https://swapi.dev/api/people/30/", {headers: {Accepts: "application/json"}});
15 | check(response, { "status is 200": (r) => r.status === 200 });
16 | };
--------------------------------------------------------------------------------
/k6/scripts/example.js:
--------------------------------------------------------------------------------
1 | import http from 'k6/http';
2 | import { sleep } from 'k6';
3 |
4 | export default function () {
5 | http.get('https://test.k6.io');
6 | sleep(1);
7 | }
8 |
--------------------------------------------------------------------------------
/k6/scripts/meetup.js:
--------------------------------------------------------------------------------
1 | import { sleep, group } from "k6";
2 | import http from "k6/http";
3 |
4 | export const options = {
5 | ext: {
6 | loadimpact: {
7 | distribution: {
8 | "amazon:us:ashburn": { loadZone: "amazon:us:ashburn", percent: 100 },
9 | },
10 | },
11 | },
12 | stages: [{ target: 1, duration: "1m" }],
13 | thresholds: {},
14 | };
15 |
16 | export default function main() {
17 | let response;
18 |
19 | group("page_2 - https://www.meetup.com/", function () {
20 | response = http.get("https://www.meetup.com/", {
21 | headers: {
22 | "cache-control": "no-cache",
23 | "sec-ch-ua":
24 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
25 | "sec-ch-ua-mobile": "?0",
26 | dnt: "1",
27 | "upgrade-insecure-requests": "1",
28 | accept:
29 | "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
30 | "sec-fetch-site": "same-origin",
31 | "sec-fetch-mode": "navigate",
32 | "sec-fetch-user": "?1",
33 | "sec-fetch-dest": "document",
34 | "accept-encoding": "gzip, deflate, br",
35 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
36 | "sec-gpc": "1",
37 | },
38 | });
39 | response = http.get(
40 | "https://www.meetup.com/_next/image?url=%2Fimages%2Fshared%2Fonline_events.svg&w=1080&q=75",
41 | {
42 | headers: {
43 | "cache-control": "no-cache",
44 | "sec-ch-ua":
45 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
46 | dnt: "1",
47 | "sec-ch-ua-mobile": "?0",
48 | accept:
49 | "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
50 | "sec-fetch-site": "same-origin",
51 | "sec-fetch-mode": "no-cors",
52 | "sec-fetch-dest": "image",
53 | "accept-encoding": "gzip, deflate, br",
54 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
55 | "sec-gpc": "1",
56 | },
57 | }
58 | );
59 | response = http.get(
60 | "https://www.meetup.com/_next/static/css/61af7b0caae9cacc00d7.css",
61 | {
62 | headers: {
63 | "cache-control": "no-cache",
64 | "sec-ch-ua":
65 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
66 | dnt: "1",
67 | "sec-ch-ua-mobile": "?0",
68 | accept: "text/css,*/*;q=0.1",
69 | "sec-fetch-site": "same-origin",
70 | "sec-fetch-mode": "no-cors",
71 | "sec-fetch-dest": "style",
72 | "accept-encoding": "gzip, deflate, br",
73 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
74 | "sec-gpc": "1",
75 | },
76 | }
77 | );
78 | response = http.get(
79 | "https://www.meetup.com/_next/static/css/2aa60a7450588f710f04.css",
80 | {
81 | headers: {
82 | "cache-control": "no-cache",
83 | "sec-ch-ua":
84 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
85 | dnt: "1",
86 | "sec-ch-ua-mobile": "?0",
87 | accept: "text/css,*/*;q=0.1",
88 | "sec-fetch-site": "same-origin",
89 | "sec-fetch-mode": "no-cors",
90 | "sec-fetch-dest": "style",
91 | "accept-encoding": "gzip, deflate, br",
92 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
93 | "sec-gpc": "1",
94 | },
95 | }
96 | );
97 | response = http.get(
98 | "https://www.meetup.com/_next/static/chunks/main-ed70ae135667b51396fd.js",
99 | {
100 | headers: {
101 | "cache-control": "no-cache",
102 | "sec-ch-ua":
103 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
104 | dnt: "1",
105 | "sec-ch-ua-mobile": "?0",
106 | accept: "*/*",
107 | "sec-fetch-site": "same-origin",
108 | "sec-fetch-mode": "no-cors",
109 | "sec-fetch-dest": "script",
110 | "accept-encoding": "gzip, deflate, br",
111 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
112 | "sec-gpc": "1",
113 | },
114 | }
115 | );
116 | response = http.get(
117 | "https://www.meetup.com/_next/static/chunks/webpack-2504c87d1cb25e21f7ee.js",
118 | {
119 | headers: {
120 | "cache-control": "no-cache",
121 | "sec-ch-ua":
122 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
123 | dnt: "1",
124 | "sec-ch-ua-mobile": "?0",
125 | accept: "*/*",
126 | "sec-fetch-site": "same-origin",
127 | "sec-fetch-mode": "no-cors",
128 | "sec-fetch-dest": "script",
129 | "accept-encoding": "gzip, deflate, br",
130 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
131 | "sec-gpc": "1",
132 | },
133 | }
134 | );
135 | response = http.get(
136 | "https://www.meetup.com/_next/static/chunks/framework.66a79ec164b9f6c6083c.js",
137 | {
138 | headers: {
139 | "cache-control": "no-cache",
140 | "sec-ch-ua":
141 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
142 | dnt: "1",
143 | "sec-ch-ua-mobile": "?0",
144 | accept: "*/*",
145 | "sec-fetch-site": "same-origin",
146 | "sec-fetch-mode": "no-cors",
147 | "sec-fetch-dest": "script",
148 | "accept-encoding": "gzip, deflate, br",
149 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
150 | "sec-gpc": "1",
151 | },
152 | }
153 | );
154 | response = http.get(
155 | "https://www.meetup.com/_next/static/chunks/commons.87243c40c4adf9332d31.js",
156 | {
157 | headers: {
158 | "cache-control": "no-cache",
159 | "sec-ch-ua":
160 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
161 | dnt: "1",
162 | "sec-ch-ua-mobile": "?0",
163 | accept: "*/*",
164 | "sec-fetch-site": "same-origin",
165 | "sec-fetch-mode": "no-cors",
166 | "sec-fetch-dest": "script",
167 | "accept-encoding": "gzip, deflate, br",
168 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
169 | "sec-gpc": "1",
170 | },
171 | }
172 | );
173 | response = http.get(
174 | "https://www.meetup.com/_next/static/chunks/f78efe678e3d4c6d2f3324b234ba879b394fd7a5.34f4dd8374861356bbfe.js",
175 | {
176 | headers: {
177 | "cache-control": "no-cache",
178 | "sec-ch-ua":
179 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
180 | dnt: "1",
181 | "sec-ch-ua-mobile": "?0",
182 | accept: "*/*",
183 | "sec-fetch-site": "same-origin",
184 | "sec-fetch-mode": "no-cors",
185 | "sec-fetch-dest": "script",
186 | "accept-encoding": "gzip, deflate, br",
187 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
188 | "sec-gpc": "1",
189 | },
190 | }
191 | );
192 | response = http.get(
193 | "https://www.meetup.com/_next/static/chunks/ab111e260f13b9af801980beaf2143243f3031f4.a7a5b776bc1c4ce3b640.js",
194 | {
195 | headers: {
196 | "cache-control": "no-cache",
197 | "sec-ch-ua":
198 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
199 | dnt: "1",
200 | "sec-ch-ua-mobile": "?0",
201 | accept: "*/*",
202 | "sec-fetch-site": "same-origin",
203 | "sec-fetch-mode": "no-cors",
204 | "sec-fetch-dest": "script",
205 | "accept-encoding": "gzip, deflate, br",
206 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
207 | "sec-gpc": "1",
208 | },
209 | }
210 | );
211 | response = http.get(
212 | "https://www.meetup.com/_next/static/chunks/71247caf95475e3ea7f9a0f8a30beb258b23d005.fd6b1b5424913a584fa9.js",
213 | {
214 | headers: {
215 | "cache-control": "no-cache",
216 | "sec-ch-ua":
217 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
218 | dnt: "1",
219 | "sec-ch-ua-mobile": "?0",
220 | accept: "*/*",
221 | "sec-fetch-site": "same-origin",
222 | "sec-fetch-mode": "no-cors",
223 | "sec-fetch-dest": "script",
224 | "accept-encoding": "gzip, deflate, br",
225 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
226 | "sec-gpc": "1",
227 | },
228 | }
229 | );
230 | response = http.get(
231 | "https://www.meetup.com/_next/static/chunks/pages/_app-e4f9ab85afe7649be774.js",
232 | {
233 | headers: {
234 | "cache-control": "no-cache",
235 | "sec-ch-ua":
236 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
237 | dnt: "1",
238 | "sec-ch-ua-mobile": "?0",
239 | accept: "*/*",
240 | "sec-fetch-site": "same-origin",
241 | "sec-fetch-mode": "no-cors",
242 | "sec-fetch-dest": "script",
243 | "accept-encoding": "gzip, deflate, br",
244 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
245 | "sec-gpc": "1",
246 | },
247 | }
248 | );
249 | response = http.get(
250 | "https://www.meetup.com/_next/static/chunks/faf7f81857e86714c5b7ec6ee085feff2a058b19.96c6dbd48161f5e0614c.js",
251 | {
252 | headers: {
253 | "cache-control": "no-cache",
254 | "sec-ch-ua":
255 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
256 | dnt: "1",
257 | "sec-ch-ua-mobile": "?0",
258 | accept: "*/*",
259 | "sec-fetch-site": "same-origin",
260 | "sec-fetch-mode": "no-cors",
261 | "sec-fetch-dest": "script",
262 | "accept-encoding": "gzip, deflate, br",
263 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
264 | "sec-gpc": "1",
265 | },
266 | }
267 | );
268 | response = http.get(
269 | "https://www.meetup.com/_next/static/chunks/9b7bc37e5ed0342374271c973f94fd149c3c8f2f.04f317746d700ad3196d.js",
270 | {
271 | headers: {
272 | "cache-control": "no-cache",
273 | "sec-ch-ua":
274 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
275 | dnt: "1",
276 | "sec-ch-ua-mobile": "?0",
277 | accept: "*/*",
278 | "sec-fetch-site": "same-origin",
279 | "sec-fetch-mode": "no-cors",
280 | "sec-fetch-dest": "script",
281 | "accept-encoding": "gzip, deflate, br",
282 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
283 | "sec-gpc": "1",
284 | },
285 | }
286 | );
287 | response = http.get(
288 | "https://www.meetup.com/_next/static/chunks/1ea392b2883c1b78fe504ed021e0cbafff3e53cc.24574793eefaa605b884.js",
289 | {
290 | headers: {
291 | "cache-control": "no-cache",
292 | "sec-ch-ua":
293 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
294 | dnt: "1",
295 | "sec-ch-ua-mobile": "?0",
296 | accept: "*/*",
297 | "sec-fetch-site": "same-origin",
298 | "sec-fetch-mode": "no-cors",
299 | "sec-fetch-dest": "script",
300 | "accept-encoding": "gzip, deflate, br",
301 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
302 | "sec-gpc": "1",
303 | },
304 | }
305 | );
306 | response = http.get(
307 | "https://www.meetup.com/_next/static/chunks/6c783d5d1a4ac3619ac103246ed7b50684ef3e6a.030b03c467caa82f72fa.js",
308 | {
309 | headers: {
310 | "cache-control": "no-cache",
311 | "sec-ch-ua":
312 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
313 | dnt: "1",
314 | "sec-ch-ua-mobile": "?0",
315 | accept: "*/*",
316 | "sec-fetch-site": "same-origin",
317 | "sec-fetch-mode": "no-cors",
318 | "sec-fetch-dest": "script",
319 | "accept-encoding": "gzip, deflate, br",
320 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
321 | "sec-gpc": "1",
322 | },
323 | }
324 | );
325 | response = http.get(
326 | "https://www.meetup.com/_next/static/chunks/1bc96372777c09050872b165b2f2c126303ce1eb.b4eb28a35d797efb0e94.js",
327 | {
328 | headers: {
329 | "cache-control": "no-cache",
330 | "sec-ch-ua":
331 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
332 | dnt: "1",
333 | "sec-ch-ua-mobile": "?0",
334 | accept: "*/*",
335 | "sec-fetch-site": "same-origin",
336 | "sec-fetch-mode": "no-cors",
337 | "sec-fetch-dest": "script",
338 | "accept-encoding": "gzip, deflate, br",
339 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
340 | "sec-gpc": "1",
341 | },
342 | }
343 | );
344 | response = http.get(
345 | "https://www.meetup.com/_next/static/chunks/d951b7790b60983d82b33e53f3a34312c35ba38e.43f7b1155781ccde0df2.js",
346 | {
347 | headers: {
348 | "cache-control": "no-cache",
349 | "sec-ch-ua":
350 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
351 | dnt: "1",
352 | "sec-ch-ua-mobile": "?0",
353 | accept: "*/*",
354 | "sec-fetch-site": "same-origin",
355 | "sec-fetch-mode": "no-cors",
356 | "sec-fetch-dest": "script",
357 | "accept-encoding": "gzip, deflate, br",
358 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
359 | "sec-gpc": "1",
360 | },
361 | }
362 | );
363 | response = http.get(
364 | "https://www.meetup.com/_next/static/chunks/17f632b099af03e4e58dfce0e900177b533452f2.bb867dd59562531dfb72.js",
365 | {
366 | headers: {
367 | "cache-control": "no-cache",
368 | "sec-ch-ua":
369 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
370 | dnt: "1",
371 | "sec-ch-ua-mobile": "?0",
372 | accept: "*/*",
373 | "sec-fetch-site": "same-origin",
374 | "sec-fetch-mode": "no-cors",
375 | "sec-fetch-dest": "script",
376 | "accept-encoding": "gzip, deflate, br",
377 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
378 | "sec-gpc": "1",
379 | },
380 | }
381 | );
382 | response = http.get(
383 | "https://www.meetup.com/_next/static/chunks/c62b1f5506a3d85383b562dbd5dbc47675d7d427.6b800a74768e7ff40927.js",
384 | {
385 | headers: {
386 | "cache-control": "no-cache",
387 | "sec-ch-ua":
388 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
389 | dnt: "1",
390 | "sec-ch-ua-mobile": "?0",
391 | accept: "*/*",
392 | "sec-fetch-site": "same-origin",
393 | "sec-fetch-mode": "no-cors",
394 | "sec-fetch-dest": "script",
395 | "accept-encoding": "gzip, deflate, br",
396 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
397 | "sec-gpc": "1",
398 | },
399 | }
400 | );
401 | response = http.get(
402 | "https://www.meetup.com/_next/static/chunks/pages/index-e1dd67c9cba2f7c768c0.js",
403 | {
404 | headers: {
405 | "cache-control": "no-cache",
406 | "sec-ch-ua":
407 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
408 | dnt: "1",
409 | "sec-ch-ua-mobile": "?0",
410 | accept: "*/*",
411 | "sec-fetch-site": "same-origin",
412 | "sec-fetch-mode": "no-cors",
413 | "sec-fetch-dest": "script",
414 | "accept-encoding": "gzip, deflate, br",
415 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
416 | "sec-gpc": "1",
417 | },
418 | }
419 | );
420 | sleep(0.5);
421 | response = http.get(
422 | "https://www.meetup.com/_next/image/?url=%2Fimages%2Fshared%2Fonline_events.svg&w=1080&q=75",
423 | {
424 | headers: {
425 | "cache-control": "no-cache",
426 | "sec-ch-ua":
427 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
428 | dnt: "1",
429 | "sec-ch-ua-mobile": "?0",
430 | accept:
431 | "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
432 | "sec-fetch-site": "same-origin",
433 | "sec-fetch-mode": "no-cors",
434 | "sec-fetch-dest": "image",
435 | "accept-encoding": "gzip, deflate, br",
436 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
437 | "sec-gpc": "1",
438 | },
439 | }
440 | );
441 | response = http.get(
442 | "https://www.meetup.com/_next/static/media/Graphik-Regular.5a6c8ef9a003d72adbb0b4afe7be75c3.woff2",
443 | {
444 | headers: {
445 | "cache-control": "no-cache",
446 | "sec-ch-ua":
447 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
448 | origin: "https://www.meetup.com",
449 | "sec-ch-ua-mobile": "?0",
450 | dnt: "1",
451 | accept: "*/*",
452 | "sec-fetch-site": "same-origin",
453 | "sec-fetch-mode": "cors",
454 | "sec-fetch-dest": "font",
455 | "accept-encoding": "gzip, deflate, br",
456 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
457 | "sec-gpc": "1",
458 | },
459 | }
460 | );
461 | response = http.get(
462 | "https://www.meetup.com/_next/static/media/Graphik-Medium.e928c9211e8ec2178f619817ebe13fa8.woff2",
463 | {
464 | headers: {
465 | "cache-control": "no-cache",
466 | "sec-ch-ua":
467 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
468 | origin: "https://www.meetup.com",
469 | "sec-ch-ua-mobile": "?0",
470 | dnt: "1",
471 | accept: "*/*",
472 | "sec-fetch-site": "same-origin",
473 | "sec-fetch-mode": "cors",
474 | "sec-fetch-dest": "font",
475 | "accept-encoding": "gzip, deflate, br",
476 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
477 | "sec-gpc": "1",
478 | },
479 | }
480 | );
481 | response = http.get(
482 | "https://www.meetup.com/_next/static/media/Graphik-Bold.6cf8492ed686fc8f8c3268c9c55d8ba7.woff2",
483 | {
484 | headers: {
485 | "cache-control": "no-cache",
486 | "sec-ch-ua":
487 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
488 | origin: "https://www.meetup.com",
489 | "sec-ch-ua-mobile": "?0",
490 | dnt: "1",
491 | accept: "*/*",
492 | "sec-fetch-site": "same-origin",
493 | "sec-fetch-mode": "cors",
494 | "sec-fetch-dest": "font",
495 | "accept-encoding": "gzip, deflate, br",
496 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
497 | "sec-gpc": "1",
498 | },
499 | }
500 | );
501 | response = http.get(
502 | "https://www.meetup.com/_next/static/media/Graphik-Semibold.1e706ac579d254bd92f758b39369570d.woff2",
503 | {
504 | headers: {
505 | "cache-control": "no-cache",
506 | "sec-ch-ua":
507 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
508 | origin: "https://www.meetup.com",
509 | "sec-ch-ua-mobile": "?0",
510 | dnt: "1",
511 | accept: "*/*",
512 | "sec-fetch-site": "same-origin",
513 | "sec-fetch-mode": "cors",
514 | "sec-fetch-dest": "font",
515 | "accept-encoding": "gzip, deflate, br",
516 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
517 | "sec-gpc": "1",
518 | },
519 | }
520 | );
521 | response = http.get(
522 | "https://www.meetup.com/_next/static/f4678ea91ab83c0aa83ff0cc207835e50aa56f87/_buildManifest.js",
523 | {
524 | headers: {
525 | "cache-control": "no-cache",
526 | "sec-ch-ua":
527 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
528 | dnt: "1",
529 | "sec-ch-ua-mobile": "?0",
530 | accept: "*/*",
531 | "sec-fetch-site": "same-origin",
532 | "sec-fetch-mode": "no-cors",
533 | "sec-fetch-dest": "script",
534 | "accept-encoding": "gzip, deflate, br",
535 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
536 | "sec-gpc": "1",
537 | },
538 | }
539 | );
540 | response = http.get(
541 | "https://www.meetup.com/_next/static/f4678ea91ab83c0aa83ff0cc207835e50aa56f87/_ssgManifest.js",
542 | {
543 | headers: {
544 | "cache-control": "no-cache",
545 | "sec-ch-ua":
546 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
547 | dnt: "1",
548 | "sec-ch-ua-mobile": "?0",
549 | accept: "*/*",
550 | "sec-fetch-site": "same-origin",
551 | "sec-fetch-mode": "no-cors",
552 | "sec-fetch-dest": "script",
553 | "accept-encoding": "gzip, deflate, br",
554 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
555 | "sec-gpc": "1",
556 | },
557 | }
558 | );
559 | sleep(0.9);
560 | response = http.get(
561 | "https://www.meetup.com/_next/static/css/3a8076264c44bd8dffcf.css",
562 | {
563 | headers: {
564 | "cache-control": "no-cache",
565 | "sec-ch-ua":
566 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
567 | dnt: "1",
568 | "sec-ch-ua-mobile": "?0",
569 | accept: "text/css,*/*;q=0.1",
570 | "sec-fetch-site": "same-origin",
571 | "sec-fetch-mode": "no-cors",
572 | "sec-fetch-dest": "style",
573 | "accept-encoding": "gzip, deflate, br",
574 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
575 | "sec-gpc": "1",
576 | },
577 | }
578 | );
579 | response = http.get(
580 | "https://www.meetup.com/_next/static/chunks/81.8c1c2c08edbbcb2376c8.js",
581 | {
582 | headers: {
583 | "cache-control": "no-cache",
584 | "sec-ch-ua":
585 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
586 | dnt: "1",
587 | "sec-ch-ua-mobile": "?0",
588 | accept: "*/*",
589 | "sec-fetch-site": "same-origin",
590 | "sec-fetch-mode": "no-cors",
591 | "sec-fetch-dest": "script",
592 | "accept-encoding": "gzip, deflate, br",
593 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
594 | "sec-gpc": "1",
595 | },
596 | }
597 | );
598 | response = http.get(
599 | "https://analytics-tracking.meetup.com/data?records=eyJyZWNvcmRzIjpbeyJzb3VyY2UiOiJidWlsZC1tZWV0dXAiLCJzY2hlbWFGdWxsbmFtZSI6ImNvbS5tZWV0dXAuYmFzZS5hdnJvLlZpZXciLCJzY2hlbWFWZXJzaW9uIjoidjIiLCJpc1Rlc3REYXRhIjpmYWxzZSwiZGF0YSI6IntcInZpZXdJZFwiOlwiZDRlNDZiODgtMjQxOC00ZDRlLTlmMjEtNWI5N2YwODc4ZmY0XCIsXCJicm93c2VySWRcIjpcIjA2Njc1NTZiLTBmZTUtNDAyMS05MmZiLTEzYTYzN2FjMWY0NFwiLFwiZGV2aWNlVGltZXN0YW1wXCI6XCIyMDIxLTA4LTA0VDE5OjQ3OjIyLjYzOS0wNDowMFwiLFwibWVtYmVySWRcIjowLFwicmVmZXJyZXJcIjpcImh0dHBzOi8vd3d3Lm1lZXR1cC5jb20vXCIsXCJwYWdlTmFtZVwiOlwiaG9tZXBhZ2VMb2dnZWRPdXRcIixcInZpZXdOYW1lXCI6XCJob21lcGFnZUxvZ2dlZE91dFwiLFwidmlld1R5cGVcIjpcInBhZ2VcIn0ifV0sIm1lbWJlcklkIjowLCJ2aWV3SWQiOiJkNGU0NmI4OC0yNDE4LTRkNGUtOWYyMS01Yjk3ZjA4NzhmZjQiLCJicm93c2VySWQiOiIwNjY3NTU2Yi0wZmU1LTQwMjEtOTJmYi0xM2E2MzdhYzFmNDQiLCJyZWZlcmVyIjoiaHR0cHM6Ly93d3cubWVldHVwLmNvbS8iLCJ1cmwiOiJodHRwczovL3d3dy5tZWV0dXAuY29tLyJ9",
600 | {
601 | headers: {
602 | "sec-ch-ua":
603 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
604 | DNT: "1",
605 | "sec-ch-ua-mobile": "?0",
606 | },
607 | }
608 | );
609 | sleep(0.5);
610 | response = http.get("https://www.meetup.com/img/favicon.ico", {
611 | headers: {
612 | "cache-control": "no-cache",
613 | "sec-ch-ua":
614 | '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
615 | dnt: "1",
616 | "sec-ch-ua-mobile": "?0",
617 | accept:
618 | "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
619 | "sec-fetch-site": "same-origin",
620 | "sec-fetch-mode": "no-cors",
621 | "sec-fetch-dest": "image",
622 | "accept-encoding": "gzip, deflate, br",
623 | "accept-language": "en-US,en;q=0.9,ja;q=0.8",
624 | "sec-gpc": "1",
625 | },
626 | });
627 | });
628 | }
629 |
630 |
--------------------------------------------------------------------------------
/playwright/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unlikelyzero/js-perf-toolkit/4004c02caea4683337619c03e5c79eed3c6dd55a/playwright/README.md
--------------------------------------------------------------------------------
/playwright/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "requires": true,
3 | "lockfileVersion": 1,
4 | "dependencies": {
5 | "@ampproject/remapping": {
6 | "version": "2.1.2",
7 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
8 | "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
9 | "dev": true,
10 | "requires": {
11 | "@jridgewell/trace-mapping": "^0.3.0"
12 | }
13 | },
14 | "@babel/code-frame": {
15 | "version": "7.16.7",
16 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
17 | "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
18 | "dev": true,
19 | "requires": {
20 | "@babel/highlight": "^7.16.7"
21 | }
22 | },
23 | "@babel/compat-data": {
24 | "version": "7.17.0",
25 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz",
26 | "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==",
27 | "dev": true
28 | },
29 | "@babel/core": {
30 | "version": "7.17.5",
31 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz",
32 | "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==",
33 | "dev": true,
34 | "requires": {
35 | "@ampproject/remapping": "^2.1.0",
36 | "@babel/code-frame": "^7.16.7",
37 | "@babel/generator": "^7.17.3",
38 | "@babel/helper-compilation-targets": "^7.16.7",
39 | "@babel/helper-module-transforms": "^7.16.7",
40 | "@babel/helpers": "^7.17.2",
41 | "@babel/parser": "^7.17.3",
42 | "@babel/template": "^7.16.7",
43 | "@babel/traverse": "^7.17.3",
44 | "@babel/types": "^7.17.0",
45 | "convert-source-map": "^1.7.0",
46 | "debug": "^4.1.0",
47 | "gensync": "^1.0.0-beta.2",
48 | "json5": "^2.1.2",
49 | "semver": "^6.3.0"
50 | }
51 | },
52 | "@babel/generator": {
53 | "version": "7.17.3",
54 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz",
55 | "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==",
56 | "dev": true,
57 | "requires": {
58 | "@babel/types": "^7.17.0",
59 | "jsesc": "^2.5.1",
60 | "source-map": "^0.5.0"
61 | }
62 | },
63 | "@babel/helper-annotate-as-pure": {
64 | "version": "7.16.7",
65 | "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
66 | "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
67 | "dev": true,
68 | "requires": {
69 | "@babel/types": "^7.16.7"
70 | }
71 | },
72 | "@babel/helper-compilation-targets": {
73 | "version": "7.16.7",
74 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz",
75 | "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==",
76 | "dev": true,
77 | "requires": {
78 | "@babel/compat-data": "^7.16.4",
79 | "@babel/helper-validator-option": "^7.16.7",
80 | "browserslist": "^4.17.5",
81 | "semver": "^6.3.0"
82 | }
83 | },
84 | "@babel/helper-create-class-features-plugin": {
85 | "version": "7.17.6",
86 | "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz",
87 | "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==",
88 | "dev": true,
89 | "requires": {
90 | "@babel/helper-annotate-as-pure": "^7.16.7",
91 | "@babel/helper-environment-visitor": "^7.16.7",
92 | "@babel/helper-function-name": "^7.16.7",
93 | "@babel/helper-member-expression-to-functions": "^7.16.7",
94 | "@babel/helper-optimise-call-expression": "^7.16.7",
95 | "@babel/helper-replace-supers": "^7.16.7",
96 | "@babel/helper-split-export-declaration": "^7.16.7"
97 | }
98 | },
99 | "@babel/helper-environment-visitor": {
100 | "version": "7.16.7",
101 | "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
102 | "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
103 | "dev": true,
104 | "requires": {
105 | "@babel/types": "^7.16.7"
106 | }
107 | },
108 | "@babel/helper-function-name": {
109 | "version": "7.16.7",
110 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
111 | "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
112 | "dev": true,
113 | "requires": {
114 | "@babel/helper-get-function-arity": "^7.16.7",
115 | "@babel/template": "^7.16.7",
116 | "@babel/types": "^7.16.7"
117 | }
118 | },
119 | "@babel/helper-get-function-arity": {
120 | "version": "7.16.7",
121 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
122 | "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
123 | "dev": true,
124 | "requires": {
125 | "@babel/types": "^7.16.7"
126 | }
127 | },
128 | "@babel/helper-hoist-variables": {
129 | "version": "7.16.7",
130 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
131 | "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
132 | "dev": true,
133 | "requires": {
134 | "@babel/types": "^7.16.7"
135 | }
136 | },
137 | "@babel/helper-member-expression-to-functions": {
138 | "version": "7.16.7",
139 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
140 | "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
141 | "dev": true,
142 | "requires": {
143 | "@babel/types": "^7.16.7"
144 | }
145 | },
146 | "@babel/helper-module-imports": {
147 | "version": "7.16.7",
148 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
149 | "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
150 | "dev": true,
151 | "requires": {
152 | "@babel/types": "^7.16.7"
153 | }
154 | },
155 | "@babel/helper-module-transforms": {
156 | "version": "7.17.6",
157 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz",
158 | "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==",
159 | "dev": true,
160 | "requires": {
161 | "@babel/helper-environment-visitor": "^7.16.7",
162 | "@babel/helper-module-imports": "^7.16.7",
163 | "@babel/helper-simple-access": "^7.16.7",
164 | "@babel/helper-split-export-declaration": "^7.16.7",
165 | "@babel/helper-validator-identifier": "^7.16.7",
166 | "@babel/template": "^7.16.7",
167 | "@babel/traverse": "^7.17.3",
168 | "@babel/types": "^7.17.0"
169 | }
170 | },
171 | "@babel/helper-optimise-call-expression": {
172 | "version": "7.16.7",
173 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
174 | "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
175 | "dev": true,
176 | "requires": {
177 | "@babel/types": "^7.16.7"
178 | }
179 | },
180 | "@babel/helper-plugin-utils": {
181 | "version": "7.16.7",
182 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
183 | "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
184 | "dev": true
185 | },
186 | "@babel/helper-replace-supers": {
187 | "version": "7.16.7",
188 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
189 | "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
190 | "dev": true,
191 | "requires": {
192 | "@babel/helper-environment-visitor": "^7.16.7",
193 | "@babel/helper-member-expression-to-functions": "^7.16.7",
194 | "@babel/helper-optimise-call-expression": "^7.16.7",
195 | "@babel/traverse": "^7.16.7",
196 | "@babel/types": "^7.16.7"
197 | }
198 | },
199 | "@babel/helper-simple-access": {
200 | "version": "7.16.7",
201 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
202 | "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
203 | "dev": true,
204 | "requires": {
205 | "@babel/types": "^7.16.7"
206 | }
207 | },
208 | "@babel/helper-skip-transparent-expression-wrappers": {
209 | "version": "7.16.0",
210 | "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
211 | "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
212 | "dev": true,
213 | "requires": {
214 | "@babel/types": "^7.16.0"
215 | }
216 | },
217 | "@babel/helper-split-export-declaration": {
218 | "version": "7.16.7",
219 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
220 | "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
221 | "dev": true,
222 | "requires": {
223 | "@babel/types": "^7.16.7"
224 | }
225 | },
226 | "@babel/helper-validator-identifier": {
227 | "version": "7.16.7",
228 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
229 | "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
230 | "dev": true
231 | },
232 | "@babel/helper-validator-option": {
233 | "version": "7.16.7",
234 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
235 | "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
236 | "dev": true
237 | },
238 | "@babel/helpers": {
239 | "version": "7.17.2",
240 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz",
241 | "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==",
242 | "dev": true,
243 | "requires": {
244 | "@babel/template": "^7.16.7",
245 | "@babel/traverse": "^7.17.0",
246 | "@babel/types": "^7.17.0"
247 | }
248 | },
249 | "@babel/highlight": {
250 | "version": "7.16.10",
251 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
252 | "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
253 | "dev": true,
254 | "requires": {
255 | "@babel/helper-validator-identifier": "^7.16.7",
256 | "chalk": "^2.0.0",
257 | "js-tokens": "^4.0.0"
258 | }
259 | },
260 | "@babel/parser": {
261 | "version": "7.17.3",
262 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz",
263 | "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==",
264 | "dev": true
265 | },
266 | "@babel/plugin-proposal-class-properties": {
267 | "version": "7.16.7",
268 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
269 | "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
270 | "dev": true,
271 | "requires": {
272 | "@babel/helper-create-class-features-plugin": "^7.16.7",
273 | "@babel/helper-plugin-utils": "^7.16.7"
274 | }
275 | },
276 | "@babel/plugin-proposal-dynamic-import": {
277 | "version": "7.16.7",
278 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
279 | "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
280 | "dev": true,
281 | "requires": {
282 | "@babel/helper-plugin-utils": "^7.16.7",
283 | "@babel/plugin-syntax-dynamic-import": "^7.8.3"
284 | }
285 | },
286 | "@babel/plugin-proposal-export-namespace-from": {
287 | "version": "7.16.7",
288 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
289 | "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
290 | "dev": true,
291 | "requires": {
292 | "@babel/helper-plugin-utils": "^7.16.7",
293 | "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
294 | }
295 | },
296 | "@babel/plugin-proposal-logical-assignment-operators": {
297 | "version": "7.16.7",
298 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
299 | "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
300 | "dev": true,
301 | "requires": {
302 | "@babel/helper-plugin-utils": "^7.16.7",
303 | "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
304 | }
305 | },
306 | "@babel/plugin-proposal-nullish-coalescing-operator": {
307 | "version": "7.16.7",
308 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
309 | "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
310 | "dev": true,
311 | "requires": {
312 | "@babel/helper-plugin-utils": "^7.16.7",
313 | "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
314 | }
315 | },
316 | "@babel/plugin-proposal-numeric-separator": {
317 | "version": "7.16.7",
318 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
319 | "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
320 | "dev": true,
321 | "requires": {
322 | "@babel/helper-plugin-utils": "^7.16.7",
323 | "@babel/plugin-syntax-numeric-separator": "^7.10.4"
324 | }
325 | },
326 | "@babel/plugin-proposal-optional-chaining": {
327 | "version": "7.16.7",
328 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
329 | "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
330 | "dev": true,
331 | "requires": {
332 | "@babel/helper-plugin-utils": "^7.16.7",
333 | "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
334 | "@babel/plugin-syntax-optional-chaining": "^7.8.3"
335 | }
336 | },
337 | "@babel/plugin-proposal-private-methods": {
338 | "version": "7.16.11",
339 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
340 | "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
341 | "dev": true,
342 | "requires": {
343 | "@babel/helper-create-class-features-plugin": "^7.16.10",
344 | "@babel/helper-plugin-utils": "^7.16.7"
345 | }
346 | },
347 | "@babel/plugin-proposal-private-property-in-object": {
348 | "version": "7.16.7",
349 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
350 | "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
351 | "dev": true,
352 | "requires": {
353 | "@babel/helper-annotate-as-pure": "^7.16.7",
354 | "@babel/helper-create-class-features-plugin": "^7.16.7",
355 | "@babel/helper-plugin-utils": "^7.16.7",
356 | "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
357 | }
358 | },
359 | "@babel/plugin-syntax-async-generators": {
360 | "version": "7.8.4",
361 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
362 | "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
363 | "dev": true,
364 | "requires": {
365 | "@babel/helper-plugin-utils": "^7.8.0"
366 | }
367 | },
368 | "@babel/plugin-syntax-dynamic-import": {
369 | "version": "7.8.3",
370 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
371 | "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
372 | "dev": true,
373 | "requires": {
374 | "@babel/helper-plugin-utils": "^7.8.0"
375 | }
376 | },
377 | "@babel/plugin-syntax-export-namespace-from": {
378 | "version": "7.8.3",
379 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
380 | "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
381 | "dev": true,
382 | "requires": {
383 | "@babel/helper-plugin-utils": "^7.8.3"
384 | }
385 | },
386 | "@babel/plugin-syntax-json-strings": {
387 | "version": "7.8.3",
388 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
389 | "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
390 | "dev": true,
391 | "requires": {
392 | "@babel/helper-plugin-utils": "^7.8.0"
393 | }
394 | },
395 | "@babel/plugin-syntax-jsx": {
396 | "version": "7.16.7",
397 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
398 | "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
399 | "dev": true,
400 | "requires": {
401 | "@babel/helper-plugin-utils": "^7.16.7"
402 | }
403 | },
404 | "@babel/plugin-syntax-logical-assignment-operators": {
405 | "version": "7.10.4",
406 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
407 | "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
408 | "dev": true,
409 | "requires": {
410 | "@babel/helper-plugin-utils": "^7.10.4"
411 | }
412 | },
413 | "@babel/plugin-syntax-nullish-coalescing-operator": {
414 | "version": "7.8.3",
415 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
416 | "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
417 | "dev": true,
418 | "requires": {
419 | "@babel/helper-plugin-utils": "^7.8.0"
420 | }
421 | },
422 | "@babel/plugin-syntax-numeric-separator": {
423 | "version": "7.10.4",
424 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
425 | "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
426 | "dev": true,
427 | "requires": {
428 | "@babel/helper-plugin-utils": "^7.10.4"
429 | }
430 | },
431 | "@babel/plugin-syntax-object-rest-spread": {
432 | "version": "7.8.3",
433 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
434 | "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
435 | "dev": true,
436 | "requires": {
437 | "@babel/helper-plugin-utils": "^7.8.0"
438 | }
439 | },
440 | "@babel/plugin-syntax-optional-catch-binding": {
441 | "version": "7.8.3",
442 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
443 | "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
444 | "dev": true,
445 | "requires": {
446 | "@babel/helper-plugin-utils": "^7.8.0"
447 | }
448 | },
449 | "@babel/plugin-syntax-optional-chaining": {
450 | "version": "7.8.3",
451 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
452 | "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
453 | "dev": true,
454 | "requires": {
455 | "@babel/helper-plugin-utils": "^7.8.0"
456 | }
457 | },
458 | "@babel/plugin-syntax-private-property-in-object": {
459 | "version": "7.14.5",
460 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
461 | "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
462 | "dev": true,
463 | "requires": {
464 | "@babel/helper-plugin-utils": "^7.14.5"
465 | }
466 | },
467 | "@babel/plugin-syntax-typescript": {
468 | "version": "7.16.7",
469 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz",
470 | "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==",
471 | "dev": true,
472 | "requires": {
473 | "@babel/helper-plugin-utils": "^7.16.7"
474 | }
475 | },
476 | "@babel/plugin-transform-modules-commonjs": {
477 | "version": "7.16.8",
478 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
479 | "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
480 | "dev": true,
481 | "requires": {
482 | "@babel/helper-module-transforms": "^7.16.7",
483 | "@babel/helper-plugin-utils": "^7.16.7",
484 | "@babel/helper-simple-access": "^7.16.7",
485 | "babel-plugin-dynamic-import-node": "^2.3.3"
486 | }
487 | },
488 | "@babel/plugin-transform-react-jsx": {
489 | "version": "7.17.3",
490 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz",
491 | "integrity": "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==",
492 | "dev": true,
493 | "requires": {
494 | "@babel/helper-annotate-as-pure": "^7.16.7",
495 | "@babel/helper-module-imports": "^7.16.7",
496 | "@babel/helper-plugin-utils": "^7.16.7",
497 | "@babel/plugin-syntax-jsx": "^7.16.7",
498 | "@babel/types": "^7.17.0"
499 | }
500 | },
501 | "@babel/plugin-transform-typescript": {
502 | "version": "7.16.8",
503 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz",
504 | "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==",
505 | "dev": true,
506 | "requires": {
507 | "@babel/helper-create-class-features-plugin": "^7.16.7",
508 | "@babel/helper-plugin-utils": "^7.16.7",
509 | "@babel/plugin-syntax-typescript": "^7.16.7"
510 | }
511 | },
512 | "@babel/preset-typescript": {
513 | "version": "7.16.7",
514 | "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz",
515 | "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==",
516 | "dev": true,
517 | "requires": {
518 | "@babel/helper-plugin-utils": "^7.16.7",
519 | "@babel/helper-validator-option": "^7.16.7",
520 | "@babel/plugin-transform-typescript": "^7.16.7"
521 | }
522 | },
523 | "@babel/template": {
524 | "version": "7.16.7",
525 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
526 | "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
527 | "dev": true,
528 | "requires": {
529 | "@babel/code-frame": "^7.16.7",
530 | "@babel/parser": "^7.16.7",
531 | "@babel/types": "^7.16.7"
532 | }
533 | },
534 | "@babel/traverse": {
535 | "version": "7.17.3",
536 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
537 | "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
538 | "dev": true,
539 | "requires": {
540 | "@babel/code-frame": "^7.16.7",
541 | "@babel/generator": "^7.17.3",
542 | "@babel/helper-environment-visitor": "^7.16.7",
543 | "@babel/helper-function-name": "^7.16.7",
544 | "@babel/helper-hoist-variables": "^7.16.7",
545 | "@babel/helper-split-export-declaration": "^7.16.7",
546 | "@babel/parser": "^7.17.3",
547 | "@babel/types": "^7.17.0",
548 | "debug": "^4.1.0",
549 | "globals": "^11.1.0"
550 | }
551 | },
552 | "@babel/types": {
553 | "version": "7.17.0",
554 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
555 | "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
556 | "dev": true,
557 | "requires": {
558 | "@babel/helper-validator-identifier": "^7.16.7",
559 | "to-fast-properties": "^2.0.0"
560 | }
561 | },
562 | "@jest/types": {
563 | "version": "27.5.1",
564 | "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz",
565 | "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==",
566 | "dev": true,
567 | "requires": {
568 | "@types/istanbul-lib-coverage": "^2.0.0",
569 | "@types/istanbul-reports": "^3.0.0",
570 | "@types/node": "*",
571 | "@types/yargs": "^16.0.0",
572 | "chalk": "^4.0.0"
573 | },
574 | "dependencies": {
575 | "ansi-styles": {
576 | "version": "4.3.0",
577 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
578 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
579 | "dev": true,
580 | "requires": {
581 | "color-convert": "^2.0.1"
582 | }
583 | },
584 | "chalk": {
585 | "version": "4.1.2",
586 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
587 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
588 | "dev": true,
589 | "requires": {
590 | "ansi-styles": "^4.1.0",
591 | "supports-color": "^7.1.0"
592 | }
593 | },
594 | "color-convert": {
595 | "version": "2.0.1",
596 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
597 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
598 | "dev": true,
599 | "requires": {
600 | "color-name": "~1.1.4"
601 | }
602 | },
603 | "color-name": {
604 | "version": "1.1.4",
605 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
606 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
607 | "dev": true
608 | },
609 | "has-flag": {
610 | "version": "4.0.0",
611 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
612 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
613 | "dev": true
614 | },
615 | "supports-color": {
616 | "version": "7.2.0",
617 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
618 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
619 | "dev": true,
620 | "requires": {
621 | "has-flag": "^4.0.0"
622 | }
623 | }
624 | }
625 | },
626 | "@jridgewell/resolve-uri": {
627 | "version": "3.0.5",
628 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
629 | "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
630 | "dev": true
631 | },
632 | "@jridgewell/sourcemap-codec": {
633 | "version": "1.4.11",
634 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
635 | "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==",
636 | "dev": true
637 | },
638 | "@jridgewell/trace-mapping": {
639 | "version": "0.3.4",
640 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz",
641 | "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==",
642 | "dev": true,
643 | "requires": {
644 | "@jridgewell/resolve-uri": "^3.0.3",
645 | "@jridgewell/sourcemap-codec": "^1.4.10"
646 | }
647 | },
648 | "@playwright/test": {
649 | "version": "1.18.1",
650 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.18.1.tgz",
651 | "integrity": "sha512-v6jAM2GpRvf4MUvSLkrAXg101XT9mLu2X2NbCnEoj7GHBXwavDlAJDMwh4Hn8oipDxB6MS6FTcr7opXsIMNwrA==",
652 | "dev": true,
653 | "requires": {
654 | "@babel/code-frame": "^7.14.5",
655 | "@babel/core": "^7.14.8",
656 | "@babel/plugin-proposal-class-properties": "^7.14.5",
657 | "@babel/plugin-proposal-dynamic-import": "^7.14.5",
658 | "@babel/plugin-proposal-export-namespace-from": "^7.14.5",
659 | "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
660 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
661 | "@babel/plugin-proposal-numeric-separator": "^7.14.5",
662 | "@babel/plugin-proposal-optional-chaining": "^7.14.5",
663 | "@babel/plugin-proposal-private-methods": "^7.14.5",
664 | "@babel/plugin-proposal-private-property-in-object": "^7.14.5",
665 | "@babel/plugin-syntax-async-generators": "^7.8.4",
666 | "@babel/plugin-syntax-json-strings": "^7.8.3",
667 | "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
668 | "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
669 | "@babel/plugin-transform-modules-commonjs": "^7.14.5",
670 | "@babel/plugin-transform-react-jsx": "^7.14.5",
671 | "@babel/preset-typescript": "^7.14.5",
672 | "babel-plugin-module-resolver": "^4.1.0",
673 | "colors": "1.4.0",
674 | "commander": "^8.2.0",
675 | "debug": "^4.1.1",
676 | "expect": "=27.2.5",
677 | "jest-matcher-utils": "=27.2.5",
678 | "jpeg-js": "^0.4.2",
679 | "json5": "^2.2.0",
680 | "mime": "^2.4.6",
681 | "minimatch": "^3.0.3",
682 | "ms": "^2.1.2",
683 | "open": "^8.3.0",
684 | "pirates": "^4.0.1",
685 | "pixelmatch": "^5.2.1",
686 | "playwright-core": "=1.18.1",
687 | "pngjs": "^5.0.0",
688 | "rimraf": "^3.0.2",
689 | "source-map-support": "^0.4.18",
690 | "stack-utils": "^2.0.3",
691 | "yazl": "^2.5.1"
692 | },
693 | "dependencies": {
694 | "playwright-core": {
695 | "version": "1.18.1",
696 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.18.1.tgz",
697 | "integrity": "sha512-NALGl8R1GHzGLlhUApmpmfh6M1rrrPcDTygWvhTbprxwGB9qd/j9DRwyn4HTQcUB6o0/VOpo46fH9ez3+D/Rog==",
698 | "dev": true,
699 | "requires": {
700 | "commander": "^8.2.0",
701 | "debug": "^4.1.1",
702 | "extract-zip": "^2.0.1",
703 | "https-proxy-agent": "^5.0.0",
704 | "jpeg-js": "^0.4.2",
705 | "mime": "^2.4.6",
706 | "pngjs": "^5.0.0",
707 | "progress": "^2.0.3",
708 | "proper-lockfile": "^4.1.1",
709 | "proxy-from-env": "^1.1.0",
710 | "rimraf": "^3.0.2",
711 | "socks-proxy-agent": "^6.1.0",
712 | "stack-utils": "^2.0.3",
713 | "ws": "^7.4.6",
714 | "yauzl": "^2.10.0",
715 | "yazl": "^2.5.1"
716 | }
717 | }
718 | }
719 | },
720 | "@types/istanbul-lib-coverage": {
721 | "version": "2.0.4",
722 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
723 | "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
724 | "dev": true
725 | },
726 | "@types/istanbul-lib-report": {
727 | "version": "3.0.0",
728 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
729 | "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
730 | "dev": true,
731 | "requires": {
732 | "@types/istanbul-lib-coverage": "*"
733 | }
734 | },
735 | "@types/istanbul-reports": {
736 | "version": "3.0.1",
737 | "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
738 | "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
739 | "dev": true,
740 | "requires": {
741 | "@types/istanbul-lib-report": "*"
742 | }
743 | },
744 | "@types/node": {
745 | "version": "17.0.21",
746 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
747 | "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
748 | "dev": true
749 | },
750 | "@types/stack-utils": {
751 | "version": "2.0.1",
752 | "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
753 | "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
754 | "dev": true
755 | },
756 | "@types/yargs": {
757 | "version": "16.0.4",
758 | "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz",
759 | "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==",
760 | "dev": true,
761 | "requires": {
762 | "@types/yargs-parser": "*"
763 | }
764 | },
765 | "@types/yargs-parser": {
766 | "version": "21.0.0",
767 | "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
768 | "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
769 | "dev": true
770 | },
771 | "@types/yauzl": {
772 | "version": "2.9.2",
773 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
774 | "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
775 | "dev": true,
776 | "optional": true,
777 | "requires": {
778 | "@types/node": "*"
779 | }
780 | },
781 | "agent-base": {
782 | "version": "6.0.2",
783 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
784 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
785 | "dev": true,
786 | "requires": {
787 | "debug": "4"
788 | }
789 | },
790 | "ansi-regex": {
791 | "version": "5.0.1",
792 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
793 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
794 | "dev": true
795 | },
796 | "ansi-styles": {
797 | "version": "3.2.1",
798 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
799 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
800 | "dev": true,
801 | "requires": {
802 | "color-convert": "^1.9.0"
803 | }
804 | },
805 | "babel-plugin-dynamic-import-node": {
806 | "version": "2.3.3",
807 | "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
808 | "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
809 | "dev": true,
810 | "requires": {
811 | "object.assign": "^4.1.0"
812 | }
813 | },
814 | "babel-plugin-module-resolver": {
815 | "version": "4.1.0",
816 | "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz",
817 | "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==",
818 | "dev": true,
819 | "requires": {
820 | "find-babel-config": "^1.2.0",
821 | "glob": "^7.1.6",
822 | "pkg-up": "^3.1.0",
823 | "reselect": "^4.0.0",
824 | "resolve": "^1.13.1"
825 | }
826 | },
827 | "balanced-match": {
828 | "version": "1.0.2",
829 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
830 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
831 | "dev": true
832 | },
833 | "brace-expansion": {
834 | "version": "1.1.11",
835 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
836 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
837 | "dev": true,
838 | "requires": {
839 | "balanced-match": "^1.0.0",
840 | "concat-map": "0.0.1"
841 | }
842 | },
843 | "braces": {
844 | "version": "3.0.2",
845 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
846 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
847 | "dev": true,
848 | "requires": {
849 | "fill-range": "^7.0.1"
850 | }
851 | },
852 | "browserslist": {
853 | "version": "4.20.0",
854 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz",
855 | "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==",
856 | "dev": true,
857 | "requires": {
858 | "caniuse-lite": "^1.0.30001313",
859 | "electron-to-chromium": "^1.4.76",
860 | "escalade": "^3.1.1",
861 | "node-releases": "^2.0.2",
862 | "picocolors": "^1.0.0"
863 | }
864 | },
865 | "buffer-crc32": {
866 | "version": "0.2.13",
867 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
868 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
869 | "dev": true
870 | },
871 | "call-bind": {
872 | "version": "1.0.2",
873 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
874 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
875 | "dev": true,
876 | "requires": {
877 | "function-bind": "^1.1.1",
878 | "get-intrinsic": "^1.0.2"
879 | }
880 | },
881 | "caniuse-lite": {
882 | "version": "1.0.30001314",
883 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz",
884 | "integrity": "sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw==",
885 | "dev": true
886 | },
887 | "chalk": {
888 | "version": "2.4.2",
889 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
890 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
891 | "dev": true,
892 | "requires": {
893 | "ansi-styles": "^3.2.1",
894 | "escape-string-regexp": "^1.0.5",
895 | "supports-color": "^5.3.0"
896 | }
897 | },
898 | "color-convert": {
899 | "version": "1.9.3",
900 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
901 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
902 | "dev": true,
903 | "requires": {
904 | "color-name": "1.1.3"
905 | }
906 | },
907 | "color-name": {
908 | "version": "1.1.3",
909 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
910 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
911 | "dev": true
912 | },
913 | "colors": {
914 | "version": "1.4.0",
915 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
916 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
917 | "dev": true
918 | },
919 | "commander": {
920 | "version": "8.3.0",
921 | "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
922 | "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
923 | "dev": true
924 | },
925 | "concat-map": {
926 | "version": "0.0.1",
927 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
928 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
929 | "dev": true
930 | },
931 | "convert-source-map": {
932 | "version": "1.8.0",
933 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
934 | "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
935 | "dev": true,
936 | "requires": {
937 | "safe-buffer": "~5.1.1"
938 | }
939 | },
940 | "debug": {
941 | "version": "4.3.3",
942 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
943 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
944 | "dev": true,
945 | "requires": {
946 | "ms": "2.1.2"
947 | },
948 | "dependencies": {
949 | "ms": {
950 | "version": "2.1.2",
951 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
952 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
953 | "dev": true
954 | }
955 | }
956 | },
957 | "define-lazy-prop": {
958 | "version": "2.0.0",
959 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
960 | "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
961 | "dev": true
962 | },
963 | "define-properties": {
964 | "version": "1.1.3",
965 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
966 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
967 | "dev": true,
968 | "requires": {
969 | "object-keys": "^1.0.12"
970 | }
971 | },
972 | "diff-sequences": {
973 | "version": "27.5.1",
974 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
975 | "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
976 | "dev": true
977 | },
978 | "electron-to-chromium": {
979 | "version": "1.4.80",
980 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.80.tgz",
981 | "integrity": "sha512-COsbJCGVYCc/aAY4cd94x1Js3q0r406YKGbdL8LXHg0O9dEjuFEFU/vZneRxBxKo/f1lLHi0YyAR7sbFM+i8Bg==",
982 | "dev": true
983 | },
984 | "end-of-stream": {
985 | "version": "1.4.4",
986 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
987 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
988 | "dev": true,
989 | "requires": {
990 | "once": "^1.4.0"
991 | }
992 | },
993 | "escalade": {
994 | "version": "3.1.1",
995 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
996 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
997 | "dev": true
998 | },
999 | "escape-string-regexp": {
1000 | "version": "1.0.5",
1001 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1002 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
1003 | "dev": true
1004 | },
1005 | "expect": {
1006 | "version": "27.2.5",
1007 | "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.5.tgz",
1008 | "integrity": "sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==",
1009 | "dev": true,
1010 | "requires": {
1011 | "@jest/types": "^27.2.5",
1012 | "ansi-styles": "^5.0.0",
1013 | "jest-get-type": "^27.0.6",
1014 | "jest-matcher-utils": "^27.2.5",
1015 | "jest-message-util": "^27.2.5",
1016 | "jest-regex-util": "^27.0.6"
1017 | },
1018 | "dependencies": {
1019 | "ansi-styles": {
1020 | "version": "5.2.0",
1021 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
1022 | "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
1023 | "dev": true
1024 | }
1025 | }
1026 | },
1027 | "extract-zip": {
1028 | "version": "2.0.1",
1029 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
1030 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
1031 | "dev": true,
1032 | "requires": {
1033 | "@types/yauzl": "^2.9.1",
1034 | "debug": "^4.1.1",
1035 | "get-stream": "^5.1.0",
1036 | "yauzl": "^2.10.0"
1037 | }
1038 | },
1039 | "fd-slicer": {
1040 | "version": "1.1.0",
1041 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
1042 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
1043 | "dev": true,
1044 | "requires": {
1045 | "pend": "~1.2.0"
1046 | }
1047 | },
1048 | "fill-range": {
1049 | "version": "7.0.1",
1050 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1051 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1052 | "dev": true,
1053 | "requires": {
1054 | "to-regex-range": "^5.0.1"
1055 | }
1056 | },
1057 | "find-babel-config": {
1058 | "version": "1.2.0",
1059 | "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz",
1060 | "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==",
1061 | "dev": true,
1062 | "requires": {
1063 | "json5": "^0.5.1",
1064 | "path-exists": "^3.0.0"
1065 | },
1066 | "dependencies": {
1067 | "json5": {
1068 | "version": "0.5.1",
1069 | "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
1070 | "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
1071 | "dev": true
1072 | }
1073 | }
1074 | },
1075 | "find-up": {
1076 | "version": "3.0.0",
1077 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
1078 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
1079 | "dev": true,
1080 | "requires": {
1081 | "locate-path": "^3.0.0"
1082 | }
1083 | },
1084 | "fs.realpath": {
1085 | "version": "1.0.0",
1086 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1087 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
1088 | "dev": true
1089 | },
1090 | "function-bind": {
1091 | "version": "1.1.1",
1092 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1093 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
1094 | "dev": true
1095 | },
1096 | "gensync": {
1097 | "version": "1.0.0-beta.2",
1098 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1099 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1100 | "dev": true
1101 | },
1102 | "get-intrinsic": {
1103 | "version": "1.1.1",
1104 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
1105 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
1106 | "dev": true,
1107 | "requires": {
1108 | "function-bind": "^1.1.1",
1109 | "has": "^1.0.3",
1110 | "has-symbols": "^1.0.1"
1111 | }
1112 | },
1113 | "get-stream": {
1114 | "version": "5.2.0",
1115 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
1116 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
1117 | "dev": true,
1118 | "requires": {
1119 | "pump": "^3.0.0"
1120 | }
1121 | },
1122 | "glob": {
1123 | "version": "7.2.0",
1124 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
1125 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
1126 | "dev": true,
1127 | "requires": {
1128 | "fs.realpath": "^1.0.0",
1129 | "inflight": "^1.0.4",
1130 | "inherits": "2",
1131 | "minimatch": "^3.0.4",
1132 | "once": "^1.3.0",
1133 | "path-is-absolute": "^1.0.0"
1134 | }
1135 | },
1136 | "globals": {
1137 | "version": "11.12.0",
1138 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
1139 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
1140 | "dev": true
1141 | },
1142 | "graceful-fs": {
1143 | "version": "4.2.9",
1144 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
1145 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
1146 | "dev": true
1147 | },
1148 | "has": {
1149 | "version": "1.0.3",
1150 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1151 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1152 | "dev": true,
1153 | "requires": {
1154 | "function-bind": "^1.1.1"
1155 | }
1156 | },
1157 | "has-flag": {
1158 | "version": "3.0.0",
1159 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
1160 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
1161 | "dev": true
1162 | },
1163 | "has-symbols": {
1164 | "version": "1.0.3",
1165 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1166 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
1167 | "dev": true
1168 | },
1169 | "https-proxy-agent": {
1170 | "version": "5.0.0",
1171 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
1172 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
1173 | "dev": true,
1174 | "requires": {
1175 | "agent-base": "6",
1176 | "debug": "4"
1177 | }
1178 | },
1179 | "inflight": {
1180 | "version": "1.0.6",
1181 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1182 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1183 | "dev": true,
1184 | "requires": {
1185 | "once": "^1.3.0",
1186 | "wrappy": "1"
1187 | }
1188 | },
1189 | "inherits": {
1190 | "version": "2.0.4",
1191 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1192 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1193 | "dev": true
1194 | },
1195 | "ip": {
1196 | "version": "1.1.5",
1197 | "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
1198 | "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
1199 | "dev": true
1200 | },
1201 | "is-core-module": {
1202 | "version": "2.8.1",
1203 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
1204 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
1205 | "dev": true,
1206 | "requires": {
1207 | "has": "^1.0.3"
1208 | }
1209 | },
1210 | "is-docker": {
1211 | "version": "2.2.1",
1212 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
1213 | "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
1214 | "dev": true
1215 | },
1216 | "is-number": {
1217 | "version": "7.0.0",
1218 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1219 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1220 | "dev": true
1221 | },
1222 | "is-wsl": {
1223 | "version": "2.2.0",
1224 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
1225 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
1226 | "dev": true,
1227 | "requires": {
1228 | "is-docker": "^2.0.0"
1229 | }
1230 | },
1231 | "jest-diff": {
1232 | "version": "27.5.1",
1233 | "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
1234 | "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
1235 | "dev": true,
1236 | "requires": {
1237 | "chalk": "^4.0.0",
1238 | "diff-sequences": "^27.5.1",
1239 | "jest-get-type": "^27.5.1",
1240 | "pretty-format": "^27.5.1"
1241 | },
1242 | "dependencies": {
1243 | "ansi-styles": {
1244 | "version": "4.3.0",
1245 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1246 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1247 | "dev": true,
1248 | "requires": {
1249 | "color-convert": "^2.0.1"
1250 | }
1251 | },
1252 | "chalk": {
1253 | "version": "4.1.2",
1254 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1255 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1256 | "dev": true,
1257 | "requires": {
1258 | "ansi-styles": "^4.1.0",
1259 | "supports-color": "^7.1.0"
1260 | }
1261 | },
1262 | "color-convert": {
1263 | "version": "2.0.1",
1264 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1265 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1266 | "dev": true,
1267 | "requires": {
1268 | "color-name": "~1.1.4"
1269 | }
1270 | },
1271 | "color-name": {
1272 | "version": "1.1.4",
1273 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1274 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1275 | "dev": true
1276 | },
1277 | "has-flag": {
1278 | "version": "4.0.0",
1279 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1280 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1281 | "dev": true
1282 | },
1283 | "supports-color": {
1284 | "version": "7.2.0",
1285 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1286 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1287 | "dev": true,
1288 | "requires": {
1289 | "has-flag": "^4.0.0"
1290 | }
1291 | }
1292 | }
1293 | },
1294 | "jest-get-type": {
1295 | "version": "27.5.1",
1296 | "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
1297 | "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
1298 | "dev": true
1299 | },
1300 | "jest-matcher-utils": {
1301 | "version": "27.2.5",
1302 | "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz",
1303 | "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==",
1304 | "dev": true,
1305 | "requires": {
1306 | "chalk": "^4.0.0",
1307 | "jest-diff": "^27.2.5",
1308 | "jest-get-type": "^27.0.6",
1309 | "pretty-format": "^27.2.5"
1310 | },
1311 | "dependencies": {
1312 | "ansi-styles": {
1313 | "version": "4.3.0",
1314 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1315 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1316 | "dev": true,
1317 | "requires": {
1318 | "color-convert": "^2.0.1"
1319 | }
1320 | },
1321 | "chalk": {
1322 | "version": "4.1.2",
1323 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1324 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1325 | "dev": true,
1326 | "requires": {
1327 | "ansi-styles": "^4.1.0",
1328 | "supports-color": "^7.1.0"
1329 | }
1330 | },
1331 | "color-convert": {
1332 | "version": "2.0.1",
1333 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1334 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1335 | "dev": true,
1336 | "requires": {
1337 | "color-name": "~1.1.4"
1338 | }
1339 | },
1340 | "color-name": {
1341 | "version": "1.1.4",
1342 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1343 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1344 | "dev": true
1345 | },
1346 | "has-flag": {
1347 | "version": "4.0.0",
1348 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1349 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1350 | "dev": true
1351 | },
1352 | "supports-color": {
1353 | "version": "7.2.0",
1354 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1355 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1356 | "dev": true,
1357 | "requires": {
1358 | "has-flag": "^4.0.0"
1359 | }
1360 | }
1361 | }
1362 | },
1363 | "jest-message-util": {
1364 | "version": "27.5.1",
1365 | "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz",
1366 | "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==",
1367 | "dev": true,
1368 | "requires": {
1369 | "@babel/code-frame": "^7.12.13",
1370 | "@jest/types": "^27.5.1",
1371 | "@types/stack-utils": "^2.0.0",
1372 | "chalk": "^4.0.0",
1373 | "graceful-fs": "^4.2.9",
1374 | "micromatch": "^4.0.4",
1375 | "pretty-format": "^27.5.1",
1376 | "slash": "^3.0.0",
1377 | "stack-utils": "^2.0.3"
1378 | },
1379 | "dependencies": {
1380 | "ansi-styles": {
1381 | "version": "4.3.0",
1382 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1383 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1384 | "dev": true,
1385 | "requires": {
1386 | "color-convert": "^2.0.1"
1387 | }
1388 | },
1389 | "chalk": {
1390 | "version": "4.1.2",
1391 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1392 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1393 | "dev": true,
1394 | "requires": {
1395 | "ansi-styles": "^4.1.0",
1396 | "supports-color": "^7.1.0"
1397 | }
1398 | },
1399 | "color-convert": {
1400 | "version": "2.0.1",
1401 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1402 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1403 | "dev": true,
1404 | "requires": {
1405 | "color-name": "~1.1.4"
1406 | }
1407 | },
1408 | "color-name": {
1409 | "version": "1.1.4",
1410 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1411 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1412 | "dev": true
1413 | },
1414 | "has-flag": {
1415 | "version": "4.0.0",
1416 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1417 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1418 | "dev": true
1419 | },
1420 | "supports-color": {
1421 | "version": "7.2.0",
1422 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1423 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1424 | "dev": true,
1425 | "requires": {
1426 | "has-flag": "^4.0.0"
1427 | }
1428 | }
1429 | }
1430 | },
1431 | "jest-regex-util": {
1432 | "version": "27.5.1",
1433 | "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz",
1434 | "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==",
1435 | "dev": true
1436 | },
1437 | "jpeg-js": {
1438 | "version": "0.4.3",
1439 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz",
1440 | "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==",
1441 | "dev": true
1442 | },
1443 | "js-tokens": {
1444 | "version": "4.0.0",
1445 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1446 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1447 | "dev": true
1448 | },
1449 | "jsesc": {
1450 | "version": "2.5.2",
1451 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
1452 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
1453 | "dev": true
1454 | },
1455 | "json5": {
1456 | "version": "2.2.0",
1457 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
1458 | "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
1459 | "dev": true,
1460 | "requires": {
1461 | "minimist": "^1.2.5"
1462 | }
1463 | },
1464 | "locate-path": {
1465 | "version": "3.0.0",
1466 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
1467 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
1468 | "dev": true,
1469 | "requires": {
1470 | "p-locate": "^3.0.0",
1471 | "path-exists": "^3.0.0"
1472 | }
1473 | },
1474 | "micromatch": {
1475 | "version": "4.0.4",
1476 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
1477 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
1478 | "dev": true,
1479 | "requires": {
1480 | "braces": "^3.0.1",
1481 | "picomatch": "^2.2.3"
1482 | }
1483 | },
1484 | "mime": {
1485 | "version": "2.6.0",
1486 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
1487 | "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
1488 | "dev": true
1489 | },
1490 | "minimatch": {
1491 | "version": "3.1.2",
1492 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1493 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1494 | "dev": true,
1495 | "requires": {
1496 | "brace-expansion": "^1.1.7"
1497 | }
1498 | },
1499 | "minimist": {
1500 | "version": "1.2.5",
1501 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
1502 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
1503 | "dev": true
1504 | },
1505 | "ms": {
1506 | "version": "2.1.3",
1507 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1508 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1509 | "dev": true
1510 | },
1511 | "node-fetch": {
1512 | "version": "2.6.7",
1513 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
1514 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
1515 | "dev": true,
1516 | "requires": {
1517 | "whatwg-url": "^5.0.0"
1518 | }
1519 | },
1520 | "node-releases": {
1521 | "version": "2.0.2",
1522 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
1523 | "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
1524 | "dev": true
1525 | },
1526 | "object-keys": {
1527 | "version": "1.1.1",
1528 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
1529 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
1530 | "dev": true
1531 | },
1532 | "object.assign": {
1533 | "version": "4.1.2",
1534 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
1535 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
1536 | "dev": true,
1537 | "requires": {
1538 | "call-bind": "^1.0.0",
1539 | "define-properties": "^1.1.3",
1540 | "has-symbols": "^1.0.1",
1541 | "object-keys": "^1.1.1"
1542 | }
1543 | },
1544 | "once": {
1545 | "version": "1.4.0",
1546 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1547 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1548 | "dev": true,
1549 | "requires": {
1550 | "wrappy": "1"
1551 | }
1552 | },
1553 | "open": {
1554 | "version": "8.4.0",
1555 | "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
1556 | "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
1557 | "dev": true,
1558 | "requires": {
1559 | "define-lazy-prop": "^2.0.0",
1560 | "is-docker": "^2.1.1",
1561 | "is-wsl": "^2.2.0"
1562 | }
1563 | },
1564 | "p-limit": {
1565 | "version": "2.3.0",
1566 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
1567 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
1568 | "dev": true,
1569 | "requires": {
1570 | "p-try": "^2.0.0"
1571 | }
1572 | },
1573 | "p-locate": {
1574 | "version": "3.0.0",
1575 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
1576 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
1577 | "dev": true,
1578 | "requires": {
1579 | "p-limit": "^2.0.0"
1580 | }
1581 | },
1582 | "p-try": {
1583 | "version": "2.2.0",
1584 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
1585 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
1586 | "dev": true
1587 | },
1588 | "path-exists": {
1589 | "version": "3.0.0",
1590 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
1591 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
1592 | "dev": true
1593 | },
1594 | "path-is-absolute": {
1595 | "version": "1.0.1",
1596 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1597 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
1598 | "dev": true
1599 | },
1600 | "path-parse": {
1601 | "version": "1.0.7",
1602 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1603 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1604 | "dev": true
1605 | },
1606 | "pend": {
1607 | "version": "1.2.0",
1608 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
1609 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
1610 | "dev": true
1611 | },
1612 | "picocolors": {
1613 | "version": "1.0.0",
1614 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
1615 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
1616 | "dev": true
1617 | },
1618 | "picomatch": {
1619 | "version": "2.3.1",
1620 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1621 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1622 | "dev": true
1623 | },
1624 | "pirates": {
1625 | "version": "4.0.5",
1626 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
1627 | "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
1628 | "dev": true
1629 | },
1630 | "pixelmatch": {
1631 | "version": "5.2.1",
1632 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.2.1.tgz",
1633 | "integrity": "sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==",
1634 | "dev": true,
1635 | "requires": {
1636 | "pngjs": "^4.0.1"
1637 | },
1638 | "dependencies": {
1639 | "pngjs": {
1640 | "version": "4.0.1",
1641 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-4.0.1.tgz",
1642 | "integrity": "sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==",
1643 | "dev": true
1644 | }
1645 | }
1646 | },
1647 | "pkg-up": {
1648 | "version": "3.1.0",
1649 | "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
1650 | "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
1651 | "dev": true,
1652 | "requires": {
1653 | "find-up": "^3.0.0"
1654 | }
1655 | },
1656 | "playwright": {
1657 | "version": "1.18.1",
1658 | "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.18.1.tgz",
1659 | "integrity": "sha512-8EaX9EtbtAoMq5tnzIsoA3b/V86V/6Mq2skuOU4qEw+5OVxs1lwesDwmjy/RVU1Qfx5UuwSQzhp45wyH22oa+A==",
1660 | "dev": true,
1661 | "requires": {
1662 | "playwright-core": "=1.18.1"
1663 | },
1664 | "dependencies": {
1665 | "playwright-core": {
1666 | "version": "1.18.1",
1667 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.18.1.tgz",
1668 | "integrity": "sha512-NALGl8R1GHzGLlhUApmpmfh6M1rrrPcDTygWvhTbprxwGB9qd/j9DRwyn4HTQcUB6o0/VOpo46fH9ez3+D/Rog==",
1669 | "dev": true,
1670 | "requires": {
1671 | "commander": "^8.2.0",
1672 | "debug": "^4.1.1",
1673 | "extract-zip": "^2.0.1",
1674 | "https-proxy-agent": "^5.0.0",
1675 | "jpeg-js": "^0.4.2",
1676 | "mime": "^2.4.6",
1677 | "pngjs": "^5.0.0",
1678 | "progress": "^2.0.3",
1679 | "proper-lockfile": "^4.1.1",
1680 | "proxy-from-env": "^1.1.0",
1681 | "rimraf": "^3.0.2",
1682 | "socks-proxy-agent": "^6.1.0",
1683 | "stack-utils": "^2.0.3",
1684 | "ws": "^7.4.6",
1685 | "yauzl": "^2.10.0",
1686 | "yazl": "^2.5.1"
1687 | }
1688 | }
1689 | }
1690 | },
1691 | "pngjs": {
1692 | "version": "5.0.0",
1693 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
1694 | "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
1695 | "dev": true
1696 | },
1697 | "pretty-format": {
1698 | "version": "27.5.1",
1699 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
1700 | "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
1701 | "dev": true,
1702 | "requires": {
1703 | "ansi-regex": "^5.0.1",
1704 | "ansi-styles": "^5.0.0",
1705 | "react-is": "^17.0.1"
1706 | },
1707 | "dependencies": {
1708 | "ansi-styles": {
1709 | "version": "5.2.0",
1710 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
1711 | "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
1712 | "dev": true
1713 | }
1714 | }
1715 | },
1716 | "progress": {
1717 | "version": "2.0.3",
1718 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
1719 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
1720 | "dev": true
1721 | },
1722 | "proper-lockfile": {
1723 | "version": "4.1.2",
1724 | "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
1725 | "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
1726 | "dev": true,
1727 | "requires": {
1728 | "graceful-fs": "^4.2.4",
1729 | "retry": "^0.12.0",
1730 | "signal-exit": "^3.0.2"
1731 | }
1732 | },
1733 | "proxy-from-env": {
1734 | "version": "1.1.0",
1735 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
1736 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
1737 | "dev": true
1738 | },
1739 | "pump": {
1740 | "version": "3.0.0",
1741 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
1742 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
1743 | "dev": true,
1744 | "requires": {
1745 | "end-of-stream": "^1.1.0",
1746 | "once": "^1.3.1"
1747 | }
1748 | },
1749 | "react-is": {
1750 | "version": "17.0.2",
1751 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
1752 | "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
1753 | "dev": true
1754 | },
1755 | "reselect": {
1756 | "version": "4.1.5",
1757 | "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
1758 | "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==",
1759 | "dev": true
1760 | },
1761 | "resolve": {
1762 | "version": "1.22.0",
1763 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
1764 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
1765 | "dev": true,
1766 | "requires": {
1767 | "is-core-module": "^2.8.1",
1768 | "path-parse": "^1.0.7",
1769 | "supports-preserve-symlinks-flag": "^1.0.0"
1770 | }
1771 | },
1772 | "retry": {
1773 | "version": "0.12.0",
1774 | "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
1775 | "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
1776 | "dev": true
1777 | },
1778 | "rimraf": {
1779 | "version": "3.0.2",
1780 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1781 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1782 | "dev": true,
1783 | "requires": {
1784 | "glob": "^7.1.3"
1785 | }
1786 | },
1787 | "safe-buffer": {
1788 | "version": "5.1.2",
1789 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1790 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
1791 | "dev": true
1792 | },
1793 | "semver": {
1794 | "version": "6.3.0",
1795 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
1796 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
1797 | "dev": true
1798 | },
1799 | "signal-exit": {
1800 | "version": "3.0.7",
1801 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
1802 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
1803 | "dev": true
1804 | },
1805 | "slash": {
1806 | "version": "3.0.0",
1807 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
1808 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
1809 | "dev": true
1810 | },
1811 | "smart-buffer": {
1812 | "version": "4.2.0",
1813 | "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
1814 | "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
1815 | "dev": true
1816 | },
1817 | "socks": {
1818 | "version": "2.6.2",
1819 | "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
1820 | "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
1821 | "dev": true,
1822 | "requires": {
1823 | "ip": "^1.1.5",
1824 | "smart-buffer": "^4.2.0"
1825 | }
1826 | },
1827 | "socks-proxy-agent": {
1828 | "version": "6.1.1",
1829 | "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz",
1830 | "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==",
1831 | "dev": true,
1832 | "requires": {
1833 | "agent-base": "^6.0.2",
1834 | "debug": "^4.3.1",
1835 | "socks": "^2.6.1"
1836 | }
1837 | },
1838 | "source-map": {
1839 | "version": "0.5.7",
1840 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
1841 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
1842 | "dev": true
1843 | },
1844 | "source-map-support": {
1845 | "version": "0.4.18",
1846 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
1847 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
1848 | "dev": true,
1849 | "requires": {
1850 | "source-map": "^0.5.6"
1851 | }
1852 | },
1853 | "stack-utils": {
1854 | "version": "2.0.5",
1855 | "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
1856 | "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==",
1857 | "dev": true,
1858 | "requires": {
1859 | "escape-string-regexp": "^2.0.0"
1860 | },
1861 | "dependencies": {
1862 | "escape-string-regexp": {
1863 | "version": "2.0.0",
1864 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
1865 | "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
1866 | "dev": true
1867 | }
1868 | }
1869 | },
1870 | "supports-color": {
1871 | "version": "5.5.0",
1872 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1873 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1874 | "dev": true,
1875 | "requires": {
1876 | "has-flag": "^3.0.0"
1877 | }
1878 | },
1879 | "supports-preserve-symlinks-flag": {
1880 | "version": "1.0.0",
1881 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1882 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1883 | "dev": true
1884 | },
1885 | "to-fast-properties": {
1886 | "version": "2.0.0",
1887 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
1888 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
1889 | "dev": true
1890 | },
1891 | "to-regex-range": {
1892 | "version": "5.0.1",
1893 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1894 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1895 | "dev": true,
1896 | "requires": {
1897 | "is-number": "^7.0.0"
1898 | }
1899 | },
1900 | "tr46": {
1901 | "version": "0.0.3",
1902 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1903 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
1904 | "dev": true
1905 | },
1906 | "webidl-conversions": {
1907 | "version": "3.0.1",
1908 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1909 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
1910 | "dev": true
1911 | },
1912 | "whatwg-url": {
1913 | "version": "5.0.0",
1914 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1915 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
1916 | "dev": true,
1917 | "requires": {
1918 | "tr46": "~0.0.3",
1919 | "webidl-conversions": "^3.0.0"
1920 | }
1921 | },
1922 | "wrappy": {
1923 | "version": "1.0.2",
1924 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1925 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
1926 | "dev": true
1927 | },
1928 | "ws": {
1929 | "version": "7.5.7",
1930 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
1931 | "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
1932 | "dev": true
1933 | },
1934 | "yauzl": {
1935 | "version": "2.10.0",
1936 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
1937 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
1938 | "dev": true,
1939 | "requires": {
1940 | "buffer-crc32": "~0.2.3",
1941 | "fd-slicer": "~1.1.0"
1942 | }
1943 | },
1944 | "yazl": {
1945 | "version": "2.5.1",
1946 | "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
1947 | "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
1948 | "dev": true,
1949 | "requires": {
1950 | "buffer-crc32": "~0.2.3"
1951 | }
1952 | }
1953 | }
1954 | }
1955 |
--------------------------------------------------------------------------------
/playwright/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "@playwright/test": "1.18.1",
4 | "node-fetch": "^2.6.7",
5 | "playwright": "^1.18.1"
6 | },
7 | "scripts": {
8 | "test:local:basic": "npx playwright test --project=local-chrome basic",
9 | "test:local:capabilities": "npx playwright test --project=local-chrome capabilities",
10 | "test:local:variability": "npx playwright test --project=local-chrome zeroed --repeat-each=50",
11 | "test:browserless:capabilities": "npx playwright test --project=browserless capabilities",
12 | "test:browserless:variability": "npx playwright test --project=browserless zeroed --repeat-each=5"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/playwright/playwright.config.js:
--------------------------------------------------------------------------------
1 | // playwright.config.js
2 | // @ts-check
3 |
4 | /** @type {import('@playwright/test').PlaywrightTestConfig} */
5 | const config = {
6 | testDir: '.',
7 | testMatch: '**/*.spec.js',
8 | timeout: 30 * 1000,
9 | use: {
10 | viewport: {
11 | width: 1024,
12 | height: 768
13 | },
14 | headless: false,
15 | video: 'on',
16 | screenshot: 'on',
17 | trace: 'on',
18 | baseURL: 'https://playwright.dev/',
19 | ignoreHTTPSErrors: true
20 | },
21 | workers: 1,
22 | projects: [
23 | // -- browserless Configurations --
24 | {
25 | name: 'browserless',
26 | use: {
27 | headless: false,
28 | browserName: 'chromium',
29 | trace: 'off',
30 | video: 'off',
31 | screenshot: 'off',
32 | }
33 | },
34 | // -- Local Browsers --
35 | {
36 | name: "local-chrome",
37 | use: {
38 | browserName: 'chromium',
39 | channel: 'chrome',
40 | contextOptions: { recordHar: { path: './har.har'}}
41 | },
42 | }
43 | ]
44 | };
45 |
46 | module.exports = config;
47 |
--------------------------------------------------------------------------------
/playwright/tests/addObserver.js:
--------------------------------------------------------------------------------
1 | function addObserver() {
2 | console.log('this is being executed');
3 | window.longtasks = [];
4 | const observer = new PerformanceObserver((list) => {
5 | for (const entry of list.getEntries()) {
6 | // `entry` is a PerformanceEntry instance.
7 | longtasks.push([entry.attribution[0].containerSrc, entry.attribution[0].containerType, entry.attribution[0].name]);
8 | console.log(entry.entryType);
9 | console.log(entry.startTime); // DOMHighResTimeStamp
10 | console.log(entry.duration); // DOMHighResTimeStamp
11 | }
12 | });
13 | // Start observing the entry types you care about.
14 | observer.observe({entryTypes: ['longtask']});
15 | };
16 |
17 | addObserver();
18 |
19 | /*
20 | test.only('LongTasks and PerformanceObserver', async ({page, browser}) => {
21 | // const client = await page.context().newCDPSession(page);
22 | // await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
23 | await page.addInitScript({
24 | path: './perf/tests/pw/addObserver.js'
25 | });
26 | await page.goto(website);
27 | await page.waitForTimeout(1000 * 5);
28 | const longtasks = await page.evaluate(() => window.longtasks);
29 | console.log(longtasks);
30 |
31 | });
32 | */
33 |
--------------------------------------------------------------------------------
/playwright/tests/basic.spec.js:
--------------------------------------------------------------------------------
1 | const { test, browser } = require('./fixtures');
2 | const { expect } = require('@playwright/test');
3 |
4 | test.describe('Basic Google Search', () => {
5 | test('Basic Google Search', async ({ page, browser }) => {
6 |
7 | /* This should be replaced to demo record and playback */
8 |
9 | // Go to https://www.google.com/
10 | await page.goto('https://www.google.com/');
11 | // Click [aria-label="Search"]
12 | await page.click('[aria-label="Search"]');
13 | // Fill [aria-label="Search"]
14 | await page.fill('[aria-label="Search"]', 'playwright');
15 | // Press Enter
16 | await Promise.all([
17 | page.waitForNavigation(/*{ url: 'https://www.google.com/search?q=playwright&source=hp&ei=fgJjYprIDpfL0PEPn6COSA&iflsig=AHkkrS4AAAAAYmMQjhW1giF3oINn91kfb6MtqnHZBt3B&ved=0ahUKEwia_6qmtKj3AhWXJTQIHR-QAwkQ4dUDCAo&uact=5&oq=playwright&gs_lcp=Cgdnd3Mtd2l6EAMyCwgAEIAEELEDEIMBMggIABCABBCxAzILCAAQgAQQsQMQgwEyCwgAEIAEELEDEIMBMgsIABCABBCxAxCDATILCAAQgAQQsQMQgwEyBAgAEAMyCwguEIAEEMcBEK8BMgUIABCABDIOCC4QgAQQsQMQxwEQ0QM6DggAEI8BEOoCEIwDEOUCOhQILhCPARDHARCvARDqAhCMAxDlAjoOCC4QjwEQ6gIQjAMQ5QI6CwguEIAEEMcBEKMCOhEILhCABBCxAxCDARDHARDRAzoLCC4QgAQQsQMQgwE6DgguEIAEELEDEMcBEKMCOggILhCxAxCDAToFCC4QgAQ6CAguEIAEENQCOhEILhCABBCxAxCDARDHARCjAjoICAAQsQMQgwE6CAgAEIAEEMkDOgUIABCSAzoFCAAQsQNQyylYl0BggExoAXAAeAGAAYYCiAHbB5IBBTguMC4ymAEAoAEBsAEK&sclient=gws-wiz' }*/),
18 | page.press('[aria-label="Search"]', 'Enter')
19 | ]);
20 |
21 | });
22 | });
--------------------------------------------------------------------------------
/playwright/tests/bingLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unlikelyzero/js-perf-toolkit/4004c02caea4683337619c03e5c79eed3c6dd55a/playwright/tests/bingLogo.png
--------------------------------------------------------------------------------
/playwright/tests/capabilities.spec.js:
--------------------------------------------------------------------------------
1 | const { test, browser } = require('./fixtures');
2 | const { expect } = require('@playwright/test');
3 |
4 | const fs = require('fs');
5 | const path = require('path');
6 |
7 |
8 | const localImagePath = path.join(__dirname, "./assets/style.css");
9 |
10 |
11 | test.describe('Demo Capabilities', () => {
12 | test('Access the running devtools and request CDP Performance metrics', async ({ page, browser }) => {
13 |
14 | // Create a new connection to an existing CDPSession to enable Performance Measurements
15 | const client = await page.context().newCDPSession(page);
16 | // Tell the DevTools session to record performance metrics
17 | // https://chromedevtools.github.io/devtools-protocol/tot/Performance/#method-getMetrics
18 | await client.send('Performance.enable');
19 |
20 | // Go to https://www.google.com/
21 | await page.goto('https://www.google.com/');
22 | // Click [aria-label="Search"]
23 | await page.click('[aria-label="Search"]');
24 | // Fill [aria-label="Search"]
25 | await page.fill('[aria-label="Search"]', 'playwright');
26 | // Press Enter
27 | await Promise.all([
28 | page.waitForNavigation(),
29 | page.press('[aria-label="Search"]', 'Enter')
30 | ]);
31 |
32 | console.log("\n==== Devtools: Performance.getMetrics ====\n");
33 | let performanceMetrics = await client.send('Performance.getMetrics');
34 | console.log( performanceMetrics.metrics );
35 |
36 | });
37 |
38 | test('Capture Performance Timeline Trace during test execution and demonstrate marks', async ({ page, browser }) => {
39 |
40 | console.log("\n==== Devtools: startTracing ====\n");
41 | await browser.startTracing(page, {path: './trace.json', screenshots: true});
42 |
43 | // Go to https://www.google.com/
44 | await page.goto('https://www.google.com/');
45 |
46 | //Use performance.mark API
47 | await page.evaluate(() => (window.performance.mark("perf:start")));
48 |
49 | // Click [aria-label="Search"]
50 | await page.click('[aria-label="Search"]');
51 | // Fill [aria-label="Search"]
52 | await page.fill('[aria-label="Search"]', 'playwright');
53 |
54 | //Performance.mark API
55 | await page.evaluate(() => (window.performance.mark("perf:stop")));
56 |
57 | //Performance.measure API
58 | await page.evaluate(() => (window.performance.measure("overall","perf:start","perf:stop")));
59 |
60 | //Get All Performance Marks Including Google's
61 | const getAllMarksJson = await page.evaluate(() => JSON.stringify(window.performance.getEntriesByType("mark")));
62 | const getAllMarks = JSON.parse(getAllMarksJson);
63 | console.log('window.performance.getEntriesByType("mark")', getAllMarks);
64 |
65 | //Get All Performance Marks Including Google's
66 | const getAllMeasuresJson = await page.evaluate(() => JSON.stringify(window.performance.getEntriesByType("measure")));
67 | const getAllMeasures = JSON.parse(getAllMeasuresJson);
68 | console.log('window.performance.getEntriesByType("measure")', getAllMeasures);
69 |
70 | // Press Enter
71 | await Promise.all([
72 | page.waitForNavigation(),
73 | page.press('[aria-label="Search"]', 'Enter')
74 | ]);
75 |
76 | console.log("\n==== Devtools: stopTracing ====\n");
77 | await browser.stopTracing();
78 |
79 | });
80 |
81 | test('Add DevTools Network Delay', async ({ page, browser }) => {
82 | const client = await page.target().createCDPSession();
83 | await client.send('Network.enable')
84 | await client.send('Network.emulateNetworkConditions', {
85 | latency: 500
86 | })
87 |
88 | // Go to https://www.google.com/
89 | await page.goto('https://www.google.com/');
90 |
91 | // Click [aria-label="Search"]
92 | await page.click('[aria-label="Search"]');
93 | // Fill [aria-label="Search"]
94 | await page.fill('[aria-label="Search"]', 'playwright');
95 |
96 | // Press Enter
97 | await Promise.all([
98 | page.waitForNavigation(),
99 | page.press('[aria-label="Search"]', 'Enter')
100 | ]);
101 |
102 | });
103 |
104 | test('Route Image Replacement', async ({ page, browser, context }) => {
105 | await context.addInitScript(() => delete window.navigator.serviceWorker);
106 |
107 | const client = await page.context().newCDPSession(page);
108 | // Tell the DevTools session to record performance metrics
109 | // https://chromedevtools.github.io/devtools-protocol/tot/Performance/#method-getMetrics
110 | await client.send('Overlay.setShowFPSCounter', { show: true });
111 |
112 | // URL to replace
113 | const remoteFilePath = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png';
114 | // Local (override) file to use instead
115 | const localFilePath = path.join(__dirname, "./bingLogo.png");
116 |
117 | await page.route('https://www.google.com/images/branding/googlelogo/2x/*.png', (route) => {
118 |
119 | const url = route.request().url();
120 | console.log(`Intercepted ${url}`);
121 |
122 | if (url === remoteFilePath && !url.match(localFilePath)) {
123 | route.fulfill({
124 | body: fs.readFileSync(
125 | localFilePath
126 | )
127 | });
128 | } else {
129 | route.continue();
130 | }
131 | })
132 | // Go to https://www.google.com/
133 | await page.goto('https://www.google.com/');
134 |
135 | // Click [aria-label="Search"]
136 | await page.click('[aria-label="Search"]');
137 | // Fill [aria-label="Search"]
138 | await page.fill('[aria-label="Search"]', 'playwright');
139 |
140 | // Press Enter
141 | await Promise.all([
142 | page.waitForNavigation(),
143 | page.press('[aria-label="Search"]', 'Enter')
144 | ]);
145 |
146 | await page.screenshot();
147 | });
148 |
149 | });
--------------------------------------------------------------------------------
/playwright/tests/fixtures.js:
--------------------------------------------------------------------------------
1 | const base = require('@playwright/test');
2 |
3 | exports.test = base.test.extend({
4 | browser: async ({ playwright, browser }, use, workerInfo) => {
5 | // Use browserless if configured from the playwright.config project
6 | // Currently using .connectOverCDP()
7 | if (workerInfo.project.name.match(/browserless/)) {
8 | const vBrowser = await playwright.chromium.connectOverCDP({
9 | endpointURL: 'ws://localhost:3003'
10 | });
11 | //playwright endpoint for .connect()
12 | //const vBrowser = await playwright.chromium.connect({
13 | // wsEndpoint: 'wss://'
14 | //})
15 | await use(vBrowser);
16 | } else {
17 | // Use Local Browser for testing.
18 | await use(browser);
19 | }
20 | },
21 | });
--------------------------------------------------------------------------------
/playwright/tests/googlelogo_light_color_272x92dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unlikelyzero/js-perf-toolkit/4004c02caea4683337619c03e5c79eed3c6dd55a/playwright/tests/googlelogo_light_color_272x92dp.png
--------------------------------------------------------------------------------
/playwright/tests/influxDemo.spec.js:
--------------------------------------------------------------------------------
1 | const { test } = require('./fixtures');
2 | const { expect } = require('@playwright/test');
3 | const { influx } = require('./influxUtils');
4 |
5 |
6 | test.describe('feature foo', () => {
7 |
8 | test('my test', async ({ page }) => {
9 | await page.goto('/');
10 | await influx.write(
11 | 'test_mesurement',
12 | { tag1: 'tag 1 value' },
13 | { field1: 12, field2: 2.3 },
14 | Date.now()
15 | );
16 | });
17 | });
--------------------------------------------------------------------------------
/playwright/tests/influxUtils.js:
--------------------------------------------------------------------------------
1 | const { InfluxDB, Point } = require('@influxdata/influxdb-client');
2 | const { url, token, org, bucket, log } = require('../../influxdb/env.js');
3 | const { hostname } = require('os');
4 | const { LoaderTargetPlugin } = require('webpack');
5 |
6 |
7 | function isInt(n){
8 | return Number(n) === n && n % 1 === 0;
9 | }
10 |
11 | function isFloat(n){
12 | return Number(n) === n && n % 1 !== 0;
13 | }
14 |
15 | function influxInitialize() {
16 | const writeApi = new InfluxDB({url, token}).getWriteApi(org, bucket, 'ns'); // create a write API, expecting point timestamps in nanoseconds (can be also 's', 'ms', 'us')
17 | writeApi.useDefaultTags({location: hostname}); // setup default tags for all writes through this API
18 | return {
19 | write: (measurement, tag, field, timestamp) => {
20 | if (true) {
21 | console.log('*** WRITE POINT ***');
22 | }
23 |
24 | // write point with the current (client-side) timestamp
25 | let point = new Point(measurement);
26 |
27 | // send multiple tags in as multiproperty object
28 | // ex: { tag1: 'value1', tag2: 'value2' }
29 | for (const [name, value] of Object.entries(tag)) {
30 | point.tag(name, value);
31 | }
32 |
33 | // send multiple values in as multiproperty object
34 | // ex: { field1: 2.3, field2: 2 }
35 | for (const [name, value] of Object.entries(field)) {
36 | if (isInt(value)) {
37 | point.intField(name, value);
38 | } else if (isFloat(value)) {
39 | point.floatField(name, value);
40 | } else if (typeof variable == 'boolean') {
41 | point.booleanField(name, value);
42 | }
43 | }
44 |
45 | if (timestamp) {
46 | point.timestamp(timestamp);
47 | }
48 |
49 | writeApi.writePoint(point);
50 |
51 | if (LoaderTargetPlugin) {
52 | console.log(` ${point.toString()}`);
53 | }
54 |
55 | },
56 | close: () => {
57 | // WriteApi always buffer data into batches to optimize data transfer to InfluxDB server and retries
58 | // writing upon server/network failure. writeApi.flush() can be called to flush the buffered data,
59 | // close() also flushes the remaining buffered data and then cancels pending retries.
60 | writeApi
61 | .close()
62 | .then(() => {
63 | if (log) {
64 | console.log('FINISHED ... now try ./query.ts');
65 | }
66 | })
67 | .catch(e => {
68 | console.error(e)
69 |
70 | if (log) {
71 | console.log('\nFinished ERROR');
72 | }
73 | });
74 | }
75 | };
76 |
77 | }
78 |
79 | module.exports.influx = influxInitialize();
80 | //exports.influx = influxInitialize();
--------------------------------------------------------------------------------
/playwright/tests/old_capabilities.spec.js:
--------------------------------------------------------------------------------
1 | const { test, browser } = require('./fixtures');
2 | const { expect } = require('@playwright/test');
3 |
4 | const fetch = require('node-fetch');
5 | const fs = require('fs');
6 |
7 | const heapDumpUrl = 'http://localhost:3003/heapdump'
8 |
9 | const startHeapSnapShot = './start.heapsnapshot'
10 | const endHeapSnapShot = './end.heapsnapshot'
11 |
12 | test.describe('Demo Capabilities', () => {
13 | test.skip('Access the running devtools and request CDP Performance metrics', async ({ page, browser }) => {
14 | // Create a new connection to an existing CDPSession to enable Performance Measurements
15 | const client = await page.context().newCDPSession(page);
16 | // Tell the DevTools session to record performance metrics
17 | // https://chromedevtools.github.io/devtools-protocol/tot/Performance/#method-getMetrics
18 | await client.send('Performance.enable');
19 |
20 | // Go to https://www.google.com/
21 | await page.goto('https://www.google.com/');
22 | // Click [aria-label="Search"]
23 | await page.click('[aria-label="Search"]');
24 | // Fill [aria-label="Search"]
25 | await page.fill('[aria-label="Search"]', 'playwright');
26 | // Press Enter
27 | await Promise.all([
28 | page.waitForNavigation(),
29 | page.press('[aria-label="Search"]', 'Enter')
30 | ]);
31 |
32 | console.log("\n==== Devtools: Performance.getMetrics ====\n");
33 | let performanceMetrics = await client.send('Performance.getMetrics');
34 | console.log( performanceMetrics.metrics );
35 |
36 | });
37 |
38 | test('Capture Trace during test execution and demonstrate marks', async ({ page, browser }) => {
39 | // Create a new connection to an existing CDPSession to enable Performance Measurements
40 | const client = await page.context().newCDPSession(page);
41 | await page.evaluate(() => (window.performance.mark("perf:start")));
42 |
43 | // Go to https://www.google.com/
44 | await page.goto('https://www.google.com/');
45 | // Click [aria-label="Search"]
46 | await page.click('[aria-label="Search"]');
47 | // Fill [aria-label="Search"]
48 | await page.fill('[aria-label="Search"]', 'playwright');
49 | // Press Enter
50 | await Promise.all([
51 | page.waitForNavigation(),
52 | page.press('[aria-label="Search"]', 'Enter')
53 | ]);
54 |
55 | await page.evaluate(() => (window.performance.mark("perf:stop")));
56 |
57 | console.log("\n==== Devtools: Performance.getMetrics ====\n");
58 | let performanceMetrics = await client.send('Performance.getMetrics');
59 | console.log( performanceMetrics.metrics );
60 |
61 | });
62 |
63 |
64 |
65 |
66 | test.skip('Demo Capabilities', async ({ page, browser }) => {
67 |
68 | // Create a new connection to an existing CDPSession to enable Performance Measurements
69 | const client = await page.context().newCDPSession(page);
70 | await client.send('Performance.enable');
71 |
72 | console.log("\n==== Devtools: Performance.getMetrics ====\n");
73 | let performanceMetrics = await client.send('Performance.getMetrics');
74 | console.log( performanceMetrics.metrics );
75 |
76 | console.log("\n==== Devtools: startTracing ====\n");
77 | //await browser.startTracing(page,{path:`trace.json`,screenshots:true, categories: ['devtools.timeline']});
78 | await browser.startTracing(page, {path: './trace.json', screenshots: true});
79 |
80 |
81 | console.log("\n==== Browserless: gather heapsnapshot ====\n");
82 | //Get startHeadSnapShot
83 | console.log('Gathering start.heapsnapshot')
84 | await fetch(heapDumpUrl)
85 | .then(res => res.text())
86 | .then(data => {
87 | fs.writeFile(startHeapSnapShot, data, err => {
88 | if (err) {
89 | console.error(err)
90 | return;
91 | }
92 | console.log('Success: saved file', startHeapSnapShot);
93 | });
94 | });
95 |
96 |
97 | console.log("\n==== Best Practice: Define your floor for test transferability ====\n");
98 | //Baseline page measurement of HTML
99 | await console.time('htmlfloor');
100 | //Create simple HTML to inject and test agains
101 | await page.setContent(`
102 | Hello world
103 |
104 | Edit me
105 |
106 |
107 |
108 |
109 | `);
110 |
111 | await page.pause();
112 |
113 | await page.locator('.visible').isVisible();
114 | await console.timeLog('htmlfloor');
115 |
116 | await console.time('cold:load');
117 | await console.time('cold:idle');
118 |
119 |
120 |
121 |
122 | console.log("\n==== Browserless: gather heapsnapshot2 ====\n");
123 | //Get end Heapsnapshot
124 | console.log('Gathering end.heapsnapshot')
125 | await fetch(heapDumpUrl)
126 | .then(res => res.text())
127 | .then(data => {
128 | fs.writeFile(endHeapSnapShot, data, err => {
129 | if (err) {
130 | console.error(err)
131 | return;
132 | }
133 | console.log('Success: saved file', endHeapSnapShot);
134 | });
135 | }), { timeout: 120000 };
136 |
137 | await page.goto('/');
138 |
139 | // Inject Performance Observer
140 | // await page.addScriptTag({type: 'module', url: 'https://unpkg.com/@sumup/performance-observer@1.0.2/dist/performance-observer.es5.min.js?module'})
141 | // await page.waitForFunction(() => window.PerformanceObserverEntryList);
142 |
143 | //Example of setting arbitrary mark on performance timeline
144 | await page.evaluate(() => (window.performance.mark("perf:start")));
145 |
146 | await page.waitForLoadState('load');
147 | await console.timeLog('cold:load');
148 | await page.waitForLoadState('networkidle');
149 | await console.timeLog('cold:idle');
150 |
151 | // Executes Navigation API within the page cont
152 | // await page.evaluate(() => JSON.stringify(window.performance.mark("perf:start")));
153 | // await page.evaluate(function() {window.performance.mark("perf:start")});
154 |
155 | //Reloading to simulate "Warm Cache"
156 | await console.time('reload:idle');
157 | await console.time('reload:load');
158 |
159 | await page.reload();
160 | await page.waitForLoadState('load')
161 | await console.timeLog('reload:load');
162 | await page.waitForLoadState('networkidle');
163 | await console.timeLog('reload:idle');
164 |
165 | await page.evaluate(() => (window.performance.mark("perf:reloaded")));
166 |
167 | console.log("\n==== [UNDER CONSTRUCTION] performance.measure our marks! ====\n");
168 | //await page.evaluate(() => (window.performance.measure("overall","perf:start","perf:reloaded")));
169 |
170 | console.log("\n==== Devtools: stopTracing ====\n");
171 | await browser.stopTracing();
172 |
173 | console.log("\n==== Gather all resource timing and filter for svg ====\n");
174 | const resourceTimingJson = await page.evaluate(() => JSON.stringify(window.performance.getEntriesByType('resource')));
175 |
176 | //Get Resource Timing for svg elements
177 | const resourceTiming = JSON.parse(resourceTimingJson);
178 | const logoResourceTiming = resourceTiming.find(element => element.name.includes('.svg'));
179 | console.log('performance.resource .svg timing',logoResourceTiming);
180 |
181 | console.log("\n==== Gather all resource timing for navigation ====\n");
182 | //Get Performance Timing
183 | const performanceTimingJson = await page.evaluate(() => JSON.stringify(window.performance.timing));
184 | const performanceTiming = JSON.parse(performanceTimingJson);
185 |
186 | console.log('performance.window.timing', performanceTiming);
187 |
188 | console.log("\n==== [UNDER CONSTRUCTION] Gather all longTask events ====\n");
189 | // //FIX Long Task API Attempt
190 | // const longTaskTimingJson = await page.evaluate(() => JSON.stringify(window.performance.getEntriesByType('longtask')));
191 |
192 | // const longTaskTiming = JSON.parse(longTaskTimingJson);
193 | // console.log('longtask timing',longTaskTiming);
194 |
195 | // //FIX Long Task API Attempt 2
196 | // const results = await page.evaluate(function() {return window.longtasks});
197 | // await console.log(results);
198 | // let longTaskResults = await page.evaluate(function() {return window.longtasks});
199 | // console.log('long task results', JSON.stringify(longTaskResults));
200 |
201 | });
202 | });
--------------------------------------------------------------------------------
/playwright/tests/variability.spec.js:
--------------------------------------------------------------------------------
1 | const { expect } = require('@playwright/test');
2 | const { test, browser } = require('./fixtures.js');
3 |
4 | /*
5 | Demonstrates run-over-run variability with simple time log statements.
6 |
7 | Example output:
8 |
9 | Running 10 tests using 1 worker
10 |
11 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
12 | variability:example: 878.970ms
13 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
14 | variability:example: 636.198ms
15 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
16 | variability:example: 1075.154ms
17 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
18 | variability:example: 731.857ms
19 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
20 | variability:example: 879.356ms
21 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
22 | variability:example: 722.682ms
23 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
24 | variability:example: 510.165ms
25 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
26 | variability:example: 1153.010ms
27 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
28 | variability:example: 780.326ms
29 | ✓ [local-chrome] › tests/variability.spec.js:4:1 › basic test (3s)
30 | variability:example: 584.115ms
31 |
32 | */
33 | test('basic test', async ({ page, browser }) => {
34 | await console.time('variability:example');
35 | await page.goto('https://playwright.dev/');
36 | const title = page.locator('.navbar__inner .navbar__title');
37 | await expect(title).toHaveText('Playwright');
38 | await console.timeLog('variability:example');
39 | });
40 |
41 | test('basic test - with network shaping', async ({ page, browser }) => {
42 | // This uses the DevToolsProtocol to do traffic shaping from the perspective of Chrome to the target URL.
43 | // Note: this does NOT affect WS traffic and has issues with http 1.1/2.0/3.0 compatibility
44 | const client = await page.context().newCDPSession(page);
45 | await client.send('Network.emulateNetworkConditions', {
46 | 'offline': false,
47 | 'downloadThroughput': 2000 * 1024 / 2,
48 | 'uploadThroughput': 2000 * 1024 / 2,
49 | 'latency': 200
50 | })
51 | await console.time('variability:example');
52 | await page.goto('https://playwright.dev/');
53 | const title = page.locator('.navbar__inner .navbar__title');
54 | await expect(title).toHaveText('Playwright');
55 | await console.timeLog('variability:example');
56 | });
57 |
58 | test.skip('basic test - with CPU Modification', async ({ page, browser }) => {
59 | // This uses the DevToolsProtocol to throttle CPU Utilization
60 | const client = await page.context().newCDPSession(page);
61 | await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
62 | await console.time('variability:example');
63 | await page.goto('https://playwright.dev/');
64 | const title = page.locator('.navbar__inner .navbar__title');
65 | await expect(title).toHaveText('Playwright');
66 | await console.timeLog('variability:example');
67 | });
68 |
69 |
--------------------------------------------------------------------------------
/playwright/tests/zeroed.perf.spec.js:
--------------------------------------------------------------------------------
1 | const { test, browser } = require('./fixtures');
2 | const { expect } = require('@playwright/test');
3 |
4 | //This test suite is designed to measure the baseline of performance for transferrability
5 | // purposes.
6 |
7 | test.describe('Baseline Performance Tests', () => {
8 | test('Zeroed baseline', async ({page, browser}) => {
9 |
10 | await console.time('htmlfloor');
11 | await page.setContent(`
12 | Hello world
13 |
14 | `);
15 | await page.locator('.visible').isVisible();
16 | await console.timeLog('htmlfloor');
17 | });
18 | });
19 |
20 | /*
21 | Example output from running this test 50x:
22 |
23 |
24 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (2s)
25 | htmlfloor: 85.922ms
26 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
27 | htmlfloor: 99.194ms
28 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
29 | htmlfloor: 72.545ms
30 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
31 | htmlfloor: 59.577ms
32 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
33 | htmlfloor: 68.636ms
34 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
35 | htmlfloor: 74.77ms
36 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
37 | htmlfloor: 71.038ms
38 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
39 | htmlfloor: 70.09ms
40 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
41 | htmlfloor: 68.657ms
42 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
43 | htmlfloor: 57.2ms
44 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
45 | htmlfloor: 69.429ms
46 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
47 | htmlfloor: 84.199ms
48 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
49 | htmlfloor: 73.039ms
50 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
51 | htmlfloor: 72.93ms
52 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
53 | htmlfloor: 58.18ms
54 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
55 | htmlfloor: 77.522ms
56 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
57 | htmlfloor: 54.095ms
58 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
59 | htmlfloor: 71.071ms
60 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
61 | htmlfloor: 72.019ms
62 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
63 | htmlfloor: 79.432ms
64 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
65 | htmlfloor: 67.809ms
66 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
67 | htmlfloor: 74.899ms
68 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
69 | htmlfloor: 54.268ms
70 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
71 | htmlfloor: 77.018ms
72 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
73 | htmlfloor: 65.866ms
74 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
75 | htmlfloor: 66.524ms
76 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
77 | htmlfloor: 54.205ms
78 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
79 | htmlfloor: 72.134ms
80 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
81 | htmlfloor: 57.835ms
82 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
83 | htmlfloor: 58.624ms
84 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
85 | htmlfloor: 117.735ms
86 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
87 | htmlfloor: 70.716ms
88 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
89 | htmlfloor: 71.982ms
90 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
91 | htmlfloor: 80.7ms
92 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
93 | htmlfloor: 56.118ms
94 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
95 | htmlfloor: 66.857ms
96 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
97 | htmlfloor: 54.95ms
98 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
99 | htmlfloor: 83.009ms
100 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
101 | htmlfloor: 83.164ms
102 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
103 | htmlfloor: 73.895ms
104 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
105 | htmlfloor: 76.928ms
106 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
107 | htmlfloor: 73.632ms
108 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
109 | htmlfloor: 78.305ms
110 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
111 | htmlfloor: 73.716ms
112 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
113 | htmlfloor: 74.934ms
114 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
115 | htmlfloor: 69.667ms
116 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
117 | htmlfloor: 78.358ms
118 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
119 | htmlfloor: 128.104ms
120 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
121 | htmlfloor: 78.004ms
122 | ✓ [local-chrome] › tests/zeroed.perf.spec.js:23:3 › Baseline Performance (1s)
123 | htmlfloor: 67.591ms
124 | */
125 |
--------------------------------------------------------------------------------
/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 | rule_files:
5 | scrape_configs:
6 | - job_name: 'prometheus'
7 | static_configs:
8 | - targets: [ 'localhost:9090' ]
9 | - job_name: 'cadvisor'
10 | static_configs:
11 | - targets: [ 'mon_cadvisor:8080' ]
12 | metrics_path: '/metrics'
13 | - job_name: 'browserless'
14 | static_configs:
15 | - targets: [ 'browserless:3000' ]
16 | metrics_path: '/prometheus'
17 | scrape_interval: 1s
18 | - job_name: 'toxiproxy'
19 | static_configs:
20 | - targets: [ 'mon_toxiproxy:8474' ]
21 | metrics_path: '/metrics'
22 |
23 |
--------------------------------------------------------------------------------
/xk6-browser/example.js:
--------------------------------------------------------------------------------
1 | import launcher from "k6/x/browser";
2 | import { check } from "k6";
3 |
4 | export default function() {
5 | const browser = launcher.launch('chromium', {
6 | headless: false
7 | });
8 | const context = browser.newContext();
9 | const page = context.newPage();
10 |
11 | // Inject page content
12 | page.setContent(`
13 | Hello world
14 |
15 | Edit me
16 |
17 |
18 |
19 |
20 | `);
21 |
22 | // Check state
23 | check(page, {
24 | 'visible': p => p.$('.visible').isVisible(),
25 | 'hidden': p => p.$('.hidden').isHidden(),
26 | 'editable': p => p.$('.editable').isEditable(),
27 | 'enabled': p => p.$('.enabled').isEnabled(),
28 | 'disabled': p => p.$('.disabled').isDisabled(),
29 | 'checked': p => p.$('.checked').isChecked(),
30 | 'unchecked': p => p.$('.unchecked').isChecked() === false,
31 | });
32 |
33 | page.close();
34 | browser.close();
35 | }
--------------------------------------------------------------------------------