├── .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 |
  1. 28 | About The Project 29 | 32 |
  2. 33 |
  3. 34 | Getting Started 35 | 39 |
  4. 40 |
  5. Usage
  6. 41 |
  7. Roadmap
  8. 42 |
  9. License
  10. 43 |
  11. Contact
  12. 44 |
  13. Acknowledgements
  14. 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 | } --------------------------------------------------------------------------------