From d4fb97bf0dab2ccfcd57426923bb8f0dccea9ea7 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 10:13:31 -0700
Subject: [PATCH 001/155] initial setup of automation solution with a login
test
---
e2e/.eslintrc.json | 35 ++++++++++++++
e2e/.gitignore | 3 ++
e2e/.prettierrc | 14 ++++++
e2e/Dockerfile | 10 ++++
e2e/READEME.md | 66 +++++++++++++++++++++++++++
e2e/cypress.env.local.json | 6 +++
e2e/cypress.json | 8 ++++
e2e/cypress/support/api-commands.ts | 8 ++++
e2e/cypress/support/commands.ts | 25 ++++++++++
e2e/cypress/support/global.d.ts | 11 +++++
e2e/cypress/support/index.ts | 4 ++
e2e/cypress/support/login-commands.ts | 38 +++++++++++++++
e2e/cypress/tests/login.spec.ts | 19 ++++++++
e2e/docker-compose.yml | 10 ++++
e2e/package.json | 27 +++++++++++
e2e/tsconfig.json | 11 +++++
16 files changed, 295 insertions(+)
create mode 100644 e2e/.eslintrc.json
create mode 100644 e2e/.gitignore
create mode 100644 e2e/.prettierrc
create mode 100644 e2e/Dockerfile
create mode 100644 e2e/READEME.md
create mode 100644 e2e/cypress.env.local.json
create mode 100644 e2e/cypress.json
create mode 100644 e2e/cypress/support/api-commands.ts
create mode 100644 e2e/cypress/support/commands.ts
create mode 100644 e2e/cypress/support/global.d.ts
create mode 100644 e2e/cypress/support/index.ts
create mode 100644 e2e/cypress/support/login-commands.ts
create mode 100644 e2e/cypress/tests/login.spec.ts
create mode 100644 e2e/docker-compose.yml
create mode 100644 e2e/package.json
create mode 100644 e2e/tsconfig.json
diff --git a/e2e/.eslintrc.json b/e2e/.eslintrc.json
new file mode 100644
index 000000000..09f75e2b9
--- /dev/null
+++ b/e2e/.eslintrc.json
@@ -0,0 +1,35 @@
+{
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "prettier/@typescript-eslint",
+ "plugin:prettier/recommended",
+ "plugin:cypress/recommended",
+ "plugin:chai-friendly/recommended"
+ ],
+ "plugins": ["@typescript-eslint", "prettier", "cypress", "chai-friendly"],
+ "env": {
+ "browser": true,
+ "node": true,
+ "commonjs": true,
+ "es6": true,
+ "cypress/globals": true
+ },
+ "rules": {
+ "prettier/prettier": [
+ "error",
+ { "singleQuote": true, "semi": false, "printWidth": 90, "endOfLine": "auto" }
+ ],
+ "no-useless-catch": "off",
+ "no-unused-expressions": 0,
+ "@typescript-eslint/camelcase": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "cypress/no-assigning-return-values": "error",
+ "cypress/no-unnecessary-waiting": "error",
+ "cypress/assertion-before-screenshot": "warn",
+ "cypress/no-force": "warn",
+ "cypress/no-async-tests": "error",
+ "chai-friendly/no-unused-expressions": 2
+ },
+ "parser": "@typescript-eslint/parser"
+}
diff --git a/e2e/.gitignore b/e2e/.gitignore
new file mode 100644
index 000000000..3138a5752
--- /dev/null
+++ b/e2e/.gitignore
@@ -0,0 +1,3 @@
+integration
+*-lock.json
+cypress.env.json
\ No newline at end of file
diff --git a/e2e/.prettierrc b/e2e/.prettierrc
new file mode 100644
index 000000000..1385df39a
--- /dev/null
+++ b/e2e/.prettierrc
@@ -0,0 +1,14 @@
+
+{
+ "semi": false,
+ "singleQuote": true,
+ "printWidth": 90,
+ "overrides": [
+ {
+ "files": "*.spec.ts",
+ "options": {
+ "printWidth": 120
+ }
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
new file mode 100644
index 000000000..175fc533b
--- /dev/null
+++ b/e2e/Dockerfile
@@ -0,0 +1,10 @@
+FROM cypress/included:3.2.0
+
+COPY . /e2e
+
+RUN npm install
+
+CMD [ "cy:run" ]
+
+ENTRYPOINT [ "npm", "run" ]
+
diff --git a/e2e/READEME.md b/e2e/READEME.md
new file mode 100644
index 000000000..82198eb57
--- /dev/null
+++ b/e2e/READEME.md
@@ -0,0 +1,66 @@
+# End-to-End Test Automation
+
+This repository contains a testing solution, with the tests written in Cypress.
+
+Additionally this app is configured to run tests locally and Docker.
+
+The tests are written to be directly compared to the official API Services Portal tests.
+
+Each test covers the same functionality found in the official API Services Portal tests but utilizes the Cypress API.
+
+## Help + Testing
+
+The steps below will take you all the way through Cypress. It is assumed you have nothing installed except for node + git.
+
+**If you get stuck, here is more help:**
+
+- [Gitter Channel](https://gitter.im/cypress-io/cypress)
+- [Cypress Docs](https://on.cypress.io)
+- [Cypress CLI Tool Docs](https://github.com/cypress-io/cypress-cli)
+
+### 1. Install Cypress
+
+[Follow these instructions to install Cypress.](https://docs.cypress.io/guides/getting-started/installing-cypress)
+
+### 2. Run Tests
+
+* Clone this repository
+* Create a new file `cypress.env.json` from `cypress.env.local.json`
+
+#### Locally
+
+* Run `npm install` to install all the dependencies
+* Run `npm run cy:run` to run the tests
+
+#### Docker
+
+#### Docker Compose
+
+#### GitHub Actions
+
+
+
+## Cypress IntelliSense
+
+If you use modern IDE that supports TypeScript (like VSCode), you can benefit
+from Cypress type declarations included with the `cypress` NPM module. Just
+add `@ts-check` to the spec file and configure "dummy"
+[tsconfig.json](tsconfig.json) file and see IntelliSense over `cy.`
+commands.
+
+### Custom commands
+
+* This project also adds several custom commands in [cypress/support/index.js](cypress/support/index.ts).
+* To let TypeScript compiler know that we have added a custom command and have IntelliSense working, I have described the type signature of the custom command in file [cypress/support/global.d.ts](cypress/support/global.d.ts).
+* To include the new ".d.ts" file into IntelliSense, I could update `tsconfig.json` or I could add another special comment to the JavaScript spec files - `///
+
+// type definitions for custom commands will resolve to "cypress/support/global.d.ts"
+///
+```
+
+**Related:** [IntelliSense for custom Chai assertions added to Cypress](https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/extending-cypress__chai-assertions#code-completion)
+
diff --git a/e2e/cypress.env.local.json b/e2e/cypress.env.local.json
new file mode 100644
index 000000000..0afacafa3
--- /dev/null
+++ b/e2e/cypress.env.local.json
@@ -0,0 +1,6 @@
+{
+ "oidc-issuer": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
+ "tests-env": "dev",
+ "username": "",
+ "password": ""
+}
diff --git a/e2e/cypress.json b/e2e/cypress.json
new file mode 100644
index 000000000..f0ec5afa2
--- /dev/null
+++ b/e2e/cypress.json
@@ -0,0 +1,8 @@
+{
+ "baseUrl": "https://api-services-portal-dev.apps.silver.devops.gov.bc.ca",
+ "integrationFolder": "cypress/tests",
+ "screenshotOnRunFailure": false,
+ "video": false,
+ "defaultCommandTimeout": 1000,
+ "requestTimeout": 1000
+}
diff --git a/e2e/cypress/support/api-commands.ts b/e2e/cypress/support/api-commands.ts
new file mode 100644
index 000000000..4a79b87d5
--- /dev/null
+++ b/e2e/cypress/support/api-commands.ts
@@ -0,0 +1,8 @@
+Cypress.Commands.add('callApi', (options: any) => {
+ cy.request({
+ ...options,
+ }).then((res) => {
+ expect([200, 201]).to.contain(res.status)
+ cy.wrap(res)
+ })
+})
diff --git a/e2e/cypress/support/commands.ts b/e2e/cypress/support/commands.ts
new file mode 100644
index 000000000..119ab03f7
--- /dev/null
+++ b/e2e/cypress/support/commands.ts
@@ -0,0 +1,25 @@
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
new file mode 100644
index 000000000..cf361fce9
--- /dev/null
+++ b/e2e/cypress/support/global.d.ts
@@ -0,0 +1,11 @@
+///
+
+declare namespace Cypress {
+ interface Chainable {
+ loginToDev(username: string, password: string): Chainable
+
+ verifySession(url: string): Chainable
+
+ callApi(options: Partial): Chainable>
+ }
+}
diff --git a/e2e/cypress/support/index.ts b/e2e/cypress/support/index.ts
new file mode 100644
index 000000000..15b04314a
--- /dev/null
+++ b/e2e/cypress/support/index.ts
@@ -0,0 +1,4 @@
+import './commands'
+import 'cypress-xpath'
+import './login-commands'
+import './api-commands'
diff --git a/e2e/cypress/support/login-commands.ts b/e2e/cypress/support/login-commands.ts
new file mode 100644
index 000000000..0c2d42b9e
--- /dev/null
+++ b/e2e/cypress/support/login-commands.ts
@@ -0,0 +1,38 @@
+Cypress.Commands.add('loginToDev', (username, password) => {
+ const oidcProviderURL = new URL(Cypress.env('oidc-issuer'))
+ const appURL = new URL(Cypress.config('baseUrl'))
+
+ cy.location().should((loc) => {
+ expect(loc.protocol).to.eq(oidcProviderURL.protocol)
+ expect(loc.hostname).to.eq(oidcProviderURL.hostname)
+ })
+
+ Cypress.log({
+ name: 'Login to Dev',
+ displayName: 'LOGIN_DEV',
+ message: [`🔐 Authenticating | ${username}`],
+ })
+
+ cy.get('#username').type(username)
+ cy.get('#password').type(password)
+ cy.get('#kc-login').click()
+
+ cy.location().should((loc) => {
+ expect(loc.protocol).to.eq(appURL.protocol)
+ expect(loc.hostname).to.eq(appURL.hostname)
+ })
+})
+
+Cypress.Commands.add('verifySession', (url: string) => {
+ cy.callApi({ method: 'GET', url: url }).then((res) => {
+ expect(res.body).to.include({
+ anonymous: false,
+ })
+ Cypress.log({
+ name: 'Session Info',
+ displayName: 'SESSION_INFO',
+ message: JSON.stringify(res.body),
+ })
+ cy.log('Session established successfully')
+ })
+})
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
new file mode 100644
index 000000000..77b6af042
--- /dev/null
+++ b/e2e/cypress/tests/login.spec.ts
@@ -0,0 +1,19 @@
+describe('aps portal login page', () => {
+ beforeEach(() => {
+ cy.visit('/')
+ })
+
+ it('displays login button', () => {
+ cy.xpath('//button').contains('Login')
+ })
+
+ it('login into portal', () => {
+ cy.xpath("//button[normalize-space()='Login']").click()
+ const oidcProviderURL = new URL(Cypress.env('oidc-issuer'))
+
+ if (Cypress.env('tests-env') === 'dev') {
+ cy.loginToDev(Cypress.env('username'), Cypress.env('password'))
+ cy.verifySession(Cypress.config('baseUrl') + '/admin/session')
+ }
+ })
+})
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
new file mode 100644
index 000000000..f2b52664c
--- /dev/null
+++ b/e2e/docker-compose.yml
@@ -0,0 +1,10 @@
+version: '3.2'
+
+services:
+ cypress:
+ image: 'cypress/included:3.2.0'
+ container_name: cypress-e2e
+ command: npm run cy:run
+ working_dir: /e2e
+ volumes:
+ - ./:/e2e
diff --git a/e2e/package.json b/e2e/package.json
new file mode 100644
index 000000000..256e9c0fe
--- /dev/null
+++ b/e2e/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "bcgov-aps-portal-e2e",
+ "version": "1.0.0",
+ "description": "End to End and Integration Tests for APS Portal",
+ "main": "index.js",
+ "author": "BC Gov APS",
+ "license": "MIT",
+ "scripts": {
+ "cy:open": "cypress open",
+ "cy:run": "cypress run --config watchForFileChanges=false"
+ },
+ "devDependencies": {
+ "@cypress/code-coverage": "^3.9.8",
+ "@cypress/instrument-cra": "^1.4.0",
+ "@typescript-eslint/eslint-plugin": "^4.28.1",
+ "@typescript-eslint/parser": "^4.28.1",
+ "cypress": "^7.6.0",
+ "cypress-xpath": "^1.6.2",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-chai-friendly": "^0.7.1",
+ "eslint-plugin-cypress": "^2.11.3",
+ "eslint-plugin-import": "^2.23.4",
+ "eslint-plugin-prettier": "^3.4.0",
+ "prettier": "^2.3.2",
+ "typescript": "^4.3.5"
+ }
+}
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
new file mode 100644
index 000000000..5d3536730
--- /dev/null
+++ b/e2e/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["es5", "dom", "ES2015"],
+ "types": ["cypress"],
+ "allowJs": true
+ },
+ "include": ["./cypress/**/*.ts"],
+ "exclude": [],
+ "noEmit": true
+}
From fb39c2b4c6a1492a5cf7cf99edbb25df1fd1aa3a Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 10:23:19 -0700
Subject: [PATCH 002/155] Adding a sample plugin index file
---
e2e/cypress/plugins/index.js | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 e2e/cypress/plugins/index.js
diff --git a/e2e/cypress/plugins/index.js b/e2e/cypress/plugins/index.js
new file mode 100644
index 000000000..fd170fba6
--- /dev/null
+++ b/e2e/cypress/plugins/index.js
@@ -0,0 +1,17 @@
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+module.exports = (on, config) => {
+ // `on` is used to hook into various events Cypress emits
+ // `config` is the resolved Cypress config
+}
From b6166c4f4467d505de30acb618d51f05cb8e34c1 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 10:24:57 -0700
Subject: [PATCH 003/155] Updating it to ts
---
e2e/cypress/plugins/{index.js => index.ts} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename e2e/cypress/plugins/{index.js => index.ts} (100%)
diff --git a/e2e/cypress/plugins/index.js b/e2e/cypress/plugins/index.ts
similarity index 100%
rename from e2e/cypress/plugins/index.js
rename to e2e/cypress/plugins/index.ts
From 08695159e4fc1e9baea811da3264e77b8eec6380 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 12:44:17 -0700
Subject: [PATCH 004/155] updated docker file and compose to run the e2e as a
service locally
---
e2e/Dockerfile | 16 +++++++++-------
e2e/cypress.json | 6 +++++-
e2e/cypress/tests/login.spec.ts | 6 +++---
e2e/docker-compose.yml | 11 ++++++-----
e2e/package.json | 10 ++++++----
5 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 175fc533b..8033e548a 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -1,10 +1,12 @@
-FROM cypress/included:3.2.0
+FROM cypress/included:7.6.0
-COPY . /e2e
+COPY cypress.json .
+COPY cypress.env.json .
+COPY tsconfig.json .
+COPY package.json .
+COPY package-lock.json .
+COPY ./cypress/ cypress
-RUN npm install
-
-CMD [ "cy:run" ]
-
-ENTRYPOINT [ "npm", "run" ]
+RUN npm ci --production
+CMD [ "--config-file", "./cypress.json" ]
\ No newline at end of file
diff --git a/e2e/cypress.json b/e2e/cypress.json
index f0ec5afa2..a8210bc9f 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -4,5 +4,9 @@
"screenshotOnRunFailure": false,
"video": false,
"defaultCommandTimeout": 1000,
- "requestTimeout": 1000
+ "requestTimeout": 1000,
+ "reporter": "junit",
+ "reporterOptions": {
+ "toConsole": true
+ }
}
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
index 77b6af042..27d913429 100644
--- a/e2e/cypress/tests/login.spec.ts
+++ b/e2e/cypress/tests/login.spec.ts
@@ -1,13 +1,13 @@
-describe('aps portal login page', () => {
+describe('User navigates aps portal login page and', () => {
beforeEach(() => {
cy.visit('/')
})
- it('displays login button', () => {
+ it('finds login button', () => {
cy.xpath('//button').contains('Login')
})
- it('login into portal', () => {
+ it('enter credentials to login into portal', () => {
cy.xpath("//button[normalize-space()='Login']").click()
const oidcProviderURL = new URL(Cypress.env('oidc-issuer'))
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index f2b52664c..679e42cb4 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -2,9 +2,10 @@ version: '3.2'
services:
cypress:
- image: 'cypress/included:3.2.0'
+ image: 'aps-cypress-e2e:latest'
container_name: cypress-e2e
- command: npm run cy:run
- working_dir: /e2e
- volumes:
- - ./:/e2e
+ build:
+ context: .
+ dockerfile: Dockerfile
+ # environment:
+ # DEBUG: cypress:* - Writes complete log
diff --git a/e2e/package.json b/e2e/package.json
index 256e9c0fe..87b787a23 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -10,18 +10,20 @@
"cy:run": "cypress run --config watchForFileChanges=false"
},
"devDependencies": {
- "@cypress/code-coverage": "^3.9.8",
- "@cypress/instrument-cra": "^1.4.0",
"@typescript-eslint/eslint-plugin": "^4.28.1",
"@typescript-eslint/parser": "^4.28.1",
"cypress": "^7.6.0",
- "cypress-xpath": "^1.6.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-chai-friendly": "^0.7.1",
"eslint-plugin-cypress": "^2.11.3",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-prettier": "^3.4.0",
- "prettier": "^2.3.2",
+ "prettier": "^2.3.2"
+ },
+ "dependencies": {
+ "@cypress/code-coverage": "^3.9.8",
+ "@cypress/instrument-cra": "^1.4.0",
+ "cypress-xpath": "^1.6.2",
"typescript": "^4.3.5"
}
}
From 5c77863a018cba4001e9c23d57fc36d78fe081e6 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 13:00:34 -0700
Subject: [PATCH 005/155] Updated the readme with docker instructions
---
e2e/READEME.md | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/e2e/READEME.md b/e2e/READEME.md
index 82198eb57..3a8dcfac8 100644
--- a/e2e/READEME.md
+++ b/e2e/READEME.md
@@ -27,18 +27,24 @@ The steps below will take you all the way through Cypress. It is assumed you hav
* Clone this repository
* Create a new file `cypress.env.json` from `cypress.env.local.json`
-#### Locally
+#### 2.1 Locally
* Run `npm install` to install all the dependencies
* Run `npm run cy:run` to run the tests
-#### Docker
+#### 2.2 Docker
-#### Docker Compose
+* Run `docker build -t aps-cypress-e2e:latest ` to build an image
+* Run `docker run --rm -it -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
-#### GitHub Actions
+#### 2.3 Docker Compose
+* Run `docker-compose up` to spin a container that run cypress as a service and it executes the tests
+* Run `docker-compose down` to tear down the container
+#### 2.4 GitHub Actions
+
+* Any new commit pushed to `feature` branch would trigger a job and deploys a container and it executes the tests
## Cypress IntelliSense
From c3cae4fef50f790899202aca3b7e510b78f5b064 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 13:36:22 -0700
Subject: [PATCH 006/155] Added a github workflow to build and deploy to an
openshift container
---
.github/workflows/ci-build-deploy-e2e.yaml | 122 +++++++++++++++++++++
e2e/READEME.md | 25 ++---
2 files changed, 134 insertions(+), 13 deletions(-)
create mode 100644 .github/workflows/ci-build-deploy-e2e.yaml
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
new file mode 100644
index 000000000..94ecb45fa
--- /dev/null
+++ b/.github/workflows/ci-build-deploy-e2e.yaml
@@ -0,0 +1,122 @@
+name: Build and Deploy Cypress and Execute Tests
+
+on:
+ push:
+ branches:
+ - 'util/automation-*'
+
+env:
+ REGISTRY: docker.pkg.github.com
+ REGISTRY_USERNAME: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
+ REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Docker meta
+ id: docker_meta
+ uses: docker/metadata-action@v3
+ with:
+ images: ${{ env.REGISTRY }}/bcgov/api-services-portal/aps-cypress-e2e
+
+ - name: Set DEPLOY_ID which will deploy a custom deploy to 'dev' environment
+ run: |
+ echo '::set-output name=DEPLOY_ID::${{ steps.docker_meta.outputs.version }}'
+ echo '::set-output name=APP_VERSION::${{ fromJSON(steps.docker_meta.outputs.json).labels['org.opencontainers.image.version'] }}'
+ echo '::set-output name=APP_REVISION::${{ fromJSON(steps.docker_meta.outputs.json).labels['org.opencontainers.image.revision'] }}'
+ id: set-deploy-id
+
+ - name: Get deploy ID
+ run: echo "The DEPLOY_ID is ${{ steps.set-deploy-id.outputs.DEPLOY_ID }}"
+
+ - uses: actions/checkout@v2
+
+ - name: Install oc
+ uses: redhat-actions/oc-installer@v1
+ with:
+ version: '4.6'
+
+ - name: Authenticate and set context
+ uses: redhat-actions/oc-login@v1
+ with:
+ openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }}
+ openshift_token: ${{ secrets.OPENSHIFT_TOKEN }}
+
+ # Disables SSL cert checking. Use this if you don't have the certificate authority data.
+ insecure_skip_tls_verify: true
+
+ namespace: ${{ env.OPENSHIFT_NAMESPACE }}
+
+ - name: Login to DockerHub
+ uses: docker/login-action@v1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ env.REGISTRY_USERNAME }}
+ password: ${{ env.REGISTRY_PASSWORD }}
+
+ - uses: actions/cache@v2
+ with:
+ path: /tmp/.buildx-cache
+ key: ${{ runner.os }}-buildx-${{ github.sha }}
+ restore-keys: |
+ ${{ runner.os }}-buildx-
+
+ - name: Set up Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v1
+
+ - name: Build
+ uses: docker/build-push-action@v2
+ with:
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache
+ context: ./e2e
+ file: Dockerfile
+ tags: ${{ steps.docker_meta.outputs.tags }}
+ load: true
+ build-args: |
+ GITHUB_API_TOKEN=${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
+ APP_VERSION=${{ steps.set-deploy-id.outputs.APP_VERSION }}
+ APP_REVISION=${{ steps.set-deploy-id.outputs.APP_REVISION }}
+
+ - name: Push
+ run: docker push ${{ steps.docker_meta.outputs.tags }}
+
+ - name: 'Get Helm'
+ run: |
+ curl -L -O https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz
+ tar -xf helm-v3.4.2-linux-amd64.tar.gz
+
+ - name: 'Deploy e2e Testing Suite'
+ run: |
+ export PATH=$PATH:`pwd`/linux-amd64
+
+ echo "
+ podAnnotations:
+ sha: $GITHUB_SHA
+
+ replicaCount: 1
+
+ rollingUpdate:
+ maxUnavailable: 50%
+ maxSurge: 50%
+
+ image:
+ repository: ${{ env.REGISTRY }}/bcgov/api-services-portal/aps-cypress-e2e
+ tag: ${{ steps.set-deploy-id.outputs.DEPLOY_ID }}
+ pullPolicy: Always
+
+ imagePullSecrets:
+ - name: dev-github-read-packages-creds
+
+ podSecurityContext:
+ fsGroup: ${{ secrets.RUNNING_UID_GID }}
+
+ securityContext:
+ runAsUser: ${{ secrets.RUNNING_UID_GID }}
+
+ " > values.yaml
+
+ helm repo add bcgov http://bcgov.github.io/helm-charts
+ helm upgrade --install proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }} -f values.yaml bcgov/generic-api
diff --git a/e2e/READEME.md b/e2e/READEME.md
index 3a8dcfac8..a72d4fd57 100644
--- a/e2e/READEME.md
+++ b/e2e/READEME.md
@@ -24,27 +24,27 @@ The steps below will take you all the way through Cypress. It is assumed you hav
### 2. Run Tests
-* Clone this repository
-* Create a new file `cypress.env.json` from `cypress.env.local.json`
+- Clone this repository
+- Create a new file `cypress.env.json` from `cypress.env.local.json`
#### 2.1 Locally
-* Run `npm install` to install all the dependencies
-* Run `npm run cy:run` to run the tests
+- Run `npm install` to install all the dependencies
+- Run `npm run cy:run` to run the tests
#### 2.2 Docker
-* Run `docker build -t aps-cypress-e2e:latest ` to build an image
-* Run `docker run --rm -it -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
+- Run `docker build -t aps-cypress-e2e:latest ` to build an image
+- Run `docker run --rm -it -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
#### 2.3 Docker Compose
-* Run `docker-compose up` to spin a container that run cypress as a service and it executes the tests
-* Run `docker-compose down` to tear down the container
+- Run `docker-compose up` to spin a container that run cypress as a service and it executes the tests
+- Run `docker-compose down` to tear down the container
#### 2.4 GitHub Actions
-* Any new commit pushed to `feature` branch would trigger a job and deploys a container and it executes the tests
+- Any new commit pushed to `feature/automation-*` branch triggers a job (`.github/workflows/ci-build-deploy-e2e.yaml`) and deploys a container to execute the test suite
## Cypress IntelliSense
@@ -56,9 +56,9 @@ commands.
### Custom commands
-* This project also adds several custom commands in [cypress/support/index.js](cypress/support/index.ts).
-* To let TypeScript compiler know that we have added a custom command and have IntelliSense working, I have described the type signature of the custom command in file [cypress/support/global.d.ts](cypress/support/global.d.ts).
-* To include the new ".d.ts" file into IntelliSense, I could update `tsconfig.json` or I could add another special comment to the JavaScript spec files - `///
Date: Tue, 6 Jul 2021 13:38:34 -0700
Subject: [PATCH 007/155] Updated the path to Dockerfile
---
.github/workflows/ci-build-deploy-e2e.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
index 94ecb45fa..fc65bcca3 100644
--- a/.github/workflows/ci-build-deploy-e2e.yaml
+++ b/.github/workflows/ci-build-deploy-e2e.yaml
@@ -72,7 +72,7 @@ jobs:
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
context: ./e2e
- file: Dockerfile
+ file: ./e2e/Dockerfile
tags: ${{ steps.docker_meta.outputs.tags }}
load: true
build-args: |
From b1c0c26f6b47dbd83b56a6377614a914b0726171 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 13:40:39 -0700
Subject: [PATCH 008/155] Updated gitignore to include package-lock
---
e2e/.gitignore | 1 -
e2e/package-lock.json | 6568 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 6568 insertions(+), 1 deletion(-)
create mode 100644 e2e/package-lock.json
diff --git a/e2e/.gitignore b/e2e/.gitignore
index 3138a5752..ebd8db215 100644
--- a/e2e/.gitignore
+++ b/e2e/.gitignore
@@ -1,3 +1,2 @@
integration
-*-lock.json
cypress.env.json
\ No newline at end of file
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
new file mode 100644
index 000000000..8c11dee3f
--- /dev/null
+++ b/e2e/package-lock.json
@@ -0,0 +1,6568 @@
+{
+ "name": "bcgov-aps-portal-e2e",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+ "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+ "requires": {
+ "@babel/highlight": "^7.14.5"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz",
+ "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw=="
+ },
+ "@babel/core": {
+ "version": "7.4.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz",
+ "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==",
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/generator": "^7.4.4",
+ "@babel/helpers": "^7.4.4",
+ "@babel/parser": "^7.4.5",
+ "@babel/template": "^7.4.4",
+ "@babel/traverse": "^7.4.5",
+ "@babel/types": "^7.4.4",
+ "convert-source-map": "^1.1.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.11",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz",
+ "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==",
+ "requires": {
+ "@babel/types": "^7.14.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz",
+ "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz",
+ "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==",
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz",
+ "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==",
+ "requires": {
+ "@babel/compat-data": "^7.14.5",
+ "@babel/helper-validator-option": "^7.14.5",
+ "browserslist": "^4.16.6",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.14.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz",
+ "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.14.5",
+ "@babel/helper-function-name": "^7.14.5",
+ "@babel/helper-member-expression-to-functions": "^7.14.5",
+ "@babel/helper-optimise-call-expression": "^7.14.5",
+ "@babel/helper-replace-supers": "^7.14.5",
+ "@babel/helper-split-export-declaration": "^7.14.5"
+ }
+ },
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz",
+ "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.14.5",
+ "regexpu-core": "^4.7.1"
+ }
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz",
+ "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz",
+ "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.14.5",
+ "@babel/template": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz",
+ "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz",
+ "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz",
+ "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz",
+ "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz",
+ "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.14.5",
+ "@babel/helper-replace-supers": "^7.14.5",
+ "@babel/helper-simple-access": "^7.14.5",
+ "@babel/helper-split-export-declaration": "^7.14.5",
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "@babel/template": "^7.14.5",
+ "@babel/traverse": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz",
+ "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz",
+ "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ=="
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz",
+ "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.14.5",
+ "@babel/helper-wrap-function": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz",
+ "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==",
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.14.5",
+ "@babel/helper-optimise-call-expression": "^7.14.5",
+ "@babel/traverse": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz",
+ "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz",
+ "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz",
+ "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==",
+ "requires": {
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+ "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz",
+ "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz",
+ "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.14.5",
+ "@babel/template": "^7.14.5",
+ "@babel/traverse": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.14.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz",
+ "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==",
+ "requires": {
+ "@babel/template": "^7.14.5",
+ "@babel/traverse": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+ "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz",
+ "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA=="
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz",
+ "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-remap-async-to-generator": "^7.14.5",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz",
+ "integrity": "sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.3.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz",
+ "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz",
+ "integrity": "sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz",
+ "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz",
+ "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz",
+ "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz",
+ "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz",
+ "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-remap-async-to-generator": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz",
+ "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz",
+ "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz",
+ "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.14.5",
+ "@babel/helper-function-name": "^7.14.5",
+ "@babel/helper-optimise-call-expression": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-replace-supers": "^7.14.5",
+ "@babel/helper-split-export-declaration": "^7.14.5",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz",
+ "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz",
+ "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz",
+ "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz",
+ "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz",
+ "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==",
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz",
+ "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz",
+ "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz",
+ "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz",
+ "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz",
+ "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz",
+ "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-simple-access": "^7.14.5",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz",
+ "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==",
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.14.5",
+ "@babel/helper-module-transforms": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz",
+ "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz",
+ "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz",
+ "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz",
+ "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-replace-supers": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz",
+ "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz",
+ "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-react-display-name": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.5.tgz",
+ "integrity": "sha512-07aqY1ChoPgIxsuDviptRpVkWCSbXWmzQqcgy65C6YSFOfPFvb/DX3bBRHh7pCd/PMEEYHYWUTSVkCbkVainYQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-react-jsx": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.5.tgz",
+ "integrity": "sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.14.5",
+ "@babel/helper-module-imports": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/plugin-syntax-jsx": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-self": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.5.tgz",
+ "integrity": "sha512-M/fmDX6n0cfHK/NLTcPmrfVAORKDhK8tyjDhyxlUjYyPYYO8FRWwuxBA3WBx8kWN/uBUuwGa3s/0+hQ9JIN3Tg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-source": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.5.tgz",
+ "integrity": "sha512-1TpSDnD9XR/rQ2tzunBVPThF5poaYT9GqP+of8fAtguYuI/dm2RkrMBDemsxtY0XBzvW7nXjYM0hRyKX9QYj7Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz",
+ "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==",
+ "requires": {
+ "regenerator-transform": "^0.14.2"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz",
+ "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-runtime": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.2.0.tgz",
+ "integrity": "sha512-jIgkljDdq4RYDnJyQsiWbdvGeei/0MOTtSHKO/rfbd/mXBxNpdlulMx49L0HQ4pug1fXannxoqCI+fYSle9eSw==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "resolve": "^1.8.1",
+ "semver": "^5.5.1"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz",
+ "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.14.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz",
+ "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz",
+ "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz",
+ "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz",
+ "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz",
+ "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.4.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz",
+ "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
+ "@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.4.4",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-syntax-async-generators": "^7.2.0",
+ "@babel/plugin-syntax-json-strings": "^7.2.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-transform-arrow-functions": "^7.2.0",
+ "@babel/plugin-transform-async-to-generator": "^7.4.4",
+ "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
+ "@babel/plugin-transform-block-scoping": "^7.4.4",
+ "@babel/plugin-transform-classes": "^7.4.4",
+ "@babel/plugin-transform-computed-properties": "^7.2.0",
+ "@babel/plugin-transform-destructuring": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.2.0",
+ "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
+ "@babel/plugin-transform-for-of": "^7.4.4",
+ "@babel/plugin-transform-function-name": "^7.4.4",
+ "@babel/plugin-transform-literals": "^7.2.0",
+ "@babel/plugin-transform-member-expression-literals": "^7.2.0",
+ "@babel/plugin-transform-modules-amd": "^7.2.0",
+ "@babel/plugin-transform-modules-commonjs": "^7.4.4",
+ "@babel/plugin-transform-modules-systemjs": "^7.4.4",
+ "@babel/plugin-transform-modules-umd": "^7.2.0",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5",
+ "@babel/plugin-transform-new-target": "^7.4.4",
+ "@babel/plugin-transform-object-super": "^7.2.0",
+ "@babel/plugin-transform-parameters": "^7.4.4",
+ "@babel/plugin-transform-property-literals": "^7.2.0",
+ "@babel/plugin-transform-regenerator": "^7.4.5",
+ "@babel/plugin-transform-reserved-words": "^7.2.0",
+ "@babel/plugin-transform-shorthand-properties": "^7.2.0",
+ "@babel/plugin-transform-spread": "^7.2.0",
+ "@babel/plugin-transform-sticky-regex": "^7.2.0",
+ "@babel/plugin-transform-template-literals": "^7.4.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.2.0",
+ "@babel/plugin-transform-unicode-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "browserslist": "^4.6.0",
+ "core-js-compat": "^3.1.1",
+ "invariant": "^2.2.2",
+ "js-levenshtein": "^1.1.3",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
+ "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
+ "requires": {
+ "@babel/compat-data": "^7.14.7",
+ "@babel/helper-compilation-targets": "^7.14.5",
+ "@babel/helper-plugin-utils": "^7.14.5",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.14.5"
+ }
+ }
+ }
+ },
+ "@babel/preset-react": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz",
+ "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-transform-react-display-name": "^7.0.0",
+ "@babel/plugin-transform-react-jsx": "^7.0.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.0.0",
+ "@babel/plugin-transform-react-jsx-source": "^7.0.0"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
+ "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
+ "requires": {
+ "regenerator-runtime": "^0.12.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
+ "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
+ }
+ }
+ },
+ "@babel/template": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz",
+ "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==",
+ "requires": {
+ "@babel/code-frame": "^7.14.5",
+ "@babel/parser": "^7.14.5",
+ "@babel/types": "^7.14.5"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.14.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz",
+ "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==",
+ "requires": {
+ "@babel/code-frame": "^7.14.5",
+ "@babel/generator": "^7.14.5",
+ "@babel/helper-function-name": "^7.14.5",
+ "@babel/helper-hoist-variables": "^7.14.5",
+ "@babel/helper-split-export-declaration": "^7.14.5",
+ "@babel/parser": "^7.14.7",
+ "@babel/types": "^7.14.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz",
+ "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@cypress/browserify-preprocessor": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@cypress/browserify-preprocessor/-/browserify-preprocessor-3.0.1.tgz",
+ "integrity": "sha512-sErmFSEr5287bLMRl0POGnyFtJCs/lSk5yxrUIJUIHZ8eDvtTEr0V93xRgLjJVG54gJU4MbpHy1mRPA9VZbtQA==",
+ "requires": {
+ "@babel/core": "7.4.5",
+ "@babel/plugin-proposal-class-properties": "7.3.0",
+ "@babel/plugin-proposal-object-rest-spread": "7.3.2",
+ "@babel/plugin-transform-runtime": "7.2.0",
+ "@babel/preset-env": "7.4.5",
+ "@babel/preset-react": "7.0.0",
+ "@babel/runtime": "7.3.1",
+ "babel-plugin-add-module-exports": "1.0.2",
+ "babelify": "10.0.0",
+ "bluebird": "3.5.3",
+ "browserify": "16.2.3",
+ "coffeeify": "3.0.1",
+ "coffeescript": "1.12.7",
+ "debug": "4.1.1",
+ "fs-extra": "9.0.0",
+ "lodash.clonedeep": "4.5.0",
+ "through2": "^2.0.0",
+ "watchify": "3.11.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "@cypress/code-coverage": {
+ "version": "3.9.8",
+ "resolved": "https://registry.npmjs.org/@cypress/code-coverage/-/code-coverage-3.9.8.tgz",
+ "integrity": "sha512-DxZjozoLoIq8h0xrlB6CKb7gcEo1wqFaLYhb/V1oZwixogwRXUgWnQuqTdgBo9A7TrlOc6LsKXEAbIRps0R+Jg==",
+ "requires": {
+ "@cypress/browserify-preprocessor": "3.0.1",
+ "chalk": "4.1.1",
+ "dayjs": "1.10.5",
+ "debug": "4.3.2",
+ "execa": "4.1.0",
+ "globby": "11.0.4",
+ "istanbul-lib-coverage": "3.0.0",
+ "js-yaml": "3.14.1",
+ "nyc": "15.1.0"
+ }
+ },
+ "@cypress/instrument-cra": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@cypress/instrument-cra/-/instrument-cra-1.4.0.tgz",
+ "integrity": "sha512-gXf540xL0jcUXkWyrA2Ug9rzs+jRkc9EPhnRi8XfbnRjdF4lvnn108N6x0lgTApMTbbpCDbVuskHGXDmIuD3CQ==",
+ "requires": {
+ "babel-plugin-istanbul": "6.0.0",
+ "debug": "4.2.0",
+ "find-yarn-workspace-root": "^2.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ }
+ }
+ },
+ "@cypress/request": {
+ "version": "2.88.5",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.5.tgz",
+ "integrity": "sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "@cypress/xvfb": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
+ "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "requires": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ }
+ },
+ "@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz",
+ "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==",
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+ "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "14.17.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz",
+ "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==",
+ "dev": true
+ },
+ "@types/sinonjs__fake-timers": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz",
+ "integrity": "sha512-E1dU4fzC9wN2QK2Cr1MLCfyHM8BoNnRFvuf45LYMPNDA+WqbNzC45S4UzPxvp1fFJ1rvSGU0bPvdd35VLmXG8g==",
+ "dev": true
+ },
+ "@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "@types/yauzl": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
+ "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz",
+ "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "4.28.2",
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "debug": "^4.3.1",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.1.0",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "@typescript-eslint/experimental-utils": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz",
+ "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.7",
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/typescript-estree": "4.28.2",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz",
+ "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/typescript-estree": "4.28.2",
+ "debug": "^4.3.1"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz",
+ "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/visitor-keys": "4.28.2"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz",
+ "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz",
+ "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/visitor-keys": "4.28.2",
+ "debug": "^4.3.1",
+ "globby": "^11.0.3",
+ "is-glob": "^4.0.1",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz",
+ "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "eslint-visitor-keys": "^2.0.0"
+ }
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="
+ },
+ "acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "requires": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ }
+ },
+ "acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA=="
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.21.3"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true
+ }
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "append-transform": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+ "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
+ "requires": {
+ "default-require-extensions": "^3.0.0"
+ }
+ },
+ "arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true
+ },
+ "archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+ },
+ "array-includes": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz",
+ "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.2",
+ "get-intrinsic": "^1.1.1",
+ "is-string": "^1.0.5"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ },
+ "array.prototype.flat": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz",
+ "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.1"
+ }
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "async": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
+ "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "babel-plugin-add-module-exports": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.2.tgz",
+ "integrity": "sha512-4paN7RivvU3Rzju1vGSHWPjO8Y0rI6droWvSFKI6dvEQ4mvoV0zGojnlzVRfI6N8zISo6VERXt3coIuVmzuvNg==",
+ "requires": {
+ "chokidar": "^2.0.4"
+ }
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
+ "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^4.0.0",
+ "test-exclude": "^6.0.0"
+ }
+ },
+ "babelify": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz",
+ "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg=="
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "blob-util": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
+ "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
+ "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
+ },
+ "bn.js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
+ "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browser-pack": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
+ "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==",
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "combine-source-map": "~0.8.0",
+ "defined": "^1.0.0",
+ "safe-buffer": "^5.1.1",
+ "through2": "^2.0.0",
+ "umd": "^3.0.0"
+ }
+ },
+ "browser-resolve": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",
+ "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",
+ "requires": {
+ "resolve": "1.1.7"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="
+ }
+ }
+ },
+ "browserify": {
+ "version": "16.2.3",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz",
+ "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==",
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^1.11.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "^5.0.2",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.0",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^2.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.0.0",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp": "^0.5.0",
+ "module-deps": "^6.0.0",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "~0.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^2.0.0",
+ "stream-http": "^2.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.10.1",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+ "requires": {
+ "bn.js": "^5.0.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+ "requires": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.16.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
+ "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001219",
+ "colorette": "^1.2.2",
+ "electron-to-chromium": "^1.3.723",
+ "escalade": "^3.1.1",
+ "node-releases": "^1.1.71"
+ }
+ },
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "cached-path-relative": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz",
+ "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg=="
+ },
+ "cachedir": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
+ "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
+ "dev": true
+ },
+ "caching-transform": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+ "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
+ "requires": {
+ "hasha": "^5.0.0",
+ "make-dir": "^3.0.0",
+ "package-hash": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001242",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001242.tgz",
+ "integrity": "sha512-KvNuZ/duufelMB3w2xtf9gEWCSxJwUgoxOx5b6ScLXC4kPc9xsczUVCPrQU26j5kOsHM4pSUL54tAZt5THQKug=="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+ "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "check-more-types": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
+ "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "ci-info": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz",
+ "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-table3": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz",
+ "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==",
+ "dev": true,
+ "requires": {
+ "colors": "^1.1.2",
+ "object-assign": "^4.1.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "requires": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "coffeeify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/coffeeify/-/coffeeify-3.0.1.tgz",
+ "integrity": "sha512-Qjnr7UX6ldK1PHV7wCnv7AuCd4q19KTUtwJnu/6JRJB4rfm12zvcXtKdacUoePOKr1I4ka/ydKiwWpNAdsQb0g==",
+ "requires": {
+ "convert-source-map": "^1.3.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "coffeescript": {
+ "version": "1.12.7",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz",
+ "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA=="
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "colorette": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
+ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w=="
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true,
+ "optional": true
+ },
+ "combine-source-map": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+ "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=",
+ "requires": {
+ "convert-source-map": "~1.1.0",
+ "inline-source-map": "~0.6.0",
+ "lodash.memoize": "~3.0.3",
+ "source-map": "~0.5.3"
+ },
+ "dependencies": {
+ "convert-source-map": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+ "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA="
+ }
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true
+ },
+ "common-tags": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
+ "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+ },
+ "core-js-compat": {
+ "version": "3.15.2",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz",
+ "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==",
+ "requires": {
+ "browserslist": "^4.16.6",
+ "semver": "7.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "create-ecdh": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.5.3"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "cypress": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-7.6.0.tgz",
+ "integrity": "sha512-tTwQExY28CKt6cY85/2V1uLExcMfpBEBWXt/EcE2ht/Onl9k4lxUS7ul1UnUO5MrYwMIHMdGVh13DxdzXj4Z5w==",
+ "dev": true,
+ "requires": {
+ "@cypress/request": "^2.88.5",
+ "@cypress/xvfb": "^1.2.4",
+ "@types/node": "^14.14.31",
+ "@types/sinonjs__fake-timers": "^6.0.2",
+ "@types/sizzle": "^2.3.2",
+ "arch": "^2.2.0",
+ "blob-util": "^2.0.2",
+ "bluebird": "^3.7.2",
+ "cachedir": "^2.3.0",
+ "chalk": "^4.1.0",
+ "check-more-types": "^2.24.0",
+ "cli-cursor": "^3.1.0",
+ "cli-table3": "~0.6.0",
+ "commander": "^5.1.0",
+ "common-tags": "^1.8.0",
+ "dayjs": "^1.10.4",
+ "debug": "^4.3.2",
+ "enquirer": "^2.3.6",
+ "eventemitter2": "^6.4.3",
+ "execa": "4.1.0",
+ "executable": "^4.1.1",
+ "extract-zip": "2.0.1",
+ "figures": "^3.2.0",
+ "fs-extra": "^9.1.0",
+ "getos": "^3.2.1",
+ "is-ci": "^3.0.0",
+ "is-installed-globally": "~0.4.0",
+ "lazy-ass": "^1.6.0",
+ "listr2": "^3.8.3",
+ "lodash": "^4.17.21",
+ "log-symbols": "^4.0.0",
+ "minimist": "^1.2.5",
+ "ospath": "^1.2.2",
+ "pretty-bytes": "^5.6.0",
+ "ramda": "~0.27.1",
+ "request-progress": "^3.0.0",
+ "supports-color": "^8.1.1",
+ "tmp": "~0.2.1",
+ "untildify": "^4.0.0",
+ "url": "^0.11.0",
+ "yauzl": "^2.10.0"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
+ }
+ },
+ "cypress-xpath": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/cypress-xpath/-/cypress-xpath-1.6.2.tgz",
+ "integrity": "sha512-mtwJPl840GQPGtb480fKR5vDIcijBHhAVwby5/AIPIT/UVT7UJhM2L42/R+venR7N01I0PoOJErb6UiMbCyUxg=="
+ },
+ "dash-ast": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
+ "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA=="
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "dayjs": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz",
+ "integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g=="
+ },
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+ },
+ "default-require-extensions": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
+ "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
+ "requires": {
+ "strip-bom": "^4.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "deps-sort": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz",
+ "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==",
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "shasum-object": "^1.0.0",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+ "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "detective": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
+ "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
+ "requires": {
+ "acorn-node": "^1.6.1",
+ "defined": "^1.0.0",
+ "minimist": "^1.1.1"
+ }
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
+ },
+ "duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.3.768",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.768.tgz",
+ "integrity": "sha512-I4UMZHhVSK2pwt8jOIxTi3GIuc41NkddtKT/hpuxp9GO5UWJgDKTBa4TACppbVAuKtKbMK6BhQZvT5tFF1bcNA=="
+ },
+ "elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "requires": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
+ "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.2",
+ "is-callable": "^1.2.3",
+ "is-negative-zero": "^2.0.1",
+ "is-regex": "^1.1.3",
+ "is-string": "^1.0.6",
+ "object-inspect": "^1.10.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "string.prototype.trimend": "^1.0.4",
+ "string.prototype.trimstart": "^1.0.4",
+ "unbox-primitive": "^1.0.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-error": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "eslint-config-prettier": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
+ "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
+ "dev": true
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz",
+ "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==",
+ "dev": true,
+ "requires": {
+ "debug": "^2.6.9",
+ "resolve": "^1.13.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz",
+ "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7",
+ "pkg-dir": "^2.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-chai-friendly": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.7.1.tgz",
+ "integrity": "sha512-0xhGiSQ+9oWtNc6IZPUR+6ChKbEvLXwT9oZZ5NcGlPzHVKGn1YKwQFj7a9yL3rnRKbWF7b3RkRYEP8kN6dPOwQ==",
+ "dev": true
+ },
+ "eslint-plugin-cypress": {
+ "version": "2.11.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.3.tgz",
+ "integrity": "sha512-hOoAid+XNFtpvOzZSNWP5LDrQBEJwbZwjib4XJ1KcRYKjeVj0mAmPmucG4Egli4j/aruv+Ow/acacoloWWCl9Q==",
+ "dev": true,
+ "requires": {
+ "globals": "^11.12.0"
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.23.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz",
+ "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.3",
+ "array.prototype.flat": "^1.2.4",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.4",
+ "eslint-module-utils": "^2.6.1",
+ "find-up": "^2.0.0",
+ "has": "^1.0.3",
+ "is-core-module": "^2.4.0",
+ "minimatch": "^3.0.4",
+ "object.values": "^1.1.3",
+ "pkg-up": "^2.0.0",
+ "read-pkg-up": "^3.0.0",
+ "resolve": "^1.20.0",
+ "tsconfig-paths": "^3.9.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-prettier": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz",
+ "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0"
+ }
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "eventemitter2": {
+ "version": "6.4.4",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz",
+ "integrity": "sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==",
+ "dev": true
+ },
+ "events": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz",
+ "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg=="
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "executable": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
+ "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
+ "dev": true,
+ "requires": {
+ "pify": "^2.2.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "requires": {
+ "@types/yauzl": "^2.9.1",
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz",
+ "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==",
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ },
+ "micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-safe-stringify": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
+ "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
+ },
+ "fastq": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz",
+ "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==",
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "dev": true,
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "optional": true
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "find-cache-dir": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+ "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
+ }
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "find-yarn-workspace-root": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+ "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+ "requires": {
+ "micromatch": "^4.0.2"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ },
+ "micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "foreground-child": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+ "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fromentries": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+ "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg=="
+ },
+ "fs-extra": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
+ "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
+ },
+ "get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ=="
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+ },
+ "getos": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
+ "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
+ "dev": true,
+ "requires": {
+ "async": "^3.2.0"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "global-dirs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+ "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+ "dev": true,
+ "requires": {
+ "ini": "2.0.0"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ },
+ "globby": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
+ "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
+ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "requires": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "hasha": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+ "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
+ "requires": {
+ "is-stream": "^2.0.0",
+ "type-fest": "^0.8.0"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="
+ },
+ "htmlescape": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+ "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E="
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="
+ },
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true
+ },
+ "inline-source-map": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+ "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=",
+ "requires": {
+ "source-map": "~0.5.3"
+ }
+ },
+ "insert-module-globals": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz",
+ "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==",
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "acorn-node": "^1.5.2",
+ "combine-source-map": "^0.8.0",
+ "concat-stream": "^1.6.1",
+ "is-buffer": "^1.1.0",
+ "path-is-absolute": "^1.0.1",
+ "process": "~0.11.0",
+ "through2": "^2.0.0",
+ "undeclared-identifiers": "^1.1.2",
+ "xtend": "^4.0.0"
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bigint": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
+ "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
+ "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "is-callable": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
+ "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz",
+ "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^3.1.1"
+ }
+ },
+ "is-core-module": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+ "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
+ "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ }
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ }
+ },
+ "is-negative-zero": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-number-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
+ "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
+ "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
+ },
+ "is-string": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
+ "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+ "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg=="
+ },
+ "istanbul-lib-hook": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+ "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
+ "requires": {
+ "append-transform": "^2.0.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.14.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz",
+ "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==",
+ "requires": {
+ "@babel/code-frame": "^7.14.5",
+ "@babel/generator": "^7.14.5",
+ "@babel/helper-compilation-targets": "^7.14.5",
+ "@babel/helper-module-transforms": "^7.14.5",
+ "@babel/helpers": "^7.14.6",
+ "@babel/parser": "^7.14.6",
+ "@babel/template": "^7.14.5",
+ "@babel/traverse": "^7.14.5",
+ "@babel/types": "^7.14.5",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.1.2",
+ "semver": "^6.3.0",
+ "source-map": "^0.5.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "istanbul-lib-processinfo": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
+ "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
+ "requires": {
+ "archy": "^1.0.0",
+ "cross-spawn": "^7.0.0",
+ "istanbul-lib-coverage": "^3.0.0-alpha.1",
+ "make-dir": "^3.0.0",
+ "p-map": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "uuid": "^3.3.3"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
+ "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz",
+ "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==",
+ "requires": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ }
+ },
+ "js-levenshtein": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
+ "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz",
+ "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=",
+ "requires": {
+ "jsonify": "~0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ },
+ "dependencies": {
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
+ }
+ }
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+ },
+ "labeled-stream-splicer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz",
+ "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "stream-splicer": "^2.0.0"
+ }
+ },
+ "lazy-ass": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
+ "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=",
+ "dev": true
+ },
+ "listr2": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.10.0.tgz",
+ "integrity": "sha512-eP40ZHihu70sSmqFNbNy2NL1YwImmlMmPh9WO5sLmPDleurMHt3n+SwEWNu2kzKScexZnkyFtc1VI0z/TGlmpw==",
+ "dev": true,
+ "requires": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^1.2.2",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rxjs": "^6.6.7",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
+ },
+ "lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI="
+ },
+ "lodash.memoize": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+ "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ }
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "requires": {
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.48.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
+ "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.31",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
+ "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.48.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "module-deps": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz",
+ "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==",
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "browser-resolve": "^2.0.0",
+ "cached-path-relative": "^1.0.2",
+ "concat-stream": "~1.6.0",
+ "defined": "^1.0.0",
+ "detective": "^5.2.0",
+ "duplexer2": "^0.1.2",
+ "inherits": "^2.0.1",
+ "parents": "^1.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.4.0",
+ "stream-combiner2": "^1.1.1",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "dependencies": {
+ "browser-resolve": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz",
+ "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==",
+ "requires": {
+ "resolve": "^1.17.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nan": {
+ "version": "2.14.2",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+ "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "node-preload": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+ "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+ "requires": {
+ "process-on-spawn": "^1.0.0"
+ }
+ },
+ "node-releases": {
+ "version": "1.1.73",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
+ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg=="
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "nyc": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+ "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
+ "requires": {
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "caching-transform": "^4.0.0",
+ "convert-source-map": "^1.7.0",
+ "decamelize": "^1.2.0",
+ "find-cache-dir": "^3.2.0",
+ "find-up": "^4.1.0",
+ "foreground-child": "^2.0.0",
+ "get-package-type": "^0.1.0",
+ "glob": "^7.1.6",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-hook": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.0",
+ "istanbul-lib-processinfo": "^2.0.2",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.2",
+ "make-dir": "^3.0.0",
+ "node-preload": "^0.2.1",
+ "p-map": "^3.0.0",
+ "process-on-spawn": "^1.0.0",
+ "resolve-from": "^5.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "spawn-wrap": "^2.0.0",
+ "test-exclude": "^6.0.0",
+ "yargs": "^15.0.2"
+ }
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
+ "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
+ "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.2"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "ospath": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
+ "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=",
+ "dev": true
+ },
+ "outpipe": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz",
+ "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=",
+ "requires": {
+ "shell-quote": "^1.4.2"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-map": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+ "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ },
+ "package-hash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+ "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
+ "requires": {
+ "graceful-fs": "^4.1.15",
+ "hasha": "^5.0.0",
+ "lodash.flattendeep": "^4.4.0",
+ "release-zalgo": "^1.0.0"
+ }
+ },
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+ },
+ "parents": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+ "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=",
+ "requires": {
+ "path-platform": "~0.11.15"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
+ "requires": {
+ "asn1.js": "^5.2.0",
+ "browserify-aes": "^1.0.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ=="
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "path-platform": {
+ "version": "0.11.15",
+ "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+ "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I="
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
+ },
+ "pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "requires": {
+ "find-up": "^4.0.0"
+ }
+ },
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+ },
+ "prettier": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
+ "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
+ "pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "process-on-spawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+ "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+ "requires": {
+ "fromentries": "^1.2.0"
+ }
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ }
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
+ },
+ "ramda": {
+ "version": "0.27.1",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
+ "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==",
+ "dev": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "read-only-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+ "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=",
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
+ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^3.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="
+ },
+ "regenerate-unicode-properties": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
+ "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
+ "requires": {
+ "regenerate": "^1.4.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ },
+ "regenerator-transform": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
+ "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
+ "requires": {
+ "@babel/runtime": "^7.8.4"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.14.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz",
+ "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ }
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz",
+ "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==",
+ "requires": {
+ "regenerate": "^1.4.0",
+ "regenerate-unicode-properties": "^8.2.0",
+ "regjsgen": "^0.5.1",
+ "regjsparser": "^0.6.4",
+ "unicode-match-property-ecmascript": "^1.0.4",
+ "unicode-match-property-value-ecmascript": "^1.2.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
+ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A=="
+ },
+ "regjsparser": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz",
+ "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==",
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+ }
+ }
+ },
+ "release-zalgo": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+ "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=",
+ "requires": {
+ "es6-error": "^4.0.1"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+ "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ=="
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
+ "dev": true,
+ "requires": {
+ "throttleit": "^1.0.0"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+ },
+ "resolve": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+ "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+ "requires": {
+ "is-core-module": "^2.2.0",
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shasum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
+ "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=",
+ "requires": {
+ "json-stable-stringify": "~0.0.0",
+ "sha.js": "~2.4.4"
+ }
+ },
+ "shasum-object": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz",
+ "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==",
+ "requires": {
+ "fast-safe-stringify": "^2.0.7"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+ },
+ "shell-quote": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg=="
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
+ },
+ "simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
+ },
+ "slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+ "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
+ },
+ "spawn-wrap": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+ "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
+ "requires": {
+ "foreground-child": "^2.0.0",
+ "is-windows": "^1.0.2",
+ "make-dir": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "which": "^2.0.1"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+ "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-combiner2": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+ "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=",
+ "requires": {
+ "duplexer2": "~0.1.0",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-splicer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz",
+ "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "string-width": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+ "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+ "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
+ },
+ "subarg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+ "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=",
+ "requires": {
+ "minimist": "^1.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "syntax-error": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz",
+ "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==",
+ "requires": {
+ "acorn-node": "^1.2.0"
+ }
+ },
+ "test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "requires": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+ "requires": {
+ "process": "~0.11.0"
+ }
+ },
+ "tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "requires": {
+ "rimraf": "^3.0.0"
+ }
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "tsconfig-paths": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz",
+ "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==",
+ "dev": true,
+ "requires": {
+ "json5": "^2.2.0",
+ "minimist": "^1.2.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
+ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw=="
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+ "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
+ },
+ "umd": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
+ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow=="
+ },
+ "unbox-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+ "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has-bigints": "^1.0.1",
+ "has-symbols": "^1.0.2",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "undeclared-identifiers": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz",
+ "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==",
+ "requires": {
+ "acorn-node": "^1.3.0",
+ "dash-ast": "^1.0.0",
+ "get-assigned-identifiers": "^1.2.0",
+ "simple-concat": "^1.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ=="
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^1.0.4",
+ "unicode-property-aliases-ecmascript": "^1.0.4"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
+ "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ=="
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
+ "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg=="
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+ }
+ }
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
+ },
+ "util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
+ },
+ "watchify": {
+ "version": "3.11.1",
+ "resolved": "https://registry.npmjs.org/watchify/-/watchify-3.11.1.tgz",
+ "integrity": "sha512-WwnUClyFNRMB2NIiHgJU9RQPQNqVeFk7OmZaWf5dC5EnNa0Mgr7imBydbaJ7tGTuPM2hz1Cb4uiBvK9NVxMfog==",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "browserify": "^16.1.0",
+ "chokidar": "^2.1.1",
+ "defined": "^1.0.0",
+ "outpipe": "^1.1.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
+ "y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "requires": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ }
+ }
+}
From 0109d72c5b4ccf4554c42cb87b784c8d5b03eac5 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 15:42:39 -0700
Subject: [PATCH 009/155] using .env file to store the user creds
---
.github/workflows/ci-build-deploy-e2e.yaml | 10 ++++++++++
e2e/.env.local | 2 ++
e2e/Dockerfile | 1 -
e2e/READEME.md | 3 ++-
e2e/cypress.env.local.json | 6 ------
e2e/cypress.json | 4 ++++
e2e/cypress/plugins/index.ts | 2 ++
e2e/cypress/support/login-commands.ts | 2 +-
e2e/cypress/tests/login.spec.ts | 6 +++---
e2e/docker-compose.yml | 2 ++
e2e/package-lock.json | 17 ++++++++++++++---
e2e/package.json | 2 ++
e2e/tsconfig.json | 2 +-
13 files changed, 43 insertions(+), 16 deletions(-)
create mode 100644 e2e/.env.local
delete mode 100644 e2e/cypress.env.local.json
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
index fc65bcca3..be8361e74 100644
--- a/.github/workflows/ci-build-deploy-e2e.yaml
+++ b/.github/workflows/ci-build-deploy-e2e.yaml
@@ -116,6 +116,16 @@ jobs:
securityContext:
runAsUser: ${{ secrets.RUNNING_UID_GID }}
+ extraVolumeMounts:
+ - name: aps-portal-e2e-user-creds
+ mountPath: "/"
+ readOnly: true
+
+ extraVolumes:
+ - name: aps-portal-e2e-user-creds
+ secret:
+ secretName: bcgov-aps-portal-e2e-generic-api-secrets
+
" > values.yaml
helm repo add bcgov http://bcgov.github.io/helm-charts
diff --git a/e2e/.env.local b/e2e/.env.local
new file mode 100644
index 000000000..5482c11d2
--- /dev/null
+++ b/e2e/.env.local
@@ -0,0 +1,2 @@
+CYPRESS_PORTAL_USERNAME=
+CYPRESS_PORTAL_PASSWORD=
\ No newline at end of file
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 8033e548a..a695c0dea 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -1,7 +1,6 @@
FROM cypress/included:7.6.0
COPY cypress.json .
-COPY cypress.env.json .
COPY tsconfig.json .
COPY package.json .
COPY package-lock.json .
diff --git a/e2e/READEME.md b/e2e/READEME.md
index a72d4fd57..8f43493a6 100644
--- a/e2e/READEME.md
+++ b/e2e/READEME.md
@@ -25,7 +25,8 @@ The steps below will take you all the way through Cypress. It is assumed you hav
### 2. Run Tests
- Clone this repository
-- Create a new file `cypress.env.json` from `cypress.env.local.json`
+- Create a new file `.env` from `.env.local`
+- Replace `` with appropriate values
#### 2.1 Locally
diff --git a/e2e/cypress.env.local.json b/e2e/cypress.env.local.json
deleted file mode 100644
index 0afacafa3..000000000
--- a/e2e/cypress.env.local.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "oidc-issuer": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
- "tests-env": "dev",
- "username": "",
- "password": ""
-}
diff --git a/e2e/cypress.json b/e2e/cypress.json
index a8210bc9f..d19b556c3 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -8,5 +8,9 @@
"reporter": "junit",
"reporterOptions": {
"toConsole": true
+ },
+ "env": {
+ "OIDC_ISSUER": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
+ "TESTS_ENV": "dev"
}
}
diff --git a/e2e/cypress/plugins/index.ts b/e2e/cypress/plugins/index.ts
index fd170fba6..6e55f6cb5 100644
--- a/e2e/cypress/plugins/index.ts
+++ b/e2e/cypress/plugins/index.ts
@@ -15,3 +15,5 @@ module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
+
+require('dotenv').config()
diff --git a/e2e/cypress/support/login-commands.ts b/e2e/cypress/support/login-commands.ts
index 0c2d42b9e..0b73e1571 100644
--- a/e2e/cypress/support/login-commands.ts
+++ b/e2e/cypress/support/login-commands.ts
@@ -1,5 +1,5 @@
Cypress.Commands.add('loginToDev', (username, password) => {
- const oidcProviderURL = new URL(Cypress.env('oidc-issuer'))
+ const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
const appURL = new URL(Cypress.config('baseUrl'))
cy.location().should((loc) => {
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
index 27d913429..fecf5efd5 100644
--- a/e2e/cypress/tests/login.spec.ts
+++ b/e2e/cypress/tests/login.spec.ts
@@ -9,10 +9,10 @@ describe('User navigates aps portal login page and', () => {
it('enter credentials to login into portal', () => {
cy.xpath("//button[normalize-space()='Login']").click()
- const oidcProviderURL = new URL(Cypress.env('oidc-issuer'))
+ const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
- if (Cypress.env('tests-env') === 'dev') {
- cy.loginToDev(Cypress.env('username'), Cypress.env('password'))
+ if (Cypress.env('TESTS_ENV') === 'dev') {
+ cy.loginToDev(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
cy.verifySession(Cypress.config('baseUrl') + '/admin/session')
}
})
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index 679e42cb4..90138f43f 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -9,3 +9,5 @@ services:
dockerfile: Dockerfile
# environment:
# DEBUG: cypress:* - Writes complete log
+ env_file:
+ - .env
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 8c11dee3f..6f2eba1f5 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -998,9 +998,9 @@
"dev": true
},
"@types/node": {
- "version": "14.17.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz",
- "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==",
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz",
+ "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==",
"dev": true
},
"@types/sinonjs__fake-timers": {
@@ -2288,6 +2288,12 @@
"yauzl": "^2.10.0"
},
"dependencies": {
+ "@types/node": {
+ "version": "14.17.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz",
+ "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==",
+ "dev": true
+ },
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -2504,6 +2510,11 @@
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
"integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
},
+ "dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
+ },
"duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
diff --git a/e2e/package.json b/e2e/package.json
index 87b787a23..fe6a86910 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -10,6 +10,7 @@
"cy:run": "cypress run --config watchForFileChanges=false"
},
"devDependencies": {
+ "@types/node": "^16.0.0",
"@typescript-eslint/eslint-plugin": "^4.28.1",
"@typescript-eslint/parser": "^4.28.1",
"cypress": "^7.6.0",
@@ -24,6 +25,7 @@
"@cypress/code-coverage": "^3.9.8",
"@cypress/instrument-cra": "^1.4.0",
"cypress-xpath": "^1.6.2",
+ "dotenv": "^10.0.0",
"typescript": "^4.3.5"
}
}
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
index 5d3536730..693c528bb 100644
--- a/e2e/tsconfig.json
+++ b/e2e/tsconfig.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom", "ES2015"],
- "types": ["cypress"],
+ "types": ["cypress", "node"],
"allowJs": true
},
"include": ["./cypress/**/*.ts"],
From be339a73a00e3100e5ac623a3c6b18cf60d5c39d Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 17:05:12 -0700
Subject: [PATCH 010/155] added workdir to dockerfile and updated the secret
mount path
---
.github/workflows/ci-build-deploy-e2e.yaml | 2 +-
e2e/Dockerfile | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
index be8361e74..a957af05b 100644
--- a/.github/workflows/ci-build-deploy-e2e.yaml
+++ b/.github/workflows/ci-build-deploy-e2e.yaml
@@ -118,7 +118,7 @@ jobs:
extraVolumeMounts:
- name: aps-portal-e2e-user-creds
- mountPath: "/"
+ mountPath: "/e2e"
readOnly: true
extraVolumes:
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index a695c0dea..e33a9feee 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -1,5 +1,7 @@
FROM cypress/included:7.6.0
+WORKDIR /e2e
+
COPY cypress.json .
COPY tsconfig.json .
COPY package.json .
From 97014acd2eb7faf896a4e4512d8ff83309b9462b Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 6 Jul 2021 19:27:36 -0700
Subject: [PATCH 011/155] Updated dockerfile and mount path for env
---
.github/workflows/ci-build-deploy-e2e.yaml | 2 +-
e2e/Dockerfile | 20 +++++++++++---------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
index a957af05b..54f6365db 100644
--- a/.github/workflows/ci-build-deploy-e2e.yaml
+++ b/.github/workflows/ci-build-deploy-e2e.yaml
@@ -118,7 +118,7 @@ jobs:
extraVolumeMounts:
- name: aps-portal-e2e-user-creds
- mountPath: "/e2e"
+ mountPath: "/app"
readOnly: true
extraVolumes:
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index e33a9feee..0f0a21771 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -1,13 +1,15 @@
-FROM cypress/included:7.6.0
+FROM cypress/base:12.19.0
-WORKDIR /e2e
+WORKDIR /app
-COPY cypress.json .
-COPY tsconfig.json .
-COPY package.json .
-COPY package-lock.json .
-COPY ./cypress/ cypress
+COPY cypress.json /app
+COPY tsconfig.json /app
+COPY package.json /app
+COPY package-lock.json /app
+ADD cypress /app/cypress
-RUN npm ci --production
+RUN npm install
-CMD [ "--config-file", "./cypress.json" ]
\ No newline at end of file
+CMD [ "--config-file", "/app/cypress.json" ]
+
+ENTRYPOINT ["npm", "run", "cy:run"]
\ No newline at end of file
From 468809c662ca255c34502b8f6c541095d1eadf51 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 7 Jul 2021 07:49:47 -0700
Subject: [PATCH 012/155] Running the auto tests through github actions
---
.github/workflows/aps-cypress-e2e.yaml | 17 +++
.github/workflows/ci-build-deploy-e2e.yaml | 132 ---------------------
e2e/.env.local | 2 -
e2e/Dockerfile | 18 +--
e2e/READEME.md | 2 +-
e2e/cypress.env.local.json | 4 +
e2e/cypress/plugins/index.ts | 4 +-
e2e/docker-compose.yml | 2 -
8 files changed, 33 insertions(+), 148 deletions(-)
create mode 100644 .github/workflows/aps-cypress-e2e.yaml
delete mode 100644 .github/workflows/ci-build-deploy-e2e.yaml
delete mode 100644 e2e/.env.local
create mode 100644 e2e/cypress.env.local.json
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
new file mode 100644
index 000000000..301d1e657
--- /dev/null
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -0,0 +1,17 @@
+name: Build and Deploy Cypress and Execute Tests
+
+on:
+ push:
+ branches:
+ - 'util/automation-*'
+
+jobs:
+ cypress-run:
+ runs-on: ubuntu-latest
+ container: cypress/included:4.11.0
+ steps:
+ - uses: actions/checkout@v1
+ - run: |
+ cd e2e
+ npm install --production
+ npm run cy:run --config-file cypress.json
diff --git a/.github/workflows/ci-build-deploy-e2e.yaml b/.github/workflows/ci-build-deploy-e2e.yaml
deleted file mode 100644
index 54f6365db..000000000
--- a/.github/workflows/ci-build-deploy-e2e.yaml
+++ /dev/null
@@ -1,132 +0,0 @@
-name: Build and Deploy Cypress and Execute Tests
-
-on:
- push:
- branches:
- - 'util/automation-*'
-
-env:
- REGISTRY: docker.pkg.github.com
- REGISTRY_USERNAME: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
- REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Docker meta
- id: docker_meta
- uses: docker/metadata-action@v3
- with:
- images: ${{ env.REGISTRY }}/bcgov/api-services-portal/aps-cypress-e2e
-
- - name: Set DEPLOY_ID which will deploy a custom deploy to 'dev' environment
- run: |
- echo '::set-output name=DEPLOY_ID::${{ steps.docker_meta.outputs.version }}'
- echo '::set-output name=APP_VERSION::${{ fromJSON(steps.docker_meta.outputs.json).labels['org.opencontainers.image.version'] }}'
- echo '::set-output name=APP_REVISION::${{ fromJSON(steps.docker_meta.outputs.json).labels['org.opencontainers.image.revision'] }}'
- id: set-deploy-id
-
- - name: Get deploy ID
- run: echo "The DEPLOY_ID is ${{ steps.set-deploy-id.outputs.DEPLOY_ID }}"
-
- - uses: actions/checkout@v2
-
- - name: Install oc
- uses: redhat-actions/oc-installer@v1
- with:
- version: '4.6'
-
- - name: Authenticate and set context
- uses: redhat-actions/oc-login@v1
- with:
- openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }}
- openshift_token: ${{ secrets.OPENSHIFT_TOKEN }}
-
- # Disables SSL cert checking. Use this if you don't have the certificate authority data.
- insecure_skip_tls_verify: true
-
- namespace: ${{ env.OPENSHIFT_NAMESPACE }}
-
- - name: Login to DockerHub
- uses: docker/login-action@v1
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ env.REGISTRY_USERNAME }}
- password: ${{ env.REGISTRY_PASSWORD }}
-
- - uses: actions/cache@v2
- with:
- path: /tmp/.buildx-cache
- key: ${{ runner.os }}-buildx-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-buildx-
-
- - name: Set up Docker Buildx
- id: buildx
- uses: docker/setup-buildx-action@v1
-
- - name: Build
- uses: docker/build-push-action@v2
- with:
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache
- context: ./e2e
- file: ./e2e/Dockerfile
- tags: ${{ steps.docker_meta.outputs.tags }}
- load: true
- build-args: |
- GITHUB_API_TOKEN=${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
- APP_VERSION=${{ steps.set-deploy-id.outputs.APP_VERSION }}
- APP_REVISION=${{ steps.set-deploy-id.outputs.APP_REVISION }}
-
- - name: Push
- run: docker push ${{ steps.docker_meta.outputs.tags }}
-
- - name: 'Get Helm'
- run: |
- curl -L -O https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz
- tar -xf helm-v3.4.2-linux-amd64.tar.gz
-
- - name: 'Deploy e2e Testing Suite'
- run: |
- export PATH=$PATH:`pwd`/linux-amd64
-
- echo "
- podAnnotations:
- sha: $GITHUB_SHA
-
- replicaCount: 1
-
- rollingUpdate:
- maxUnavailable: 50%
- maxSurge: 50%
-
- image:
- repository: ${{ env.REGISTRY }}/bcgov/api-services-portal/aps-cypress-e2e
- tag: ${{ steps.set-deploy-id.outputs.DEPLOY_ID }}
- pullPolicy: Always
-
- imagePullSecrets:
- - name: dev-github-read-packages-creds
-
- podSecurityContext:
- fsGroup: ${{ secrets.RUNNING_UID_GID }}
-
- securityContext:
- runAsUser: ${{ secrets.RUNNING_UID_GID }}
-
- extraVolumeMounts:
- - name: aps-portal-e2e-user-creds
- mountPath: "/app"
- readOnly: true
-
- extraVolumes:
- - name: aps-portal-e2e-user-creds
- secret:
- secretName: bcgov-aps-portal-e2e-generic-api-secrets
-
- " > values.yaml
-
- helm repo add bcgov http://bcgov.github.io/helm-charts
- helm upgrade --install proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }} -f values.yaml bcgov/generic-api
diff --git a/e2e/.env.local b/e2e/.env.local
deleted file mode 100644
index 5482c11d2..000000000
--- a/e2e/.env.local
+++ /dev/null
@@ -1,2 +0,0 @@
-CYPRESS_PORTAL_USERNAME=
-CYPRESS_PORTAL_PASSWORD=
\ No newline at end of file
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 0f0a21771..02e2f395d 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -1,15 +1,15 @@
-FROM cypress/base:12.19.0
+FROM cypress/included:7.6.0
-WORKDIR /app
+WORKDIR /e2e
-COPY cypress.json /app
-COPY tsconfig.json /app
-COPY package.json /app
-COPY package-lock.json /app
-ADD cypress /app/cypress
+COPY cypress.json /e2e
+COPY tsconfig.json /e2e
+COPY package.json /e2e
+COPY package-lock.json /e2e
+ADD cypress /e2e/cypress
-RUN npm install
+RUN npm install --production
-CMD [ "--config-file", "/app/cypress.json" ]
+CMD [ "--config-file", "/e2e/cypress.json" ]
ENTRYPOINT ["npm", "run", "cy:run"]
\ No newline at end of file
diff --git a/e2e/READEME.md b/e2e/READEME.md
index 8f43493a6..d41dbde44 100644
--- a/e2e/READEME.md
+++ b/e2e/READEME.md
@@ -25,7 +25,7 @@ The steps below will take you all the way through Cypress. It is assumed you hav
### 2. Run Tests
- Clone this repository
-- Create a new file `.env` from `.env.local`
+- Create a new file `cypress.env.json` from `cypress.env.local.json`
- Replace `` with appropriate values
#### 2.1 Locally
diff --git a/e2e/cypress.env.local.json b/e2e/cypress.env.local.json
new file mode 100644
index 000000000..e247c77f0
--- /dev/null
+++ b/e2e/cypress.env.local.json
@@ -0,0 +1,4 @@
+{
+ "PORTAL_USERNAME": "",
+ "PORTAL_PASSWORD": ""
+}
diff --git a/e2e/cypress/plugins/index.ts b/e2e/cypress/plugins/index.ts
index 6e55f6cb5..da055abb7 100644
--- a/e2e/cypress/plugins/index.ts
+++ b/e2e/cypress/plugins/index.ts
@@ -11,9 +11,9 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
+require('dotenv').config()
+
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
-
-require('dotenv').config()
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index 90138f43f..679e42cb4 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -9,5 +9,3 @@ services:
dockerfile: Dockerfile
# environment:
# DEBUG: cypress:* - Writes complete log
- env_file:
- - .env
From e4ecb7a76a19dfa9025df6e32df98f1a3c14e28c Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 7 Jul 2021 08:09:15 -0700
Subject: [PATCH 013/155] Added mochawesome reporter
---
e2e/cypress.json | 6 +-
e2e/package-lock.json | 268 +++++++++++++++++++++++++++++++++++++++++-
e2e/package.json | 1 +
3 files changed, 271 insertions(+), 4 deletions(-)
diff --git a/e2e/cypress.json b/e2e/cypress.json
index d19b556c3..880e547ba 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -5,9 +5,11 @@
"video": false,
"defaultCommandTimeout": 1000,
"requestTimeout": 1000,
- "reporter": "junit",
+ "reporter": "mochawesome",
"reporterOptions": {
- "toConsole": true
+ "reportFilename": "bcgov-aps-cypress-e2e-report",
+ "quiet": true,
+ "reportDir": "results"
},
"env": {
"OIDC_ISSUER": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 6f2eba1f5..7f8fc9fb7 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -2354,6 +2354,11 @@
"assert-plus": "^1.0.0"
}
},
+ "dateformat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q=="
+ },
"dayjs": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz",
@@ -2471,6 +2476,11 @@
"minimist": "^1.1.1"
}
},
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w=="
+ },
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -2635,6 +2645,11 @@
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -3389,6 +3404,11 @@
"nan": "^2.12.1"
}
},
+ "fsu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz",
+ "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A=="
+ },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -4196,8 +4216,7 @@
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
- "dev": true
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"json5": {
"version": "2.2.0",
@@ -4375,6 +4394,26 @@
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI="
},
+ "lodash.isempty": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4="
+ },
+ "lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="
+ },
+ "lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
"lodash.memoize": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
@@ -4616,6 +4655,193 @@
"minimist": "^1.2.5"
}
},
+ "mochawesome": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-6.2.2.tgz",
+ "integrity": "sha512-NuIxYo8zczmL5XWLNFiud21OsAJHXrflt2lcRY2u8a3TilGwglhzTPjUHZCLqJvbqj2CnIHX2ueqOh1ViUNDPw==",
+ "requires": {
+ "chalk": "^4.1.0",
+ "diff": "^5.0.0",
+ "json-stringify-safe": "^5.0.1",
+ "lodash.isempty": "^4.4.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isobject": "^3.0.2",
+ "lodash.isstring": "^4.0.1",
+ "mochawesome-report-generator": "^5.2.0",
+ "strip-ansi": "^6.0.0",
+ "uuid": "^8.3.2"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+ }
+ }
+ },
+ "mochawesome-report-generator": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-5.2.0.tgz",
+ "integrity": "sha512-DDY/3jSkM/VrWy0vJtdYOf6qBLdaPaLcI7rQmBVbnclIX7AKniE1Rhz3T/cMT/7u54W5EHNo1z84z7efotq/Eg==",
+ "requires": {
+ "chalk": "^2.4.2",
+ "dateformat": "^3.0.2",
+ "escape-html": "^1.0.3",
+ "fs-extra": "^7.0.0",
+ "fsu": "^1.0.2",
+ "lodash.isfunction": "^3.0.8",
+ "opener": "^1.5.2",
+ "prop-types": "^15.7.2",
+ "tcomb": "^3.2.17",
+ "tcomb-validation": "^3.3.0",
+ "validator": "^10.11.0",
+ "yargs": "^13.2.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
"module-deps": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz",
@@ -4853,6 +5079,11 @@
"mimic-fn": "^2.1.0"
}
},
+ "opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="
+ },
"os-browserify": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
@@ -5139,6 +5370,16 @@
"fromentries": "^1.2.0"
}
},
+ "prop-types": {
+ "version": "15.7.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
+ "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.8.1"
+ }
+ },
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -5223,6 +5464,11 @@
"safe-buffer": "^5.1.0"
}
},
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"read-only-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
@@ -6033,6 +6279,19 @@
"acorn-node": "^1.2.0"
}
},
+ "tcomb": {
+ "version": "3.2.29",
+ "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz",
+ "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ=="
+ },
+ "tcomb-validation": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
+ "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
+ "requires": {
+ "tcomb": "^3.0.0"
+ }
+ },
"test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -6417,6 +6676,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
+ },
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
diff --git a/e2e/package.json b/e2e/package.json
index fe6a86910..9c8c08946 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -26,6 +26,7 @@
"@cypress/instrument-cra": "^1.4.0",
"cypress-xpath": "^1.6.2",
"dotenv": "^10.0.0",
+ "mochawesome": "^6.2.2",
"typescript": "^4.3.5"
}
}
From 86742501a935245e5247add2988d95073f254d15 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Thu, 8 Jul 2021 16:11:56 -0700
Subject: [PATCH 014/155] Added a new custom commands to get session and token
information. Created a new spec to verify the logout functionality
---
e2e/.gitignore | 3 +-
e2e/cypress.json | 10 +-
e2e/cypress/support/api-commands.ts | 5 +-
e2e/cypress/support/auth-commands.ts | 87 ++++++++++++++
e2e/cypress/support/commands.ts | 7 ++
e2e/cypress/support/global.d.ts | 8 +-
e2e/cypress/support/index.ts | 2 +-
e2e/cypress/support/login-commands.ts | 38 ------
e2e/cypress/tests/login.spec.ts | 15 ++-
e2e/cypress/tests/logout.spec.ts | 33 ++++++
e2e/package-lock.json | 137 +++++++++++++++++++++-
e2e/package.json | 11 +-
e2e/tsconfig.json | 2 +-
local/oauth2-proxy/oauth2-proxy-local.cfg | 3 +-
14 files changed, 300 insertions(+), 61 deletions(-)
create mode 100644 e2e/cypress/support/auth-commands.ts
delete mode 100644 e2e/cypress/support/login-commands.ts
create mode 100644 e2e/cypress/tests/logout.spec.ts
diff --git a/e2e/.gitignore b/e2e/.gitignore
index ebd8db215..4ba72e3b3 100644
--- a/e2e/.gitignore
+++ b/e2e/.gitignore
@@ -1,2 +1,3 @@
integration
-cypress.env.json
\ No newline at end of file
+cypress.env.json
+results
\ No newline at end of file
diff --git a/e2e/cypress.json b/e2e/cypress.json
index 880e547ba..1ffe26ed5 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -3,13 +3,13 @@
"integrationFolder": "cypress/tests",
"screenshotOnRunFailure": false,
"video": false,
- "defaultCommandTimeout": 1000,
- "requestTimeout": 1000,
+ "watchForFileChanges": true,
"reporter": "mochawesome",
"reporterOptions": {
- "reportFilename": "bcgov-aps-cypress-e2e-report",
- "quiet": true,
- "reportDir": "results"
+ "reportDir": "results",
+ "html": false,
+ "json": true,
+ "overwrite": false
},
"env": {
"OIDC_ISSUER": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
diff --git a/e2e/cypress/support/api-commands.ts b/e2e/cypress/support/api-commands.ts
index 4a79b87d5..ca96766c8 100644
--- a/e2e/cypress/support/api-commands.ts
+++ b/e2e/cypress/support/api-commands.ts
@@ -1,8 +1,9 @@
-Cypress.Commands.add('callApi', (options: any) => {
+Cypress.Commands.add('callApi', (options: Cypress.RequestOptions) => {
cy.request({
...options,
- }).then((res) => {
+ }).then((res: Cypress.Response) => {
expect([200, 201]).to.contain(res.status)
+ cy.log(JSON.stringify(res))
cy.wrap(res)
})
})
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
new file mode 100644
index 000000000..52d27adb3
--- /dev/null
+++ b/e2e/cypress/support/auth-commands.ts
@@ -0,0 +1,87 @@
+import { opendir } from 'fs'
+import * as jwt from 'jsonwebtoken'
+
+Cypress.Commands.add('loginToDev', (username, password) => {
+ const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
+ const appURL = new URL(Cypress.config('baseUrl'))
+
+ cy.location().should((loc) => {
+ expect(loc.protocol).to.eq(oidcProviderURL.protocol)
+ expect(loc.hostname).to.eq(oidcProviderURL.hostname)
+ })
+
+ const log = Cypress.log({
+ name: 'Login to Dev',
+ displayName: 'LOGIN_DEV',
+ message: [`🔐 Authenticating | ${username}`],
+ autoEnd: false,
+ })
+
+ cy.get('#username').type(username)
+ cy.get('#password').type(password)
+ cy.get('#kc-login').click()
+
+ cy.location().should((loc) => {
+ expect(loc.protocol).to.eq(appURL.protocol)
+ expect(loc.hostname).to.eq(appURL.hostname)
+ })
+ //saving the session cookie
+ cy.getCookies().then((cookies) => {
+ cookies.map((cookie) => {
+ Cypress.Cookies.preserveOnce(cookie.name)
+ })
+ })
+
+ log.end()
+})
+
+Cypress.Commands.add('getSession', (url: string) => {
+ cy.request({ method: 'GET', url: url })
+ .then((response) => {
+ expect(response.status).to.eq(200)
+ expect(response.body).to.include({ anonymous: false })
+ })
+ .then((response: any) => {
+ const log = Cypress.log({
+ name: 'Session Info',
+ displayName: 'SESSION_INFO',
+ message: JSON.stringify(response.body.user),
+ })
+ })
+ .then((response) => {
+ cy.wrap(response.body)
+ })
+})
+
+Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
+ const log = Cypress.log({
+ displayName: 'AUTH0 LOGIN',
+ message: [`🔐 Authenticating | ${username}`],
+ autoEnd: false,
+ })
+ log.snapshot('before')
+ cy.request({
+ method: 'POST',
+ url: Cypress.env('OIDC_ISSUER') + '/protocol/openid-connect/token',
+ body: {
+ grant_type: 'password',
+ username: Cypress.env('PORTAL_USERNAME'),
+ password: Cypress.env('PORTAL_PASSWORD'),
+ Scope: 'openid',
+ client_id: Cypress.env('CLIENT_ID'),
+ client_secret: Cypress.env('CLIENT_SECRET'),
+ },
+ form: true,
+ }).then(({ body }: any) => {
+ const user: any = jwt.decode(body.id_token)
+ const userItem = {
+ token: body.access_token,
+ user: {
+ ...user,
+ },
+ }
+ cy.log(JSON.stringify(userItem))
+ })
+ log.snapshot('after')
+ log.end()
+})
diff --git a/e2e/cypress/support/commands.ts b/e2e/cypress/support/commands.ts
index 119ab03f7..12d76a91e 100644
--- a/e2e/cypress/support/commands.ts
+++ b/e2e/cypress/support/commands.ts
@@ -22,4 +22,11 @@
//
//
// -- This will overwrite an existing command --
+
+import * as Mocha from 'mocha'
+
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+const addContext = require('mochawesome/addContext')
+Cypress.Commands.add('addContext', (message) => {
+ cy.once('test:after:run', (test) => addContext({ test }, message))
+})
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index cf361fce9..d133d4755 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -4,8 +4,12 @@ declare namespace Cypress {
interface Chainable {
loginToDev(username: string, password: string): Chainable
- verifySession(url: string): Chainable
+ getSession(url: string): Chainable
- callApi(options: Partial): Chainable>
+ callApi(options: Partial): Chainable
+
+ addContext(message: any): Chainable
+
+ loginByAuthAPI(username: string, password: string): Chainable
}
}
diff --git a/e2e/cypress/support/index.ts b/e2e/cypress/support/index.ts
index 15b04314a..a3a3948cb 100644
--- a/e2e/cypress/support/index.ts
+++ b/e2e/cypress/support/index.ts
@@ -1,4 +1,4 @@
import './commands'
import 'cypress-xpath'
-import './login-commands'
+import './auth-commands'
import './api-commands'
diff --git a/e2e/cypress/support/login-commands.ts b/e2e/cypress/support/login-commands.ts
deleted file mode 100644
index 0b73e1571..000000000
--- a/e2e/cypress/support/login-commands.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-Cypress.Commands.add('loginToDev', (username, password) => {
- const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
- const appURL = new URL(Cypress.config('baseUrl'))
-
- cy.location().should((loc) => {
- expect(loc.protocol).to.eq(oidcProviderURL.protocol)
- expect(loc.hostname).to.eq(oidcProviderURL.hostname)
- })
-
- Cypress.log({
- name: 'Login to Dev',
- displayName: 'LOGIN_DEV',
- message: [`🔐 Authenticating | ${username}`],
- })
-
- cy.get('#username').type(username)
- cy.get('#password').type(password)
- cy.get('#kc-login').click()
-
- cy.location().should((loc) => {
- expect(loc.protocol).to.eq(appURL.protocol)
- expect(loc.hostname).to.eq(appURL.hostname)
- })
-})
-
-Cypress.Commands.add('verifySession', (url: string) => {
- cy.callApi({ method: 'GET', url: url }).then((res) => {
- expect(res.body).to.include({
- anonymous: false,
- })
- Cypress.log({
- name: 'Session Info',
- displayName: 'SESSION_INFO',
- message: JSON.stringify(res.body),
- })
- cy.log('Session established successfully')
- })
-})
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
index fecf5efd5..1698d814c 100644
--- a/e2e/cypress/tests/login.spec.ts
+++ b/e2e/cypress/tests/login.spec.ts
@@ -1,19 +1,22 @@
-describe('User navigates aps portal login page and', () => {
+describe('Login spec', () => {
beforeEach(() => {
cy.visit('/')
})
-
- it('finds login button', () => {
+ it('should have login button', () => {
cy.xpath('//button').contains('Login')
})
- it('enter credentials to login into portal', () => {
+ it('should allow user to authenticate', () => {
cy.xpath("//button[normalize-space()='Login']").click()
- const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
if (Cypress.env('TESTS_ENV') === 'dev') {
cy.loginToDev(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
- cy.verifySession(Cypress.config('baseUrl') + '/admin/session')
}
})
+
+ it('should save user session after login', () => {
+ cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
+ cy.log('logged user - ' + JSON.stringify(sessionObj.user))
+ })
+ })
})
diff --git a/e2e/cypress/tests/logout.spec.ts b/e2e/cypress/tests/logout.spec.ts
new file mode 100644
index 000000000..5ececcf05
--- /dev/null
+++ b/e2e/cypress/tests/logout.spec.ts
@@ -0,0 +1,33 @@
+describe('Logout spec', () => {
+ beforeEach(() => {
+ cy.visit('/')
+ })
+ it('should check user session and login if not logged on', () => {
+ if (cy.xpath('//button').contains('Login')) {
+ cy.xpath("//button[normalize-space()='Login']").click()
+ if (Cypress.env('TESTS_ENV') === 'dev') {
+ cy.loginToDev(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
+ }
+ cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
+ expect(sessionObj.anonymous).to.eq(false)
+ cy.log('logged user - ' + JSON.stringify(sessionObj.user))
+ })
+ } else {
+ cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
+ cy.log('logged user - ' + JSON.stringify(sessionObj.user))
+ })
+ }
+ })
+
+ it('should allow user to logout', () => {
+ cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
+ cy.contains(sessionObj.user.name).click()
+ })
+
+ cy.contains('Sign Out').click()
+ })
+
+ it('should show login button after logout', () => {
+ cy.xpath('//button').contains('Login')
+ })
+})
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 7f8fc9fb7..d8f790ce6 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -997,6 +997,30 @@
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
"dev": true
},
+ "@types/jsonwebtoken": {
+ "version": "8.5.4",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz",
+ "integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/mocha": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz",
+ "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==",
+ "dev": true
+ },
+ "@types/mochawesome": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/@types/mochawesome/-/mochawesome-6.2.0.tgz",
+ "integrity": "sha512-OiwEcIy47t99YEW479OuQe9Ljvu3y6PPPQyPChV0GO0MtraZq9FgGVIBPU1DxqlsIjxw7Edij6j49HutvQOzKQ==",
+ "dev": true,
+ "requires": {
+ "@types/mocha": "*"
+ }
+ },
"@types/node": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz",
@@ -1784,6 +1808,11 @@
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
"dev": true
},
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -2543,6 +2572,14 @@
"safer-buffer": "^2.1.0"
}
},
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"electron-to-chromium": {
"version": "1.3.768",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.768.tgz",
@@ -4252,6 +4289,23 @@
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
},
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -4264,6 +4318,25 @@
"verror": "1.10.0"
}
},
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -4394,6 +4467,16 @@
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI="
},
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
"lodash.isempty": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
@@ -4404,11 +4487,26 @@
"resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
"integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="
},
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
"lodash.isobject": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
"integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
},
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
@@ -4422,8 +4520,7 @@
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
- "dev": true
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"log-symbols": {
"version": "4.1.0",
@@ -4679,6 +4776,42 @@
}
}
},
+ "mochawesome-merge": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.2.0.tgz",
+ "integrity": "sha512-FSMzagh+8hTShhFXdBLE4/zS2WALcDruoD0bmtiwHEjfyQszR/iEGFTgbuM5ewA5At3qeSGwGsT0k2Stt64NdQ==",
+ "requires": {
+ "fs-extra": "^7.0.1",
+ "glob": "^7.1.6",
+ "uuid": "^3.3.2",
+ "yargs": "^15.3.1"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
+ }
+ }
+ },
"mochawesome-report-generator": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-5.2.0.tgz",
diff --git a/e2e/package.json b/e2e/package.json
index 9c8c08946..5c7541deb 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -6,10 +6,15 @@
"author": "BC Gov APS",
"license": "MIT",
"scripts": {
- "cy:open": "cypress open",
- "cy:run": "cypress run --config watchForFileChanges=false"
+ "cy:open": "cypress open --config-file cypress.json",
+ "cy:run": "cypress run --config-file cypress.json",
+ "cy:run:cfg": "cypress run --config",
+ "moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-cypress-e2e-report.json",
+ "moch:html": "marge results/report/bcgov-aps-cypress-e2e-report.json --reportDir results/report --inline"
},
"devDependencies": {
+ "@types/jsonwebtoken": "^8.5.4",
+ "@types/mochawesome": "^6.2.0",
"@types/node": "^16.0.0",
"@typescript-eslint/eslint-plugin": "^4.28.1",
"@typescript-eslint/parser": "^4.28.1",
@@ -26,7 +31,9 @@
"@cypress/instrument-cra": "^1.4.0",
"cypress-xpath": "^1.6.2",
"dotenv": "^10.0.0",
+ "jsonwebtoken": "^8.5.1",
"mochawesome": "^6.2.2",
+ "mochawesome-merge": "^4.2.0",
"typescript": "^4.3.5"
}
}
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
index 693c528bb..849470c00 100644
--- a/e2e/tsconfig.json
+++ b/e2e/tsconfig.json
@@ -5,7 +5,7 @@
"types": ["cypress", "node"],
"allowJs": true
},
- "include": ["./cypress/**/*.ts"],
+ "include": ["./cypress/**/*.ts", "**/*.d.ts"],
"exclude": [],
"noEmit": true
}
diff --git a/local/oauth2-proxy/oauth2-proxy-local.cfg b/local/oauth2-proxy/oauth2-proxy-local.cfg
index 77d3c73a3..7d1aae073 100644
--- a/local/oauth2-proxy/oauth2-proxy-local.cfg
+++ b/local/oauth2-proxy/oauth2-proxy-local.cfg
@@ -22,4 +22,5 @@ set_authorization_header="false"
pass_authorization_header="false"
skip_auth_regex="/health|/home|/public|/docs|/redirect|/_next|/images|/devportal|/manager|/ds/api|/signout|/ds/api/swagger.yaml|^[/]$"
whitelist_domains="*"
-upstreams=["http://apsportal.localtest.me:3000"]
\ No newline at end of file
+upstreams=["http://apsportal.localtest.me:3000"]
+skip_provider_button='true'
\ No newline at end of file
From f5f2d2c2e90be1fc1c8c207af3aa20d81b877e01 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 13:41:28 -0700
Subject: [PATCH 015/155] Added cypress as a service to run the e2e tests
---
docker-compose.yml | 17 ++++++++++++++++-
e2e/Dockerfile | 3 +++
e2e/cypress.env.local.json | 4 +++-
e2e/cypress.json | 5 +++--
e2e/entrypoint.sh | 19 +++++++++++++++++++
5 files changed, 44 insertions(+), 4 deletions(-)
create mode 100755 e2e/entrypoint.sh
diff --git a/docker-compose.yml b/docker-compose.yml
index d66981272..4fb2b4ed5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -102,12 +102,27 @@ services:
entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
depends_on:
- feeder
- restart: on-failure
volumes:
- ./local/feeder-init:/tmp
networks:
- portal
- keycloak
+ # cypress:
+ # image: 'aps-cypress-e2e:latest'
+ # container_name: cypress-e2e
+ # entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ # build:
+ # context: ./e2e
+ # dockerfile: Dockerfile
+ # environment:
+ # # DEBUG: cypress:* - Writes complete log
+ # CYPRESS_PORTAL_USERNAME: local
+ # CYPRESS_PORTAL_PASSWORD: local
+ # CYPRESS_CLIENT_ID: aps-portal
+ # CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ # networks:
+ # - keycloak
+ # - oauth2-proxy
kong-db:
image: postgres:latest
container_name: kong-db
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 02e2f395d..5460f8ddd 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -2,10 +2,13 @@ FROM cypress/included:7.6.0
WORKDIR /e2e
+RUN apt-get install curl
+
COPY cypress.json /e2e
COPY tsconfig.json /e2e
COPY package.json /e2e
COPY package-lock.json /e2e
+COPY entrypoint.sh /tmp
ADD cypress /e2e/cypress
RUN npm install --production
diff --git a/e2e/cypress.env.local.json b/e2e/cypress.env.local.json
index e247c77f0..adb6be601 100644
--- a/e2e/cypress.env.local.json
+++ b/e2e/cypress.env.local.json
@@ -1,4 +1,6 @@
{
"PORTAL_USERNAME": "",
- "PORTAL_PASSWORD": ""
+ "PORTAL_PASSWORD": "",
+ "CLIENT_ID": "",
+ "CLIENT_SECRET": ""
}
diff --git a/e2e/cypress.json b/e2e/cypress.json
index 1ffe26ed5..0988a7b93 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -1,5 +1,5 @@
{
- "baseUrl": "https://api-services-portal-dev.apps.silver.devops.gov.bc.ca",
+ "baseUrl": "http://oauth2proxy.localtest.me:4180",
"integrationFolder": "cypress/tests",
"screenshotOnRunFailure": false,
"video": false,
@@ -11,8 +11,9 @@
"json": true,
"overwrite": false
},
+ "chromeWebSecurity": false,
"env": {
- "OIDC_ISSUER": "https://authz-apps-gov-bc-ca.dev.api.gov.bc.ca/auth/realms/aps-v2",
+ "OIDC_ISSUER": "http://keycloak.localtest.me:9080/auth/realms/master",
"TESTS_ENV": "dev"
}
}
diff --git a/e2e/entrypoint.sh b/e2e/entrypoint.sh
new file mode 100755
index 000000000..8650aa65a
--- /dev/null
+++ b/e2e/entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+cd /tmp
+
+while true; do
+ keycloakstatus=$(curl -o /dev/null -Isw '%{http_code}\n' http://keycloak.localtest.me:9080/auth/realms/master)
+ echo "$keycloakstatus"
+ if [[ "$keycloakstatus" == "200" ]]; then
+ echo "Keycloak is up"
+ cd /e2e
+ npm run cy:run
+ break
+ else
+ echo "Waiting for Keycloak....."
+ sleep 2m
+ fi
+done
+
+
From 9c5a9a2b5826184b0986737825cb64b877c36756 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 14:12:11 -0700
Subject: [PATCH 016/155] Optimized the login custom command
---
e2e/cypress/support/auth-commands.ts | 4 ++--
e2e/cypress/support/global.d.ts | 2 +-
e2e/cypress/tests/login.spec.ts | 6 +-----
e2e/cypress/tests/logout.spec.ts | 6 +-----
4 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 52d27adb3..0e523d015 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -1,10 +1,10 @@
import { opendir } from 'fs'
import * as jwt from 'jsonwebtoken'
-Cypress.Commands.add('loginToDev', (username, password) => {
+Cypress.Commands.add('login', (username, password) => {
const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
const appURL = new URL(Cypress.config('baseUrl'))
-
+ cy.xpath("//button[normalize-space()='Login']").click()
cy.location().should((loc) => {
expect(loc.protocol).to.eq(oidcProviderURL.protocol)
expect(loc.hostname).to.eq(oidcProviderURL.hostname)
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index d133d4755..d77bacc9f 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -2,7 +2,7 @@
declare namespace Cypress {
interface Chainable {
- loginToDev(username: string, password: string): Chainable
+ login(username: string, password: string): Chainable
getSession(url: string): Chainable
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
index 1698d814c..794c49dfd 100644
--- a/e2e/cypress/tests/login.spec.ts
+++ b/e2e/cypress/tests/login.spec.ts
@@ -7,11 +7,7 @@ describe('Login spec', () => {
})
it('should allow user to authenticate', () => {
- cy.xpath("//button[normalize-space()='Login']").click()
-
- if (Cypress.env('TESTS_ENV') === 'dev') {
- cy.loginToDev(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
- }
+ cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
})
it('should save user session after login', () => {
diff --git a/e2e/cypress/tests/logout.spec.ts b/e2e/cypress/tests/logout.spec.ts
index 5ececcf05..e41261919 100644
--- a/e2e/cypress/tests/logout.spec.ts
+++ b/e2e/cypress/tests/logout.spec.ts
@@ -4,12 +4,8 @@ describe('Logout spec', () => {
})
it('should check user session and login if not logged on', () => {
if (cy.xpath('//button').contains('Login')) {
- cy.xpath("//button[normalize-space()='Login']").click()
- if (Cypress.env('TESTS_ENV') === 'dev') {
- cy.loginToDev(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
- }
+ cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
- expect(sessionObj.anonymous).to.eq(false)
cy.log('logged user - ' + JSON.stringify(sessionObj.user))
})
} else {
From 85c2a45790b36e853670b8859f17d23e93d70b54 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 18:48:25 -0700
Subject: [PATCH 017/155] Updated E2E github actions to spin up aps portal and
perform E2E testing
---
.env.local | 4 ++-
.github/workflows/aps-cypress-e2e.yaml | 23 ++++++++++++----
docker-compose.yml | 38 +++++++++++++-------------
3 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/.env.local b/.env.local
index 485f151d7..fb9322868 100644
--- a/.env.local
+++ b/.env.local
@@ -21,4 +21,6 @@ KEYCLOAK_REALM=master
EMAIL_ENABLED=false
EXTERNAL_URL=http://oauth2proxy.localtest.me:4180
OIDC_ISSUER=http://keycloak.localtest.me:9080/auth/realms/master
-LOCAL_ENV=true
\ No newline at end of file
+LOCAL_ENV=true
+WORKING_PATH=/tmp
+DESTINATION_URL=
\ No newline at end of file
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 301d1e657..271fb04f7 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -8,10 +8,23 @@ on:
jobs:
cypress-run:
runs-on: ubuntu-latest
- container: cypress/included:4.11.0
+ container:
+ image: lucasalt/act_base:latest
steps:
- uses: actions/checkout@v1
- - run: |
- cd e2e
- npm install --production
- npm run cy:run --config-file cypress.json
+ - name: Spin up API Services Portal and Run E2E Tests
+ run: docker-compose -f docker-compose.yml up -d
+ - name: Stop the Containers
+ run: |
+ while true; do
+ if [ "$(docker ps -aq -f status=exited -f name=cypress-e2e)" ]; then
+ # cleanup
+ docker-compose stop
+ sleep 1m
+ docker-compose down
+ break
+ else
+ echo "Waiting for Cypress to Complete E2E Tests....."
+ sleep 3m
+ fi
+ done
diff --git a/docker-compose.yml b/docker-compose.yml
index 4fb2b4ed5..4792d6792 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -51,7 +51,7 @@ services:
- ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
restart: unless-stopped
env_file:
- - .env
+ - .env.local
networks:
keycloak: {}
portal: {}
@@ -68,7 +68,7 @@ services:
context: .
dockerfile: Dockerfile
env_file:
- - .env
+ - .env.local
ports:
- 3000:3000
networks:
@@ -87,7 +87,7 @@ services:
context: ./feeds
dockerfile: Dockerfile
env_file:
- - ./feeds/.env
+ - ./feeds/.env.local
ports:
- 6000:6000
networks:
@@ -107,22 +107,22 @@ services:
networks:
- portal
- keycloak
- # cypress:
- # image: 'aps-cypress-e2e:latest'
- # container_name: cypress-e2e
- # entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
- # build:
- # context: ./e2e
- # dockerfile: Dockerfile
- # environment:
- # # DEBUG: cypress:* - Writes complete log
- # CYPRESS_PORTAL_USERNAME: local
- # CYPRESS_PORTAL_PASSWORD: local
- # CYPRESS_CLIENT_ID: aps-portal
- # CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
- # networks:
- # - keycloak
- # - oauth2-proxy
+ cypress:
+ image: 'aps-cypress-e2e:latest'
+ container_name: cypress-e2e
+ entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ build:
+ context: ./e2e
+ dockerfile: Dockerfile
+ environment:
+ # DEBUG: cypress:* - Writes complete log
+ CYPRESS_PORTAL_USERNAME: local
+ CYPRESS_PORTAL_PASSWORD: local
+ CYPRESS_CLIENT_ID: aps-portal
+ CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ networks:
+ - keycloak
+ - oauth2-proxy
kong-db:
image: postgres:latest
container_name: kong-db
From 21fa4083c97c3c0aa3145c885d85e0ef9e2c1b8e Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 19:32:56 -0700
Subject: [PATCH 018/155] Added a command to check the status of containers
---
.github/workflows/aps-cypress-e2e.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 271fb04f7..b17bea8d5 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -24,7 +24,8 @@ jobs:
docker-compose down
break
else
+ docker ps -a
echo "Waiting for Cypress to Complete E2E Tests....."
- sleep 3m
+ sleep 1m
fi
done
From b83a0f754725a5cea73b2cffe2ab2523f3ff5fb2 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 19:58:12 -0700
Subject: [PATCH 019/155] Testing keycloak in github environment
---
.github/workflows/aps-cypress-e2e.yaml | 2 +-
docker-compose.yml | 258 ++++++++++++-------------
2 files changed, 129 insertions(+), 131 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index b17bea8d5..518952b21 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -17,7 +17,7 @@ jobs:
- name: Stop the Containers
run: |
while true; do
- if [ "$(docker ps -aq -f status=exited -f name=cypress-e2e)" ]; then
+ if [ "$(docker ps -aq -f status=exited -f name=keycloak)" ]; then
# cleanup
docker-compose stop
sleep 1m
diff --git a/docker-compose.yml b/docker-compose.yml
index 4792d6792..222ccf0fb 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -39,90 +39,90 @@ services:
keycloak:
aliases:
- keycloak.localtest.me
- oauth2-proxy:
- image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
- container_name: oauth2-proxy
- command: --config ./oauth2-proxy.cfg
- depends_on:
- - keycloak
- ports:
- - 4180:4180/tcp
- volumes:
- - ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
- restart: unless-stopped
- env_file:
- - .env.local
- networks:
- keycloak: {}
- portal: {}
- kong-net: {}
- oauth2-proxy:
- aliases:
- - oauth2proxy.localtest.me
- apsportal:
- container_name: apsportal
- image: apsportal:latest
- depends_on:
- - keycloak
- build:
- context: .
- dockerfile: Dockerfile
- env_file:
- - .env.local
- ports:
- - 3000:3000
- networks:
- portal:
- aliases:
- - apsportal.localtest.me
- keycloak: {}
- oauth2-proxy: {}
- kong-net: {}
- feeder:
- container_name: feeder
- image: feeder:latest
- depends_on:
- - oauth2-proxy
- build:
- context: ./feeds
- dockerfile: Dockerfile
- env_file:
- - ./feeds/.env.local
- ports:
- - 6000:6000
- networks:
- portal:
- aliases:
- - feeder.localtest.me
- kong-net: {}
- feeder-seeding:
- container_name: feeder-seeding
- image: feeder:latest
- command: ''
- entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
- depends_on:
- - feeder
- volumes:
- - ./local/feeder-init:/tmp
- networks:
- - portal
- - keycloak
- cypress:
- image: 'aps-cypress-e2e:latest'
- container_name: cypress-e2e
- entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
- build:
- context: ./e2e
- dockerfile: Dockerfile
- environment:
- # DEBUG: cypress:* - Writes complete log
- CYPRESS_PORTAL_USERNAME: local
- CYPRESS_PORTAL_PASSWORD: local
- CYPRESS_CLIENT_ID: aps-portal
- CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
- networks:
- - keycloak
- - oauth2-proxy
+ # oauth2-proxy:
+ # image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
+ # container_name: oauth2-proxy
+ # command: --config ./oauth2-proxy.cfg
+ # depends_on:
+ # - keycloak
+ # ports:
+ # - 4180:4180/tcp
+ # volumes:
+ # - ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
+ # restart: unless-stopped
+ # env_file:
+ # - .env.local
+ # networks:
+ # keycloak: {}
+ # portal: {}
+ # kong-net: {}
+ # oauth2-proxy:
+ # aliases:
+ # - oauth2proxy.localtest.me
+ # apsportal:
+ # container_name: apsportal
+ # image: apsportal:latest
+ # depends_on:
+ # - keycloak
+ # build:
+ # context: .
+ # dockerfile: Dockerfile
+ # env_file:
+ # - .env.local
+ # ports:
+ # - 3000:3000
+ # networks:
+ # portal:
+ # aliases:
+ # - apsportal.localtest.me
+ # keycloak: {}
+ # oauth2-proxy: {}
+ # kong-net: {}
+ # feeder:
+ # container_name: feeder
+ # image: feeder:latest
+ # depends_on:
+ # - oauth2-proxy
+ # build:
+ # context: ./feeds
+ # dockerfile: Dockerfile
+ # env_file:
+ # - ./feeds/.env.local
+ # ports:
+ # - 6000:6000
+ # networks:
+ # portal:
+ # aliases:
+ # - feeder.localtest.me
+ # kong-net: {}
+ # feeder-seeding:
+ # container_name: feeder-seeding
+ # image: feeder:latest
+ # command: ''
+ # entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
+ # depends_on:
+ # - feeder
+ # volumes:
+ # - ./local/feeder-init:/tmp
+ # networks:
+ # - portal
+ # - keycloak
+ # cypress:
+ # image: 'aps-cypress-e2e:latest'
+ # container_name: cypress-e2e
+ # entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ # build:
+ # context: ./e2e
+ # dockerfile: Dockerfile
+ # environment:
+ # # DEBUG: cypress:* - Writes complete log
+ # CYPRESS_PORTAL_USERNAME: local
+ # CYPRESS_PORTAL_PASSWORD: local
+ # CYPRESS_CLIENT_ID: aps-portal
+ # CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ # networks:
+ # - keycloak
+ # - oauth2-proxy
kong-db:
image: postgres:latest
container_name: kong-db
@@ -140,51 +140,49 @@ services:
- kong-net
- keycloak
- portal
- kong-migrations:
- image: kong:latest
- command: kong migrations bootstrap
- depends_on:
- - kong-db
- environment: *common-variables
- networks:
- - kong-net
- restart: on-failure
- kong-migrations-up:
- image: kong:latest
- command: kong migrations up && kong migrations finish
- depends_on:
- - kong-db
- environment: *common-variables
- networks:
- - kong-net
- restart: on-failure
- kong:
- image: kong:latest
- container_name: kong
- depends_on:
- - kong-migrations
- - kong-migrations-up
- environment:
- <<: *common-variables
- KONG_ADMIN_ACCESS_LOG: /dev/stdout
- KONG_ADMIN_ERROR_LOG: /dev/stderr
- KONG_CASSANDRA_CONTACT_POINTS: kong-db
- KONG_NGINX_WORKER_PROCESSES: '1'
- KONG_PROXY_ACCESS_LOG: /dev/stdout
- KONG_PROXY_ERROR_LOG: /dev/stderr
- KONG_ADMIN_LISTEN: 0.0.0.0:8001
- ports:
- - 8000:8000
- - 8001:8001
- networks:
- kong-net:
- aliases:
- - kong.localtest.me
- restart: on-failure:5
+ # kong-migrations:
+ # image: kong:latest
+ # command: kong migrations bootstrap
+ # depends_on:
+ # - kong-db
+ # environment: *common-variables
+ # networks:
+ # - kong-net
+ # restart: on-failure
+ # kong-migrations-up:
+ # image: kong:latest
+ # command: kong migrations up && kong migrations finish
+ # depends_on:
+ # - kong-db
+ # environment: *common-variables
+ # networks:
+ # - kong-net
+ # restart: on-failure
+ # kong:
+ # image: kong:latest
+ # container_name: kong
+ # depends_on:
+ # - kong-migrations
+ # - kong-migrations-up
+ # environment:
+ # <<: *common-variables
+ # KONG_ADMIN_ACCESS_LOG: /dev/stdout
+ # KONG_ADMIN_ERROR_LOG: /dev/stderr
+ # KONG_CASSANDRA_CONTACT_POINTS: kong-db
+ # KONG_NGINX_WORKER_PROCESSES: '1'
+ # KONG_PROXY_ACCESS_LOG: /dev/stdout
+ # KONG_PROXY_ERROR_LOG: /dev/stderr
+ # KONG_ADMIN_LISTEN: 0.0.0.0:8001
+ # ports:
+ # - 8000:8000
+ # - 8001:8001
+ # networks:
+ # kong-net:
+ # aliases:
+ # - kong.localtest.me
+ # restart: on-failure:5
networks:
keycloak: {}
- oauth2-proxy: {}
- portal: {}
- kong-net: {}
-volumes:
- aps-pg-data: {}
+ # oauth2-proxy: {}
+ # portal: {}
+ # kong-net: {}
From b01825304be04519a47a21d74292630d4dd945b4 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 19:58:53 -0700
Subject: [PATCH 020/155] Added missing network
---
docker-compose.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 222ccf0fb..0f038475d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -39,6 +39,7 @@ services:
keycloak:
aliases:
- keycloak.localtest.me
+ kong-net: {}
# oauth2-proxy:
# image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
# container_name: oauth2-proxy
@@ -139,7 +140,7 @@ services:
networks:
- kong-net
- keycloak
- - portal
+ #- portal
# kong-migrations:
# image: kong:latest
# command: kong migrations bootstrap
@@ -185,4 +186,4 @@ networks:
keycloak: {}
# oauth2-proxy: {}
# portal: {}
- # kong-net: {}
+ kong-net: {}
From 437901aa8830d151a6ff4885db88f946ede5dd66 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 20:06:29 -0700
Subject: [PATCH 021/155] Running services open to view the complete log
---
.github/workflows/aps-cypress-e2e.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 518952b21..123385020 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
- run: docker-compose -f docker-compose.yml up -d
+ run: docker-compose -f docker-compose.yml up
- name: Stop the Containers
run: |
while true; do
From 07952ea9ca59417d4ead70cee295d9c8fbf06374 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 20:29:20 -0700
Subject: [PATCH 022/155] Adding volumes
---
.github/workflows/aps-cypress-e2e.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 123385020..ad9da11eb 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -10,6 +10,7 @@ jobs:
runs-on: ubuntu-latest
container:
image: lucasalt/act_base:latest
+ options: -v /var/run/docker.sock:/var/run/docker.sock -v ${{ github.workspace }}:/home/nkuruba/nithin/Git/api-services-portal
steps:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
From 6c8b874c124bc0a7e804501daff225064e40b702 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 23:28:24 -0700
Subject: [PATCH 023/155] updated github workflow to use default ubuntu-latest
image to run the docker compose
---
.github/workflows/aps-cypress-e2e.yaml | 5 +-
docker-compose.yml | 257 +++++++++++++------------
2 files changed, 130 insertions(+), 132 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index ad9da11eb..0f97d5f77 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -8,13 +8,10 @@ on:
jobs:
cypress-run:
runs-on: ubuntu-latest
- container:
- image: lucasalt/act_base:latest
- options: -v /var/run/docker.sock:/var/run/docker.sock -v ${{ github.workspace }}:/home/nkuruba/nithin/Git/api-services-portal
steps:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
- run: docker-compose -f docker-compose.yml up
+ run: docker-compose up
- name: Stop the Containers
run: |
while true; do
diff --git a/docker-compose.yml b/docker-compose.yml
index 0f038475d..fb4e5522a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -40,90 +40,91 @@ services:
aliases:
- keycloak.localtest.me
kong-net: {}
- # oauth2-proxy:
- # image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
- # container_name: oauth2-proxy
- # command: --config ./oauth2-proxy.cfg
- # depends_on:
- # - keycloak
- # ports:
- # - 4180:4180/tcp
- # volumes:
- # - ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
- # restart: unless-stopped
- # env_file:
- # - .env.local
- # networks:
- # keycloak: {}
- # portal: {}
- # kong-net: {}
- # oauth2-proxy:
- # aliases:
- # - oauth2proxy.localtest.me
- # apsportal:
- # container_name: apsportal
- # image: apsportal:latest
- # depends_on:
- # - keycloak
- # build:
- # context: .
- # dockerfile: Dockerfile
- # env_file:
- # - .env.local
- # ports:
- # - 3000:3000
- # networks:
- # portal:
- # aliases:
- # - apsportal.localtest.me
- # keycloak: {}
- # oauth2-proxy: {}
- # kong-net: {}
- # feeder:
- # container_name: feeder
- # image: feeder:latest
- # depends_on:
- # - oauth2-proxy
- # build:
- # context: ./feeds
- # dockerfile: Dockerfile
- # env_file:
- # - ./feeds/.env.local
- # ports:
- # - 6000:6000
- # networks:
- # portal:
- # aliases:
- # - feeder.localtest.me
- # kong-net: {}
- # feeder-seeding:
- # container_name: feeder-seeding
- # image: feeder:latest
- # command: ''
- # entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
- # depends_on:
- # - feeder
- # volumes:
- # - ./local/feeder-init:/tmp
- # networks:
- # - portal
- # - keycloak
- # cypress:
- # image: 'aps-cypress-e2e:latest'
- # container_name: cypress-e2e
- # entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
- # build:
- # context: ./e2e
- # dockerfile: Dockerfile
- # environment:
- # # DEBUG: cypress:* - Writes complete log
- # CYPRESS_PORTAL_USERNAME: local
- # CYPRESS_PORTAL_PASSWORD: local
- # CYPRESS_CLIENT_ID: aps-portal
- # CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
- # networks:
- # - keycloak
- # - oauth2-proxy
+ oauth2-proxy:
+ image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
+ container_name: oauth2-proxy
+ command: --config ./oauth2-proxy.cfg
+ depends_on:
+ - keycloak
+ ports:
+ - 4180:4180/tcp
+ volumes:
+ - ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
+ restart: unless-stopped
+ env_file:
+ - .env
+ networks:
+ keycloak: {}
+ portal: {}
+ kong-net: {}
+ oauth2-proxy:
+ aliases:
+ - oauth2proxy.localtest.me
+ apsportal:
+ container_name: apsportal
+ image: apsportal:latest
+ depends_on:
+ - keycloak
+ build:
+ context: .
+ dockerfile: Dockerfile
+ env_file:
+ - .env
+ ports:
+ - 3000:3000
+ networks:
+ portal:
+ aliases:
+ - apsportal.localtest.me
+ keycloak: {}
+ oauth2-proxy: {}
+ kong-net: {}
+ feeder:
+ container_name: feeder
+ image: feeder:latest
+ depends_on:
+ - oauth2-proxy
+ build:
+ context: ./feeds
+ dockerfile: Dockerfile
+ env_file:
+ - ./feeds/.env
+ restart: on-failure
+ ports:
+ - 6000:6000
+ networks:
+ portal:
+ aliases:
+ - feeder.localtest.me
+ kong-net: {}
+ feeder-seeding:
+ container_name: feeder-seeding
+ image: feeder:latest
+ command: ''
+ entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
+ depends_on:
+ - feeder
+ volumes:
+ - ./local/feeder-init:/tmp
+ networks:
+ - portal
+ - keycloak
+ cypress:
+ image: 'aps-cypress-e2e:latest'
+ container_name: cypress-e2e
+ entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ build:
+ context: ./e2e
+ dockerfile: Dockerfile
+ environment:
+ # DEBUG: cypress:* - Writes complete log
+ CYPRESS_PORTAL_USERNAME: local
+ CYPRESS_PORTAL_PASSWORD: local
+ CYPRESS_CLIENT_ID: aps-portal
+ CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ networks:
+ - keycloak
+ - oauth2-proxy
kong-db:
image: postgres:latest
container_name: kong-db
@@ -140,50 +141,50 @@ services:
networks:
- kong-net
- keycloak
- #- portal
- # kong-migrations:
- # image: kong:latest
- # command: kong migrations bootstrap
- # depends_on:
- # - kong-db
- # environment: *common-variables
- # networks:
- # - kong-net
- # restart: on-failure
- # kong-migrations-up:
- # image: kong:latest
- # command: kong migrations up && kong migrations finish
- # depends_on:
- # - kong-db
- # environment: *common-variables
- # networks:
- # - kong-net
- # restart: on-failure
- # kong:
- # image: kong:latest
- # container_name: kong
- # depends_on:
- # - kong-migrations
- # - kong-migrations-up
- # environment:
- # <<: *common-variables
- # KONG_ADMIN_ACCESS_LOG: /dev/stdout
- # KONG_ADMIN_ERROR_LOG: /dev/stderr
- # KONG_CASSANDRA_CONTACT_POINTS: kong-db
- # KONG_NGINX_WORKER_PROCESSES: '1'
- # KONG_PROXY_ACCESS_LOG: /dev/stdout
- # KONG_PROXY_ERROR_LOG: /dev/stderr
- # KONG_ADMIN_LISTEN: 0.0.0.0:8001
- # ports:
- # - 8000:8000
- # - 8001:8001
- # networks:
- # kong-net:
- # aliases:
- # - kong.localtest.me
- # restart: on-failure:5
+ - portal
+ kong-migrations:
+ image: kong:latest
+ command: kong migrations bootstrap
+ depends_on:
+ - kong-db
+ environment: *common-variables
+ networks:
+ - kong-net
+ restart: on-failure
+ kong-migrations-up:
+ image: kong:latest
+ command: kong migrations up && kong migrations finish
+ depends_on:
+ - kong-db
+ environment: *common-variables
+ networks:
+ - kong-net
+ restart: on-failure
+ kong:
+ image: kong:latest
+ container_name: kong
+ depends_on:
+ - kong-migrations
+ - kong-migrations-up
+ environment:
+ <<: *common-variables
+ KONG_ADMIN_ACCESS_LOG: /dev/stdout
+ KONG_ADMIN_ERROR_LOG: /dev/stderr
+ KONG_CASSANDRA_CONTACT_POINTS: kong-db
+ KONG_NGINX_WORKER_PROCESSES: '1'
+ KONG_PROXY_ACCESS_LOG: /dev/stdout
+ KONG_PROXY_ERROR_LOG: /dev/stderr
+ KONG_ADMIN_LISTEN: 0.0.0.0:8001
+ ports:
+ - 8000:8000
+ - 8001:8001
+ networks:
+ kong-net:
+ aliases:
+ - kong.localtest.me
+ restart: on-failure:5
networks:
keycloak: {}
- # oauth2-proxy: {}
- # portal: {}
+ oauth2-proxy: {}
+ portal: {}
kong-net: {}
From 94e4b4fc3576e56b5f5b6f3d1ac2ca4f0728dadf Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 23:29:47 -0700
Subject: [PATCH 024/155] upddated docker compose to use .env.local file
---
docker-compose.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index fb4e5522a..10fa78a13 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -52,7 +52,7 @@ services:
- ./local/oauth2-proxy/oauth2-proxy-local.cfg:/oauth2-proxy.cfg
restart: unless-stopped
env_file:
- - .env
+ - .env.local
networks:
keycloak: {}
portal: {}
@@ -69,7 +69,7 @@ services:
context: .
dockerfile: Dockerfile
env_file:
- - .env
+ - .env.local
ports:
- 3000:3000
networks:
@@ -88,7 +88,7 @@ services:
context: ./feeds
dockerfile: Dockerfile
env_file:
- - ./feeds/.env
+ - ./feeds/.env.local
restart: on-failure
ports:
- 6000:6000
From b20669298a38fe9c209c7f50564f24d3ed75945b Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 9 Jul 2021 23:47:27 -0700
Subject: [PATCH 025/155] Updated wait time for cypress to allow for initial
data seeding
---
.github/workflows/aps-cypress-e2e.yaml | 4 ++--
e2e/entrypoint.sh | 4 +++-
local/feeder-init/init.sh | 2 +-
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 0f97d5f77..2553b92a5 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -11,11 +11,11 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
- run: docker-compose up
+ run: docker-compose up -d
- name: Stop the Containers
run: |
while true; do
- if [ "$(docker ps -aq -f status=exited -f name=keycloak)" ]; then
+ if [ "$(docker ps -aq -f status=exited -f name=cypress)" ]; then
# cleanup
docker-compose stop
sleep 1m
diff --git a/e2e/entrypoint.sh b/e2e/entrypoint.sh
index 8650aa65a..0c7eac025 100755
--- a/e2e/entrypoint.sh
+++ b/e2e/entrypoint.sh
@@ -8,11 +8,13 @@ while true; do
if [[ "$keycloakstatus" == "200" ]]; then
echo "Keycloak is up"
cd /e2e
+ # added sleep to wait for initial data seeding
+ sleep 2m
npm run cy:run
break
else
echo "Waiting for Keycloak....."
- sleep 2m
+ sleep 3m
fi
done
diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh
index 9025c00ed..94b616dd0 100755
--- a/local/feeder-init/init.sh
+++ b/local/feeder-init/init.sh
@@ -16,7 +16,7 @@ while true; do
break
else
echo "Waiting for Keycloak....."
- sleep 2m
+ sleep 1m
fi
done
From 2e7dd932dd752d5876efafb4694cffda8629d66c Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 10 Jul 2021 21:43:26 -0700
Subject: [PATCH 026/155] Updated github action to save the test report as
artifact
---
.github/workflows/aps-cypress-e2e.yaml | 8 +-
docker-compose.yml | 2 +
e2e/Dockerfile | 4 +-
e2e/docker-compose.yml | 2 +
e2e/entrypoint.sh | 2 +-
e2e/package-lock.json | 157 +++++++++++++++++--------
e2e/package.json | 4 +-
7 files changed, 122 insertions(+), 57 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 2553b92a5..1cc95358b 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -12,17 +12,21 @@ jobs:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
run: docker-compose up -d
+ - name: Upload E2E Test Report as Artifact
+ run: actions/upload-artifact@v2
+ with:
+ name: E2E Test Report
+ path: ${{ github.workspace }}/e2e/results/report/*.html
- name: Stop the Containers
run: |
while true; do
- if [ "$(docker ps -aq -f status=exited -f name=cypress)" ]; then
+ if [ "$(docker ps -aq -f status=exited -f name=cypress-e2e)" ]; then
# cleanup
docker-compose stop
sleep 1m
docker-compose down
break
else
- docker ps -a
echo "Waiting for Cypress to Complete E2E Tests....."
sleep 1m
fi
diff --git a/docker-compose.yml b/docker-compose.yml
index 10fa78a13..2a5b4175e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -122,6 +122,8 @@ services:
CYPRESS_PORTAL_PASSWORD: local
CYPRESS_CLIENT_ID: aps-portal
CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ volumes:
+ - ./e2e/results/report:/e2e/results/report
networks:
- keycloak
- oauth2-proxy
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 5460f8ddd..2a271ca3f 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -13,6 +13,4 @@ ADD cypress /e2e/cypress
RUN npm install --production
-CMD [ "--config-file", "/e2e/cypress.json" ]
-
-ENTRYPOINT ["npm", "run", "cy:run"]
\ No newline at end of file
+ENTRYPOINT ["npm", "run", "cy:run:html"]
\ No newline at end of file
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index 679e42cb4..eff818669 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -9,3 +9,5 @@ services:
dockerfile: Dockerfile
# environment:
# DEBUG: cypress:* - Writes complete log
+ volumes:
+ - ./results/report:/e2e/results/report
diff --git a/e2e/entrypoint.sh b/e2e/entrypoint.sh
index 0c7eac025..2a7104f18 100755
--- a/e2e/entrypoint.sh
+++ b/e2e/entrypoint.sh
@@ -10,7 +10,7 @@ while true; do
cd /e2e
# added sleep to wait for initial data seeding
sleep 2m
- npm run cy:run
+ npm run cy:run:html
break
else
echo "Waiting for Keycloak....."
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index d8f790ce6..5bf22e9c5 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -2632,7 +2632,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
"requires": {
"is-arrayish": "^0.2.1"
}
@@ -2641,7 +2640,6 @@
"version": "1.18.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
"integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@@ -2665,7 +2663,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@@ -3609,8 +3606,7 @@
"has-bigints": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
- "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
- "dev": true
+ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"has-flag": {
"version": "3.0.0",
@@ -3709,8 +3705,7 @@
"hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
},
"html-escaper": {
"version": "2.0.2",
@@ -3837,14 +3832,12 @@
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-bigint": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
- "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
- "dev": true
+ "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA=="
},
"is-binary-path": {
"version": "1.0.1",
@@ -3858,7 +3851,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2"
}
@@ -3871,8 +3863,7 @@
"is-callable": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
- "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
- "dev": true
+ "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
},
"is-ci": {
"version": "3.0.0",
@@ -3912,8 +3903,7 @@
"is-date-object": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
- "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
- "dev": true
+ "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A=="
},
"is-descriptor": {
"version": "0.1.6",
@@ -3968,8 +3958,7 @@
"is-negative-zero": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
- "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
- "dev": true
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
},
"is-number": {
"version": "3.0.0",
@@ -3992,8 +3981,7 @@
"is-number-object": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
- "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
- "dev": true
+ "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw=="
},
"is-path-inside": {
"version": "3.0.3",
@@ -4013,7 +4001,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-symbols": "^1.0.2"
@@ -4027,14 +4014,12 @@
"is-string": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
- "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
- "dev": true
+ "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w=="
},
"is-symbol": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
@@ -4227,8 +4212,7 @@
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"json-schema": {
"version": "0.2.3",
@@ -4422,7 +4406,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
"integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"parse-json": "^4.0.0",
@@ -4433,14 +4416,12 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
},
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
}
}
},
@@ -4636,6 +4617,11 @@
"safe-buffer": "^5.1.2"
}
},
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
+ },
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -5036,6 +5022,11 @@
"to-regex": "^3.0.1"
}
},
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
"node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
@@ -5053,7 +5044,6 @@
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
"requires": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
@@ -5066,6 +5056,72 @@
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -5150,8 +5206,7 @@
"object-inspect": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
- "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
- "dev": true
+ "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw=="
},
"object-keys": {
"version": "1.1.1",
@@ -5305,7 +5360,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
@@ -5385,6 +5439,11 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
},
+ "pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA=="
+ },
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -5614,7 +5673,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
"integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
"requires": {
"load-json-file": "^4.0.0",
"normalize-package-data": "^2.3.2",
@@ -5625,7 +5683,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
- "dev": true,
"requires": {
"pify": "^3.0.0"
}
@@ -5633,8 +5690,7 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
}
}
},
@@ -6216,7 +6272,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
- "dev": true,
"requires": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
@@ -6225,14 +6280,12 @@
"spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
},
"spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
"requires": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
@@ -6241,8 +6294,7 @@
"spdx-license-ids": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
- "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
- "dev": true
+ "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ=="
},
"split-string": {
"version": "3.1.0",
@@ -6342,11 +6394,20 @@
"strip-ansi": "^6.0.0"
}
},
+ "string.prototype.padend": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz",
+ "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.2"
+ }
+ },
"string.prototype.trimend": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -6356,7 +6417,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -6624,7 +6684,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
- "dev": true,
"requires": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
@@ -6803,7 +6862,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
"requires": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
@@ -6856,7 +6914,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
diff --git a/e2e/package.json b/e2e/package.json
index 5c7541deb..847e4b484 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -10,7 +10,8 @@
"cy:run": "cypress run --config-file cypress.json",
"cy:run:cfg": "cypress run --config",
"moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-cypress-e2e-report.json",
- "moch:html": "marge results/report/bcgov-aps-cypress-e2e-report.json --reportDir results/report --inline"
+ "moch:html": "marge results/report/bcgov-aps-cypress-e2e-report.json --reportDir results/report --inline",
+ "cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html"
},
"devDependencies": {
"@types/jsonwebtoken": "^8.5.4",
@@ -34,6 +35,7 @@
"jsonwebtoken": "^8.5.1",
"mochawesome": "^6.2.2",
"mochawesome-merge": "^4.2.0",
+ "npm-run-all": "^4.1.5",
"typescript": "^4.3.5"
}
}
From fe0d6bf3e931aa4e146d473f1fbc2bedbac76e03 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 10 Jul 2021 21:46:30 -0700
Subject: [PATCH 027/155] Updated github action workflow syntax
---
.github/workflows/aps-cypress-e2e.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 1cc95358b..d5d86aaf1 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -13,7 +13,7 @@ jobs:
- name: Spin up API Services Portal and Run E2E Tests
run: docker-compose up -d
- name: Upload E2E Test Report as Artifact
- run: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v2
with:
name: E2E Test Report
path: ${{ github.workspace }}/e2e/results/report/*.html
From 275e557dc2730069a3804e4983ad7320ff7a5840 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 10 Jul 2021 22:04:01 -0700
Subject: [PATCH 028/155] Updated workflow to wait until cypress exits to
upload the artifact
---
.github/workflows/aps-cypress-e2e.yaml | 10 +++++-----
e2e/entrypoint.sh | 4 ++--
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index d5d86aaf1..4e6889c5a 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -12,11 +12,6 @@ jobs:
- uses: actions/checkout@v1
- name: Spin up API Services Portal and Run E2E Tests
run: docker-compose up -d
- - name: Upload E2E Test Report as Artifact
- uses: actions/upload-artifact@v2
- with:
- name: E2E Test Report
- path: ${{ github.workspace }}/e2e/results/report/*.html
- name: Stop the Containers
run: |
while true; do
@@ -31,3 +26,8 @@ jobs:
sleep 1m
fi
done
+ - name: Upload E2E Test Report as Artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: E2E Test Report
+ path: ${{ github.workspace }}/e2e/results/report/*.html
diff --git a/e2e/entrypoint.sh b/e2e/entrypoint.sh
index 2a7104f18..ced59c816 100755
--- a/e2e/entrypoint.sh
+++ b/e2e/entrypoint.sh
@@ -9,12 +9,12 @@ while true; do
echo "Keycloak is up"
cd /e2e
# added sleep to wait for initial data seeding
- sleep 2m
+ sleep 1m
npm run cy:run:html
break
else
echo "Waiting for Keycloak....."
- sleep 3m
+ sleep 2m
fi
done
From 479df31e8346d139d77d6032e3166f6ff1f119d0 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sun, 11 Jul 2021 23:20:42 -0700
Subject: [PATCH 029/155] Updated environment variables and documentation
---
docker-compose.yml | 3 +++
e2e/.env.local | 6 ++++++
e2e/READEME.md | 6 +++---
e2e/cypress.env.local.json | 6 ------
e2e/cypress.json | 7 +------
e2e/docker-compose.yml | 4 ++--
e2e/package.json | 4 ++--
7 files changed, 17 insertions(+), 19 deletions(-)
create mode 100644 e2e/.env.local
delete mode 100644 e2e/cypress.env.local.json
diff --git a/docker-compose.yml b/docker-compose.yml
index 2a5b4175e..6d6b374db 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -102,6 +102,7 @@ services:
image: feeder:latest
command: ''
entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
+ restart: on-failure
depends_on:
- feeder
volumes:
@@ -118,10 +119,12 @@ services:
dockerfile: Dockerfile
environment:
# DEBUG: cypress:* - Writes complete log
+ CYPRESS_BASE_URL: http://oauth2proxy.localtest.me:4180
CYPRESS_PORTAL_USERNAME: local
CYPRESS_PORTAL_PASSWORD: local
CYPRESS_CLIENT_ID: aps-portal
CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
+ CYPRESS_OIDC_ISSUER: http://keycloak.localtest.me:9080/auth/realms/master
volumes:
- ./e2e/results/report:/e2e/results/report
networks:
diff --git a/e2e/.env.local b/e2e/.env.local
new file mode 100644
index 000000000..607363d47
--- /dev/null
+++ b/e2e/.env.local
@@ -0,0 +1,6 @@
+CYPRESS_BASE_URL=
+CYPRESS_PORTAL_USERNAME=
+CYPRESS_PORTAL_PASSWORD=
+CYPRESS_CLIENT_ID=
+CYPRESS_CLIENT_SECRET=
+CYPRESS_OIDC_ISSUER=
diff --git a/e2e/READEME.md b/e2e/READEME.md
index d41dbde44..3d6ba1176 100644
--- a/e2e/READEME.md
+++ b/e2e/READEME.md
@@ -25,7 +25,7 @@ The steps below will take you all the way through Cypress. It is assumed you hav
### 2. Run Tests
- Clone this repository
-- Create a new file `cypress.env.json` from `cypress.env.local.json`
+- Create a new file `.env` from `.env.local`
- Replace `` with appropriate values
#### 2.1 Locally
@@ -36,7 +36,7 @@ The steps below will take you all the way through Cypress. It is assumed you hav
#### 2.2 Docker
- Run `docker build -t aps-cypress-e2e:latest ` to build an image
-- Run `docker run --rm -it -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
+- Run `docker run --rm -it --env-file .env -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
#### 2.3 Docker Compose
@@ -45,7 +45,7 @@ The steps below will take you all the way through Cypress. It is assumed you hav
#### 2.4 GitHub Actions
-- Any new commit pushed to `feature/automation-*` branch triggers a job (`.github/workflows/ci-build-deploy-e2e.yaml`) and deploys a container to execute the test suite
+- Any new commit pushed to `feature/automation-*` branch triggers a job (`.github/workflows/aps-cypress-e2e.yaml`) and deploys a container to execute the test suite
## Cypress IntelliSense
diff --git a/e2e/cypress.env.local.json b/e2e/cypress.env.local.json
deleted file mode 100644
index adb6be601..000000000
--- a/e2e/cypress.env.local.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "PORTAL_USERNAME": "",
- "PORTAL_PASSWORD": "",
- "CLIENT_ID": "",
- "CLIENT_SECRET": ""
-}
diff --git a/e2e/cypress.json b/e2e/cypress.json
index 0988a7b93..47ab9f178 100644
--- a/e2e/cypress.json
+++ b/e2e/cypress.json
@@ -1,5 +1,4 @@
{
- "baseUrl": "http://oauth2proxy.localtest.me:4180",
"integrationFolder": "cypress/tests",
"screenshotOnRunFailure": false,
"video": false,
@@ -11,9 +10,5 @@
"json": true,
"overwrite": false
},
- "chromeWebSecurity": false,
- "env": {
- "OIDC_ISSUER": "http://keycloak.localtest.me:9080/auth/realms/master",
- "TESTS_ENV": "dev"
- }
+ "chromeWebSecurity": false
}
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index eff818669..f23b2eaad 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -7,7 +7,7 @@ services:
build:
context: .
dockerfile: Dockerfile
- # environment:
- # DEBUG: cypress:* - Writes complete log
+ env_file:
+ - .env
volumes:
- ./results/report:/e2e/results/report
diff --git a/e2e/package.json b/e2e/package.json
index 847e4b484..44efffd9e 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -9,8 +9,8 @@
"cy:open": "cypress open --config-file cypress.json",
"cy:run": "cypress run --config-file cypress.json",
"cy:run:cfg": "cypress run --config",
- "moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-cypress-e2e-report.json",
- "moch:html": "marge results/report/bcgov-aps-cypress-e2e-report.json --reportDir results/report --inline",
+ "moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-e2e-report.json",
+ "moch:html": "marge results/report/bcgov-aps-e2e-report.json --reportDir results/report -i -t 'API Services Portal E2E Test Report'",
"cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html"
},
"devDependencies": {
From 3eadd97164dce35940f2b4145d4b955662435921 Mon Sep 17 00:00:00 2001
From: NithinKuruba <81444731+NithinKuruba@users.noreply.github.com>
Date: Mon, 12 Jul 2021 12:14:27 -0700
Subject: [PATCH 030/155] Removing cypress.json to make it environment specific
---
e2e/cypress.json | 14 --------------
1 file changed, 14 deletions(-)
delete mode 100644 e2e/cypress.json
diff --git a/e2e/cypress.json b/e2e/cypress.json
deleted file mode 100644
index 47ab9f178..000000000
--- a/e2e/cypress.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "integrationFolder": "cypress/tests",
- "screenshotOnRunFailure": false,
- "video": false,
- "watchForFileChanges": true,
- "reporter": "mochawesome",
- "reporterOptions": {
- "reportDir": "results",
- "html": false,
- "json": true,
- "overwrite": false
- },
- "chromeWebSecurity": false
-}
From 12b895e148b7493dee5934748b132d6a6e036a9e Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 12 Jul 2021 12:38:36 -0700
Subject: [PATCH 031/155] Updated the cypress config file and readme
---
docker-compose.yml | 8 --------
e2e/.env.local | 6 ------
e2e/.gitignore | 3 ++-
e2e/Dockerfile | 2 +-
e2e/{READEME.md => README.md} | 22 ++++++++++++----------
e2e/cypress.local.json | 22 ++++++++++++++++++++++
e2e/docker-compose.yml | 13 -------------
e2e/package.json | 4 ++--
8 files changed, 39 insertions(+), 41 deletions(-)
delete mode 100644 e2e/.env.local
rename e2e/{READEME.md => README.md} (79%)
create mode 100644 e2e/cypress.local.json
delete mode 100644 e2e/docker-compose.yml
diff --git a/docker-compose.yml b/docker-compose.yml
index 6d6b374db..8eaf97aa4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -117,14 +117,6 @@ services:
build:
context: ./e2e
dockerfile: Dockerfile
- environment:
- # DEBUG: cypress:* - Writes complete log
- CYPRESS_BASE_URL: http://oauth2proxy.localtest.me:4180
- CYPRESS_PORTAL_USERNAME: local
- CYPRESS_PORTAL_PASSWORD: local
- CYPRESS_CLIENT_ID: aps-portal
- CYPRESS_CLIENT_SECRET: 8e1a17ed-cb93-4806-ac32-e303d1c86018
- CYPRESS_OIDC_ISSUER: http://keycloak.localtest.me:9080/auth/realms/master
volumes:
- ./e2e/results/report:/e2e/results/report
networks:
diff --git a/e2e/.env.local b/e2e/.env.local
deleted file mode 100644
index 607363d47..000000000
--- a/e2e/.env.local
+++ /dev/null
@@ -1,6 +0,0 @@
-CYPRESS_BASE_URL=
-CYPRESS_PORTAL_USERNAME=
-CYPRESS_PORTAL_PASSWORD=
-CYPRESS_CLIENT_ID=
-CYPRESS_CLIENT_SECRET=
-CYPRESS_OIDC_ISSUER=
diff --git a/e2e/.gitignore b/e2e/.gitignore
index 4ba72e3b3..16e8fbf37 100644
--- a/e2e/.gitignore
+++ b/e2e/.gitignore
@@ -1,3 +1,4 @@
integration
cypress.env.json
-results
\ No newline at end of file
+results
+cypress.json
\ No newline at end of file
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 2a271ca3f..649647a78 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -4,7 +4,7 @@ WORKDIR /e2e
RUN apt-get install curl
-COPY cypress.json /e2e
+COPY cypress.local.json /e2e
COPY tsconfig.json /e2e
COPY package.json /e2e
COPY package-lock.json /e2e
diff --git a/e2e/READEME.md b/e2e/README.md
similarity index 79%
rename from e2e/READEME.md
rename to e2e/README.md
index 3d6ba1176..3be3cd86c 100644
--- a/e2e/READEME.md
+++ b/e2e/README.md
@@ -25,23 +25,25 @@ The steps below will take you all the way through Cypress. It is assumed you hav
### 2. Run Tests
- Clone this repository
-- Create a new file `.env` from `.env.local`
-- Replace `` with appropriate values
+- Run `npm install` to install all the dependencies
#### 2.1 Locally
-- Run `npm install` to install all the dependencies
-- Run `npm run cy:run` to run the tests
+##### 2.1.1 Cypress Test Runner
+
+- Create a new file `cypress.json` from `cypress.local.json`
+
+- Run `npm run cy:open` to open the test runner and execute tests selectively
-#### 2.2 Docker
+##### 2.2.2 Cypress Headless
-- Run `docker build -t aps-cypress-e2e:latest ` to build an image
-- Run `docker run --rm -it --env-file .env -name aps-cypress-e2e aps-cypress-e2e:latest` to spin up a container to run the tests
+- Run `npm run cy:run` to run the tests and print the results to the console
+- Run `npm run cy:run:html` to run the tests and generate `mochawesome` report under `results/report`
-#### 2.3 Docker Compose
+#### 2.2 Docker Compose
-- Run `docker-compose up` to spin a container that run cypress as a service and it executes the tests
-- Run `docker-compose down` to tear down the container
+- Run `docker-compose up` under parent folder `api-services-portal` to spin up a local environment, which includes cypress as one of the service and it executes the tests
+- Run `docker-compose down` to tear down the containers
#### 2.4 GitHub Actions
diff --git a/e2e/cypress.local.json b/e2e/cypress.local.json
new file mode 100644
index 000000000..833bf2c87
--- /dev/null
+++ b/e2e/cypress.local.json
@@ -0,0 +1,22 @@
+{
+ "baseUrl": "http://oauth2proxy.localtest.me:4180",
+ "integrationFolder": "cypress/tests",
+ "screenshotOnRunFailure": false,
+ "video": false,
+ "watchForFileChanges": true,
+ "reporter": "mochawesome",
+ "reporterOptions": {
+ "reportDir": "results",
+ "html": false,
+ "json": true,
+ "overwrite": false
+ },
+ "chromeWebSecurity": false,
+ "env": {
+ "PORTAL_USERNAME": "local",
+ "PORTAL_PASSWORD": "local",
+ "CLIENT_ID": "aps-portal",
+ "CLIENT_SECRET": "8e1a17ed-cb93-4806-ac32-e303d1c86018",
+ "OIDC_ISSUER": "http://keycloak.localtest.me:9080"
+ }
+}
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
deleted file mode 100644
index f23b2eaad..000000000
--- a/e2e/docker-compose.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-version: '3.2'
-
-services:
- cypress:
- image: 'aps-cypress-e2e:latest'
- container_name: cypress-e2e
- build:
- context: .
- dockerfile: Dockerfile
- env_file:
- - .env
- volumes:
- - ./results/report:/e2e/results/report
diff --git a/e2e/package.json b/e2e/package.json
index 44efffd9e..a5f4f6159 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -7,8 +7,8 @@
"license": "MIT",
"scripts": {
"cy:open": "cypress open --config-file cypress.json",
- "cy:run": "cypress run --config-file cypress.json",
- "cy:run:cfg": "cypress run --config",
+ "cy:run": "cypress run --config-file cypress.local.json",
+ "cy:run:dev": "cypress run --config-file cypress.json",
"moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-e2e-report.json",
"moch:html": "marge results/report/bcgov-aps-e2e-report.json --reportDir results/report -i -t 'API Services Portal E2E Test Report'",
"cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html"
From 124caf759cede7252c8dec5aa8798df47afbe529 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 12 Jul 2021 19:55:33 -0700
Subject: [PATCH 032/155] added a dependency to cypress
---
docker-compose.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docker-compose.yml b/docker-compose.yml
index 8eaf97aa4..815effe0f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -114,6 +114,8 @@ services:
image: 'aps-cypress-e2e:latest'
container_name: cypress-e2e
entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ depends_on:
+ - feeder-seeding
build:
context: ./e2e
dockerfile: Dockerfile
From 76bef0e5e75512ff574b902327832e38dbe93297 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 13 Jul 2021 11:13:34 -0700
Subject: [PATCH 033/155] Updated login and logout specs to one single spec
that defines authentication flow
---
e2e/cypress/support/auth-commands.ts | 35 +++++++++++++++++-----------
e2e/cypress/support/global.d.ts | 6 ++++-
e2e/cypress/tests/01-auth.spec.ts | 28 ++++++++++++++++++++++
e2e/cypress/tests/login.spec.ts | 18 --------------
e2e/cypress/tests/logout.spec.ts | 29 -----------------------
5 files changed, 54 insertions(+), 62 deletions(-)
create mode 100644 e2e/cypress/tests/01-auth.spec.ts
delete mode 100644 e2e/cypress/tests/login.spec.ts
delete mode 100644 e2e/cypress/tests/logout.spec.ts
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 0e523d015..a7a3f89da 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -25,32 +25,30 @@ Cypress.Commands.add('login', (username, password) => {
expect(loc.protocol).to.eq(appURL.protocol)
expect(loc.hostname).to.eq(appURL.hostname)
})
+ log.end()
+})
+
+Cypress.Commands.add('saveCookies', () => {
//saving the session cookie
cy.getCookies().then((cookies) => {
cookies.map((cookie) => {
Cypress.Cookies.preserveOnce(cookie.name)
})
})
-
- log.end()
})
-Cypress.Commands.add('getSession', (url: string) => {
- cy.request({ method: 'GET', url: url })
- .then((response) => {
- expect(response.status).to.eq(200)
- expect(response.body).to.include({ anonymous: false })
- })
- .then((response: any) => {
+Cypress.Commands.add('getSession', () => {
+ cy.request({ method: 'GET', url: Cypress.config('baseUrl') + '/admin/session' }).then(
+ (res) => {
+ cy.wrap(res).as('session')
+ expect(res.status).to.eq(200)
const log = Cypress.log({
name: 'Session Info',
displayName: 'SESSION_INFO',
- message: JSON.stringify(response.body.user),
+ message: JSON.stringify(res.body),
})
- })
- .then((response) => {
- cy.wrap(response.body)
- })
+ }
+ )
})
Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
@@ -85,3 +83,12 @@ Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
log.snapshot('after')
log.end()
})
+
+Cypress.Commands.add('logout', () => {
+ cy.getSession().then(() => {
+ cy.get('@session').then((res: any) => {
+ cy.contains(res.body.user.name).click()
+ cy.contains('Sign Out').click()
+ })
+ })
+})
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index d77bacc9f..5c054e047 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -4,12 +4,16 @@ declare namespace Cypress {
interface Chainable {
login(username: string, password: string): Chainable
- getSession(url: string): Chainable
+ getSession(): Chainable
callApi(options: Partial): Chainable
addContext(message: any): Chainable
loginByAuthAPI(username: string, password: string): Chainable
+
+ logout(): Chainable
+
+ saveCookies(): Chainable
}
}
diff --git a/e2e/cypress/tests/01-auth.spec.ts b/e2e/cypress/tests/01-auth.spec.ts
new file mode 100644
index 000000000..e9d5c46f7
--- /dev/null
+++ b/e2e/cypress/tests/01-auth.spec.ts
@@ -0,0 +1,28 @@
+describe('Authentication spec', () => {
+ before(() => {
+ cy.clearCookies()
+ })
+ afterEach(() => {
+ cy.saveCookies()
+ })
+ it('should find login button', () => {
+ cy.visit('/')
+ cy.xpath('//button').contains('Login')
+ })
+
+ it('should allow user to authenticate', () => {
+ cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
+ })
+
+ it('should save user session after login', () => {
+ cy.getSession().then(() => {
+ cy.get('@session').then((res: any) => {
+ expect(res.body).to.include({ anonymous: false })
+ })
+ })
+ })
+
+ it('should allow user to logout', () => {
+ cy.logout()
+ })
+})
diff --git a/e2e/cypress/tests/login.spec.ts b/e2e/cypress/tests/login.spec.ts
deleted file mode 100644
index 794c49dfd..000000000
--- a/e2e/cypress/tests/login.spec.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-describe('Login spec', () => {
- beforeEach(() => {
- cy.visit('/')
- })
- it('should have login button', () => {
- cy.xpath('//button').contains('Login')
- })
-
- it('should allow user to authenticate', () => {
- cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
- })
-
- it('should save user session after login', () => {
- cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
- cy.log('logged user - ' + JSON.stringify(sessionObj.user))
- })
- })
-})
diff --git a/e2e/cypress/tests/logout.spec.ts b/e2e/cypress/tests/logout.spec.ts
deleted file mode 100644
index e41261919..000000000
--- a/e2e/cypress/tests/logout.spec.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-describe('Logout spec', () => {
- beforeEach(() => {
- cy.visit('/')
- })
- it('should check user session and login if not logged on', () => {
- if (cy.xpath('//button').contains('Login')) {
- cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
- cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
- cy.log('logged user - ' + JSON.stringify(sessionObj.user))
- })
- } else {
- cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
- cy.log('logged user - ' + JSON.stringify(sessionObj.user))
- })
- }
- })
-
- it('should allow user to logout', () => {
- cy.getSession(Cypress.config('baseUrl') + '/admin/session').then((sessionObj: any) => {
- cy.contains(sessionObj.user.name).click()
- })
-
- cy.contains('Sign Out').click()
- })
-
- it('should show login button after logout', () => {
- cy.xpath('//button').contains('Login')
- })
-})
From eed2466dc034bf05a79fe9e06966d55d6d08cd7f Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 13 Jul 2021 11:53:01 -0700
Subject: [PATCH 034/155] Saving cookies before each test
---
e2e/README.md | 6 +++---
e2e/cypress/support/auth-commands.ts | 2 ++
e2e/cypress/tests/01-auth.spec.ts | 7 ++++---
e2e/package.json | 3 ++-
4 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/e2e/README.md b/e2e/README.md
index 3be3cd86c..81f3bf9f4 100644
--- a/e2e/README.md
+++ b/e2e/README.md
@@ -29,16 +29,16 @@ The steps below will take you all the way through Cypress. It is assumed you hav
#### 2.1 Locally
-##### 2.1.1 Cypress Test Runner
+- Create a new file `cypress.json` from `cypress.local.json` and update any params if necessary
-- Create a new file `cypress.json` from `cypress.local.json`
+##### 2.1.1 Cypress Test Runner
- Run `npm run cy:open` to open the test runner and execute tests selectively
##### 2.2.2 Cypress Headless
- Run `npm run cy:run` to run the tests and print the results to the console
-- Run `npm run cy:run:html` to run the tests and generate `mochawesome` report under `results/report`
+- Run `npm run cy:run:dev:html` to run the tests and generate `mochawesome` report under `results/report`
#### 2.2 Docker Compose
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index a7a3f89da..1858119ac 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -26,6 +26,7 @@ Cypress.Commands.add('login', (username, password) => {
expect(loc.hostname).to.eq(appURL.hostname)
})
log.end()
+ cy.saveCookies()
})
Cypress.Commands.add('saveCookies', () => {
@@ -49,6 +50,7 @@ Cypress.Commands.add('getSession', () => {
})
}
)
+ cy.saveCookies()
})
Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
diff --git a/e2e/cypress/tests/01-auth.spec.ts b/e2e/cypress/tests/01-auth.spec.ts
index e9d5c46f7..4a993af9a 100644
--- a/e2e/cypress/tests/01-auth.spec.ts
+++ b/e2e/cypress/tests/01-auth.spec.ts
@@ -1,9 +1,10 @@
-describe('Authentication spec', () => {
+describe('Authentication spec', { retries: 2 }, () => {
before(() => {
cy.clearCookies()
})
- afterEach(() => {
- cy.saveCookies()
+
+ beforeEach(() => {
+ cy.visit('/')
})
it('should find login button', () => {
cy.visit('/')
diff --git a/e2e/package.json b/e2e/package.json
index a5f4f6159..2fef30564 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -11,7 +11,8 @@
"cy:run:dev": "cypress run --config-file cypress.json",
"moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-e2e-report.json",
"moch:html": "marge results/report/bcgov-aps-e2e-report.json --reportDir results/report -i -t 'API Services Portal E2E Test Report'",
- "cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html"
+ "cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html",
+ "cy:run:dev:html": "run-s --continue-on-error cy:run:dev moch:json moch:html"
},
"devDependencies": {
"@types/jsonwebtoken": "^8.5.4",
From 2df64c64512309fbaedcc0b172e01f50dfd64169 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 13 Jul 2021 19:47:48 -0700
Subject: [PATCH 035/155] Updated the cypress config to include app screenshots
upon test failure
---
.github/workflows/aps-cypress-e2e.yaml | 4 ++--
e2e/cypress.local.json | 3 ++-
e2e/cypress/support/auth-commands.ts | 2 +-
e2e/cypress/support/index.ts | 9 +++++++++
e2e/package.json | 4 ++--
5 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index 4e6889c5a..c143c87dd 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -29,5 +29,5 @@ jobs:
- name: Upload E2E Test Report as Artifact
uses: actions/upload-artifact@v2
with:
- name: E2E Test Report
- path: ${{ github.workspace }}/e2e/results/report/*.html
+ name: report
+ path: ${{ github.workspace }}/e2e/results/report
diff --git a/e2e/cypress.local.json b/e2e/cypress.local.json
index 833bf2c87..cb4529417 100644
--- a/e2e/cypress.local.json
+++ b/e2e/cypress.local.json
@@ -1,7 +1,8 @@
{
"baseUrl": "http://oauth2proxy.localtest.me:4180",
"integrationFolder": "cypress/tests",
- "screenshotOnRunFailure": false,
+ "screenshotOnRunFailure": true,
+ "screenshotsFolder": "results/report/assets",
"video": false,
"watchForFileChanges": true,
"reporter": "mochawesome",
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 1858119ac..63a6dc57f 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -4,7 +4,7 @@ import * as jwt from 'jsonwebtoken'
Cypress.Commands.add('login', (username, password) => {
const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
const appURL = new URL(Cypress.config('baseUrl'))
- cy.xpath("//button[normalize-space()='Login']").click()
+ cy.xpath('//button').contains('Login').click()
cy.location().should((loc) => {
expect(loc.protocol).to.eq(oidcProviderURL.protocol)
expect(loc.hostname).to.eq(oidcProviderURL.hostname)
diff --git a/e2e/cypress/support/index.ts b/e2e/cypress/support/index.ts
index a3a3948cb..02e72124f 100644
--- a/e2e/cypress/support/index.ts
+++ b/e2e/cypress/support/index.ts
@@ -2,3 +2,12 @@ import './commands'
import 'cypress-xpath'
import './auth-commands'
import './api-commands'
+
+const addContext = require('mochawesome/addContext')
+
+Cypress.on('test:after:run', (test, runnable) => {
+ if (test.state === 'failed') {
+ const screenshot = `assets/${Cypress.spec.name}/${runnable.parent.title} -- ${test.title} (failed).png`
+ addContext({ test }, screenshot)
+ }
+})
diff --git a/e2e/package.json b/e2e/package.json
index 2fef30564..c349f7c7a 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -9,8 +9,8 @@
"cy:open": "cypress open --config-file cypress.json",
"cy:run": "cypress run --config-file cypress.local.json",
"cy:run:dev": "cypress run --config-file cypress.json",
- "moch:json": "mochawesome-merge -f results/*.json -o results/report/bcgov-aps-e2e-report.json",
- "moch:html": "marge results/report/bcgov-aps-e2e-report.json --reportDir results/report -i -t 'API Services Portal E2E Test Report'",
+ "moch:json": "mochawesome-merge -f results/*.json -o results/bcgov-aps-e2e-report.json",
+ "moch:html": "marge results/bcgov-aps-e2e-report.json --reportDir results/report -i -t \"API Services Portal E2E Test Report\"",
"cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html",
"cy:run:dev:html": "run-s --continue-on-error cy:run:dev moch:json moch:html"
},
From a0099fdb5a0afa7ab380a8f4656bfe1f01240c14 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 13 Jul 2021 20:21:30 -0700
Subject: [PATCH 036/155] Saving cookies by name and removed custom command
that used to save all the cookies
---
e2e/cypress/support/auth-commands.ts | 11 -----------
e2e/cypress/support/global.d.ts | 2 --
e2e/cypress/support/index.ts | 9 +++++++++
e2e/cypress/tests/01-auth.spec.ts | 6 +-----
4 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 63a6dc57f..5c490a238 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -26,16 +26,6 @@ Cypress.Commands.add('login', (username, password) => {
expect(loc.hostname).to.eq(appURL.hostname)
})
log.end()
- cy.saveCookies()
-})
-
-Cypress.Commands.add('saveCookies', () => {
- //saving the session cookie
- cy.getCookies().then((cookies) => {
- cookies.map((cookie) => {
- Cypress.Cookies.preserveOnce(cookie.name)
- })
- })
})
Cypress.Commands.add('getSession', () => {
@@ -50,7 +40,6 @@ Cypress.Commands.add('getSession', () => {
})
}
)
- cy.saveCookies()
})
Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index 5c054e047..d8ae9e9eb 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -13,7 +13,5 @@ declare namespace Cypress {
loginByAuthAPI(username: string, password: string): Chainable
logout(): Chainable
-
- saveCookies(): Chainable
}
}
diff --git a/e2e/cypress/support/index.ts b/e2e/cypress/support/index.ts
index 02e72124f..8a665a111 100644
--- a/e2e/cypress/support/index.ts
+++ b/e2e/cypress/support/index.ts
@@ -11,3 +11,12 @@ Cypress.on('test:after:run', (test, runnable) => {
addContext({ test }, screenshot)
}
})
+
+Cypress.Cookies.defaults({
+ preserve: [
+ '_oauth2_proxy',
+ '_oauth2_proxy_csrf',
+ 'ab547b670fc5c67e38dbef98822b7c8d',
+ 'keystone.sid',
+ ],
+})
diff --git a/e2e/cypress/tests/01-auth.spec.ts b/e2e/cypress/tests/01-auth.spec.ts
index 4a993af9a..ae389bbc5 100644
--- a/e2e/cypress/tests/01-auth.spec.ts
+++ b/e2e/cypress/tests/01-auth.spec.ts
@@ -1,8 +1,4 @@
-describe('Authentication spec', { retries: 2 }, () => {
- before(() => {
- cy.clearCookies()
- })
-
+describe('Authentication spec', () => {
beforeEach(() => {
cy.visit('/')
})
From 1d33f907e09f387b678a23ef8afb47abe09aeaa5 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Thu, 15 Jul 2021 10:24:55 -0700
Subject: [PATCH 037/155] added redis as a service for storing user sessions
---
docker-compose.yml | 14 ++++++++++++++
local/oauth2-proxy/oauth2-proxy-local.cfg | 10 +++++++---
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 815effe0f..fae8db0cc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -57,6 +57,7 @@ services:
keycloak: {}
portal: {}
kong-net: {}
+ redis-net: {}
oauth2-proxy:
aliases:
- oauth2proxy.localtest.me
@@ -182,8 +183,21 @@ services:
aliases:
- kong.localtest.me
restart: on-failure:5
+ redis:
+ image: bitnami/redis:latest
+ container_name: redis
+ environment:
+ - REDIS_PASSWORD=s3cr3t
+ restart: on-failure
+ ports:
+ - 6379:6379
+ networks:
+ redis-net:
+ aliases:
+ - redis.localtest.me
networks:
keycloak: {}
oauth2-proxy: {}
portal: {}
kong-net: {}
+ redis-net: {}
diff --git a/local/oauth2-proxy/oauth2-proxy-local.cfg b/local/oauth2-proxy/oauth2-proxy-local.cfg
index e5b9242b9..066f7826d 100644
--- a/local/oauth2-proxy/oauth2-proxy-local.cfg
+++ b/local/oauth2-proxy/oauth2-proxy-local.cfg
@@ -11,9 +11,10 @@ login_url="http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-
redeem_url="http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-connect/token"
validate_url="http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-connect/userinfo"
redirect_url="http://oauth2proxy.localtest.me:4180/oauth2/callback"
+profile_url="http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-connect/userinfo"
cookie_secure="false"
-cookie_refresh="5m"
-cookie_expire="2h"
+cookie_refresh="3m"
+cookie_expire="24h"
pass_basic_auth="false"
pass_access_token="true"
set_xauthrequest="true"
@@ -23,4 +24,7 @@ pass_authorization_header="false"
skip_auth_regex="/health|/home|/public|/docs|/redirect|/_next|/images|/devportal|/manager|/ds/api|/signout|/ds/api/swagger.yaml|^[/]$"
whitelist_domains="*"
upstreams=["http://apsportal.localtest.me:3000"]
-skip_provider_button='true'
\ No newline at end of file
+skip_provider_button='true'
+redis_connection_url="redis://redis.localtest.me:6379"
+session_store_type='redis'
+redis_password='s3cr3t'
\ No newline at end of file
From df5b429f9261ba300de5f64f6c307b0cca61f7a7 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 19 Jul 2021 19:56:34 -0700
Subject: [PATCH 038/155] Added latest test cases to create namespace and
service account. Also added code to save the state to a file and use it in
the later tests.
---
e2e/.gitignore | 3 +-
e2e/Dockerfile | 2 +-
e2e/{cypress.local.json => cypress.json} | 5 +-
e2e/cypress/fixtures/api-owner.json | 12 +++++
e2e/cypress/fixtures/developer.json | 8 +++
e2e/cypress/fixtures/service.yaml | 19 +++++++
e2e/cypress/fixtures/state/store.json | 3 ++
e2e/cypress/pageObjects/home.ts | 26 ++++++++++
e2e/cypress/pageObjects/login.ts | 10 ++++
e2e/cypress/pageObjects/namespaces.ts | 9 ++++
e2e/cypress/pageObjects/serviceAccounts.ts | 29 +++++++++++
e2e/cypress/pageObjects/toolbar.ts | 10 ++++
e2e/cypress/support/api-commands.ts | 9 ----
e2e/cypress/support/auth-commands.ts | 19 +++----
e2e/cypress/support/commands.ts | 8 ---
e2e/cypress/support/global.d.ts | 17 ++++---
e2e/cypress/support/index.ts | 17 ++-----
e2e/cypress/support/util-commands.ts | 49 +++++++++++++++++++
.../{ => 01-Authentication}/01-auth.spec.ts | 14 ++++--
.../tests/02-CreateAPI/01-namespace.ts | 35 +++++++++++++
.../tests/02-CreateAPI/02-serviceaccount.ts | 47 ++++++++++++++++++
e2e/package-lock.json | 9 ++++
e2e/package.json | 11 +++--
e2e/tsconfig.json | 6 ++-
24 files changed, 316 insertions(+), 61 deletions(-)
rename e2e/{cypress.local.json => cypress.json} (76%)
create mode 100644 e2e/cypress/fixtures/api-owner.json
create mode 100644 e2e/cypress/fixtures/developer.json
create mode 100644 e2e/cypress/fixtures/service.yaml
create mode 100644 e2e/cypress/fixtures/state/store.json
create mode 100644 e2e/cypress/pageObjects/home.ts
create mode 100644 e2e/cypress/pageObjects/login.ts
create mode 100644 e2e/cypress/pageObjects/namespaces.ts
create mode 100644 e2e/cypress/pageObjects/serviceAccounts.ts
create mode 100644 e2e/cypress/pageObjects/toolbar.ts
delete mode 100644 e2e/cypress/support/api-commands.ts
create mode 100644 e2e/cypress/support/util-commands.ts
rename e2e/cypress/tests/{ => 01-Authentication}/01-auth.spec.ts (55%)
create mode 100644 e2e/cypress/tests/02-CreateAPI/01-namespace.ts
create mode 100644 e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts
diff --git a/e2e/.gitignore b/e2e/.gitignore
index 16e8fbf37..4ba72e3b3 100644
--- a/e2e/.gitignore
+++ b/e2e/.gitignore
@@ -1,4 +1,3 @@
integration
cypress.env.json
-results
-cypress.json
\ No newline at end of file
+results
\ No newline at end of file
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
index 649647a78..2a271ca3f 100644
--- a/e2e/Dockerfile
+++ b/e2e/Dockerfile
@@ -4,7 +4,7 @@ WORKDIR /e2e
RUN apt-get install curl
-COPY cypress.local.json /e2e
+COPY cypress.json /e2e
COPY tsconfig.json /e2e
COPY package.json /e2e
COPY package-lock.json /e2e
diff --git a/e2e/cypress.local.json b/e2e/cypress.json
similarity index 76%
rename from e2e/cypress.local.json
rename to e2e/cypress.json
index cb4529417..287245166 100644
--- a/e2e/cypress.local.json
+++ b/e2e/cypress.json
@@ -14,10 +14,9 @@
},
"chromeWebSecurity": false,
"env": {
- "PORTAL_USERNAME": "local",
- "PORTAL_PASSWORD": "local",
"CLIENT_ID": "aps-portal",
"CLIENT_SECRET": "8e1a17ed-cb93-4806-ac32-e303d1c86018",
- "OIDC_ISSUER": "http://keycloak.localtest.me:9080"
+ "OIDC_ISSUER": "http://keycloak.localtest.me:9080",
+ "TOKEN_URL": "http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-connect/token"
}
}
diff --git a/e2e/cypress/fixtures/api-owner.json b/e2e/cypress/fixtures/api-owner.json
new file mode 100644
index 000000000..e14a5a8dc
--- /dev/null
+++ b/e2e/cypress/fixtures/api-owner.json
@@ -0,0 +1,12 @@
+{
+ "user": {
+ "credentials": {
+ "username": "awsummer@idir",
+ "password": "awsummer"
+ }
+ },
+ "namespace": "platform",
+ "serviceAccount": {
+ "scopes": ["GatewayConfig.Publish", "Namespace.Manage", "Content.Publish"]
+ }
+}
diff --git a/e2e/cypress/fixtures/developer.json b/e2e/cypress/fixtures/developer.json
new file mode 100644
index 000000000..e734d0caf
--- /dev/null
+++ b/e2e/cypress/fixtures/developer.json
@@ -0,0 +1,8 @@
+{
+ "user": {
+ "credentials": {
+ "username": "local",
+ "password": "local"
+ }
+ }
+}
diff --git a/e2e/cypress/fixtures/service.yaml b/e2e/cypress/fixtures/service.yaml
new file mode 100644
index 000000000..92c1163bf
--- /dev/null
+++ b/e2e/cypress/fixtures/service.yaml
@@ -0,0 +1,19 @@
+services:
+ - name: a-service-for-platform
+ host: httpbin.org
+ tags: [ns.platform]
+ port: 443
+ protocol: https
+ retries: 0
+ routes:
+ - name: a-service-for-platform-route
+ tags: [ns.platform]
+ hosts:
+ - a-service-for-platform.api.gov.bc.ca
+ paths:
+ - /
+ methods:
+ - GET
+ strip_path: false
+ https_redirect_status_code: 426
+ path_handling: v0
diff --git a/e2e/cypress/fixtures/state/store.json b/e2e/cypress/fixtures/state/store.json
new file mode 100644
index 000000000..e123ef5d0
--- /dev/null
+++ b/e2e/cypress/fixtures/state/store.json
@@ -0,0 +1,3 @@
+{
+ "sa-platform-e0000000-37f7896427da": "9f0f0dc8-a5fa-4279-96dd-5f6d121a2293"
+}
\ No newline at end of file
diff --git a/e2e/cypress/pageObjects/home.ts b/e2e/cypress/pageObjects/home.ts
new file mode 100644
index 000000000..475680fc8
--- /dev/null
+++ b/e2e/cypress/pageObjects/home.ts
@@ -0,0 +1,26 @@
+class HomePage {
+ namespaceDropdown: string =
+ '/html[1]/body[1]/div[1]/header[1]/hgroup[2]/div[1]/div[1]/button[1]'
+
+ namespaceSelected: string = '/html/body/div[1]/header/hgroup[2]/div[1]/div/button/span'
+
+ namespaceNameInput: string = '/html/body/div[3]/div[4]/div/section/div/form/div/input'
+
+ createNamespace(name: string): void {
+ cy.xpath(this.namespaceDropdown).click()
+ cy.contains('Create New Namespace').click()
+ cy.xpath(this.namespaceNameInput).should('be.visible').type(name) // using `platform` as a default ns as its being seeding through feeder
+ cy.xpath("//button[normalize-space()='Create']").click()
+ cy.contains('Namespace ' + name + ' created!').should('be.visible')
+ cy.contains('Switched to ' + name + ' namespace').should('be.visible')
+ }
+
+ useNamespace(name: string): void {
+ cy.xpath(this.namespaceDropdown).click()
+ cy.contains(name).click()
+ cy.contains('Switched to ' + name + ' namespace').should('be.visible')
+ cy.xpath(this.namespaceSelected).should('include.text', name)
+ }
+}
+
+export default HomePage
diff --git a/e2e/cypress/pageObjects/login.ts b/e2e/cypress/pageObjects/login.ts
new file mode 100644
index 000000000..e2bc3477e
--- /dev/null
+++ b/e2e/cypress/pageObjects/login.ts
@@ -0,0 +1,10 @@
+class LoginPage {
+ path: string = '/'
+
+ loginButton: string = "//button[normalize-space()='Login']"
+ usernameInput: string = "//input[@id='username']"
+ passwordInput: string = "//input[@id='password']"
+ loginSubmitButton: string = "//input[@id='kc-login']"
+}
+
+export default LoginPage
diff --git a/e2e/cypress/pageObjects/namespaces.ts b/e2e/cypress/pageObjects/namespaces.ts
new file mode 100644
index 000000000..e66ed5371
--- /dev/null
+++ b/e2e/cypress/pageObjects/namespaces.ts
@@ -0,0 +1,9 @@
+import ToolBar from './toolbar'
+
+class NamespacesPage {
+ path: string = ''
+ serviceAccount: string =
+ '/html[1]/body[1]/div[1]/main[1]/div[1]/div[3]/div[1]/div[3]/h2[1]/a[1]'
+}
+
+export default NamespacesPage
diff --git a/e2e/cypress/pageObjects/serviceAccounts.ts b/e2e/cypress/pageObjects/serviceAccounts.ts
new file mode 100644
index 000000000..a7feaba51
--- /dev/null
+++ b/e2e/cypress/pageObjects/serviceAccounts.ts
@@ -0,0 +1,29 @@
+class ServiceAccountsPage {
+ path: string = '/manager/namespaces'
+ newServiceAccount: string =
+ '/html/body/div[1]/main/div/div[2]/table/tbody/tr/td/div/div/div/button'
+ shareButton: string = '/html/body/div[4]/div[4]/div/section/footer/div/button[2]'
+
+ clientId: string =
+ '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[1]/div[1]/code[1]'
+
+ clientSecret: string =
+ '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[2]/div[1]/code[1]'
+
+ createServiceAccount(scopes: string[]): void {
+ scopes.forEach((scope) => {
+ cy.contains(scope).click()
+ })
+ cy.xpath(this.shareButton).click()
+ }
+
+ saveServiceAcctCreds(): void {
+ cy.xpath(this.clientId).then(($clientId) => {
+ cy.xpath(this.clientSecret).then(($clientSecret) => {
+ cy.saveState($clientId.text(), $clientSecret.text())
+ })
+ })
+ }
+}
+
+export default ServiceAccountsPage
diff --git a/e2e/cypress/pageObjects/toolbar.ts b/e2e/cypress/pageObjects/toolbar.ts
new file mode 100644
index 000000000..2fb518eed
--- /dev/null
+++ b/e2e/cypress/pageObjects/toolbar.ts
@@ -0,0 +1,10 @@
+class ToolBar {
+ optionList = '/html[1]/body[1]/div[1]/nav[1]/ul[1]'
+ directory: string = this.optionList + '/li[1]'
+ apiAccess: string = this.optionList + '/li[2]'
+ applications: string = this.optionList + '/li[3]'
+ namespaces: string = this.optionList + '/li[4]'
+ documentation: string = this.optionList + '/li[5]'
+}
+
+export default ToolBar
diff --git a/e2e/cypress/support/api-commands.ts b/e2e/cypress/support/api-commands.ts
deleted file mode 100644
index ca96766c8..000000000
--- a/e2e/cypress/support/api-commands.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-Cypress.Commands.add('callApi', (options: Cypress.RequestOptions) => {
- cy.request({
- ...options,
- }).then((res: Cypress.Response) => {
- expect([200, 201]).to.contain(res.status)
- cy.log(JSON.stringify(res))
- cy.wrap(res)
- })
-})
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 5c490a238..39d4e3065 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -1,10 +1,11 @@
-import { opendir } from 'fs'
import * as jwt from 'jsonwebtoken'
+import LoginPage from '../pageObjects/login'
-Cypress.Commands.add('login', (username, password) => {
+Cypress.Commands.add('login', (username: string, password: string) => {
+ const login = new LoginPage()
const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
- const appURL = new URL(Cypress.config('baseUrl'))
- cy.xpath('//button').contains('Login').click()
+ const appURL = new URL(Cypress.config('baseUrl') || '')
+ cy.xpath(login.loginButton).click()
cy.location().should((loc) => {
expect(loc.protocol).to.eq(oidcProviderURL.protocol)
expect(loc.hostname).to.eq(oidcProviderURL.hostname)
@@ -17,9 +18,9 @@ Cypress.Commands.add('login', (username, password) => {
autoEnd: false,
})
- cy.get('#username').type(username)
- cy.get('#password').type(password)
- cy.get('#kc-login').click()
+ cy.xpath(login.usernameInput).type(username)
+ cy.xpath(login.passwordInput).type(password)
+ cy.xpath(login.loginSubmitButton).click()
cy.location().should((loc) => {
expect(loc.protocol).to.eq(appURL.protocol)
@@ -54,8 +55,8 @@ Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
url: Cypress.env('OIDC_ISSUER') + '/protocol/openid-connect/token',
body: {
grant_type: 'password',
- username: Cypress.env('PORTAL_USERNAME'),
- password: Cypress.env('PORTAL_PASSWORD'),
+ username: Cypress.env('DEV_USERNAME'),
+ password: Cypress.env('DEV_PASSWORD'),
Scope: 'openid',
client_id: Cypress.env('CLIENT_ID'),
client_secret: Cypress.env('CLIENT_SECRET'),
diff --git a/e2e/cypress/support/commands.ts b/e2e/cypress/support/commands.ts
index 12d76a91e..a007e9dd0 100644
--- a/e2e/cypress/support/commands.ts
+++ b/e2e/cypress/support/commands.ts
@@ -22,11 +22,3 @@
//
//
// -- This will overwrite an existing command --
-
-import * as Mocha from 'mocha'
-
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
-const addContext = require('mochawesome/addContext')
-Cypress.Commands.add('addContext', (message) => {
- cy.once('test:after:run', (test) => addContext({ test }, message))
-})
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index d8ae9e9eb..de5ede856 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -1,17 +1,22 @@
///
+///
declare namespace Cypress {
interface Chainable {
- login(username: string, password: string): Chainable
+ login(username: string, password: string): void
- getSession(): Chainable
+ getSession(): Chainable>
- callApi(options: Partial): Chainable
+ loginByAuthAPI(username: string, password: string): Chainable>
- addContext(message: any): Chainable
+ logout(): void
- loginByAuthAPI(username: string, password: string): Chainable
+ preserveCookies(): void
- logout(): Chainable
+ saveState(key: string, value: string): void
+
+ getState(key: string): string
+
+ clearState(): void
}
}
diff --git a/e2e/cypress/support/index.ts b/e2e/cypress/support/index.ts
index 8a665a111..488eae4ae 100644
--- a/e2e/cypress/support/index.ts
+++ b/e2e/cypress/support/index.ts
@@ -1,22 +1,15 @@
import './commands'
import 'cypress-xpath'
import './auth-commands'
-import './api-commands'
+import './util-commands'
+const _ = require('lodash')
+const YAML = require('yamljs')
const addContext = require('mochawesome/addContext')
-Cypress.on('test:after:run', (test, runnable) => {
+Cypress.on('test:after:run', (test: Mocha.Test, runnable: Mocha.Runnable) => {
if (test.state === 'failed') {
- const screenshot = `assets/${Cypress.spec.name}/${runnable.parent.title} -- ${test.title} (failed).png`
+ const screenshot = `assets/${Cypress.spec.name}/${runnable?.parent?.title} -- ${test.title} (failed).png`
addContext({ test }, screenshot)
}
})
-
-Cypress.Cookies.defaults({
- preserve: [
- '_oauth2_proxy',
- '_oauth2_proxy_csrf',
- 'ab547b670fc5c67e38dbef98822b7c8d',
- 'keystone.sid',
- ],
-})
diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts
new file mode 100644
index 000000000..6c0e22894
--- /dev/null
+++ b/e2e/cypress/support/util-commands.ts
@@ -0,0 +1,49 @@
+Cypress.Commands.add('preserveCookies', () => {
+ Cypress.Cookies.preserveOnce(
+ ...[
+ '_oauth2_proxy',
+ '_oauth2_proxy_csrf',
+ 'ab547b670fc5c67e38dbef98822b7c8d',
+ 'keystone.sid',
+ ]
+ )
+ Cypress.Cookies.debug(true, { verbose: false })
+})
+
+Cypress.Commands.add('saveState', (key: string, value: string) => {
+ cy.log(key, value)
+ if (key.includes('>')) {
+ let keyItems = key.split('>')
+ cy.readFile('cypress/fixtures/state/store.json').then((currState) => {
+ let newState = currState
+ _.set(newState, keyItems, value)
+ cy.writeFile('cypress/fixtures/state/store.json', newState)
+ })
+ } else {
+ cy.readFile('cypress/fixtures/state/store.json').then((currState) => {
+ currState[key] = value
+ cy.writeFile('cypress/fixtures/state/store.json', currState)
+ })
+ }
+})
+
+Cypress.Commands.add('getState', (key: string) => {
+ if (key.includes('>')) {
+ let keyItems = key.split('>')
+ cy.readFile('cypress/fixtures/state/store.json').then((state) => {
+ return _.get(state, keyItems)
+ })
+ } else {
+ cy.readFile('cypress/fixtures/state/store.json').then((state) => {
+ return state[key]
+ })
+ }
+})
+
+Cypress.Commands.add('clearState', () => {
+ cy.readFile('cypress/fixtures/state/store.json').then((currState) => {
+ currState = {}
+ cy.writeFile('cypress/fixtures/state/store.json', currState)
+ })
+ cy.log('Test state was reset')
+})
diff --git a/e2e/cypress/tests/01-auth.spec.ts b/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
similarity index 55%
rename from e2e/cypress/tests/01-auth.spec.ts
rename to e2e/cypress/tests/01-Authentication/01-auth.spec.ts
index ae389bbc5..a304c0efe 100644
--- a/e2e/cypress/tests/01-auth.spec.ts
+++ b/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
@@ -1,14 +1,20 @@
+import LoginPage from '../../pageObjects/login'
+
describe('Authentication spec', () => {
+ const login = new LoginPage()
beforeEach(() => {
- cy.visit('/')
+ cy.fixture('developer').as('developer')
+ cy.visit(login.path)
+ cy.preserveCookies()
})
it('should find login button', () => {
- cy.visit('/')
- cy.xpath('//button').contains('Login')
+ cy.xpath(login.loginButton).should('be.visible')
})
it('should allow user to authenticate', () => {
- cy.login(Cypress.env('PORTAL_USERNAME'), Cypress.env('PORTAL_PASSWORD'))
+ cy.get('@developer').then(({ user }: any) => {
+ cy.login(user.credentials.username, user.credentials.password)
+ })
})
it('should save user session after login', () => {
diff --git a/e2e/cypress/tests/02-CreateAPI/01-namespace.ts b/e2e/cypress/tests/02-CreateAPI/01-namespace.ts
new file mode 100644
index 000000000..ff320109c
--- /dev/null
+++ b/e2e/cypress/tests/02-CreateAPI/01-namespace.ts
@@ -0,0 +1,35 @@
+import HomePage from '../../pageObjects/home'
+
+describe('Namespace spec', () => {
+ const home = new HomePage()
+ beforeEach(() => {
+ cy.visit('/')
+ cy.preserveCookies()
+ cy.fixture('api-owner').as('api-owner')
+ })
+
+ it('should allow user to login as API Owner', () => {
+ cy.get('@api-owner').then(({ user }: any) => {
+ cy.login(user.credentials.username, user.credentials.password)
+ })
+ })
+ it('should display namespaces dropdown', () => {
+ cy.xpath(home.namespaceDropdown).should('be.visible')
+ })
+
+ it('should allow user to create a new namespace', () => {
+ cy.get('@api-owner').then(({ namespace }: any) => {
+ home.createNamespace(namespace)
+ })
+ })
+
+ it('should allow user to switch to new namespace', () => {
+ cy.get('@api-owner').then(({ namespace }: any) => {
+ home.useNamespace(namespace)
+ })
+ })
+
+ after(() => {
+ cy.logout()
+ })
+})
diff --git a/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts b/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts
new file mode 100644
index 000000000..c4f763660
--- /dev/null
+++ b/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts
@@ -0,0 +1,47 @@
+import HomePage from '../../pageObjects/home'
+import NamespacesPage from '../../pageObjects/namespaces'
+import ServiceAccountsPage from '../../pageObjects/serviceAccounts'
+import ToolBar from '../../pageObjects/toolbar'
+
+describe('Service Account spec', () => {
+ const home = new HomePage()
+ const nss = new NamespacesPage()
+ const sa = new ServiceAccountsPage()
+ const tb = new ToolBar()
+ before(() => {
+ cy.visit('/')
+ cy.fixture('api-owner').as('api-owner')
+ cy.get('@api-owner').then(({ user, namespace }: any) => {
+ cy.login(user.credentials.username, user.credentials.password)
+ home.useNamespace(namespace)
+ })
+ cy.xpath(tb.namespaces).click()
+ })
+
+ beforeEach(() => {
+ cy.preserveCookies()
+ cy.fixture('api-owner').as('api-owner')
+ })
+
+ it('should service accounts tab', () => {
+ cy.xpath(nss.serviceAccount).should('include.text', 'Service Accounts')
+ })
+
+ it('should allow user to create a new service account', () => {
+ cy.xpath(nss.serviceAccount).click({ force: true })
+ cy.xpath(sa.newServiceAccount).click()
+ cy.get('@api-owner').then(({ serviceAccount }: any) => {
+ cy.log(serviceAccount.scopes)
+ sa.createServiceAccount(serviceAccount.scopes)
+ })
+ })
+
+ it('should verify if client id and secret are generated', () => {
+ cy.xpath(sa.clientId).should('be.visible')
+ cy.xpath(sa.clientSecret).should('be.visible')
+ sa.saveServiceAcctCreds()
+ })
+ after(() => {
+ cy.logout()
+ })
+})
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 5bf22e9c5..8846a008b 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -6992,6 +6992,15 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "yamljs": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz",
+ "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "glob": "^7.0.5"
+ }
+ },
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
diff --git a/e2e/package.json b/e2e/package.json
index c349f7c7a..adc4315b3 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -7,15 +7,14 @@
"license": "MIT",
"scripts": {
"cy:open": "cypress open --config-file cypress.json",
- "cy:run": "cypress run --config-file cypress.local.json",
- "cy:run:dev": "cypress run --config-file cypress.json",
+ "cy:run": "cypress run --config-file cypress.json",
"moch:json": "mochawesome-merge -f results/*.json -o results/bcgov-aps-e2e-report.json",
"moch:html": "marge results/bcgov-aps-e2e-report.json --reportDir results/report -i -t \"API Services Portal E2E Test Report\"",
- "cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html",
- "cy:run:dev:html": "run-s --continue-on-error cy:run:dev moch:json moch:html"
+ "cy:run:html": "run-s --continue-on-error cy:run moch:json moch:html"
},
"devDependencies": {
"@types/jsonwebtoken": "^8.5.4",
+ "@types/mocha": "^8.2.3",
"@types/mochawesome": "^6.2.0",
"@types/node": "^16.0.0",
"@typescript-eslint/eslint-plugin": "^4.28.1",
@@ -34,9 +33,11 @@
"cypress-xpath": "^1.6.2",
"dotenv": "^10.0.0",
"jsonwebtoken": "^8.5.1",
+ "lodash": "^4.17.21",
"mochawesome": "^6.2.2",
"mochawesome-merge": "^4.2.0",
"npm-run-all": "^4.1.5",
- "typescript": "^4.3.5"
+ "typescript": "^4.3.5",
+ "yamljs": "^0.3.0"
}
}
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
index 849470c00..6bad8a76a 100644
--- a/e2e/tsconfig.json
+++ b/e2e/tsconfig.json
@@ -2,8 +2,10 @@
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom", "ES2015"],
- "types": ["cypress", "node"],
- "allowJs": true
+ "types": ["cypress", "node", "mocha", "cypress-xpath"],
+ "allowJs": true,
+ "noImplicitAny": true,
+ "strict": true
},
"include": ["./cypress/**/*.ts", "**/*.d.ts"],
"exclude": [],
From 936d65755199b882c519a8d22d907f744cb258b3 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 19 Jul 2021 19:58:17 -0700
Subject: [PATCH 039/155] Updated docker compose config for keycloak to use
postgres db and added organization and org unit data as part of initial data
seeding
---
docker-compose.yml | 22 ++++++++
feeds/.env.local | 4 +-
local/feeder-init/init.sh | 2 +
local/feeder-init/organization-unit.yaml | 10 ++++
local/feeder-init/organization.yaml | 11 ++++
local/gwa-api/.env.local | 24 +++++++++
local/gwa-api/entrypoint.sh | 67 ++++++++++++++++++++++++
7 files changed, 139 insertions(+), 1 deletion(-)
create mode 100644 local/feeder-init/organization-unit.yaml
create mode 100644 local/feeder-init/organization.yaml
create mode 100644 local/gwa-api/.env.local
create mode 100755 local/gwa-api/entrypoint.sh
diff --git a/docker-compose.yml b/docker-compose.yml
index fae8db0cc..22c3958ef 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -30,6 +30,8 @@ services:
environment:
#KEYCLOAK_USER: local
#KEYCLOAK_PASSWORD: local
+ DB_VENDOR: POSTGRES
+ DB_SCHEMA: public
DB_ADDR: kong-db:5432
DB_USER: keycloakuser
DB_PASSWORD: keycloakuser
@@ -195,9 +197,29 @@ services:
redis-net:
aliases:
- redis.localtest.me
+ gwa-api:
+ image: gateway-api:latest
+ container_name: gwa-api
+ entrypoint: sh -c "chmod +x /tmp/gwa/entrypoint.sh && sh /tmp/gwa/entrypoint.sh"
+ ports:
+ - 2000:2000
+ env_file:
+ - ./local/gwa-api/.env.local
+ restart: on-failure:5
+ volumes:
+ - ./local/gwa-api:/tmp/gwa
+ networks:
+ gwa-net:
+ aliases:
+ - gwa-api.localtest.me
+ oauth2-proxy: {}
+ portal: {}
+ kong-net: {}
+ keycloak: {}
networks:
keycloak: {}
oauth2-proxy: {}
portal: {}
kong-net: {}
redis-net: {}
+ gwa-net: {}
diff --git a/feeds/.env.local b/feeds/.env.local
index 8c898f3e3..c9eb7c447 100644
--- a/feeds/.env.local
+++ b/feeds/.env.local
@@ -1,3 +1,5 @@
WORKING_PATH=/tmp
DESTINATION_URL=http://apsportal.localtest.me:3000
-KONG_ADMIN_URL=http://kong.localtest.me:8001
\ No newline at end of file
+KONG_ADMIN_URL=http://kong.localtest.me:8001
+CKAN_URL=https://catalog.data.gov.bc.ca
+LOG_FEEDS=false
\ No newline at end of file
diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh
index 94b616dd0..943dba45b 100755
--- a/local/feeder-init/init.sh
+++ b/local/feeder-init/init.sh
@@ -13,6 +13,8 @@ while true; do
curl http://feeder.localtest.me:6000/push -F yaml=@developer-user.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-authz-profile.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-gwa-api.yaml
+ curl http://feeder.localtest.me:6000/push -F yaml=@organization.yaml
+ curl http://feeder.localtest.me:6000/push -F yaml=@organization-unit.yaml
break
else
echo "Waiting for Keycloak....."
diff --git a/local/feeder-init/organization-unit.yaml b/local/feeder-init/organization-unit.yaml
new file mode 100644
index 000000000..2434f0b99
--- /dev/null
+++ b/local/feeder-init/organization-unit.yaml
@@ -0,0 +1,10 @@
+entity: OrganizationUnit
+record:
+ id: 319b3297-846d-4b97-8095-ceb3ec505fb8
+ name: planning-and-innovation-division
+ sector: 'Health and Safety'
+ title: 'Planning and Innovation Division'
+ tags: []
+ description: ''
+ extSource: ''
+ extRecordHash: ''
diff --git a/local/feeder-init/organization.yaml b/local/feeder-init/organization.yaml
new file mode 100644
index 000000000..e7d5af7d7
--- /dev/null
+++ b/local/feeder-init/organization.yaml
@@ -0,0 +1,11 @@
+entity: Organization
+record:
+ id: 7a66db63-26f4-4052-9cd5-3272b63910f8
+ type: organization
+ name: ministry-of-health
+ sector: ''
+ title: 'Ministry of Health'
+ tags: []
+ description: 'The Ministry of Health1 has overall responsibility for ensuring that quality, appropriate, cost effective and timely health services are available for all British Columbians.'
+ extSource: ''
+ extRecordHash: ''
diff --git a/local/gwa-api/.env.local b/local/gwa-api/.env.local
new file mode 100644
index 000000000..5f135b12b
--- /dev/null
+++ b/local/gwa-api/.env.local
@@ -0,0 +1,24 @@
+PORT=2000
+LOG_LEVEL=DEBUG
+OIDC_BASE_URL=http://keycloak.localtest.me:9080/auth/realms/master
+TOKEN_MATCH_AUD=gwa
+WORKING_FOLDER=/tmp
+CONFIG_PATH=/tmp/production.json
+ENVIRONMENT=production
+KONG_ADMIN_URL=http://kong.localtest.me:8001
+KC_SERVER_URL=http://keycloak.localtest.me:9080/auth/
+KC_REALM=master
+KC_USERNAME=local
+KC_PASSWORD=local
+KC_USER_REALM=master
+KC_CLIENT_ID=admin-cli
+KC_RES_SVR_CLIENT_ID=gwa-api
+KC_RES_SVR_CLIENT_SECRET=18900468-3db1-43f7-a8af-e75f079eb742
+NSP_ENABLED=false
+PROTECTED_KUBE_NAMESPACES=
+PORTAL_ACTIVITY_URL=http://apsportal.localtest.me:3000
+PORTAL_ACTIVITY_TOKEN=
+HOST_TRANSFORM_ENABLED=false
+HOST_TRANSFORM_BASE_URL=
+PLUGINS_RATELIMITING_REDIS_PASSWORD=s3cr3t
+LOCAL_ENVIRONMENT=True
\ No newline at end of file
diff --git a/local/gwa-api/entrypoint.sh b/local/gwa-api/entrypoint.sh
new file mode 100755
index 000000000..fc44bc97b
--- /dev/null
+++ b/local/gwa-api/entrypoint.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+mkdir -p ./config
+
+cat > "${CONFIG_PATH:-./config/default.json}" < /tmp/deck.yaml <
Date: Tue, 20 Jul 2021 08:54:08 -0700
Subject: [PATCH 040/155] added trivy image scanner to scan the image
---
.github/workflows/ci-container-img-scan.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.github/workflows/ci-container-img-scan.yaml b/.github/workflows/ci-container-img-scan.yaml
index 5cad5fc72..051e2fcdd 100644
--- a/.github/workflows/ci-container-img-scan.yaml
+++ b/.github/workflows/ci-container-img-scan.yaml
@@ -22,3 +22,12 @@ jobs:
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif
+ - name: Run Trivy vulnerability scanner
+ uses: aquasecurity/trivy-action@master
+ with:
+ image-ref: 'bcgov/api-services-portal:scan'
+ format: 'table'
+ exit-code: '1'
+ ignore-unfixed: true
+ vuln-type: 'os,library'
+ severity: 'CRITICAL,HIGH'
From 93765cd5d0f514d47b5a0adb1734a1c96c5f189d Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 20 Jul 2021 09:12:54 -0700
Subject: [PATCH 041/155] updated the exit code and included medium level vulns
---
.github/workflows/ci-container-img-scan.yaml | 4 ++--
e2e/results/report/bcgov-aps-e2e-report.html | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
create mode 100644 e2e/results/report/bcgov-aps-e2e-report.html
diff --git a/.github/workflows/ci-container-img-scan.yaml b/.github/workflows/ci-container-img-scan.yaml
index 051e2fcdd..c94c04177 100644
--- a/.github/workflows/ci-container-img-scan.yaml
+++ b/.github/workflows/ci-container-img-scan.yaml
@@ -27,7 +27,7 @@ jobs:
with:
image-ref: 'bcgov/api-services-portal:scan'
format: 'table'
- exit-code: '1'
+ exit-code: '0'
ignore-unfixed: true
vuln-type: 'os,library'
- severity: 'CRITICAL,HIGH'
+ severity: 'CRITICAL,HIGH,MEDIUM'
diff --git a/e2e/results/report/bcgov-aps-e2e-report.html b/e2e/results/report/bcgov-aps-e2e-report.html
new file mode 100644
index 000000000..db384c337
--- /dev/null
+++ b/e2e/results/report/bcgov-aps-e2e-report.html
@@ -0,0 +1,17 @@
+
+Mochawesome Report
\ No newline at end of file
From 6e04a864c51d4a326608758d28997534bf86323c Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 20 Jul 2021 17:42:34 -0700
Subject: [PATCH 042/155] Updated tests with state management
---
.../{api-owner.json => apiowner.json} | 0
e2e/cypress/fixtures/state/store.json | 2 +-
e2e/cypress/pageObjects/home.ts | 10 +----
e2e/cypress/pageObjects/namespaces.ts | 9 -----
e2e/cypress/pageObjects/serviceAccounts.ts | 13 +++++--
e2e/cypress/support/auth-commands.ts | 7 ++++
e2e/cypress/support/global.d.ts | 2 +-
e2e/cypress/support/util-commands.ts | 6 ++-
.../tests/01-Authentication/01-auth.spec.ts | 3 ++
.../tests/02-CreateAPI/01-namespace.spec.ts | 33 ++++++++++++++++
.../tests/02-CreateAPI/01-namespace.ts | 35 -----------------
...ceaccount.ts => 02-serviceaccount.spec.ts} | 38 +++++++++----------
12 files changed, 79 insertions(+), 79 deletions(-)
rename e2e/cypress/fixtures/{api-owner.json => apiowner.json} (100%)
delete mode 100644 e2e/cypress/pageObjects/namespaces.ts
create mode 100644 e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
delete mode 100644 e2e/cypress/tests/02-CreateAPI/01-namespace.ts
rename e2e/cypress/tests/02-CreateAPI/{02-serviceaccount.ts => 02-serviceaccount.spec.ts} (53%)
diff --git a/e2e/cypress/fixtures/api-owner.json b/e2e/cypress/fixtures/apiowner.json
similarity index 100%
rename from e2e/cypress/fixtures/api-owner.json
rename to e2e/cypress/fixtures/apiowner.json
diff --git a/e2e/cypress/fixtures/state/store.json b/e2e/cypress/fixtures/state/store.json
index e123ef5d0..5d06da884 100644
--- a/e2e/cypress/fixtures/state/store.json
+++ b/e2e/cypress/fixtures/state/store.json
@@ -1,3 +1,3 @@
{
- "sa-platform-e0000000-37f7896427da": "9f0f0dc8-a5fa-4279-96dd-5f6d121a2293"
+ "credentials": "{'clientId': 'sa-platform-e0000000-9f1c8ffc62c4', 'clientSecret': 'bd5b926a-bcf1-4b8c-b966-a01837bbc4d2'}"
}
\ No newline at end of file
diff --git a/e2e/cypress/pageObjects/home.ts b/e2e/cypress/pageObjects/home.ts
index 475680fc8..f71b13b56 100644
--- a/e2e/cypress/pageObjects/home.ts
+++ b/e2e/cypress/pageObjects/home.ts
@@ -1,8 +1,5 @@
class HomePage {
- namespaceDropdown: string =
- '/html[1]/body[1]/div[1]/header[1]/hgroup[2]/div[1]/div[1]/button[1]'
-
- namespaceSelected: string = '/html/body/div[1]/header/hgroup[2]/div[1]/div/button/span'
+ namespaceDropdown: string = '/html/body/div[1]/header/hgroup[2]/div[1]/div/button'
namespaceNameInput: string = '/html/body/div[3]/div[4]/div/section/div/form/div/input'
@@ -11,15 +8,12 @@ class HomePage {
cy.contains('Create New Namespace').click()
cy.xpath(this.namespaceNameInput).should('be.visible').type(name) // using `platform` as a default ns as its being seeding through feeder
cy.xpath("//button[normalize-space()='Create']").click()
- cy.contains('Namespace ' + name + ' created!').should('be.visible')
- cy.contains('Switched to ' + name + ' namespace').should('be.visible')
}
useNamespace(name: string): void {
cy.xpath(this.namespaceDropdown).click()
cy.contains(name).click()
- cy.contains('Switched to ' + name + ' namespace').should('be.visible')
- cy.xpath(this.namespaceSelected).should('include.text', name)
+ cy.xpath(this.namespaceDropdown).should('include.text', name)
}
}
diff --git a/e2e/cypress/pageObjects/namespaces.ts b/e2e/cypress/pageObjects/namespaces.ts
deleted file mode 100644
index e66ed5371..000000000
--- a/e2e/cypress/pageObjects/namespaces.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import ToolBar from './toolbar'
-
-class NamespacesPage {
- path: string = ''
- serviceAccount: string =
- '/html[1]/body[1]/div[1]/main[1]/div[1]/div[3]/div[1]/div[3]/h2[1]/a[1]'
-}
-
-export default NamespacesPage
diff --git a/e2e/cypress/pageObjects/serviceAccounts.ts b/e2e/cypress/pageObjects/serviceAccounts.ts
index a7feaba51..de41c54fe 100644
--- a/e2e/cypress/pageObjects/serviceAccounts.ts
+++ b/e2e/cypress/pageObjects/serviceAccounts.ts
@@ -5,10 +5,10 @@ class ServiceAccountsPage {
shareButton: string = '/html/body/div[4]/div[4]/div/section/footer/div/button[2]'
clientId: string =
- '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[1]/div[1]/code[1]'
+ '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[1]/div[1]/code'
clientSecret: string =
- '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[2]/div[1]/code[1]'
+ '/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[2]/div[1]/code'
createServiceAccount(scopes: string[]): void {
scopes.forEach((scope) => {
@@ -20,7 +20,14 @@ class ServiceAccountsPage {
saveServiceAcctCreds(): void {
cy.xpath(this.clientId).then(($clientId) => {
cy.xpath(this.clientSecret).then(($clientSecret) => {
- cy.saveState($clientId.text(), $clientSecret.text())
+ cy.saveState(
+ 'credentials',
+ "{'clientId': '" +
+ $clientId.text() +
+ "', 'clientSecret': '" +
+ $clientSecret.text() +
+ "'}"
+ )
})
})
}
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 39d4e3065..8f8bacdd3 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -2,6 +2,7 @@ import * as jwt from 'jsonwebtoken'
import LoginPage from '../pageObjects/login'
Cypress.Commands.add('login', (username: string, password: string) => {
+ cy.log('< Log in with user ' + username)
const login = new LoginPage()
const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
const appURL = new URL(Cypress.config('baseUrl') || '')
@@ -27,9 +28,11 @@ Cypress.Commands.add('login', (username: string, password: string) => {
expect(loc.hostname).to.eq(appURL.hostname)
})
log.end()
+ cy.log('> Log in')
})
Cypress.Commands.add('getSession', () => {
+ cy.log('< Get Session')
cy.request({ method: 'GET', url: Cypress.config('baseUrl') + '/admin/session' }).then(
(res) => {
cy.wrap(res).as('session')
@@ -41,6 +44,7 @@ Cypress.Commands.add('getSession', () => {
})
}
)
+ cy.log('> Get Session')
})
Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
@@ -77,10 +81,13 @@ Cypress.Commands.add('loginByAuthAPI', (username: string, password: string) => {
})
Cypress.Commands.add('logout', () => {
+ cy.log('< Logging out')
cy.getSession().then(() => {
cy.get('@session').then((res: any) => {
cy.contains(res.body.user.name).click()
cy.contains('Sign Out').click()
+ cy.clearCookies()
})
})
+ cy.log('> Logging out')
})
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index de5ede856..45d3599da 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -17,6 +17,6 @@ declare namespace Cypress {
getState(key: string): string
- clearState(): void
+ resetState(): void
}
}
diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts
index 6c0e22894..e436cb3a2 100644
--- a/e2e/cypress/support/util-commands.ts
+++ b/e2e/cypress/support/util-commands.ts
@@ -1,4 +1,5 @@
Cypress.Commands.add('preserveCookies', () => {
+ cy.log('< Saving Cookies')
Cypress.Cookies.preserveOnce(
...[
'_oauth2_proxy',
@@ -8,9 +9,11 @@ Cypress.Commands.add('preserveCookies', () => {
]
)
Cypress.Cookies.debug(true, { verbose: false })
+ cy.log('> Saving Cookies')
})
Cypress.Commands.add('saveState', (key: string, value: string) => {
+ cy.log('< Saving State')
cy.log(key, value)
if (key.includes('>')) {
let keyItems = key.split('>')
@@ -25,6 +28,7 @@ Cypress.Commands.add('saveState', (key: string, value: string) => {
cy.writeFile('cypress/fixtures/state/store.json', currState)
})
}
+ cy.log('< Saving State')
})
Cypress.Commands.add('getState', (key: string) => {
@@ -40,7 +44,7 @@ Cypress.Commands.add('getState', (key: string) => {
}
})
-Cypress.Commands.add('clearState', () => {
+Cypress.Commands.add('resetState', () => {
cy.readFile('cypress/fixtures/state/store.json').then((currState) => {
currState = {}
cy.writeFile('cypress/fixtures/state/store.json', currState)
diff --git a/e2e/cypress/tests/01-Authentication/01-auth.spec.ts b/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
index a304c0efe..03fe6ac21 100644
--- a/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
+++ b/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
@@ -2,6 +2,9 @@ import LoginPage from '../../pageObjects/login'
describe('Authentication spec', () => {
const login = new LoginPage()
+ before(() => {
+ cy.resetState()
+ })
beforeEach(() => {
cy.fixture('developer').as('developer')
cy.visit(login.path)
diff --git a/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts b/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
new file mode 100644
index 000000000..24236b646
--- /dev/null
+++ b/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
@@ -0,0 +1,33 @@
+import HomePage from '../../pageObjects/home'
+import LoginPage from '../../pageObjects/login'
+
+describe('Namespace spec', () => {
+ const login = new LoginPage()
+ const home = new HomePage()
+
+ beforeEach(() => {
+ cy.fixture('apiowner').as('apiowner')
+ cy.visit(login.path)
+ cy.preserveCookies()
+ })
+ it('find login button', () => {
+ cy.xpath(login.loginButton).should('be.visible')
+ })
+
+ it('user authentication', () => {
+ cy.get('@apiowner').then(({ user }: any) => {
+ cy.login(user.credentials.username, user.credentials.password)
+ })
+ })
+
+ it('should allow user to create and switch to new namespace', () => {
+ cy.get('@apiowner').then(({ namespace }: any) => {
+ home.createNamespace(namespace)
+ home.useNamespace(namespace)
+ })
+ })
+
+ after(() => {
+ cy.logout()
+ })
+})
diff --git a/e2e/cypress/tests/02-CreateAPI/01-namespace.ts b/e2e/cypress/tests/02-CreateAPI/01-namespace.ts
deleted file mode 100644
index ff320109c..000000000
--- a/e2e/cypress/tests/02-CreateAPI/01-namespace.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import HomePage from '../../pageObjects/home'
-
-describe('Namespace spec', () => {
- const home = new HomePage()
- beforeEach(() => {
- cy.visit('/')
- cy.preserveCookies()
- cy.fixture('api-owner').as('api-owner')
- })
-
- it('should allow user to login as API Owner', () => {
- cy.get('@api-owner').then(({ user }: any) => {
- cy.login(user.credentials.username, user.credentials.password)
- })
- })
- it('should display namespaces dropdown', () => {
- cy.xpath(home.namespaceDropdown).should('be.visible')
- })
-
- it('should allow user to create a new namespace', () => {
- cy.get('@api-owner').then(({ namespace }: any) => {
- home.createNamespace(namespace)
- })
- })
-
- it('should allow user to switch to new namespace', () => {
- cy.get('@api-owner').then(({ namespace }: any) => {
- home.useNamespace(namespace)
- })
- })
-
- after(() => {
- cy.logout()
- })
-})
diff --git a/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts b/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts
similarity index 53%
rename from e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts
rename to e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts
index c4f763660..ab76fd334 100644
--- a/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.ts
+++ b/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts
@@ -1,44 +1,40 @@
import HomePage from '../../pageObjects/home'
-import NamespacesPage from '../../pageObjects/namespaces'
+import LoginPage from '../../pageObjects/login'
import ServiceAccountsPage from '../../pageObjects/serviceAccounts'
import ToolBar from '../../pageObjects/toolbar'
describe('Service Account spec', () => {
const home = new HomePage()
- const nss = new NamespacesPage()
const sa = new ServiceAccountsPage()
const tb = new ToolBar()
- before(() => {
- cy.visit('/')
- cy.fixture('api-owner').as('api-owner')
- cy.get('@api-owner').then(({ user, namespace }: any) => {
- cy.login(user.credentials.username, user.credentials.password)
- home.useNamespace(namespace)
- })
- cy.xpath(tb.namespaces).click()
- })
+ const login = new LoginPage()
beforeEach(() => {
+ cy.fixture('apiowner').as('apiowner')
+ cy.visit(login.path)
cy.preserveCookies()
- cy.fixture('api-owner').as('api-owner')
+ })
+ it('find login button', () => {
+ cy.xpath(login.loginButton).should('be.visible')
})
- it('should service accounts tab', () => {
- cy.xpath(nss.serviceAccount).should('include.text', 'Service Accounts')
+ it('user authentication', () => {
+ cy.get('@apiowner').then(({ user }: any) => {
+ cy.login(user.credentials.username, user.credentials.password)
+ })
})
it('should allow user to create a new service account', () => {
- cy.xpath(nss.serviceAccount).click({ force: true })
+ cy.get('@apiowner').then(({ namespace }: any) => {
+ home.useNamespace(namespace)
+ })
+ cy.xpath(tb.namespaces).click()
+ cy.contains('Service Accounts').click({ force: true })
cy.xpath(sa.newServiceAccount).click()
- cy.get('@api-owner').then(({ serviceAccount }: any) => {
+ cy.get('@apiowner').then(({ serviceAccount }: any) => {
cy.log(serviceAccount.scopes)
sa.createServiceAccount(serviceAccount.scopes)
})
- })
-
- it('should verify if client id and secret are generated', () => {
- cy.xpath(sa.clientId).should('be.visible')
- cy.xpath(sa.clientSecret).should('be.visible')
sa.saveServiceAcctCreds()
})
after(() => {
From e16caa8db9e330f40606fa5ca306254559306b5c Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 21 Jul 2021 10:23:25 -0700
Subject: [PATCH 043/155] Merged tests to resolve issues with cookies
---
e2e/cypress/fixtures/developer.json | 8 ----
e2e/cypress/fixtures/state/store.json | 4 +-
e2e/cypress/pageObjects/home.ts | 4 +-
e2e/cypress/pageObjects/serviceAccounts.ts | 5 +--
e2e/cypress/support/auth-commands.ts | 18 ++++----
e2e/cypress/support/global.d.ts | 4 +-
e2e/cypress/support/util-commands.ts | 41 ++++++++++++++++++-
.../tests/01-Authentication/01-auth.spec.ts | 34 ---------------
...eaccount.spec.ts => 01-create-api.spec.ts} | 29 ++++++-------
.../tests/02-CreateAPI/01-namespace.spec.ts | 33 ---------------
10 files changed, 70 insertions(+), 110 deletions(-)
delete mode 100644 e2e/cypress/fixtures/developer.json
delete mode 100644 e2e/cypress/tests/01-Authentication/01-auth.spec.ts
rename e2e/cypress/tests/{02-CreateAPI/02-serviceaccount.spec.ts => 01-create-api.spec.ts} (62%)
delete mode 100644 e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
diff --git a/e2e/cypress/fixtures/developer.json b/e2e/cypress/fixtures/developer.json
deleted file mode 100644
index e734d0caf..000000000
--- a/e2e/cypress/fixtures/developer.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "user": {
- "credentials": {
- "username": "local",
- "password": "local"
- }
- }
-}
diff --git a/e2e/cypress/fixtures/state/store.json b/e2e/cypress/fixtures/state/store.json
index 5d06da884..0967ef424 100644
--- a/e2e/cypress/fixtures/state/store.json
+++ b/e2e/cypress/fixtures/state/store.json
@@ -1,3 +1 @@
-{
- "credentials": "{'clientId': 'sa-platform-e0000000-9f1c8ffc62c4', 'clientSecret': 'bd5b926a-bcf1-4b8c-b966-a01837bbc4d2'}"
-}
\ No newline at end of file
+{}
diff --git a/e2e/cypress/pageObjects/home.ts b/e2e/cypress/pageObjects/home.ts
index f71b13b56..2cfda66be 100644
--- a/e2e/cypress/pageObjects/home.ts
+++ b/e2e/cypress/pageObjects/home.ts
@@ -1,12 +1,14 @@
class HomePage {
namespaceDropdown: string = '/html/body/div[1]/header/hgroup[2]/div[1]/div/button'
+ profileIcon: string =
+ '/html/body/div[1]/header/hgroup[2]/div[1]/div/span/button/span/svg[1]'
namespaceNameInput: string = '/html/body/div[3]/div[4]/div/section/div/form/div/input'
createNamespace(name: string): void {
cy.xpath(this.namespaceDropdown).click()
cy.contains('Create New Namespace').click()
- cy.xpath(this.namespaceNameInput).should('be.visible').type(name) // using `platform` as a default ns as its being seeding through feeder
+ cy.xpath(this.namespaceNameInput).type(name) // using `platform` as a default ns as its being seeding through feeder
cy.xpath("//button[normalize-space()='Create']").click()
}
diff --git a/e2e/cypress/pageObjects/serviceAccounts.ts b/e2e/cypress/pageObjects/serviceAccounts.ts
index de41c54fe..176547b50 100644
--- a/e2e/cypress/pageObjects/serviceAccounts.ts
+++ b/e2e/cypress/pageObjects/serviceAccounts.ts
@@ -1,8 +1,6 @@
class ServiceAccountsPage {
path: string = '/manager/namespaces'
- newServiceAccount: string =
- '/html/body/div[1]/main/div/div[2]/table/tbody/tr/td/div/div/div/button'
- shareButton: string = '/html/body/div[4]/div[4]/div/section/footer/div/button[2]'
+ shareButton: string = "//button[normalize-space()='Share']"
clientId: string =
'/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[1]/div[1]/code'
@@ -11,6 +9,7 @@ class ServiceAccountsPage {
'/html[1]/body[1]/div[1]/main[1]/div[1]/div[2]/div[3]/div[2]/div[1]/code'
createServiceAccount(scopes: string[]): void {
+ cy.contains('New Service Account').click()
scopes.forEach((scope) => {
cy.contains(scope).click()
})
diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts
index 8f8bacdd3..f09fbbf2c 100644
--- a/e2e/cypress/support/auth-commands.ts
+++ b/e2e/cypress/support/auth-commands.ts
@@ -1,16 +1,12 @@
import * as jwt from 'jsonwebtoken'
+import HomePage from '../pageObjects/home'
import LoginPage from '../pageObjects/login'
Cypress.Commands.add('login', (username: string, password: string) => {
cy.log('< Log in with user ' + username)
const login = new LoginPage()
- const oidcProviderURL = new URL(Cypress.env('OIDC_ISSUER'))
- const appURL = new URL(Cypress.config('baseUrl') || '')
- cy.xpath(login.loginButton).click()
- cy.location().should((loc) => {
- expect(loc.protocol).to.eq(oidcProviderURL.protocol)
- expect(loc.hostname).to.eq(oidcProviderURL.hostname)
- })
+ const appURL = new URL(Cypress.config('baseUrl')!)
+ cy.xpath(login.loginButton).should('be.visible').click()
const log = Cypress.log({
name: 'Login to Dev',
@@ -22,12 +18,11 @@ Cypress.Commands.add('login', (username: string, password: string) => {
cy.xpath(login.usernameInput).type(username)
cy.xpath(login.passwordInput).type(password)
cy.xpath(login.loginSubmitButton).click()
+ cy.wait(1000)
- cy.location().should((loc) => {
- expect(loc.protocol).to.eq(appURL.protocol)
- expect(loc.hostname).to.eq(appURL.hostname)
- })
+ log.snapshot('Post Login')
log.end()
+ cy.xpath(login.loginButton).should('not.exist')
cy.log('> Log in')
})
@@ -89,5 +84,6 @@ Cypress.Commands.add('logout', () => {
cy.clearCookies()
})
})
+ cy.wait(2000)
cy.log('> Logging out')
})
diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts
index 45d3599da..b2e80bec3 100644
--- a/e2e/cypress/support/global.d.ts
+++ b/e2e/cypress/support/global.d.ts
@@ -3,7 +3,7 @@
declare namespace Cypress {
interface Chainable {
- login(username: string, password: string): void
+ login(username: string, password: string): Chainable
getSession(): Chainable>
@@ -13,6 +13,8 @@ declare namespace Cypress {
preserveCookies(): void
+ preserveCookiesDefaults(): void
+
saveState(key: string, value: string): void
getState(key: string): string
diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts
index e436cb3a2..d251d6318 100644
--- a/e2e/cypress/support/util-commands.ts
+++ b/e2e/cypress/support/util-commands.ts
@@ -2,13 +2,50 @@ Cypress.Commands.add('preserveCookies', () => {
cy.log('< Saving Cookies')
Cypress.Cookies.preserveOnce(
...[
+ 'AUTH_SESSION_ID_LEGACY',
+ 'KC_RESTART',
+ 'KEYCLOAK_IDENTITY_LEGACY',
+ 'KEYCLOAK_LOCALE',
+ 'KEYCLOAK_LOCALE',
+ 'KEYCLOAK_SESSION_LEGACY',
'_oauth2_proxy',
'_oauth2_proxy_csrf',
- 'ab547b670fc5c67e38dbef98822b7c8d',
'keystone.sid',
]
)
- Cypress.Cookies.debug(true, { verbose: false })
+ // Cypress.Cookies.defaults({
+ // preserve: [
+ // 'AUTH_SESSION_ID_LEGACY',
+ // 'KC_RESTART',
+ // 'KEYCLOAK_IDENTITY_LEGACY',
+ // 'KEYCLOAK_LOCALE',
+ // 'KEYCLOAK_LOCALE',
+ // 'KEYCLOAK_SESSION_LEGACY',
+ // '_oauth2_proxy',
+ // '_oauth2_proxy_csrf',
+ // 'keystone.sid',
+ // ],
+ // })
+ Cypress.Cookies.debug(true)
+ cy.log('> Saving Cookies')
+})
+
+Cypress.Commands.add('preserveCookiesDefaults', () => {
+ cy.log('< Saving Cookies as Defaults')
+ Cypress.Cookies.defaults({
+ preserve: [
+ 'AUTH_SESSION_ID_LEGACY',
+ 'KC_RESTART',
+ 'KEYCLOAK_IDENTITY_LEGACY',
+ 'KEYCLOAK_LOCALE',
+ 'KEYCLOAK_LOCALE',
+ 'KEYCLOAK_SESSION_LEGACY',
+ '_oauth2_proxy',
+ '_oauth2_proxy_csrf',
+ 'keystone.sid',
+ ],
+ })
+ Cypress.Cookies.debug(true)
cy.log('> Saving Cookies')
})
diff --git a/e2e/cypress/tests/01-Authentication/01-auth.spec.ts b/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
deleted file mode 100644
index 03fe6ac21..000000000
--- a/e2e/cypress/tests/01-Authentication/01-auth.spec.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import LoginPage from '../../pageObjects/login'
-
-describe('Authentication spec', () => {
- const login = new LoginPage()
- before(() => {
- cy.resetState()
- })
- beforeEach(() => {
- cy.fixture('developer').as('developer')
- cy.visit(login.path)
- cy.preserveCookies()
- })
- it('should find login button', () => {
- cy.xpath(login.loginButton).should('be.visible')
- })
-
- it('should allow user to authenticate', () => {
- cy.get('@developer').then(({ user }: any) => {
- cy.login(user.credentials.username, user.credentials.password)
- })
- })
-
- it('should save user session after login', () => {
- cy.getSession().then(() => {
- cy.get('@session').then((res: any) => {
- expect(res.body).to.include({ anonymous: false })
- })
- })
- })
-
- it('should allow user to logout', () => {
- cy.logout()
- })
-})
diff --git a/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts b/e2e/cypress/tests/01-create-api.spec.ts
similarity index 62%
rename from e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts
rename to e2e/cypress/tests/01-create-api.spec.ts
index ab76fd334..7acfb22b8 100644
--- a/e2e/cypress/tests/02-CreateAPI/02-serviceaccount.spec.ts
+++ b/e2e/cypress/tests/01-create-api.spec.ts
@@ -1,42 +1,43 @@
-import HomePage from '../../pageObjects/home'
-import LoginPage from '../../pageObjects/login'
-import ServiceAccountsPage from '../../pageObjects/serviceAccounts'
-import ToolBar from '../../pageObjects/toolbar'
+import HomePage from '../pageObjects/home'
+import LoginPage from '../pageObjects/login'
+import ServiceAccountsPage from '../pageObjects/serviceAccounts'
+import ToolBar from '../pageObjects/toolbar'
-describe('Service Account spec', () => {
+describe('Create API Spec', () => {
+ const login = new LoginPage()
const home = new HomePage()
- const sa = new ServiceAccountsPage()
const tb = new ToolBar()
- const login = new LoginPage()
+ const sa = new ServiceAccountsPage()
beforeEach(() => {
cy.fixture('apiowner').as('apiowner')
cy.visit(login.path)
- cy.preserveCookies()
- })
- it('find login button', () => {
- cy.xpath(login.loginButton).should('be.visible')
})
- it('user authentication', () => {
+ it('authenticates api owner', () => {
cy.get('@apiowner').then(({ user }: any) => {
cy.login(user.credentials.username, user.credentials.password)
})
})
- it('should allow user to create a new service account', () => {
+ it('creates and activates new namespace', () => {
cy.get('@apiowner').then(({ namespace }: any) => {
+ home.createNamespace(namespace)
home.useNamespace(namespace)
})
+ })
+ it('creates a new service account', () => {
cy.xpath(tb.namespaces).click()
cy.contains('Service Accounts').click({ force: true })
- cy.xpath(sa.newServiceAccount).click()
cy.get('@apiowner').then(({ serviceAccount }: any) => {
cy.log(serviceAccount.scopes)
sa.createServiceAccount(serviceAccount.scopes)
})
sa.saveServiceAcctCreds()
})
+ afterEach(() => {
+ cy.preserveCookies()
+ })
after(() => {
cy.logout()
})
diff --git a/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts b/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
deleted file mode 100644
index 24236b646..000000000
--- a/e2e/cypress/tests/02-CreateAPI/01-namespace.spec.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import HomePage from '../../pageObjects/home'
-import LoginPage from '../../pageObjects/login'
-
-describe('Namespace spec', () => {
- const login = new LoginPage()
- const home = new HomePage()
-
- beforeEach(() => {
- cy.fixture('apiowner').as('apiowner')
- cy.visit(login.path)
- cy.preserveCookies()
- })
- it('find login button', () => {
- cy.xpath(login.loginButton).should('be.visible')
- })
-
- it('user authentication', () => {
- cy.get('@apiowner').then(({ user }: any) => {
- cy.login(user.credentials.username, user.credentials.password)
- })
- })
-
- it('should allow user to create and switch to new namespace', () => {
- cy.get('@apiowner').then(({ namespace }: any) => {
- home.createNamespace(namespace)
- home.useNamespace(namespace)
- })
- })
-
- after(() => {
- cy.logout()
- })
-})
From f8ba64edb82ed3b90c0fd377821844ca8539ae6a Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Thu, 22 Jul 2021 08:34:17 -0700
Subject: [PATCH 044/155] Chained namespace name assertion with the click
command
---
e2e/cypress/pageObjects/home.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/e2e/cypress/pageObjects/home.ts b/e2e/cypress/pageObjects/home.ts
index 2cfda66be..d1fdc6daf 100644
--- a/e2e/cypress/pageObjects/home.ts
+++ b/e2e/cypress/pageObjects/home.ts
@@ -14,8 +14,11 @@ class HomePage {
useNamespace(name: string): void {
cy.xpath(this.namespaceDropdown).click()
- cy.contains(name).click()
- cy.xpath(this.namespaceDropdown).should('include.text', name)
+ cy.contains(name)
+ .click()
+ .then(() => {
+ cy.xpath(this.namespaceDropdown).should('include.text', name)
+ })
}
}
From ee88804b8bc52e0c2ab64dc087f6a11b0215d7cb Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Thu, 22 Jul 2021 21:44:13 -0700
Subject: [PATCH 045/155] Add new mock data
---
src/nextapp/pages/manager/services/index.tsx | 5 +-
src/test/mock-server/data/metrics-data.js | 266 ++++++++++---------
src/test/mock-server/server.js | 27 +-
3 files changed, 149 insertions(+), 149 deletions(-)
diff --git a/src/nextapp/pages/manager/services/index.tsx b/src/nextapp/pages/manager/services/index.tsx
index f4bff0c7f..02dd0605b 100644
--- a/src/nextapp/pages/manager/services/index.tsx
+++ b/src/nextapp/pages/manager/services/index.tsx
@@ -18,7 +18,7 @@ import SearchInput from '@/components/search-input';
import { FaCaretSquareUp, FaFilter } from 'react-icons/fa';
import ServicesFilters from '@/components/services-list/services-filters';
-import breadcrumbs from '@/components/ns-breadcrumb'
+import breadcrumbs from '@/components/ns-breadcrumb';
// export const getServerSideProps = withAuth(async (context) => {
// const { user } = context;
@@ -54,7 +54,7 @@ const ServicesPage: React.FC = () => {
-
+
{
new MockList(2, (_, { id }) => ({ id })),
allGatewayConsumers: () => new MockList(4, (_, { id }) => ({ id })),
allPlugins: () => new MockList(4, (_, { id }) => ({ id })),
- allMetrics: (_query, _, args) => {
- const result = args.variableValues.days.map((d, index) => {
- const metrics = metricsData[index];
- const date = parse(d, 'yyyy-MM-dd', new Date());
- const values = [];
-
- times(24, (n) => {
- const hour = addHours(date, n);
-
- if (metrics[n]) {
- values.push([hour.getTime(), metrics[n]]);
- }
- });
-
- return {
- name: `kong_http_requests_hourly.${d}.{}`,
- query: 'kong_http_requests_hourly',
- day: d,
- metric: '{}',
- values: JSON.stringify(values),
- };
- });
-
- return result;
- },
+ allMetrics: (_query, _, args) => metricsData,
getPermissionTickets: () => new MockList(6, (_, { id }) => ({ id })),
getPermissionTicketsForResource: () =>
new MockList(6, (_, { id }) => ({ id })),
@@ -124,7 +100,6 @@ const server = mockServer(schemaWithMocks, {
legalName: 'Smith Associates',
address: {
addressLine1: '2233 Broadway South',
- addressLine1: '',
city: 'Mincetown',
postal: 'V1B4A3',
province: 'BC',
From 19788b1efd7abf3c3813c415a2566464383223f8 Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Mon, 26 Jul 2021 00:24:23 -0700
Subject: [PATCH 046/155] Touch up metric counts
---
.../components/services-list/metric-graph.tsx | 26 ++++++++++++++-----
src/nextapp/pages/manager/services/[id].tsx | 12 ++++-----
src/test/mock-server/server.js | 2 ++
3 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/src/nextapp/components/services-list/metric-graph.tsx b/src/nextapp/components/services-list/metric-graph.tsx
index 36bc012b3..b4ca57b09 100644
--- a/src/nextapp/components/services-list/metric-graph.tsx
+++ b/src/nextapp/components/services-list/metric-graph.tsx
@@ -23,6 +23,7 @@ import { scaleLinear } from 'd3-scale';
import formatISO from 'date-fns/formatISO';
import format from 'date-fns/format';
import differenceInDays from 'date-fns/differenceInDays';
+import max from 'lodash/max';
import mean from 'lodash/mean';
import numeral from 'numeral';
import round from 'lodash/round';
@@ -121,7 +122,20 @@ const MetricGraph: React.FC = ({
const totalHours = 24 * 5;
const downtime = sum(dailies.map((d) => d.downtime));
const totalRequests = sum(dailies.map((d) => d.total));
- const requestsAverage = mean(dailies.map((d) => d.total));
+ const peak: number[] | [number, string] = dailies.reduce(
+ (memo, d) => {
+ const prevPeak = Number(memo[1]);
+ const currentPeak = Number(d.peak[1]);
+
+ if (currentPeak > prevPeak) {
+ return d.peak;
+ }
+ return memo;
+ },
+ [0, '0']
+ );
+ const peakRequests = round(Number(peak[1]), 2);
+ const peakDay = format(new Date(peak[0] * 1000), 'EEE');
const usage = downtime / totalHours;
const usagePercent = usage * 100;
const color = interpolateRdYlGn(usage);
@@ -155,8 +169,8 @@ const MetricGraph: React.FC = ({
- Avg
- {numeral(requestsAverage).format('0.0a')}
+ Peak
+ {peakRequests}
Total Req
@@ -165,10 +179,8 @@ const MetricGraph: React.FC = ({
- Days since
-
- {differenceInDays(new Date(), new Date(service?.updatedAt))}
-
+ Peak Day
+ {peakDay}
Plugins
diff --git a/src/nextapp/pages/manager/services/[id].tsx b/src/nextapp/pages/manager/services/[id].tsx
index 740b3a292..5a3ae494f 100644
--- a/src/nextapp/pages/manager/services/[id].tsx
+++ b/src/nextapp/pages/manager/services/[id].tsx
@@ -95,9 +95,9 @@ const ServicePage: React.FC<
breadcrumb={breadcrumb}
title={
- {data?.GatewayService.name}
+ {data?.GatewayService?.name}
@@ -120,7 +120,7 @@ const ServicePage: React.FC<
@@ -150,7 +150,7 @@ const ServicePage: React.FC<
alt
days={range}
height={100}
- id={data?.GatewayService.name}
+ id={data?.GatewayService?.name}
service={data?.GatewayService}
/>
@@ -171,7 +171,7 @@ const ServicePage: React.FC<
-
+
|
@@ -200,7 +200,7 @@ const ServicePage: React.FC<
Host
- {data?.GatewayService.host}
+ {data?.GatewayService?.host}
Tags
diff --git a/src/test/mock-server/server.js b/src/test/mock-server/server.js
index fbf69d3bd..fc45b0a84 100644
--- a/src/test/mock-server/server.js
+++ b/src/test/mock-server/server.js
@@ -315,6 +315,8 @@ const server = mockServer(schemaWithMocks, {
casual.random_element(['GET', 'POST', 'PUT', 'DELETE']),
]),
tags: '["ns.sample"]',
+ hosts: JSON.stringify(['route']),
+ paths: JSON.stringify(['/path']),
}),
CredentialIssuer: () => {
const flow = casual.random_element([
From ddb1ccd8ae4b2bdb5a270b5001a956c3efe29e41 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 26 Jul 2021 19:04:32 -0700
Subject: [PATCH 047/155] seeding organization data for testing
---
local/feeder-init/init.sh | 2 ++
local/feeder-init/organization-unit.yaml | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 local/feeder-init/organization-unit.yaml
diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh
index 94b616dd0..0a175bfce 100755
--- a/local/feeder-init/init.sh
+++ b/local/feeder-init/init.sh
@@ -13,6 +13,8 @@ while true; do
curl http://feeder.localtest.me:6000/push -F yaml=@developer-user.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-authz-profile.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-gwa-api.yaml
+ curl http://feeder.localtest.me:6000/push -F yaml=@organization-unit.yaml
+
break
else
echo "Waiting for Keycloak....."
diff --git a/local/feeder-init/organization-unit.yaml b/local/feeder-init/organization-unit.yaml
new file mode 100644
index 000000000..d7e176570
--- /dev/null
+++ b/local/feeder-init/organization-unit.yaml
@@ -0,0 +1,20 @@
+entity: Organization
+record:
+ id: 7a66db63-26f4-4052-9cd5-3272b63910f8
+ type: organization
+ name: ministry-of-health
+ sector: ''
+ title: 'Ministry of Health'
+ tags: []
+ description: 'The Ministry of Health has overall responsibility for ensuring that quality, appropriate, cost effective and timely health services are available for all British Columbians.'
+ extSource: ''
+ extRecordHash: ''
+ orgUnits:
+ - id: 319b3297-846d-4b97-8095-ceb3ec505fb8
+ name: planning-and-innovation-division
+ sector: 'Health and Safety'
+ title: 'Planning and Innovation Division'
+ tags: []
+ description: ''
+ extSource: ''
+ extRecordHash: ''
From c08c3fc51cf58e6a12a5bcbcee6c564b1c76d671 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Tue, 27 Jul 2021 08:20:18 -0700
Subject: [PATCH 048/155] Seeding organization data for tests
---
local/feeder-init/init.sh | 5 -----
local/feeder-init/organization-unit.yaml | 13 -------------
local/feeder-init/organization.yaml | 11 -----------
3 files changed, 29 deletions(-)
delete mode 100644 local/feeder-init/organization.yaml
diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh
index fde15f4c3..0a175bfce 100755
--- a/local/feeder-init/init.sh
+++ b/local/feeder-init/init.sh
@@ -13,13 +13,8 @@ while true; do
curl http://feeder.localtest.me:6000/push -F yaml=@developer-user.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-authz-profile.yaml
curl http://feeder.localtest.me:6000/push -F yaml=@platform-gwa-api.yaml
-<<<<<<< HEAD
curl http://feeder.localtest.me:6000/push -F yaml=@organization-unit.yaml
-=======
- curl http://feeder.localtest.me:6000/push -F yaml=@organization.yaml
- curl http://feeder.localtest.me:6000/push -F yaml=@organization-unit.yaml
->>>>>>> feature/rate-limit-redis
break
else
echo "Waiting for Keycloak....."
diff --git a/local/feeder-init/organization-unit.yaml b/local/feeder-init/organization-unit.yaml
index 7472658bb..d7e176570 100644
--- a/local/feeder-init/organization-unit.yaml
+++ b/local/feeder-init/organization-unit.yaml
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
entity: Organization
record:
id: 7a66db63-26f4-4052-9cd5-3272b63910f8
@@ -19,15 +18,3 @@ record:
description: ''
extSource: ''
extRecordHash: ''
-=======
-entity: OrganizationUnit
-record:
- id: 319b3297-846d-4b97-8095-ceb3ec505fb8
- name: planning-and-innovation-division
- sector: 'Health and Safety'
- title: 'Planning and Innovation Division'
- tags: []
- description: ''
- extSource: ''
- extRecordHash: ''
->>>>>>> feature/rate-limit-redis
diff --git a/local/feeder-init/organization.yaml b/local/feeder-init/organization.yaml
deleted file mode 100644
index e7d5af7d7..000000000
--- a/local/feeder-init/organization.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-entity: Organization
-record:
- id: 7a66db63-26f4-4052-9cd5-3272b63910f8
- type: organization
- name: ministry-of-health
- sector: ''
- title: 'Ministry of Health'
- tags: []
- description: 'The Ministry of Health1 has overall responsibility for ensuring that quality, appropriate, cost effective and timely health services are available for all British Columbians.'
- extSource: ''
- extRecordHash: ''
From 3e70e5fa8ce776f8feb4ea138220866479865e4c Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Tue, 27 Jul 2021 10:54:04 -0700
Subject: [PATCH 049/155] Tidy up list
---
src/nextapp/components/services-list/metric-graph.tsx | 5 +----
src/nextapp/components/services-list/services-list.tsx | 3 +--
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/nextapp/components/services-list/metric-graph.tsx b/src/nextapp/components/services-list/metric-graph.tsx
index b4ca57b09..2086194aa 100644
--- a/src/nextapp/components/services-list/metric-graph.tsx
+++ b/src/nextapp/components/services-list/metric-graph.tsx
@@ -22,9 +22,6 @@ import { interpolateRdYlGn } from 'd3-scale-chromatic';
import { scaleLinear } from 'd3-scale';
import formatISO from 'date-fns/formatISO';
import format from 'date-fns/format';
-import differenceInDays from 'date-fns/differenceInDays';
-import max from 'lodash/max';
-import mean from 'lodash/mean';
import numeral from 'numeral';
import round from 'lodash/round';
import sum from 'lodash/sum';
@@ -135,7 +132,7 @@ const MetricGraph: React.FC = ({
[0, '0']
);
const peakRequests = round(Number(peak[1]), 2);
- const peakDay = format(new Date(peak[0] * 1000), 'EEE');
+ const peakDay = format(new Date(peak[0] * 1000), 'LLL d');
const usage = downtime / totalHours;
const usagePercent = usage * 100;
const color = interpolateRdYlGn(usage);
diff --git a/src/nextapp/components/services-list/services-list.tsx b/src/nextapp/components/services-list/services-list.tsx
index 5d6851bff..746e3d725 100644
--- a/src/nextapp/components/services-list/services-list.tsx
+++ b/src/nextapp/components/services-list/services-list.tsx
@@ -17,7 +17,7 @@ const ServicesList: React.FC = ({ search }) => {
const { data } = useApi(
'gateway-services',
{
- query: LIST_GATEWAY_SERVICES
+ query: LIST_GATEWAY_SERVICES,
},
{
suspense: true,
@@ -37,7 +37,6 @@ const ServicesList: React.FC = ({ search }) => {
)}
From fd0edd5dd64b8eabadafc9309772031db6128acd Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Tue, 27 Jul 2021 22:15:08 -0700
Subject: [PATCH 050/155] Use total requests as the number to compare against 5
day totals for each service
---
.../components/services-list/metric-graph.tsx | 16 ++++-----
.../components/services-list/service-item.tsx | 15 ++++++--
.../services-list/services-list.tsx | 35 ++++++++++++++++++-
.../shared/queries/gateway-service-queries.ts | 11 +++++-
src/test/mock-server/data/db.js | 2 +-
src/test/mock-server/server.js | 2 +-
6 files changed, 67 insertions(+), 14 deletions(-)
diff --git a/src/nextapp/components/services-list/metric-graph.tsx b/src/nextapp/components/services-list/metric-graph.tsx
index 2086194aa..e9a65d584 100644
--- a/src/nextapp/components/services-list/metric-graph.tsx
+++ b/src/nextapp/components/services-list/metric-graph.tsx
@@ -40,7 +40,7 @@ interface DailyDatum {
downtime: number;
requests: number[];
total: number;
- peak: number[];
+ peak: number | number[];
}
interface MetricGraphProps {
@@ -49,6 +49,7 @@ interface MetricGraphProps {
height?: number;
id: string;
service: GatewayService;
+ totalRequests: number;
}
const MetricGraph: React.FC = ({
@@ -57,6 +58,7 @@ const MetricGraph: React.FC = ({
height = 100,
id,
service,
+ totalRequests,
}) => {
const { data } = useApi(['metric', id], {
query: GET_METRICS,
@@ -84,7 +86,7 @@ const MetricGraph: React.FC = ({
}, 0);
const downtime = 24 - values.length;
const defaultPeakDate: number = firstDateValue.getTime();
- const peak: any = value.reduce(
+ const peak: number | [number, number] = value.reduce(
(memo, v) => {
if (memo[1] < Number(v[1])) {
return v;
@@ -116,10 +118,8 @@ const MetricGraph: React.FC = ({
requests,
};
});
- const totalHours = 24 * 5;
- const downtime = sum(dailies.map((d) => d.downtime));
- const totalRequests = sum(dailies.map((d) => d.total));
- const peak: number[] | [number, string] = dailies.reduce(
+ const totalDailyRequests = sum(dailies.map((d) => d.total));
+ const peak = dailies.reduce(
(memo, d) => {
const prevPeak = Number(memo[1]);
const currentPeak = Number(d.peak[1]);
@@ -133,7 +133,7 @@ const MetricGraph: React.FC = ({
);
const peakRequests = round(Number(peak[1]), 2);
const peakDay = format(new Date(peak[0] * 1000), 'LLL d');
- const usage = downtime / totalHours;
+ const usage = totalDailyRequests / totalRequests;
const usagePercent = usage * 100;
const color = interpolateRdYlGn(usage);
const y = scaleLinear().range([0, height]).domain([0, 1]);
@@ -172,7 +172,7 @@ const MetricGraph: React.FC = ({
Total Req
- {numeral(totalRequests).format('0.0a')}
+ {numeral(totalDailyRequests).format('0.0a')}
diff --git a/src/nextapp/components/services-list/service-item.tsx b/src/nextapp/components/services-list/service-item.tsx
index fcc78fb8a..ada8378b9 100644
--- a/src/nextapp/components/services-list/service-item.tsx
+++ b/src/nextapp/components/services-list/service-item.tsx
@@ -11,9 +11,14 @@ import { GatewayService } from '@/shared/types/query.types';
interface ServiceItemProps {
data: GatewayService;
range: string[];
+ totalRequests: number;
}
-const ServiceItem: React.FC = ({ data, range }) => {
+const ServiceItem: React.FC = ({
+ data,
+ range,
+ totalRequests,
+}) => {
const { ref, inView } = useInView();
return (
@@ -56,7 +61,13 @@ const ServiceItem: React.FC = ({ data, range }) => {
{!inView && }
{inView && (
}>
-
+
)}
diff --git a/src/nextapp/components/services-list/services-list.tsx b/src/nextapp/components/services-list/services-list.tsx
index 746e3d725..21de79f04 100644
--- a/src/nextapp/components/services-list/services-list.tsx
+++ b/src/nextapp/components/services-list/services-list.tsx
@@ -7,22 +7,50 @@ import { useApi } from '@/shared/services/api';
import { LIST_GATEWAY_SERVICES } from '@/shared/queries/gateway-service-queries';
import { dateRange } from './utils';
import ServiceItem from './service-item';
+import { useAuth } from '@/shared/services/auth';
interface ServicesListProps {
search: string;
}
const ServicesList: React.FC = ({ search }) => {
+ const { user } = useAuth();
const range = dateRange();
const { data } = useApi(
'gateway-services',
{
query: LIST_GATEWAY_SERVICES,
+ variables: {
+ days: range,
+ },
},
{
suspense: true,
}
);
+ const totalNamespaceRequests: number = React.useMemo(() => {
+ const { namespace } = user;
+ let result = 0;
+
+ if (data?.allMetrics) {
+ data.allMetrics.forEach((m) => {
+ const metric = JSON.parse(m.metric);
+
+ if (metric.service === namespace) {
+ const values = JSON.parse(m.values);
+ const dayValues = values.reduce(
+ (memo: number, v: number[] | [number, string]) => {
+ return memo + Number(v[1]);
+ },
+ 0
+ );
+ result = result + dayValues;
+ }
+ });
+ }
+
+ return result;
+ }, [data, user]);
const filterServices = React.useCallback(
(d) => {
return d.name.search(search) >= 0;
@@ -41,7 +69,12 @@ const ServicesList: React.FC = ({ search }) => {
)}
{data.allGatewayServicesByNamespace.filter(filterServices).map((d) => (
-
+
))}
>
);
diff --git a/src/nextapp/shared/queries/gateway-service-queries.ts b/src/nextapp/shared/queries/gateway-service-queries.ts
index 5d2f3f235..ca6094ad0 100644
--- a/src/nextapp/shared/queries/gateway-service-queries.ts
+++ b/src/nextapp/shared/queries/gateway-service-queries.ts
@@ -1,7 +1,7 @@
import { gql } from 'graphql-request';
export const LIST_GATEWAY_SERVICES = gql`
- query GetServices {
+ query GetServices($days: [String!]) {
allGatewayServicesByNamespace(first: 200) {
id
name
@@ -30,6 +30,15 @@ export const LIST_GATEWAY_SERVICES = gql`
name
}
}
+ allMetrics(
+ sortBy: day_ASC
+ where: { query: "kong_http_requests_daily_namespace", day_in: $days }
+ ) {
+ query
+ day
+ metric
+ values
+ }
}
`;
diff --git a/src/test/mock-server/data/db.js b/src/test/mock-server/data/db.js
index dcd40d714..acbc810dd 100644
--- a/src/test/mock-server/data/db.js
+++ b/src/test/mock-server/data/db.js
@@ -19,7 +19,7 @@ class MockDatabase {
name: 'Viktor Vaughn',
username: 'vikvaughn',
email: 'villain@doom.net',
- roles: [role],
+ roles: [role, 'portal-user'],
isAdmin: false,
namespace,
groups: null,
diff --git a/src/test/mock-server/server.js b/src/test/mock-server/server.js
index fc45b0a84..629f965ee 100644
--- a/src/test/mock-server/server.js
+++ b/src/test/mock-server/server.js
@@ -23,7 +23,7 @@ const schemas = require('./schemas');
const { sample } = require('lodash');
const app = express();
-const db = new MockDatabase('api-owner', 'dss-loc');
+const db = new MockDatabase('api-owner', 'aps-portal');
const port = 4000;
const randomNullValue = () => {
From 43d82030adbe64e3dcf9d2ae441116ce2471e1ca Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Tue, 27 Jul 2021 22:56:57 -0700
Subject: [PATCH 051/155] Style docs link on redirect page.
---
src/nextapp/pages/redirect/[id].tsx | 81 ++++++++++++++++-------------
1 file changed, 45 insertions(+), 36 deletions(-)
diff --git a/src/nextapp/pages/redirect/[id].tsx b/src/nextapp/pages/redirect/[id].tsx
index 0b5a885c8..2eee10a37 100644
--- a/src/nextapp/pages/redirect/[id].tsx
+++ b/src/nextapp/pages/redirect/[id].tsx
@@ -5,14 +5,13 @@ import {
AlertIcon,
AlertTitle,
AlertDescription,
- Link,
- VStack,
+ Button,
} from '@chakra-ui/react';
import Head from 'next/head';
-import { useAuth } from '@/shared/services/auth';
+import NextLink from 'next/link';
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
-import { Box, Center, Heading, Icon } from '@chakra-ui/react';
-import { FaExclamationCircle } from 'react-icons/fa';
+import { Icon } from '@chakra-ui/react';
+import { FaArrowCircleRight } from 'react-icons/fa';
export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.params;
@@ -20,7 +19,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
return {
props: {
id,
- url,
+ url: url ?? '',
},
};
};
@@ -52,41 +51,51 @@ const RedirectPage: React.FC<
moreDetails: '/docs/platform-api-services-portal-released',
},
};
- if (!(id in sources)) {
- return <>>;
- }
return (
<>
API Services Portal | Redirect
-
-
-
-
- {sources[id].title}
-
-
- {sources[id].moreDetails && (
- {`View the release notes..`}
- )}
-
-
+ {sources[id] && (
+
+
+
+
+ {sources[id].title}
+
+
+ {sources[id].moreDetails && (
+
+ }
+ textDecoration="underline"
+ variant="link"
+ color="bc-link"
+ sx={{
+ _hover: {
+ textDecoration: 'none',
+ },
+ }}
+ >{`View the release notes`}
+
+ )}
+
+
+ )}
>
);
};
From 5fe0b39f83ec56fc362e9decaf394e5d65f0fcea Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Wed, 28 Jul 2021 09:24:09 -0700
Subject: [PATCH 052/155] Add link styling to description links
---
src/nextapp/pages/redirect/[id].tsx | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/nextapp/pages/redirect/[id].tsx b/src/nextapp/pages/redirect/[id].tsx
index 2eee10a37..32f37148d 100644
--- a/src/nextapp/pages/redirect/[id].tsx
+++ b/src/nextapp/pages/redirect/[id].tsx
@@ -75,6 +75,15 @@ const RedirectPage: React.FC<
maxWidth="lg"
pb={5}
dangerouslySetInnerHTML={{ __html: sources[id].description }}
+ sx={{
+ '& a': {
+ textDecoration: 'underline',
+ color: 'bc-link',
+ '&:hover': {
+ textDecoration: 'none',
+ },
+ },
+ }}
>
{sources[id].moreDetails && (
From aa63a252f834e1897448573e60ed5297e62939ea Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Wed, 28 Jul 2021 12:05:14 -0700
Subject: [PATCH 053/155] Use total namespace requests for the metric
---
.../services-list/services-list.tsx | 30 +---
src/nextapp/components/services-list/utils.ts | 34 ++++
src/nextapp/pages/manager/services/[id].tsx | 15 +-
.../shared/queries/gateway-service-queries.ts | 11 +-
src/test/mock-server/data/metrics-data.js | 155 +++++++++++++++++-
src/test/mock-server/server.js | 7 +-
6 files changed, 216 insertions(+), 36 deletions(-)
diff --git a/src/nextapp/components/services-list/services-list.tsx b/src/nextapp/components/services-list/services-list.tsx
index 21de79f04..bcb1eda06 100644
--- a/src/nextapp/components/services-list/services-list.tsx
+++ b/src/nextapp/components/services-list/services-list.tsx
@@ -3,18 +3,16 @@ import { Box } from '@chakra-ui/react';
import EmptyPane from '@/components/empty-pane';
import NewProduct from '@/components/new-product';
import { useApi } from '@/shared/services/api';
-
import { LIST_GATEWAY_SERVICES } from '@/shared/queries/gateway-service-queries';
-import { dateRange } from './utils';
+
+import { dateRange, useTotalRequests } from './utils';
import ServiceItem from './service-item';
-import { useAuth } from '@/shared/services/auth';
interface ServicesListProps {
search: string;
}
const ServicesList: React.FC = ({ search }) => {
- const { user } = useAuth();
const range = dateRange();
const { data } = useApi(
'gateway-services',
@@ -28,29 +26,7 @@ const ServicesList: React.FC = ({ search }) => {
suspense: true,
}
);
- const totalNamespaceRequests: number = React.useMemo(() => {
- const { namespace } = user;
- let result = 0;
-
- if (data?.allMetrics) {
- data.allMetrics.forEach((m) => {
- const metric = JSON.parse(m.metric);
-
- if (metric.service === namespace) {
- const values = JSON.parse(m.values);
- const dayValues = values.reduce(
- (memo: number, v: number[] | [number, string]) => {
- return memo + Number(v[1]);
- },
- 0
- );
- result = result + dayValues;
- }
- });
- }
-
- return result;
- }, [data, user]);
+ const totalNamespaceRequests = useTotalRequests(data);
const filterServices = React.useCallback(
(d) => {
return d.name.search(search) >= 0;
diff --git a/src/nextapp/components/services-list/utils.ts b/src/nextapp/components/services-list/utils.ts
index 390577f18..69c71aed0 100644
--- a/src/nextapp/components/services-list/utils.ts
+++ b/src/nextapp/components/services-list/utils.ts
@@ -1,6 +1,9 @@
+import * as React from 'react';
+import { useAuth } from '@/shared/services/auth';
import format from 'date-fns/format';
import subDays from 'date-fns/subDays';
import times from 'lodash/times';
+import { Query } from '@/shared/types/query.types';
export function dateRange(days = 5): string[] {
const result = [];
@@ -14,3 +17,34 @@ export function dateRange(days = 5): string[] {
return result;
}
+
+export function useTotalRequests(data: Query): number {
+ const { user } = useAuth();
+ const totalNamespaceRequests: number = React.useMemo(() => {
+ let result = 0;
+ if (user) {
+ const { namespace } = user;
+
+ if (data?.allMetrics) {
+ data.allMetrics.forEach((m) => {
+ const metric = JSON.parse(m.metric);
+
+ if (metric.service === namespace) {
+ const values = JSON.parse(m.values);
+ const dayValues = values.reduce(
+ (memo: number, v: number[] | [number, string]) => {
+ return memo + Number(v[1]);
+ },
+ 0
+ );
+ result = result + dayValues;
+ }
+ });
+ }
+ }
+
+ return result;
+ }, [data, user]);
+
+ return totalNamespaceRequests;
+}
diff --git a/src/nextapp/pages/manager/services/[id].tsx b/src/nextapp/pages/manager/services/[id].tsx
index 5a3ae494f..af3472f9a 100644
--- a/src/nextapp/pages/manager/services/[id].tsx
+++ b/src/nextapp/pages/manager/services/[id].tsx
@@ -12,8 +12,6 @@ import {
Tbody,
Td,
Text,
- Th,
- Thead,
Tr,
Wrap,
WrapItem,
@@ -22,7 +20,7 @@ import ClientRequest from '@/components/client-request';
import isEmpty from 'lodash/isEmpty';
import PageHeader from '@/components/page-header';
import api, { useApi } from '@/shared/services/api';
-import { dateRange } from '@/components/services-list/utils';
+import { dateRange, useTotalRequests } from '@/components/services-list/utils';
import { GET_GATEWAY_SERVICE } from '@/shared/queries/gateway-service-queries';
import { FaExternalLinkSquareAlt } from 'react-icons/fa';
import EnvironmentBadge from '@/components/environment-badge';
@@ -36,6 +34,7 @@ import { Query } from '@/shared/types/query.types';
import breadcrumbs from '@/components/ns-breadcrumb';
export const getServerSideProps: GetServerSideProps = async (context) => {
+ const range: string[] = dateRange();
const queryClient = new QueryClient();
await queryClient.prefetchQuery(
@@ -43,7 +42,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
async () =>
await api(
GET_GATEWAY_SERVICE,
- { id: context.params.id },
+ { id: context.params.id, days: range },
{
headers: context.req.headers as HeadersInit,
}
@@ -54,24 +53,26 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
props: {
id: context.params.id,
dehydratedState: dehydrate(queryClient),
+ range,
},
};
};
const ServicePage: React.FC<
InferGetServerSidePropsType
-> = ({ id }) => {
- const range = dateRange();
+> = ({ id, range }) => {
const { data } = useApi(
['gateway-service', id],
{
query: GET_GATEWAY_SERVICE,
variables: {
id,
+ days: range,
},
},
{ enabled: Boolean(id), suspense: false }
);
+ const totalNamespaceRequests = useTotalRequests(data);
const breadcrumb = breadcrumbs([
{ href: '/manager/services', text: 'Services' },
]);
@@ -122,6 +123,7 @@ const ServicePage: React.FC<
height={100}
id={data?.GatewayService?.name}
service={data?.GatewayService}
+ totalRequests={totalNamespaceRequests}
/>
)}
@@ -152,6 +154,7 @@ const ServicePage: React.FC<
height={100}
id={data?.GatewayService?.name}
service={data?.GatewayService}
+ totalRequests={totalNamespaceRequests}
/>
)}
diff --git a/src/nextapp/shared/queries/gateway-service-queries.ts b/src/nextapp/shared/queries/gateway-service-queries.ts
index ca6094ad0..c6e37500a 100644
--- a/src/nextapp/shared/queries/gateway-service-queries.ts
+++ b/src/nextapp/shared/queries/gateway-service-queries.ts
@@ -43,7 +43,7 @@ export const LIST_GATEWAY_SERVICES = gql`
`;
export const GET_GATEWAY_SERVICE = gql`
- query GET($id: ID!) {
+ query GET($id: ID!, $days: [String!]) {
GatewayService(where: { id: $id }) {
id
name
@@ -78,6 +78,15 @@ export const GET_GATEWAY_SERVICE = gql`
}
updatedAt
}
+ allMetrics(
+ sortBy: day_ASC
+ where: { query: "kong_http_requests_daily_namespace", day_in: $days }
+ ) {
+ query
+ day
+ metric
+ values
+ }
}
`;
diff --git a/src/test/mock-server/data/metrics-data.js b/src/test/mock-server/data/metrics-data.js
index 3b450983c..4c63a8023 100644
--- a/src/test/mock-server/data/metrics-data.js
+++ b/src/test/mock-server/data/metrics-data.js
@@ -1,4 +1,152 @@
-module.exports = [
+const namespaceMetrics = [
+ {
+ query: 'kong_http_requests_daily_namespace',
+ day: '2021-07-10',
+ metric: JSON.stringify({ service: 'aps-portal' }),
+ values: JSON.stringify([
+ [1625900400, '0'],
+ [1625904000, '10.29'],
+ [1625907600, '6.00418410041841'],
+ [1625911200, '130.00418410041841'],
+ [1625914800, '100.00418410041841'],
+ [1625918400, '0'],
+ [1625922000, '0'],
+ [1625925600, '0'],
+ [1625929200, '0'],
+ [1625932800, '0'],
+ [1625936400, '0'],
+ [1625940000, '14.01673640167364'],
+ [1625943600, '616.90376569037656'],
+ [1625947200, '871.9665271966527'],
+ [1625950800, '3.01255230125523'],
+ [1625954400, '46.06694560669456'],
+ [1625958000, '20.1255230125523'],
+ [1625961600, '100.00418410041841'],
+ [1625965200, '0'],
+ [1625968800, '0'],
+ [1625972400, '0'],
+ [1625976000, '0'],
+ [1625979600, '0'],
+ [1625983200, '303.13807531380753'],
+ ]),
+ service: { name: 'aps-portal' },
+ },
+ {
+ query: 'kong_http_requests_daily_namespace',
+ day: '2021-07-11',
+ metric: JSON.stringify({ service: 'aps-portal' }),
+ values: JSON.stringify([
+ [1625986800, '0'],
+ [1625990400, '12.00836820083682'],
+ [1625994000, '0'],
+ [1625997600, '12.00836820083682'],
+ [1626001200, '43.01255230125523'],
+ [1626004800, '49.01673640167364'],
+ [1626008400, '10.00418410041841'],
+ [1626012000, '48.03347280334728'],
+ [1626015600, '10.00418410041841'],
+ [1626019200, '1.00418410041841'],
+ [1626022800, '0'],
+ [1626026400, '0'],
+ [1626030000, '30.01255230125523'],
+ [1626033600, '2.00836820083682'],
+ [1626037200, '200.00836820083682'],
+ [1626040800, '35.146443514644346'],
+ [1626044400, '1.00418410041841'],
+ [1626048000, '64.2678471329176'],
+ [1626051600, '1041.5899581589958'],
+ [1626055200, '0'],
+ [1626058800, '8.03347280334728'],
+ [1626062400, '20.00836820083682'],
+ [1626066000, '2.00836820083682'],
+ [1626069600, '155.64853556485355'],
+ ]),
+ service: { name: 'aps-portal' },
+ },
+ {
+ query: 'kong_http_requests_daily_namespace',
+ day: '2021-07-12',
+ metric: JSON.stringify({ service: 'aps-portal' }),
+ values: JSON.stringify([
+ [1626073200, '0'],
+ [1626076800, '200.00836820083682'],
+ [1626080400, '10.00418410041841'],
+ [1626084000, '0'],
+ [1626087600, '9.00418410041841'],
+ [1626091200, '6.00836820083682'],
+ [1626094800, '2.00836820083682'],
+ [1626098400, '10.00418410041841'],
+ [1626102000, '0'],
+ [1626105600, '1.00418410041841'],
+ [1626109200, '576.73640167364016'],
+ [1626112800, '200.00836820083682'],
+ [1626116400, '30.01255230125523'],
+ [1626120000, '15.00418410041841'],
+ [1626123600, '15.00418410041841'],
+ [1626127200, '141.58995815899578'],
+ [1626130800, '97.40585774058577'],
+ [1626134400, '93.17991631799163'],
+ [1626138000, '100.00418410041841'],
+ [1626141600, '0'],
+ [1626145200, '0'],
+ [1626148800, '20.00418410041841'],
+ [1626152400, '50.00418410041841'],
+ [1626156000, '20.00836820083682'],
+ ]),
+ service: { name: 'aps-portal' },
+ },
+ {
+ query: 'kong_http_requests_daily_namespace',
+ day: '2021-07-13',
+ metric: JSON.stringify({ service: 'aps-portal' }),
+ values: JSON.stringify([
+ [1626159600, '18.00418410041841'],
+ [1626163200, '18.00418410041841'],
+ [1626166800, '18.00418410041841'],
+ [1626170400, '0'],
+ [1626174000, '30.01255230125523'],
+ [1626177600, '0'],
+ [1626181200, '10.00418410041841'],
+ [1626184800, '3.01255230125523'],
+ [1626188400, '1.00418410041841'],
+ [1626192000, '0'],
+ [1626195600, '808.4518828451883'],
+ [1626199200, '802.4285007487669'],
+ [1626202800, '91.3807531380753'],
+ [1626206400, '238.57740585774056'],
+ [1626210000, '0'],
+ [1626213600, '804.1004184100418'],
+ [1626217200, '30.01255230125523'],
+ [1626220800, '171.29708569548971'],
+ [1626224400, '106.06694560669456'],
+ [1626228000, '20.00836820083682'],
+ [1626231600, '10.00418410041841'],
+ [1626235200, '10.00418410041841'],
+ [1626238800, '174.72803347280333'],
+ [1626242400, '20.00836820083682'],
+ ]),
+ service: { name: 'aps-portal' },
+ },
+ {
+ query: 'kong_http_requests_daily_namespace',
+ day: '2021-07-14',
+ metric: JSON.stringify({ service: 'aps-portal' }),
+ values: JSON.stringify([
+ [1626246000, '0'],
+ [1626249600, '0'],
+ [1626253200, '0'],
+ [1626256800, '0'],
+ [1626260400, '0'],
+ [1626264000, '100.00418410041841'],
+ [1626267600, '0'],
+ [1626271200, '0'],
+ [1626274800, '75.035573770491804'],
+ ]),
+ service: { name: 'aps-portal' },
+ },
+];
+
+const serviceMetrics = [
{
query: 'kong_http_requests_hourly_service',
day: '2021-07-10',
@@ -145,3 +293,8 @@ module.exports = [
service: { name: 'aps-portal' },
},
];
+
+module.exports = {
+ namespaceMetrics,
+ serviceMetrics,
+};
diff --git a/src/test/mock-server/server.js b/src/test/mock-server/server.js
index 629f965ee..3d8612ab5 100644
--- a/src/test/mock-server/server.js
+++ b/src/test/mock-server/server.js
@@ -81,7 +81,12 @@ const server = mockServer(schemaWithMocks, {
allNamespaceServiceAccounts: () => new MockList(2, (_, { id }) => ({ id })),
allGatewayConsumers: () => new MockList(4, (_, { id }) => ({ id })),
allPlugins: () => new MockList(4, (_, { id }) => ({ id })),
- allMetrics: (_query, _, args) => metricsData,
+ allMetrics: (query) => {
+ if (query.where.query === 'kong_http_requests_daily_namespace') {
+ return metricsData.namespaceMetrics;
+ }
+ return metricsData.serviceMetrics;
+ },
getPermissionTickets: () => new MockList(6, (_, { id }) => ({ id })),
getPermissionTicketsForResource: () =>
new MockList(6, (_, { id }) => ({ id })),
From f5bf3835804c32cb02fb4243ef8c8b33a4dcc909 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 28 Jul 2021 12:58:52 -0700
Subject: [PATCH 054/155] updated github action to generate trivy results and
upload them to security tab. Removed e2e test result
---
.github/workflows/ci-container-img-scan.yaml | 12 +++++++++---
e2e/results/report/bcgov-aps-e2e-report.html | 17 -----------------
2 files changed, 9 insertions(+), 20 deletions(-)
delete mode 100644 e2e/results/report/bcgov-aps-e2e-report.html
diff --git a/.github/workflows/ci-container-img-scan.yaml b/.github/workflows/ci-container-img-scan.yaml
index c94c04177..307ecdbe3 100644
--- a/.github/workflows/ci-container-img-scan.yaml
+++ b/.github/workflows/ci-container-img-scan.yaml
@@ -5,7 +5,7 @@ on:
branches: [dev, main, scan/*]
jobs:
- Anchore-Build-Scan:
+ portal-image-Scan:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
@@ -18,7 +18,7 @@ jobs:
image: 'bcgov/api-services-portal:scan'
acs-report-enable: true
fail-build: false
- - name: Upload Anchore Scan Report
+ - name: Upload Anchore Scan Results
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif
@@ -26,8 +26,14 @@ jobs:
uses: aquasecurity/trivy-action@master
with:
image-ref: 'bcgov/api-services-portal:scan'
- format: 'table'
+ format: 'template'
exit-code: '0'
ignore-unfixed: true
vuln-type: 'os,library'
severity: 'CRITICAL,HIGH,MEDIUM'
+ template: '@/contrib/sarif.tpl'
+ output: 'trivy-results.sarif'
+ - name: Upload Trivy Scan Results
+ uses: github/codeql-action/upload-sarif@v1
+ with:
+ sarif_file: 'trivy-results.sarif'
diff --git a/e2e/results/report/bcgov-aps-e2e-report.html b/e2e/results/report/bcgov-aps-e2e-report.html
deleted file mode 100644
index db384c337..000000000
--- a/e2e/results/report/bcgov-aps-e2e-report.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-Mochawesome Report
\ No newline at end of file
From f8c27ef491012075acfbd7fce9c1b961334fd77b Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 28 Jul 2021 13:20:06 -0700
Subject: [PATCH 055/155] separated anchore and trivy to be able to upload both
the results to security tab
---
.github/workflows/ci-anchore-img-scan.yaml | 24 ++++++++++++
.github/workflows/ci-container-img-scan.yaml | 39 --------------------
.github/workflows/ci-trivy-img-scan.yaml | 25 +++++++++++++
3 files changed, 49 insertions(+), 39 deletions(-)
create mode 100644 .github/workflows/ci-anchore-img-scan.yaml
delete mode 100644 .github/workflows/ci-container-img-scan.yaml
create mode 100644 .github/workflows/ci-trivy-img-scan.yaml
diff --git a/.github/workflows/ci-anchore-img-scan.yaml b/.github/workflows/ci-anchore-img-scan.yaml
new file mode 100644
index 000000000..006693df1
--- /dev/null
+++ b/.github/workflows/ci-anchore-img-scan.yaml
@@ -0,0 +1,24 @@
+name: Scan for Vulnerabilities - Anchore
+
+on:
+ push:
+ branches: [dev, main, scan/*]
+
+jobs:
+ anchore-image-Scan:
+ runs-on: ubuntu-latest
+ steps:
+ # - name: Checkout the code
+ # uses: actions/checkout@v2
+ # - name: Build the Docker image
+ # run: docker build . --file Dockerfile --tag bcgov/api-services-portal:scan
+ - name: Run the Anchore Scan
+ uses: anchore/scan-action@main
+ with:
+ image: ${{ env.REGISTRY }}/bcgov/api-services-portal/api-services-portal
+ acs-report-enable: true
+ fail-build: false
+ - name: Upload Anchore Scan Results
+ uses: github/codeql-action/upload-sarif@v1
+ with:
+ sarif_file: anchore-results.sarif
diff --git a/.github/workflows/ci-container-img-scan.yaml b/.github/workflows/ci-container-img-scan.yaml
deleted file mode 100644
index 307ecdbe3..000000000
--- a/.github/workflows/ci-container-img-scan.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: Scan for Vulnerabilities in API Services Portal Container Image
-
-on:
- push:
- branches: [dev, main, scan/*]
-
-jobs:
- portal-image-Scan:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout the code
- uses: actions/checkout@v2
- - name: Build the Docker image
- run: docker build . --file Dockerfile --tag bcgov/api-services-portal:scan
- - name: Run the Anchore scan action itself with GitHub Advanced Security code scanning integration enabled
- uses: anchore/scan-action@main
- with:
- image: 'bcgov/api-services-portal:scan'
- acs-report-enable: true
- fail-build: false
- - name: Upload Anchore Scan Results
- uses: github/codeql-action/upload-sarif@v1
- with:
- sarif_file: results.sarif
- - name: Run Trivy vulnerability scanner
- uses: aquasecurity/trivy-action@master
- with:
- image-ref: 'bcgov/api-services-portal:scan'
- format: 'template'
- exit-code: '0'
- ignore-unfixed: true
- vuln-type: 'os,library'
- severity: 'CRITICAL,HIGH,MEDIUM'
- template: '@/contrib/sarif.tpl'
- output: 'trivy-results.sarif'
- - name: Upload Trivy Scan Results
- uses: github/codeql-action/upload-sarif@v1
- with:
- sarif_file: 'trivy-results.sarif'
diff --git a/.github/workflows/ci-trivy-img-scan.yaml b/.github/workflows/ci-trivy-img-scan.yaml
new file mode 100644
index 000000000..4c6ddc013
--- /dev/null
+++ b/.github/workflows/ci-trivy-img-scan.yaml
@@ -0,0 +1,25 @@
+name: Scan for Vulnerabilities in API Services Portal Container Image
+
+on:
+ push:
+ branches: [dev, main, scan/*]
+
+jobs:
+ trivy-image-Scan:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Run Trivy Scan
+ uses: aquasecurity/trivy-action@master
+ with:
+ image-ref: ${{ env.REGISTRY }}/bcgov/api-services-portal/api-services-portal
+ format: 'template'
+ exit-code: '0'
+ ignore-unfixed: true
+ vuln-type: 'os,library'
+ severity: 'CRITICAL,HIGH,MEDIUM'
+ template: '@/contrib/sarif.tpl'
+ output: 'trivy-results.sarif'
+ - name: Upload Trivy Scan Results
+ uses: github/codeql-action/upload-sarif@v1
+ with:
+ sarif_file: 'trivy-results.sarif'
From fe06886175e07ca4da5b68538d3c9be486e1037d Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 28 Jul 2021 13:35:25 -0700
Subject: [PATCH 056/155] added env vars to pull image from container registry
---
.github/workflows/ci-anchore-img-scan.yaml | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/.github/workflows/ci-anchore-img-scan.yaml b/.github/workflows/ci-anchore-img-scan.yaml
index 006693df1..1831c8e56 100644
--- a/.github/workflows/ci-anchore-img-scan.yaml
+++ b/.github/workflows/ci-anchore-img-scan.yaml
@@ -4,6 +4,11 @@ on:
push:
branches: [dev, main, scan/*]
+env:
+ REGISTRY: ghcr.io
+ REGISTRY_USERNAME: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
+ REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
+
jobs:
anchore-image-Scan:
runs-on: ubuntu-latest
@@ -12,6 +17,12 @@ jobs:
# uses: actions/checkout@v2
# - name: Build the Docker image
# run: docker build . --file Dockerfile --tag bcgov/api-services-portal:scan
+ - name: Login to DockerHub
+ uses: docker/login-action@v1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ env.REGISTRY_USERNAME }}
+ password: ${{ env.REGISTRY_PASSWORD }}
- name: Run the Anchore Scan
uses: anchore/scan-action@main
with:
From c6cdbc33bd9dfe71a0c6c81f87965eb58693b181 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 28 Jul 2021 14:02:24 -0700
Subject: [PATCH 057/155] building an image for scanning
---
.github/workflows/ci-anchore-img-scan.yaml | 21 +++++----------------
.github/workflows/ci-trivy-img-scan.yaml | 8 ++++++--
2 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/ci-anchore-img-scan.yaml b/.github/workflows/ci-anchore-img-scan.yaml
index 1831c8e56..f01ac34dd 100644
--- a/.github/workflows/ci-anchore-img-scan.yaml
+++ b/.github/workflows/ci-anchore-img-scan.yaml
@@ -4,29 +4,18 @@ on:
push:
branches: [dev, main, scan/*]
-env:
- REGISTRY: ghcr.io
- REGISTRY_USERNAME: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
- REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
-
jobs:
anchore-image-Scan:
runs-on: ubuntu-latest
steps:
- # - name: Checkout the code
- # uses: actions/checkout@v2
- # - name: Build the Docker image
- # run: docker build . --file Dockerfile --tag bcgov/api-services-portal:scan
- - name: Login to DockerHub
- uses: docker/login-action@v1
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ env.REGISTRY_USERNAME }}
- password: ${{ env.REGISTRY_PASSWORD }}
+ - name: Checkout the code
+ uses: actions/checkout@v2
+ - name: Build the Docker image
+ run: docker build . --file Dockerfile --tag bcgov/api-services-portal:anchore-scan
- name: Run the Anchore Scan
uses: anchore/scan-action@main
with:
- image: ${{ env.REGISTRY }}/bcgov/api-services-portal/api-services-portal
+ image: 'bcgov/api-services-portal:anchore-scan'
acs-report-enable: true
fail-build: false
- name: Upload Anchore Scan Results
diff --git a/.github/workflows/ci-trivy-img-scan.yaml b/.github/workflows/ci-trivy-img-scan.yaml
index 4c6ddc013..4a08ebeda 100644
--- a/.github/workflows/ci-trivy-img-scan.yaml
+++ b/.github/workflows/ci-trivy-img-scan.yaml
@@ -1,4 +1,4 @@
-name: Scan for Vulnerabilities in API Services Portal Container Image
+name: Scan for Vulnerabilities - Trivy
on:
push:
@@ -8,10 +8,14 @@ jobs:
trivy-image-Scan:
runs-on: ubuntu-latest
steps:
+ - name: Checkout the code
+ uses: actions/checkout@v2
+ - name: Build the Docker image
+ run: docker build . --file Dockerfile --tag bcgov/api-services-portal:trivy-scan
- name: Run Trivy Scan
uses: aquasecurity/trivy-action@master
with:
- image-ref: ${{ env.REGISTRY }}/bcgov/api-services-portal/api-services-portal
+ image-ref: 'bcgov/api-services-portal:trivy-scan'
format: 'template'
exit-code: '0'
ignore-unfixed: true
From 5ed903bf8e0ab09250d00c1149a300394787dfd9 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Wed, 28 Jul 2021 14:26:27 -0700
Subject: [PATCH 058/155] updated the results file name
---
.github/workflows/ci-anchore-img-scan.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-anchore-img-scan.yaml b/.github/workflows/ci-anchore-img-scan.yaml
index f01ac34dd..39ee38ae8 100644
--- a/.github/workflows/ci-anchore-img-scan.yaml
+++ b/.github/workflows/ci-anchore-img-scan.yaml
@@ -21,4 +21,4 @@ jobs:
- name: Upload Anchore Scan Results
uses: github/codeql-action/upload-sarif@v1
with:
- sarif_file: anchore-results.sarif
+ sarif_file: results.sarif
From a9fd82499d26648f9bfda4e8d40ed29cd1229541 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Wed, 28 Jul 2021 15:28:36 -0700
Subject: [PATCH 059/155] fix CredentialIssuer authedItem missing
---
src/lists/CredentialIssuer.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lists/CredentialIssuer.js b/src/lists/CredentialIssuer.js
index ce95b0450..eb8dd83de 100644
--- a/src/lists/CredentialIssuer.js
+++ b/src/lists/CredentialIssuer.js
@@ -157,7 +157,7 @@ module.exports = {
if (!('owner' in resolvedData) && context['authedItem']) {
resolvedData['owner'] = context.authedItem.userId;
}
- if ('namespace' in context['authedItem']) {
+ if (context['authedItem'] && 'namespace' in context['authedItem']) {
resolvedData['namespace'] = context['authedItem']['namespace'];
}
}
From e93535b02034e38650f4df4d85d7bf0504c1c6de Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Thu, 29 Jul 2021 11:48:56 -0700
Subject: [PATCH 060/155] added test ids for portal elements for better
visibility in cypress tests
---
.github/workflows/aps-cypress-e2e.yaml | 2 +-
docker-compose-portal.yml | 40 +++
docker-compose.yml | 130 ++++-----
local/feeder-init/init.sh | 2 +-
.../components/auth-action/auth-action.tsx | 8 +-
.../namespace-menu/namespace-menu.tsx | 9 +-
src/nextapp/components/nav-bar/nav-bar.tsx | 1 +
.../new-namespace/new-namespace.tsx | 6 +-
.../service-account-create.tsx | 9 +-
.../pages/manager/poc/namespaces/nav.tsx | 247 +++++++++---------
.../manager/poc/service-accounts/index.tsx | 7 +-
11 files changed, 259 insertions(+), 202 deletions(-)
create mode 100644 docker-compose-portal.yml
diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml
index c143c87dd..e36c4fc7a 100644
--- a/.github/workflows/aps-cypress-e2e.yaml
+++ b/.github/workflows/aps-cypress-e2e.yaml
@@ -3,7 +3,7 @@ name: Build and Deploy Cypress and Execute Tests
on:
push:
branches:
- - 'util/automation-*'
+ - 'util/automation-not*'
jobs:
cypress-run:
diff --git a/docker-compose-portal.yml b/docker-compose-portal.yml
new file mode 100644
index 000000000..c2d311133
--- /dev/null
+++ b/docker-compose-portal.yml
@@ -0,0 +1,40 @@
+version: '3.8'
+
+services:
+ apsportal:
+ container_name: apsportal
+ image: apsportal:latest
+ build:
+ context: .
+ dockerfile: Dockerfile
+ env_file:
+ - .env.local
+ ports:
+ - 3000:3000
+ networks:
+ aps-net:
+ aliases:
+ - apsportal.localtest.me
+# feeder-seeding:
+# container_name: feeder-seeding
+# image: feeder:latest
+# command: ''
+# entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
+# restart: on-failure
+# volumes:
+# - ./local/feeder-init:/tmp
+# networks:
+# - aps-net
+# cypress:
+# image: 'aps-cypress-e2e:latest'
+# container_name: cypress-e2e
+# entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+# build:
+# context: ./e2e
+# dockerfile: Dockerfile
+# volumes:
+# - ./e2e/results/report:/e2e/results/report
+# networks:
+# - aps-net
+networks:
+ aps-net: {}
diff --git a/docker-compose.yml b/docker-compose.yml
index 22c3958ef..b9a273266 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -38,10 +38,9 @@ services:
volumes:
- ./local/keycloak/master-realm.json:/tmp/realm-config/master-realm.json
networks:
- keycloak:
+ aps-net:
aliases:
- keycloak.localtest.me
- kong-net: {}
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3
container_name: oauth2-proxy
@@ -56,32 +55,25 @@ services:
env_file:
- .env.local
networks:
- keycloak: {}
- portal: {}
- kong-net: {}
- redis-net: {}
- oauth2-proxy:
+ aps-net:
aliases:
- oauth2proxy.localtest.me
- apsportal:
- container_name: apsportal
- image: apsportal:latest
- depends_on:
- - keycloak
- build:
- context: .
- dockerfile: Dockerfile
- env_file:
- - .env.local
- ports:
- - 3000:3000
- networks:
- portal:
- aliases:
- - apsportal.localtest.me
- keycloak: {}
- oauth2-proxy: {}
- kong-net: {}
+ # apsportal:
+ # container_name: apsportal
+ # image: apsportal:latest
+ # depends_on:
+ # - keycloak
+ # build:
+ # context: .
+ # dockerfile: Dockerfile
+ # env_file:
+ # - .env.local
+ # ports:
+ # - 3000:3000
+ # networks:
+ # aps-net:
+ # aliases:
+ # - apsportal.localtest.me
feeder:
container_name: feeder
image: feeder:latest
@@ -96,37 +88,34 @@ services:
ports:
- 6000:6000
networks:
- portal:
+ aps-net:
aliases:
- feeder.localtest.me
- kong-net: {}
- feeder-seeding:
- container_name: feeder-seeding
- image: feeder:latest
- command: ''
- entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
- restart: on-failure
- depends_on:
- - feeder
- volumes:
- - ./local/feeder-init:/tmp
- networks:
- - portal
- - keycloak
- cypress:
- image: 'aps-cypress-e2e:latest'
- container_name: cypress-e2e
- entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
- depends_on:
- - feeder-seeding
- build:
- context: ./e2e
- dockerfile: Dockerfile
- volumes:
- - ./e2e/results/report:/e2e/results/report
- networks:
- - keycloak
- - oauth2-proxy
+ # feeder-seeding:
+ # container_name: feeder-seeding
+ # image: feeder:latest
+ # command: ''
+ # entrypoint: sh -c "chmod +x /tmp/init.sh && sh /tmp/init.sh"
+ # restart: on-failure
+ # depends_on:
+ # - feeder
+ # volumes:
+ # - ./local/feeder-init:/tmp
+ # networks:
+ # - aps-net
+ # cypress:
+ # image: 'aps-cypress-e2e:latest'
+ # container_name: cypress-e2e
+ # entrypoint: sh -c "chmod +x /tmp/entrypoint.sh && /tmp/entrypoint.sh"
+ # depends_on:
+ # - feeder-seeding
+ # build:
+ # context: ./e2e
+ # dockerfile: Dockerfile
+ # volumes:
+ # - ./e2e/results/report:/e2e/results/report
+ # networks:
+ # - aps-net
kong-db:
image: postgres:latest
container_name: kong-db
@@ -141,9 +130,7 @@ services:
- ./local/db/database-init.sql:/docker-entrypoint-initdb.d/1-init.sql
- ./local/db/keystone-init.sql:/docker-entrypoint-initdb.d/2-init.sql
networks:
- - kong-net
- - keycloak
- - portal
+ - aps-net
kong-migrations:
image: kong:latest
command: kong migrations bootstrap
@@ -151,7 +138,7 @@ services:
- kong-db
environment: *common-variables
networks:
- - kong-net
+ - aps-net
restart: on-failure
kong-migrations-up:
image: kong:latest
@@ -160,7 +147,7 @@ services:
- kong-db
environment: *common-variables
networks:
- - kong-net
+ - aps-net
restart: on-failure
kong:
image: kong:latest
@@ -181,7 +168,7 @@ services:
- 8000:8000
- 8001:8001
networks:
- kong-net:
+ aps-net:
aliases:
- kong.localtest.me
restart: on-failure:5
@@ -194,12 +181,12 @@ services:
ports:
- 6379:6379
networks:
- redis-net:
+ aps-net:
aliases:
- redis.localtest.me
- gwa-api:
- image: gateway-api:latest
- container_name: gwa-api
+ gwa-gateway-api:
+ image: ghcr.io/bcgov/gwa-api/gwa-gateway-api:feature-add-consumer-service
+ container_name: gwa-gateway-api
entrypoint: sh -c "chmod +x /tmp/gwa/entrypoint.sh && sh /tmp/gwa/entrypoint.sh"
ports:
- 2000:2000
@@ -209,17 +196,8 @@ services:
volumes:
- ./local/gwa-api:/tmp/gwa
networks:
- gwa-net:
+ aps-net:
aliases:
- gwa-api.localtest.me
- oauth2-proxy: {}
- portal: {}
- kong-net: {}
- keycloak: {}
networks:
- keycloak: {}
- oauth2-proxy: {}
- portal: {}
- kong-net: {}
- redis-net: {}
- gwa-net: {}
+ aps-net: {}
diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh
index 0a175bfce..a95616801 100755
--- a/local/feeder-init/init.sh
+++ b/local/feeder-init/init.sh
@@ -4,7 +4,7 @@ apk add --no-cache curl
cd /tmp
while true; do
- keycloakstatus=$(curl -o /dev/null -Isw '%{http_code}\n' http://keycloak.localtest.me:9080/auth/realms/master)
+ keycloakstatus=$(curl -o /dev/null -Isw '%{http_code}\n' http://oauth2proxy.localtest.me:4180)
echo "$keycloakstatus"
if [[ "$keycloakstatus" == "200" ]]; then
echo "Keycloak is up"
diff --git a/src/nextapp/components/auth-action/auth-action.tsx b/src/nextapp/components/auth-action/auth-action.tsx
index 83ab1e254..90ca640a1 100644
--- a/src/nextapp/components/auth-action/auth-action.tsx
+++ b/src/nextapp/components/auth-action/auth-action.tsx
@@ -57,10 +57,16 @@ const Signin: React.FC = ({ site }) => {
color="text"
onClick={onNextLinkClick}
value="/poc/my-profile"
+ data-testid="auth-menu-user-profile"
>
My Profile
-
diff --git a/src/nextapp/components/nav-bar/nav-bar.tsx b/src/nextapp/components/nav-bar/nav-bar.tsx
index 48f0166b9..f6446c767 100644
--- a/src/nextapp/components/nav-bar/nav-bar.tsx
+++ b/src/nextapp/components/nav-bar/nav-bar.tsx
@@ -80,6 +80,7 @@ const NavBar: React.FC = ({ site, links, pathname }) => {
? 'page'
: false
}
+ data-testid={'navbar-link-' + link.name}
>
{link.name}
diff --git a/src/nextapp/components/new-namespace/new-namespace.tsx b/src/nextapp/components/new-namespace/new-namespace.tsx
index c1c02fbb7..1a494a7e1 100644
--- a/src/nextapp/components/new-namespace/new-namespace.tsx
+++ b/src/nextapp/components/new-namespace/new-namespace.tsx
@@ -81,17 +81,21 @@ const NewNamespace: React.FC = ({ isOpen, onClose }) => {
name="name"
type="text"
variant="bc-input"
+ data-testid="ns-modal-name-input"
/>
-
+
diff --git a/src/nextapp/components/service-account-create/service-account-create.tsx b/src/nextapp/components/service-account-create/service-account-create.tsx
index 484bbcfb6..123421546 100644
--- a/src/nextapp/components/service-account-create/service-account-create.tsx
+++ b/src/nextapp/components/service-account-create/service-account-create.tsx
@@ -79,6 +79,7 @@ const ServiceAccountCreate: React.FC = ({
leftIcon={}
variant="primary"
onClick={onOpen}
+ data-testid="sa-create-second-btn"
>
New Service Account
@@ -103,7 +104,11 @@ const ServiceAccountCreate: React.FC = ({
{isSuccess &&
data?.currentNamespace.scopes.map((s) => (
-
+
{s.name}
@@ -119,6 +124,7 @@ const ServiceAccountCreate: React.FC = ({
@@ -126,6 +132,7 @@ const ServiceAccountCreate: React.FC = ({
isLoading={credentialGenerator.isLoading}
variant="primary"
onClick={handleCreate}
+ data-testid="sa-scopes-share-btn"
>
Share
diff --git a/src/nextapp/pages/manager/poc/namespaces/nav.tsx b/src/nextapp/pages/manager/poc/namespaces/nav.tsx
index a7ecc70df..72d4ccacf 100644
--- a/src/nextapp/pages/manager/poc/namespaces/nav.tsx
+++ b/src/nextapp/pages/manager/poc/namespaces/nav.tsx
@@ -1,137 +1,148 @@
import * as React from 'react';
-import { Box, Container, Divider, Grid, Heading, Icon, Link, Text } from '@chakra-ui/react';
+import {
+ Box,
+ Container,
+ Divider,
+ Grid,
+ Heading,
+ Icon,
+ Link,
+ Text,
+} from '@chakra-ui/react';
import Head from 'next/head';
import NextLink from 'next/link';
import Card from '@/components/card';
import GridLayout from '@/layouts/grid';
-import {
- FaServer,
-} from 'react-icons/fa';
-
+import { FaServer } from 'react-icons/fa';
+
import { useAuth } from '@/shared/services/auth';
type HomeActions = {
- title: string;
- url: string;
- icon: React.ComponentType;
- roles: string[];
- description: string;
- };
+ title: string;
+ url: string;
+ icon: React.ComponentType;
+ roles: string[];
+ description: string;
+};
+
+const actions: HomeActions[] = [
+ {
+ title: 'Gateway Services',
+ url: '/manager/services',
+ icon: FaServer,
+ roles: [],
+ description:
+ 'View your current gateway configuration, metrics and traffic patterns',
+ },
+ {
+ title: 'Products',
+ url: '/manager/products',
+ icon: FaServer,
+ roles: [],
+ description: 'Publish your API and make it discoverable',
+ },
+ {
+ title: 'Consumers',
+ url: '/manager/consumers',
+ icon: FaServer,
+ roles: [],
+ description:
+ 'Manage your prospective and existing clients - add controls, approve access, view usage',
+ },
+];
- const actions: HomeActions[] = [
- {
- title: 'Gateway Services',
- url: '/manager/services',
- icon: FaServer,
- roles: [],
- description: "View your current gateway configuration, metrics and traffic patterns"
- },
- {
- title: 'Products',
- url: '/manager/products',
- icon: FaServer,
- roles: [],
- description: "Publish your API and make it discoverable"
- },
- {
- title: 'Consumers',
- url: '/manager/consumers',
- icon: FaServer,
- roles: [],
- description: "Manage your prospective and existing clients - add controls, approve access, view usage"
- }
- ];
+const secondaryActions: HomeActions[] = [
+ {
+ title: 'Authorization Profiles',
+ url: '/manager/poc/credential-issuers',
+ icon: FaServer,
+ roles: [],
+ description: 'Manage authorization servers used to protect your APIs',
+ },
+ {
+ title: 'Service Accounts',
+ url: '/manager/poc/service-accounts',
+ icon: FaServer,
+ roles: [],
+ description:
+ 'Manage service accounts for performing functions on the namespace',
+ },
+ {
+ title: 'Activity',
+ url: '/manager/poc/activity',
+ icon: FaServer,
+ roles: [],
+ description: 'View all the activity within your namepace.',
+ },
+];
- const secondaryActions: HomeActions[] = [
- {
- title: 'Authorization Profiles',
- url: '/manager/poc/credential-issuers',
- icon: FaServer,
- roles: [],
- description: "Manage authorization servers used to protect your APIs"
- },
- {
- title: 'Service Accounts',
- url: '/manager/poc/service-accounts',
- icon: FaServer,
- roles: [],
- description: "Manage service accounts for performing functions on the namespace"
- },
- {
- title: 'Activity',
- url: '/manager/poc/activity',
- icon: FaServer,
- roles: [],
- description: "View all the activity within your namepace."
- },
- ];
-
const Navigation = () => {
- const { user } = useAuth()
+ const { user } = useAuth();
- return (
+ return (
-
-
-
- {actions
- .filter(
- (action) =>
- user?.roles.some((r: string) => action.roles.includes(r)) ||
- action.roles.length === 0
- )
- .map((action) => (
-
-
-
-
-
- {action.title}
-
-
-
-
- {action.description}
-
-
- ))}
-
-
-
-
- Other Actions:
+
+
+
+ {actions
+ .filter(
+ (action) =>
+ user?.roles.some((r: string) => action.roles.includes(r)) ||
+ action.roles.length === 0
+ )
+ .map((action) => (
+
+
+
+
+
+ {action.title}
+
+
+
+ {action.description}
+
+ ))}
+
+
-
- {secondaryActions
- .filter(
- (action) =>
- user?.roles.some((r: string) => action.roles.includes(r)) ||
- action.roles.length === 0
- )
- .map((action) => (
-
-
-
-
-
- {action.title}
-
-
-
-
- ))}
-
-
+
+ Other Actions:
+
+ {secondaryActions
+ .filter(
+ (action) =>
+ user?.roles.some((r: string) => action.roles.includes(r)) ||
+ action.roles.length === 0
+ )
+ .map((action) => (
+
+
+
+
+
+ {action.title}
+
+
+
+
+ ))}
+
+
- )
-}
+ );
+};
export default Navigation;
-
-
diff --git a/src/nextapp/pages/manager/poc/service-accounts/index.tsx b/src/nextapp/pages/manager/poc/service-accounts/index.tsx
index 8d83ace85..718a43665 100644
--- a/src/nextapp/pages/manager/poc/service-accounts/index.tsx
+++ b/src/nextapp/pages/manager/poc/service-accounts/index.tsx
@@ -109,7 +109,11 @@ const ApplicationsPage: React.FC<
};
const actions = [
-
diff --git a/src/nextapp/pages/manager/namespaces/index.tsx b/src/nextapp/pages/manager/namespaces/index.tsx
index ea5b91021..b539a4292 100644
--- a/src/nextapp/pages/manager/namespaces/index.tsx
+++ b/src/nextapp/pages/manager/namespaces/index.tsx
@@ -175,7 +175,10 @@ const NamespacesPage: React.FC = () => {
-
+
{a.title}
{
- {a.title}
+
+ {a.title}
+
From 05dcd619b28d85b9489ed686fce0f8abca71952a Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 31 Jul 2021 22:26:15 -0700
Subject: [PATCH 067/155] Updated gwa url for plugin management
---
.env.local | 2 +-
src/services/kong/consumer-service.ts | 15 ++++++++-------
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/.env.local b/.env.local
index fb9322868..f9a3b1495 100644
--- a/.env.local
+++ b/.env.local
@@ -12,7 +12,7 @@ KONG_URL=http://kong.localtest.me:8001
JWKS_URL=http://keycloak.localtest.me:9080/auth/realms/master/protocol/openid-connect/certs
FEEDER_URL=http://feeder.localtest.me:6000
NEXT_PUBLIC_API_ROOT=http://oauth2proxy.localtest.me:4180
-GWA_API_URL=http://localhost:2000
+GWA_API_URL=http://gwa-api.localtest.me:2000
GWA_PROD_ENV_SLUG=E0000000
GWA_RES_SVR_CLIENT_ID=gwa-api
GWA_RES_SVR_CLIENT_SECRET=18900468-3db1-43f7-a8af-e75f079eb742
diff --git a/src/services/kong/consumer-service.ts b/src/services/kong/consumer-service.ts
index 9ac2ad040..05e246723 100644
--- a/src/services/kong/consumer-service.ts
+++ b/src/services/kong/consumer-service.ts
@@ -39,6 +39,7 @@ const logger = Logger('kong');
export class KongConsumerService {
private kongUrl: string;
+ private gwaUrl: string = process.env.GWA_API_URL;
constructor(kongUrl: string) {
this.kongUrl = kongUrl;
@@ -143,14 +144,14 @@ export class KongConsumerService {
plugin: KongPlugin,
namespace: string
): Promise {
- const body = {};
+ const body = { ...plugin, tags: ['ns.' + namespace] };
logger.debug('[addPluginToConsumer] CALLING with ' + consumerPK);
const response = await fetch(
- `/gw/api/namespaces/${namespace}/consumers/${consumerPK}/plugins`,
+ `${this.gwaUrl}/v2/namespaces/${namespace}/consumers/${consumerPK}/plugins`,
{
method: 'post',
- body: JSON.stringify(plugin),
+ body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json',
},
@@ -172,12 +173,12 @@ export class KongConsumerService {
namespace: string
): Promise {
logger.debug('[updateConsumerPlugin] C=%s P=%s', consumerPK, pluginPK);
-
+ const body = { ...plugin, tags: ['ns.' + namespace] };
const response = await fetch(
- `/gw/api/namespaces/${namespace}/consumers/${consumerPK}/plugins/${pluginPK}`,
+ `${this.gwaUrl}/v2/namespaces/${namespace}/consumers/${consumerPK}/plugins/${pluginPK}`,
{
method: 'put',
- body: JSON.stringify(plugin),
+ body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json',
},
@@ -195,7 +196,7 @@ export class KongConsumerService {
namespace: string
): Promise {
await fetch(
- `/gw/api/namespaces/${namespace}/consumers/${consumerPK}/plugins/${pluginPK}`,
+ `${this.gwaUrl}/v2/namespaces/${namespace}/consumers/${consumerPK}/plugins/${pluginPK}`,
{
method: 'delete',
headers: {
From 3971fc734326e2eaa944d3ffaf644e6f9f3cbbb9 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 31 Jul 2021 22:53:11 -0700
Subject: [PATCH 068/155] added more tags to manage products in cypress tests
---
.../components/environments-list/delete-environment.tsx | 1 +
.../components/environments-list/environments-list.tsx | 6 +++++-
src/nextapp/components/products-list/add-environment.tsx | 9 +++++++--
src/nextapp/components/products-list/delete-product.tsx | 6 +++++-
src/nextapp/components/products-list/edit-product.tsx | 4 +++-
.../components/products-list/organization-select.tsx | 1 +
6 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/src/nextapp/components/environments-list/delete-environment.tsx b/src/nextapp/components/environments-list/delete-environment.tsx
index 89132572a..734eaaa99 100644
--- a/src/nextapp/components/environments-list/delete-environment.tsx
+++ b/src/nextapp/components/environments-list/delete-environment.tsx
@@ -53,6 +53,7 @@ const DeleteEnvironment: React.FC = ({ id }) => {
size="xs"
variant="outline"
onClick={onConfirm}
+ data-testid="prd-env-delete-btn"
>
diff --git a/src/nextapp/components/environments-list/environments-list.tsx b/src/nextapp/components/environments-list/environments-list.tsx
index 9460a04ee..71fca0141 100644
--- a/src/nextapp/components/environments-list/environments-list.tsx
+++ b/src/nextapp/components/environments-list/environments-list.tsx
@@ -119,7 +119,11 @@ const EnvironmentsList: React.FC = ({ data }) => {
-
+
Edit
diff --git a/src/nextapp/components/products-list/add-environment.tsx b/src/nextapp/components/products-list/add-environment.tsx
index 4e20c9f30..97e7d19c9 100644
--- a/src/nextapp/components/products-list/add-environment.tsx
+++ b/src/nextapp/components/products-list/add-environment.tsx
@@ -55,14 +55,19 @@ const AddEnvironment: React.FC = ({
return (
- Peak
+ Peak Req
{peakRequests}
@@ -178,7 +185,7 @@ const MetricGraph: React.FC = ({
Peak Day
- {peakDay}
+ {peakDayText}
Plugins
From b995e3b1c8ebae5c292fd8a78bc5bb69c2bb85f6 Mon Sep 17 00:00:00 2001
From: Joshua Jones
Date: Thu, 5 Aug 2021 16:20:01 -0700
Subject: [PATCH 090/155] Replace plugins with peak hour/daily instead
---
.../components/services-list/metric-graph.tsx | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/nextapp/components/services-list/metric-graph.tsx b/src/nextapp/components/services-list/metric-graph.tsx
index 4957b334e..a291ab890 100644
--- a/src/nextapp/components/services-list/metric-graph.tsx
+++ b/src/nextapp/components/services-list/metric-graph.tsx
@@ -174,22 +174,22 @@ const MetricGraph: React.FC = ({
- Peak Req
+ Peak Hourly
{peakRequests}
- Total Req
-
- {numeral(totalDailyRequests).format('0.0a')}
-
+ Peak Daily
+ {numeral(peakDay.total).format('0.0a')}
Peak Day
{peakDayText}
- Plugins
- {service?.plugins.length}
+ Total Req
+
+ {numeral(totalDailyRequests).format('0.0a')}
+
From 1fe12693f78d95e01bbe0ca4fdd4744b21a92780 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Thu, 5 Aug 2021 17:58:15 -0700
Subject: [PATCH 091/155] Able to fetch namespace by product and user list of
that namespace
---
src/lists/AccessRequest.js | 91 +++++++++++++++++++++++++++++++-------
1 file changed, 75 insertions(+), 16 deletions(-)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index 9abfd869a..e51d00b67 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -1,20 +1,34 @@
const { Text, Checkbox, Relationship } = require('@keystonejs/fields');
const { Markdown } = require('@keystonejs/fields-markdown');
-
const { byTracking } = require('../components/ByTracking');
-
const { atTracking } = require('@keystonejs/list-plugins');
-
const {
FieldEnforcementPoint,
EnforcementPoint,
} = require('../authz/enforcement');
-
const { Apply, Validate } = require('../services/workflow');
-
const {
lookupEnvironmentAndApplicationByAccessRequest,
} = require('../services/keystone/access-request');
+const {
+ lookupCredentialIssuerById,
+} = require('../services/keystone/credential-issuer');
+const {
+ doClientLoginForCredentialIssuer,
+} = require('../lists/extensions/Common');
+const { UMAResourceRegistrationService } = require('../services/uma2');
+const keystoneApi = require('../services/keystone');
+const { KeycloakPermissionTicketService } = require('../services/keycloak');
+const {
+ getSuitableOwnerToken,
+ getEnvironmentContext,
+ getResourceSets,
+ getNamespaceResourceSets,
+ isUserBasedResourceOwners,
+} = require('../lists/extensions/Common');
+const {
+ lookupProductEnvironmentServicesBySlug,
+} = require('../services/keystone');
module.exports = {
fields: {
@@ -110,9 +124,8 @@ module.exports = {
listKey,
fieldPath, // exists only for field hooks
}) {
- const noauthContext = context
- .createContext({ skipAccessControl: true })
- .sudo();
+ const noauthContext = context.createContext({ skipAccessControl: true });
+
await Apply(
noauthContext,
operation,
@@ -121,14 +134,60 @@ module.exports = {
updatedItem
);
- const accessRequest = await lookupEnvironmentAndApplicationByAccessRequest(
- noauthContext,
- updatedItem.id
- );
- console.log(
- 'This is Awesome Result Namespace: ' +
- accessRequest.productEnvironment.product.namespace
- );
+ if (operation == 'create') {
+ const accessRequest = await lookupEnvironmentAndApplicationByAccessRequest(
+ noauthContext,
+ updatedItem.id
+ );
+ console.log(
+ 'This is awesome namespace: ' +
+ accessRequest.productEnvironment.product.namespace
+ );
+ const productEnvironmentSlug = process.env.GWA_PROD_ENV_SLUG;
+
+ const prodEnv = await lookupProductEnvironmentServicesBySlug(
+ noauthContext,
+ productEnvironmentSlug
+ );
+ const envCtx = await getEnvironmentContext(context, prodEnv.id, '');
+
+ console.log('This is envCtx: ', JSON.stringify(envCtx));
+
+ const resourceIds = await getResourceSets(envCtx);
+ const resourcesApi = new UMAResourceRegistrationService(
+ envCtx.issuerEnvConfig.issuerUrl,
+ envCtx.accessToken
+ );
+ const namespaces = await resourcesApi.listResourcesByIdList(
+ resourceIds
+ );
+ const matched = namespaces
+ .filter(
+ (ns) =>
+ ns.name == accessRequest.productEnvironment.product.namespace
+ )
+ .map((ns) => ({
+ id: ns.id,
+ name: ns.name,
+ scopes: ns.resource_scopes,
+ prodEnvId: prodEnv.id,
+ }));
+ namespaceObj = matched[0];
+ console.log(
+ 'This is the same namespace: ' + JSON.stringify(namespaceObj)
+ );
+ const permissionApi = new KeycloakPermissionTicketService(
+ envCtx.issuerEnvConfig.issuerUrl,
+ envCtx.accessToken
+ );
+ const params = { resourceId: namespaceObj.id, returnNames: true };
+ const permissions = await permissionApi.listPermissions(params);
+ console.log('Permissions List: ' + JSON.stringify(permissions));
+ permissions.forEach((user) => {
+ console.log('User Name: ' + user.requesterName);
+ console.log('User Scopes: ' + user.scopeName);
+ });
+ }
},
},
};
From a799c988e5c87e1e05869283b44431b84507a6c9 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 18:55:58 -0700
Subject: [PATCH 092/155] upd build
---
.github/workflows/ci-build-deploy.yaml | 16 +++++++++++-
.../workflows/scripts/feeder-init/legal.yaml | 7 +++++
.../feeder-init/platform-authz-profile.yaml | 26 +++++++++++++++++++
.../scripts/feeder-init/platform-gwa-api.yaml | 14 ++++++++++
.github/workflows/scripts/init.sh | 23 ++++++++++++++++
.github/workflows/scripts/template.py | 8 ++++++
6 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 .github/workflows/scripts/feeder-init/legal.yaml
create mode 100644 .github/workflows/scripts/feeder-init/platform-authz-profile.yaml
create mode 100644 .github/workflows/scripts/feeder-init/platform-gwa-api.yaml
create mode 100755 .github/workflows/scripts/init.sh
create mode 100644 .github/workflows/scripts/template.py
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index ac8d44470..1c4b72ec3 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -65,6 +65,16 @@ jobs:
id: buildx
uses: docker/setup-buildx-action@v1
+ - name: 'Seed Data'
+ run: |
+ export PATH=$PATH:`pwd`/linux-amd64
+
+ PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
+ OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
+ OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
+ OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
+ .github/workflow/scripts/init.sh
+
- name: Build
uses: docker/build-push-action@v2
with:
@@ -214,8 +224,12 @@ jobs:
value: 'https://grafana-apps-gov-bc-ca.dev.api.gov.bc.ca'
GWA_API_URL:
value: 'https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca'
+ GWA_PROD_ENV_SLUG:
+ value: 'FB000000'
GWA_RES_SVR_CLIENT_ID:
- value: 'gwa-api'
+ value: '${{ secrets.OIDC_CLIENT_ID }}'
+ GWA_RES_SVR_CLIENT_SECRET:
+ value: '${{ secrets.OIDC_CLIENT_SECRET }}'
KEYCLOAK_AUTH_URL:
value: '${{ secrets.KEYCLOAK_AUTH }}'
KEYCLOAK_REALM:
diff --git a/.github/workflows/scripts/feeder-init/legal.yaml b/.github/workflows/scripts/feeder-init/legal.yaml
new file mode 100644
index 000000000..257fc7a0d
--- /dev/null
+++ b/.github/workflows/scripts/feeder-init/legal.yaml
@@ -0,0 +1,7 @@
+entity: Legal
+record:
+ id: "terms-of-use-for-api-gateway-1"
+ title: "Terms of Use for API Gateway"
+ link: "https://www2.gov.bc.ca/gov/content/data/open-data/api-terms-of-use-for-ogl-information"
+ document: terms-of-use
+ version: 1
diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
new file mode 100644
index 000000000..08f93b34d
--- /dev/null
+++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
@@ -0,0 +1,26 @@
+entity: CredentialIssuer
+record:
+ id: 'Gateway Services Resource Server'
+ namespace: platform
+ description: 'Authorization Profile for protecting the Gateway Services API'
+ flow: client-credentials
+ mode: auto
+ clientAuthenticator: client-secret
+ authPlugin: jwt-keycloak
+ clientRoles: []
+ availableScopes: []
+ resourceType: platform
+ resourceAccessScope: Namespace.Manage
+ resourceScopes:
+ - Namespace.Manage
+ - Namespace.View
+ - Access.Manage
+ - GatewayConfig.Publish
+ - Content.Publish
+ owner: awsummer@idir
+ environmentDetails:
+ - environment: prod
+ issuerUrl: '{OIDC_ISSUER}'
+ clientId: '{OIDC_CLIENT_ID}'
+ clientSecret: '{OIDC_CLIENT_SECRET}'
+ clientRegistration: managed
diff --git a/.github/workflows/scripts/feeder-init/platform-gwa-api.yaml b/.github/workflows/scripts/feeder-init/platform-gwa-api.yaml
new file mode 100644
index 000000000..c60cb50fd
--- /dev/null
+++ b/.github/workflows/scripts/feeder-init/platform-gwa-api.yaml
@@ -0,0 +1,14 @@
+entity: Product
+record:
+ id: 748D98F1F56C
+ name: Gateway Services API
+ namespace: platform
+ environments:
+ - id: FB000000
+ name: prod
+ active: true
+ approval: true
+ flow: client-credentials
+ legal: terms-of-use-for-api-gateway-1
+ services: []
+ credentialIssuer: 'Gateway Services Resource Server'
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
new file mode 100755
index 000000000..8338fca80
--- /dev/null
+++ b/.github/workflows/scripts/init.sh
@@ -0,0 +1,23 @@
+#/bin/bash
+
+python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml)
+python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
+python scripts/template.py scripts/feeder-init/platform-gwa-api.yaml platform-gwa-api.yaml
+
+while true; do
+ status=$(curl -o /dev/null -Isw '%{http_code}\n' ${PORTAL_URL}/health)
+ echo "$status"
+ if [[ "$status" == "200" ]]; then
+ echo "Portal is up"
+ kubectl port-forward service/${SERVICE} 8080:80 &
+ FWD_PID=$!
+ curl http://localhost:8080/push -F yaml=@legal.yaml
+ curl http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
+ curl http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
+ kill -9 $FWD_PID
+ break
+ else
+ echo "Waiting for Portal....."
+ sleep 1m
+ fi
+done
diff --git a/.github/workflows/scripts/template.py b/.github/workflows/scripts/template.py
new file mode 100644
index 000000000..048a1cb0a
--- /dev/null
+++ b/.github/workflows/scripts/template.py
@@ -0,0 +1,8 @@
+
+import sys
+import os
+
+t = open(sys.argv[1]).read().format(**os.environ)
+
+with open(sys.argv[2], 'w') as outfile:
+ outfile.write(t)
From fc1fe7683c6b9d87f00b5b90f79f4453286a4b4f Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 18:57:38 -0700
Subject: [PATCH 093/155] upd build
---
.github/workflows/ci-build-deploy.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 1c4b72ec3..07737db0c 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -69,11 +69,12 @@ jobs:
run: |
export PATH=$PATH:`pwd`/linux-amd64
+ ls -l
PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- .github/workflow/scripts/init.sh
+ .github/workflows/scripts/init.sh
- name: Build
uses: docker/build-push-action@v2
From 8f3e245e8ed0d2f2f89b9aa5530afaded1d7b12b Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 18:59:02 -0700
Subject: [PATCH 094/155] tweak init.sh
---
.github/workflows/ci-build-deploy.yaml | 8 ++++----
.github/workflows/scripts/init.sh | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 07737db0c..574644c10 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -61,10 +61,6 @@ jobs:
restore-keys: |
${{ runner.os }}-buildx-
- - name: Set up Docker Buildx
- id: buildx
- uses: docker/setup-buildx-action@v1
-
- name: 'Seed Data'
run: |
export PATH=$PATH:`pwd`/linux-amd64
@@ -76,6 +72,10 @@ jobs:
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
.github/workflows/scripts/init.sh
+ - name: Set up Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v1
+
- name: Build
uses: docker/build-push-action@v2
with:
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 8338fca80..16eca4cac 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -1,6 +1,6 @@
#/bin/bash
-python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml)
+python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml
python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
python scripts/template.py scripts/feeder-init/platform-gwa-api.yaml platform-gwa-api.yaml
From c692b5c8d5482998f4210e47d606e0c533348de3 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:00:01 -0700
Subject: [PATCH 095/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 574644c10..84788c57e 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -65,12 +65,12 @@ jobs:
run: |
export PATH=$PATH:`pwd`/linux-amd64
- ls -l
+
PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- .github/workflows/scripts/init.sh
+ (cd .github/workflows/scripts && ./init.sh)
- name: Set up Docker Buildx
id: buildx
From 788b7d17b7465c045cc5f54a6245b0218e366185 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:00:40 -0700
Subject: [PATCH 096/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 84788c57e..cb2596bb6 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -70,7 +70,7 @@ jobs:
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- (cd .github/workflows/scripts && ./init.sh)
+ (cd .github/workflows && ./init.sh)
- name: Set up Docker Buildx
id: buildx
From ce90b6d1e1bf314441596e1256833ecef6e4ee5b Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:01:10 -0700
Subject: [PATCH 097/155] tweak ghaction
---
.github/workflows/scripts/init.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 16eca4cac..7d900e5eb 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -1,4 +1,4 @@
-#/bin/bash
+#/bin/bash -e
python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml
python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
From 27aca9f145ae21b8dfa2b04e08d3bce3b15ab4f9 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:01:45 -0700
Subject: [PATCH 098/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index cb2596bb6..b8db816e8 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -70,7 +70,7 @@ jobs:
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- (cd .github/workflows && ./init.sh)
+ (cd .github/workflows && ./scripts/init.sh)
- name: Set up Docker Buildx
id: buildx
From fdb2f949552020361cfb75a9b324edcfc7a103f1 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:02:15 -0700
Subject: [PATCH 099/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index b8db816e8..5db546cc0 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -65,12 +65,12 @@ jobs:
run: |
export PATH=$PATH:`pwd`/linux-amd64
-
+ cd .github/workflows
PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- (cd .github/workflows && ./scripts/init.sh)
+ ./scripts/init.sh
- name: Set up Docker Buildx
id: buildx
From 0b1b31d42ab73d4cca847913c2fb42d161b60aa1 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:05:04 -0700
Subject: [PATCH 100/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 1 +
.github/workflows/scripts/init.sh | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 5db546cc0..178dbba5b 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -66,6 +66,7 @@ jobs:
export PATH=$PATH:`pwd`/linux-amd64
cd .github/workflows
+ SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-generic-api \
PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 7d900e5eb..118bcbe61 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -1,4 +1,4 @@
-#/bin/bash -e
+#/bin/bash -e +x
python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml
python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
@@ -11,9 +11,9 @@ while true; do
echo "Portal is up"
kubectl port-forward service/${SERVICE} 8080:80 &
FWD_PID=$!
- curl http://localhost:8080/push -F yaml=@legal.yaml
- curl http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
- curl http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
+ curl --fail http://localhost:8080/push -F yaml=@legal.yaml
+ curl --fail http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
+ curl --fail http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
kill -9 $FWD_PID
break
else
From 2220603c52f4f7cefdaa710112bafcf7eb7d0232 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:06:26 -0700
Subject: [PATCH 101/155] tweak ghaction
---
.github/workflows/scripts/init.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 118bcbe61..4a7356abc 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -1,4 +1,4 @@
-#/bin/bash -e +x
+#/bin/bash +e -x
python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml
python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
From 68d1fa82406dfbccd2a906e9ce3384ae286e4560 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:08:06 -0700
Subject: [PATCH 102/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 178dbba5b..554965b11 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -64,6 +64,7 @@ jobs:
- name: 'Seed Data'
run: |
export PATH=$PATH:`pwd`/linux-amd64
+ kubectl get pods
cd .github/workflows
SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-generic-api \
From ebe598eb5a86d4e77a4afad9e7989fdb0b3eb79a Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:09:35 -0700
Subject: [PATCH 103/155] tweak ghaction
---
.github/workflows/scripts/init.sh | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 4a7356abc..3bf680ee5 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -1,4 +1,4 @@
-#/bin/bash +e -x
+#/bin/bash -e -x
python scripts/template.py scripts/feeder-init/legal.yaml legal.yaml
python scripts/template.py scripts/feeder-init/platform-authz-profile.yaml platform-authz-profile.yaml
@@ -11,6 +11,7 @@ while true; do
echo "Portal is up"
kubectl port-forward service/${SERVICE} 8080:80 &
FWD_PID=$!
+ echo "Port forwarded ${SERVICE} with $FWD_PID"
curl --fail http://localhost:8080/push -F yaml=@legal.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
From 07e74146822e28193bb0656f7813614cc1815148 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:14:28 -0700
Subject: [PATCH 104/155] tweak ghaction
---
.github/workflows/nohup.out | 9 +++++++++
.github/workflows/scripts/init.sh | 4 ++--
2 files changed, 11 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/nohup.out
diff --git a/.github/workflows/nohup.out b/.github/workflows/nohup.out
new file mode 100644
index 000000000..80caff80f
--- /dev/null
+++ b/.github/workflows/nohup.out
@@ -0,0 +1,9 @@
+error: You must be logged in to the server (Unauthorized)
+error: You must be logged in to the server (Unauthorized)
+error: You must be logged in to the server (Unauthorized)
+Forwarding from 127.0.0.1:8080 -> 6000
+Forwarding from [::1]:8080 -> 6000
+Forwarding from 127.0.0.1:8080 -> 6000
+Forwarding from [::1]:8080 -> 6000
+Forwarding from 127.0.0.1:8080 -> 6000
+Forwarding from [::1]:8080 -> 6000
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 3bf680ee5..2b1f22225 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -9,13 +9,13 @@ while true; do
echo "$status"
if [[ "$status" == "200" ]]; then
echo "Portal is up"
- kubectl port-forward service/${SERVICE} 8080:80 &
+ nohup kubectl port-forward service/${SERVICE} 8080:80 &
FWD_PID=$!
echo "Port forwarded ${SERVICE} with $FWD_PID"
curl --fail http://localhost:8080/push -F yaml=@legal.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
- kill -9 $FWD_PID
+ kill $FWD_PID
break
else
echo "Waiting for Portal....."
From c845d72bf46fc1c058dba17349b9fb9759844e30 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:15:39 -0700
Subject: [PATCH 105/155] tweak ghaction
---
.github/workflows/scripts/init.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index 2b1f22225..c0898f5b2 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -12,6 +12,7 @@ while true; do
nohup kubectl port-forward service/${SERVICE} 8080:80 &
FWD_PID=$!
echo "Port forwarded ${SERVICE} with $FWD_PID"
+ sleep 5
curl --fail http://localhost:8080/push -F yaml=@legal.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
curl --fail http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
From 784670f04c26379653aad304e823f3336b7a1962 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:17:54 -0700
Subject: [PATCH 106/155] tweak ghaction
---
.../workflows/scripts/feeder-init/platform-authz-profile.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
index 08f93b34d..d488b2501 100644
--- a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
+++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
@@ -17,7 +17,7 @@ record:
- Access.Manage
- GatewayConfig.Publish
- Content.Publish
- owner: awsummer@idir
+ owner: acope@idir
environmentDetails:
- environment: prod
issuerUrl: '{OIDC_ISSUER}'
From 2e9e1c9fd4d9ddcdc95849129dc1237ee502449a Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:23:05 -0700
Subject: [PATCH 107/155] tweak ghaction
---
.github/workflows/scripts/init.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/scripts/init.sh b/.github/workflows/scripts/init.sh
index c0898f5b2..dd0f941b7 100755
--- a/.github/workflows/scripts/init.sh
+++ b/.github/workflows/scripts/init.sh
@@ -13,9 +13,9 @@ while true; do
FWD_PID=$!
echo "Port forwarded ${SERVICE} with $FWD_PID"
sleep 5
- curl --fail http://localhost:8080/push -F yaml=@legal.yaml
- curl --fail http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
- curl --fail http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
+ curl --fail -v http://localhost:8080/push -F yaml=@legal.yaml
+ curl --fail -v http://localhost:8080/push -F yaml=@platform-authz-profile.yaml
+ curl --fail -v http://localhost:8080/push -F yaml=@platform-gwa-api.yaml
kill $FWD_PID
break
else
From 843918fdc147e8cb558244d6249c0703370fce05 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:26:20 -0700
Subject: [PATCH 108/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 554965b11..6959aabf9 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -67,7 +67,7 @@ jobs:
kubectl get pods
cd .github/workflows
- SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-generic-api \
+ SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-feeder-generic-api \
PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
From 75c6052dc745b7aeb371f74c3e36f6602ecda1cb Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:26:27 -0700
Subject: [PATCH 109/155] tweak ghaction
---
.github/workflows/ci-build-deploy.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 6959aabf9..166d3f2a4 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -64,7 +64,6 @@ jobs:
- name: 'Seed Data'
run: |
export PATH=$PATH:`pwd`/linux-amd64
- kubectl get pods
cd .github/workflows
SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-feeder-generic-api \
From c2be320b190b6a727d37fccc25912f6701561b1b Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:38:59 -0700
Subject: [PATCH 110/155] tweak ghaction
---
.../workflows/scripts/feeder-init/platform-authz-profile.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
index d488b2501..8f8028dd2 100644
--- a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
+++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
@@ -17,7 +17,7 @@ record:
- Access.Manage
- GatewayConfig.Publish
- Content.Publish
- owner: acope@idir
+ owner: user_api-owner
environmentDetails:
- environment: prod
issuerUrl: '{OIDC_ISSUER}'
From 2d71ec419eb58050cfd686e1b0f48dbf4f6dcf6f Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:51:46 -0700
Subject: [PATCH 111/155] fix clientId
---
src/services/workflow/generate-credential.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/services/workflow/generate-credential.ts b/src/services/workflow/generate-credential.ts
index 4af40ff43..ed2a059fb 100644
--- a/src/services/workflow/generate-credential.ts
+++ b/src/services/workflow/generate-credential.ts
@@ -46,7 +46,6 @@ export const generateCredential = async (
requestDetails.application.id
);
- //const extraIdentifier = uuidv4().replace(/-/g,'').toUpperCase().substr(0, 8)
const clientId = productEnvironment.appId + '-' + application.appId;
const nickname = clientId;
@@ -100,8 +99,7 @@ export const generateCredential = async (
requestDetails.application.id
);
- //const extraIdentifier = uuidv4().replace(/-/g,'').toUpperCase().substr(0, 8)
- const clientId = application.appId + '-' + productEnvironment.appId;
+ const clientId = productEnvironment.appId + '-' + application.appId;
const nickname = clientId;
From 72aaf7f89afd5aac261dcf0aac93d03df9e12331 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:52:22 -0700
Subject: [PATCH 112/155] upd init
---
.github/workflows/ci-build-deploy.yaml | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index 166d3f2a4..ce4eaf47c 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -61,18 +61,6 @@ jobs:
restore-keys: |
${{ runner.os }}-buildx-
- - name: 'Seed Data'
- run: |
- export PATH=$PATH:`pwd`/linux-amd64
-
- cd .github/workflows
- SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-feeder-generic-api \
- PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
- OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
- OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
- OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
- ./scripts/init.sh
-
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
@@ -266,3 +254,15 @@ jobs:
" > values.yaml
helm repo add bcgov http://bcgov.github.io/helm-charts
helm upgrade --install proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-routes -f values.yaml bcgov/ocp-route
+
+ - name: 'Seed Data'
+ run: |
+ export PATH=$PATH:`pwd`/linux-amd64
+
+ cd .github/workflows
+ SERVICE=proto-asp-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}-feeder-generic-api \
+ PORTAL_URL=https://api-services-portal-${{ steps.set-deploy-id.outputs.DEPLOY_ID }}.apps.silver.devops.gov.bc.ca \
+ OIDC_ISSUER=${{ secrets.OIDC_ISSUER }} \
+ OIDC_CLIENT_ID=${{ secrets.OIDC_CLIENT_ID }} \
+ OIDC_CLIENT_SECRET=${{ secrets.OIDC_CLIENT_SECRET }} \
+ ./scripts/init.sh
From db222f255a4ad90aadcd446c66303859b62ed389 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 19:59:54 -0700
Subject: [PATCH 113/155] try exact username match
---
src/services/keycloak/user-service.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts
index b914e115d..ba86bb5c3 100644
--- a/src/services/keycloak/user-service.ts
+++ b/src/services/keycloak/user-service.ts
@@ -17,7 +17,10 @@ export class KeycloakUserService {
public async lookupUserByUsername(username: string) {
logger.debug('[lookupUserByUsername] %s', username);
- const users = await this.kcAdminClient.users.find({ username: username });
+ const users = await this.kcAdminClient.users.find({
+ exact: true,
+ username: username,
+ });
logger.debug('[lookupUserByUsername] : %j', users);
assert.strictEqual(users.length, 1, 'User not found ' + username);
return users[0].id;
From 8d62d23a3420007948311de6e7a336d6f2acad6a Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 20:18:15 -0700
Subject: [PATCH 114/155] remove irrelevant files
---
.github/workflows/ci-build-deploy.yaml | 2 +-
.github/workflows/nohup.out | 9 ---------
.../scripts/feeder-init/platform-authz-profile.yaml | 1 +
3 files changed, 2 insertions(+), 10 deletions(-)
delete mode 100644 .github/workflows/nohup.out
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index ce4eaf47c..df9604fd7 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -232,7 +232,7 @@ jobs:
command:
- sh
- -c
- - 'state=$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".loading | ascii_downcase\"); if [ \"$loading\" == \"true\" ]; then exit 1; fi'
+ - 'state=$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".loading | ascii_downcase\"); if [ ! \"$status\" == \"ready\" ]; then exit 1; fi'
" > values.yaml
diff --git a/.github/workflows/nohup.out b/.github/workflows/nohup.out
deleted file mode 100644
index 80caff80f..000000000
--- a/.github/workflows/nohup.out
+++ /dev/null
@@ -1,9 +0,0 @@
-error: You must be logged in to the server (Unauthorized)
-error: You must be logged in to the server (Unauthorized)
-error: You must be logged in to the server (Unauthorized)
-Forwarding from 127.0.0.1:8080 -> 6000
-Forwarding from [::1]:8080 -> 6000
-Forwarding from 127.0.0.1:8080 -> 6000
-Forwarding from [::1]:8080 -> 6000
-Forwarding from 127.0.0.1:8080 -> 6000
-Forwarding from [::1]:8080 -> 6000
diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
index 8f8028dd2..4ab0acbd7 100644
--- a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
+++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
@@ -17,6 +17,7 @@ record:
- Access.Manage
- GatewayConfig.Publish
- Content.Publish
+ - CredentialIssuer.Admin
owner: user_api-owner
environmentDetails:
- environment: prod
From e6baf29d3c9962baf6e0cf8a0786df06e83766c2 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Thu, 5 Aug 2021 20:18:57 -0700
Subject: [PATCH 115/155] remove irrelevant files
---
.../workflows/scripts/feeder-init/platform-authz-profile.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
index 4ab0acbd7..db6272aff 100644
--- a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
+++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml
@@ -8,7 +8,7 @@ record:
clientAuthenticator: client-secret
authPlugin: jwt-keycloak
clientRoles: []
- availableScopes: []
+ availableScopes: [Sample.*]
resourceType: platform
resourceAccessScope: Namespace.Manage
resourceScopes:
From 180e7bbcf3585af0c6a8324eda82f2303eaf5bad Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Fri, 6 Aug 2021 11:19:54 -0700
Subject: [PATCH 116/155] Update ci-build-deploy.yaml
---
.github/workflows/ci-build-deploy.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index df9604fd7..db58bdbfe 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -232,7 +232,7 @@ jobs:
command:
- sh
- -c
- - 'state=$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".loading | ascii_downcase\"); if [ ! \"$status\" == \"ready\" ]; then exit 1; fi'
+ - 'state=$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".status | ascii_downcase\"); if [ ! \"$state\" == \"ready\" ]; then exit 1; fi'
" > values.yaml
From 933439ec6bf6c4b77041a4fc197371d13bf40a53 Mon Sep 17 00:00:00 2001
From: ikethecoder
Date: Fri, 6 Aug 2021 11:47:19 -0700
Subject: [PATCH 117/155] Update ci-build-deploy.yaml
---
.github/workflows/ci-build-deploy.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index db58bdbfe..ae87a9cdd 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -232,7 +232,7 @@ jobs:
command:
- sh
- -c
- - 'state=$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".status | ascii_downcase\"); if [ ! \"$state\" == \"ready\" ]; then exit 1; fi'
+ - 'state=\$(curl -XGET -m 2 --silent -f -H \"Accept: application/json\" http://localhost:3000/health | jq -r \".status | ascii_downcase\"); if [ ! \"\$state\" == \"ready\" ]; then exit 1; fi'
" > values.yaml
From 4f8a431e8820a58e4730878da010a1b7d4c266a5 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 6 Aug 2021 13:25:52 -0700
Subject: [PATCH 118/155] created a custom query to fetch user details by
username
---
src/lists/AccessRequest.js | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index e51d00b67..eb3469b22 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -30,6 +30,8 @@ const {
lookupProductEnvironmentServicesBySlug,
} = require('../services/keystone');
+const KeystoneService = require('../services/keystone');
+
module.exports = {
fields: {
name: {
@@ -183,9 +185,28 @@ module.exports = {
const params = { resourceId: namespaceObj.id, returnNames: true };
const permissions = await permissionApi.listPermissions(params);
console.log('Permissions List: ' + JSON.stringify(permissions));
- permissions.forEach((user) => {
+ permissions.forEach(async (user) => {
console.log('User Name: ' + user.requesterName);
console.log('User Scopes: ' + user.scopeName);
+ const userResult = await noauthContext.executeGraphQL({
+ query: `query GetUserWithUsername($username: String!) {
+ allUsers(where: {username: $username}) {
+ id
+ name
+ username
+ email
+ }
+ }`,
+ variables: { username: user.requesterName },
+ });
+
+ console.log(
+ 'User object errors: ' + JSON.stringify(userResult.errors)
+ );
+ console.log(
+ 'This is the user object: ' +
+ JSON.stringify(userResult.data.allUsers)
+ );
});
}
},
From 0fe87aa09e86a58cef19c396746c473bf7b52a93 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Fri, 6 Aug 2021 16:15:46 -0700
Subject: [PATCH 119/155] Added config to test the email notifications
---
.github/workflows/ci-build-deploy.yaml | 6 +
src/lists/AccessRequest.js | 50 ++++---
src/services/keystone/index.ts | 7 +-
src/services/keystone/user.ts | 103 ++++++++++-----
.../notification/notification.service.ts | 125 +++++++++---------
5 files changed, 174 insertions(+), 117 deletions(-)
diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml
index ac8d44470..1f9aea118 100644
--- a/.github/workflows/ci-build-deploy.yaml
+++ b/.github/workflows/ci-build-deploy.yaml
@@ -222,6 +222,12 @@ jobs:
value: '${{ secrets.KEYCLOAK_REALM }}'
COOKIE_SECURE:
value: 'true'
+ EMAIL_ENABLED:
+ value: 'true'
+ EMAIL_FROM:
+ value: 'API.Services.Portal@gov.bc.ca'
+ EMAIL_HOST:
+ value: 'apps.smtp.gov.bc.ca'
readinessProbe:
exec:
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index eb3469b22..ba21872ad 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -28,6 +28,7 @@ const {
} = require('../lists/extensions/Common');
const {
lookupProductEnvironmentServicesBySlug,
+ lookupUserByUsername,
} = require('../services/keystone');
const KeystoneService = require('../services/keystone');
@@ -185,28 +186,35 @@ module.exports = {
const params = { resourceId: namespaceObj.id, returnNames: true };
const permissions = await permissionApi.listPermissions(params);
console.log('Permissions List: ' + JSON.stringify(permissions));
- permissions.forEach(async (user) => {
- console.log('User Name: ' + user.requesterName);
- console.log('User Scopes: ' + user.scopeName);
- const userResult = await noauthContext.executeGraphQL({
- query: `query GetUserWithUsername($username: String!) {
- allUsers(where: {username: $username}) {
- id
- name
- username
- email
- }
- }`,
- variables: { username: user.requesterName },
- });
-
- console.log(
- 'User object errors: ' + JSON.stringify(userResult.errors)
- );
- console.log(
- 'This is the user object: ' +
- JSON.stringify(userResult.data.allUsers)
+ const {
+ NotificationService,
+ } = require('../services/notification/notification.service');
+ const NotifyConfig = {
+ enabled: true,
+ secure: true,
+ from: process.env.EMAIL_FROM || '',
+ host: process.env.EMAIL_HOST || '',
+ port: process.env.EMAIL_PORT || 25,
+ user: process.env.EMAIL_USER || '',
+ pass: process.env.EMAIL_PASS || '',
+ };
+ const nc = new NotificationService(NotifyConfig);
+ permissions.forEach(async (perm) => {
+ const userDetails = await lookupUserByUsername(
+ context,
+ perm.requesterName
);
+ nc.notify(
+ { email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
+ { template: 'email-template', subject: 'Yeah!' }
+ )
+ .then((answer) => {
+ console.log('DONE!');
+ console.log('ANSWER = ' + JSON.stringify(answer));
+ })
+ .catch((err) => {
+ console.log('ERROR ! ' + err);
+ });
});
}
},
diff --git a/src/services/keystone/index.ts b/src/services/keystone/index.ts
index 88b6608ab..6f9dcf38b 100644
--- a/src/services/keystone/index.ts
+++ b/src/services/keystone/index.ts
@@ -39,4 +39,9 @@ export {
markActiveTheServiceAccess,
} from './service-access';
-export { lookupUserLegals, updateUserLegalAccept, LegalAgreed } from './user';
+export {
+ lookupUserLegals,
+ updateUserLegalAccept,
+ LegalAgreed,
+ lookupUserByUsername,
+} from './user';
diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts
index ac6529471..4ba0e27d2 100644
--- a/src/services/keystone/user.ts
+++ b/src/services/keystone/user.ts
@@ -1,53 +1,88 @@
-import { Logger } from "../../logger"
-import { User } from "./types"
+import { Logger } from '../../logger';
+import { User } from './types';
const assert = require('assert').strict;
-const logger = Logger('keystone.user')
+const logger = Logger('keystone.user');
export interface LegalAgreed {
- reference: string,
- agreedTimestamp: string
+ reference: string;
+ agreedTimestamp: string;
}
-export async function lookupUserLegals (context: any, id: string) : Promise {
- const result = await context.executeGraphQL({
- query: `query GetUser($id: ID!) {
+export async function lookupUserLegals(
+ context: any,
+ id: string
+): Promise {
+ const result = await context.executeGraphQL({
+ query: `query GetUser($id: ID!) {
User(where: {id: $id}) {
legalsAgreed
}
}`,
- variables: { id: id },
- })
- logger.debug("Query [lookupUserLegals] result %j", result)
- assert.strictEqual(result.data.User != null, true, "User not found")
- result.data.User.legalsAgreed == null && (result.data.User.legalsAgreed = '[]')
- return JSON.parse(result.data.User.legalsAgreed)
+ variables: { id: id },
+ });
+ logger.debug('Query [lookupUserLegals] result %j', result);
+ assert.strictEqual(result.data.User != null, true, 'User not found');
+ result.data.User.legalsAgreed == null &&
+ (result.data.User.legalsAgreed = '[]');
+ return JSON.parse(result.data.User.legalsAgreed);
}
-export async function updateUserLegalAccept (context: any, userId: string, legalReference: string) : Promise {
-
- const legalsAgreed : LegalAgreed[] = await lookupUserLegals (context, userId)
+export async function updateUserLegalAccept(
+ context: any,
+ userId: string,
+ legalReference: string
+): Promise {
+ const legalsAgreed: LegalAgreed[] = await lookupUserLegals(context, userId);
- if (legalsAgreed.filter(ag => ag.reference === legalReference).length == 0) {
- legalsAgreed.push({
- reference: legalReference,
- agreedTimestamp: new Date().toISOString()
- })
- const result = await context.executeGraphQL({
- query: `mutation UpdateUserWithLegalAccept($userId: ID!, $legalsAgreed: String!) {
+ if (
+ legalsAgreed.filter((ag) => ag.reference === legalReference).length == 0
+ ) {
+ legalsAgreed.push({
+ reference: legalReference,
+ agreedTimestamp: new Date().toISOString(),
+ });
+ const result = await context.executeGraphQL({
+ query: `mutation UpdateUserWithLegalAccept($userId: ID!, $legalsAgreed: String!) {
updateUser(id: $userId, data: { legalsAgreed: $legalsAgreed } ) {
legalsAgreed
}
}`,
- variables: { userId, legalsAgreed: JSON.stringify(legalsAgreed) },
- })
- logger.debug("[updateUserLegalAccept] RESULT %j", result)
- assert.strictEqual(result.data.updateUser != null, true, "Failed to update legal terms for user")
- return JSON.parse(result.data.updateUser.legalsAgreed)
- } else {
- logger.warn("[updateUserLegalAccept] User '%s' already agreed to '%s' terms", userId, legalReference)
- return legalsAgreed
- }
+ variables: { userId, legalsAgreed: JSON.stringify(legalsAgreed) },
+ });
+ logger.debug('[updateUserLegalAccept] RESULT %j', result);
+ assert.strictEqual(
+ result.data.updateUser != null,
+ true,
+ 'Failed to update legal terms for user'
+ );
+ return JSON.parse(result.data.updateUser.legalsAgreed);
+ } else {
+ logger.warn(
+ "[updateUserLegalAccept] User '%s' already agreed to '%s' terms",
+ userId,
+ legalReference
+ );
+ return legalsAgreed;
+ }
}
-
+export async function lookupUserByUsername(
+ context: any,
+ username: string
+): Promise {
+ const result = await context.executeGraphQL({
+ query: `query GetUserWithUsername($username: String!) {
+ allUsers(where: {username: $username}) {
+ id
+ name
+ username
+ email
+ }
+ }`,
+ variables: { username: username },
+ });
+ logger.debug('Query [lookupUserByUsername] result %j', result);
+ assert.strictEqual(result.data.allUsers.length, 1, 'UserNotFound');
+ return result.data.allUsers;
+}
diff --git a/src/services/notification/notification.service.ts b/src/services/notification/notification.service.ts
index 79fc7d063..99c34f56e 100644
--- a/src/services/notification/notification.service.ts
+++ b/src/services/notification/notification.service.ts
@@ -1,74 +1,77 @@
-import fs from 'fs'
-import path from 'path'
+import fs from 'fs';
+import path from 'path';
-import nodemailer from 'nodemailer'
+import nodemailer from 'nodemailer';
-import { Logger } from '../../logger'
+import { Logger } from '../../logger';
-import { NotificationConfig, EmailNotification, User } from './config'
+import { NotificationConfig, EmailNotification, User } from './config';
-import { ConfigService } from '../bceid/config.service'
+import { ConfigService } from '../bceid/config.service';
export class NotificationService {
- private notifyConfig: NotificationConfig;
- constructor(private readonly config: ConfigService) {
- this.notifyConfig = this.config.getConfig().notification;
+ private notifyConfig: NotificationConfig;
+ constructor(private readonly config: NotificationConfig) {
+ this.notifyConfig = this.config;
+ }
+
+ private templateToContent(to: User, templateName: string) {
+ const template = fs.readFileSync(
+ path.resolve(__dirname, `templates/${templateName}.html`),
+ 'utf8'
+ );
+ return template.replace('{{name}}', to.name);
+ }
+
+ public async notify(user: User, email: EmailNotification) {
+ if (!this.notifyConfig.enabled) {
+ return;
}
- private templateToContent (to: User, templateName: string) {
- const template = fs.readFileSync(path.resolve(__dirname, `templates/${templateName}.html`), 'utf8');
- return template.replace("{{name}}", to.name);
+ this.logger.verbose('Notification triggered', user);
+
+ //we don't notify the active user at all as they made the change
+ var emailContent = this.templateToContent(user, email.template);
+
+ var transportOpts = {
+ host: this.notifyConfig.host,
+ port: this.notifyConfig.port,
+ secure: this.notifyConfig.secure,
+ tls: { rejectUnauthorized: true },
+ auth: { user: null as any, pass: null as any },
+ };
+
+ if (!this.notifyConfig.secure) {
+ transportOpts['tls'] = {
+ rejectUnauthorized: false,
+ };
}
- public async notify (user: User, email: EmailNotification) {
- if (!this.notifyConfig.enabled){
- return;
- }
-
- this.logger.verbose("Notification triggered", user);
-
- //we don't notify the active user at all as they made the change
- var emailContent = this.templateToContent(user, email.template);
-
- var transportOpts = {
- host: this.notifyConfig.host,
- port: this.notifyConfig.port,
- secure: this.notifyConfig.secure,
- tls: { rejectUnauthorized: true },
- auth: { user: null as any, pass: null as any }
- }
-
- if (!this.notifyConfig.secure){
- transportOpts['tls'] = {
- rejectUnauthorized: false
- }
- }
-
- if ( (this.notifyConfig.user !== "") && (this.notifyConfig.pass !== "") ){
- transportOpts['auth'] = {
- user: this.notifyConfig.user,
- pass: this.notifyConfig.pass
- }
- }
-
- var transporter = nodemailer.createTransport(transportOpts);
-
- var mailOptions = {
- from: this.notifyConfig.from,
- to: user.email,
- subject: email.subject,
- html: emailContent
- };
-
- return transporter.sendMail(mailOptions)
- // , function (error : any, info : any) {
- // if (error) {
- // this.logger.error("Error sending email to " + mailOptions.to, error);
- // return;
- // }
- // this.logger.debug("Email sent: " + info.response);
- // })
+ if (this.notifyConfig.user !== '' && this.notifyConfig.pass !== '') {
+ transportOpts['auth'] = {
+ user: this.notifyConfig.user,
+ pass: this.notifyConfig.pass,
+ };
}
- logger = Logger('notification.service')
+ var transporter = nodemailer.createTransport(transportOpts);
+
+ var mailOptions = {
+ from: this.notifyConfig.from,
+ to: user.email,
+ subject: email.subject,
+ html: emailContent,
+ };
+
+ return transporter.sendMail(mailOptions);
+ // , function (error : any, info : any) {
+ // if (error) {
+ // this.logger.error("Error sending email to " + mailOptions.to, error);
+ // return;
+ // }
+ // this.logger.debug("Email sent: " + info.response);
+ // })
+ }
+
+ logger = Logger('notification.service');
}
From adf3c9f7f042323c586f2d8c3967a494f5de7dad Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sat, 7 Aug 2021 08:53:59 -0700
Subject: [PATCH 120/155] updated the notification service constructor
definition to use config service and cleaned up access request list
---
src/lists/AccessRequest.js | 31 ++++---------------
.../notification/notification.service.ts | 4 +--
2 files changed, 8 insertions(+), 27 deletions(-)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index ba21872ad..c3ac659e3 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -10,28 +10,21 @@ const { Apply, Validate } = require('../services/workflow');
const {
lookupEnvironmentAndApplicationByAccessRequest,
} = require('../services/keystone/access-request');
-const {
- lookupCredentialIssuerById,
-} = require('../services/keystone/credential-issuer');
-const {
- doClientLoginForCredentialIssuer,
-} = require('../lists/extensions/Common');
const { UMAResourceRegistrationService } = require('../services/uma2');
-const keystoneApi = require('../services/keystone');
const { KeycloakPermissionTicketService } = require('../services/keycloak');
const {
- getSuitableOwnerToken,
getEnvironmentContext,
getResourceSets,
- getNamespaceResourceSets,
- isUserBasedResourceOwners,
} = require('../lists/extensions/Common');
const {
lookupProductEnvironmentServicesBySlug,
lookupUserByUsername,
} = require('../services/keystone');
-const KeystoneService = require('../services/keystone');
+const { ConfigService } = require('../services/bceid/config.service');
+const {
+ NotificationService,
+} = require('../services/notification/notification.service');
module.exports = {
fields: {
@@ -186,22 +179,10 @@ module.exports = {
const params = { resourceId: namespaceObj.id, returnNames: true };
const permissions = await permissionApi.listPermissions(params);
console.log('Permissions List: ' + JSON.stringify(permissions));
- const {
- NotificationService,
- } = require('../services/notification/notification.service');
- const NotifyConfig = {
- enabled: true,
- secure: true,
- from: process.env.EMAIL_FROM || '',
- host: process.env.EMAIL_HOST || '',
- port: process.env.EMAIL_PORT || 25,
- user: process.env.EMAIL_USER || '',
- pass: process.env.EMAIL_PASS || '',
- };
- const nc = new NotificationService(NotifyConfig);
+ const nc = new NotificationService(new ConfigService());
permissions.forEach(async (perm) => {
const userDetails = await lookupUserByUsername(
- context,
+ noauthContext,
perm.requesterName
);
nc.notify(
diff --git a/src/services/notification/notification.service.ts b/src/services/notification/notification.service.ts
index 99c34f56e..a9e8df72f 100644
--- a/src/services/notification/notification.service.ts
+++ b/src/services/notification/notification.service.ts
@@ -11,8 +11,8 @@ import { ConfigService } from '../bceid/config.service';
export class NotificationService {
private notifyConfig: NotificationConfig;
- constructor(private readonly config: NotificationConfig) {
- this.notifyConfig = this.config;
+ constructor(private readonly config: ConfigService) {
+ this.notifyConfig = this.config.getConfig().notification;
}
private templateToContent(to: User, templateName: string) {
From aab190d6be8934eb963d33dad0d4893d43120cd2 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sun, 8 Aug 2021 22:21:50 -0700
Subject: [PATCH 121/155] moved config service out of bcied to use it as common
code and created an custom query to fetch users by namespace for sending
notifications
---
src/lists/AccessRequest.js | 87 ++++++----------
src/lists/extensions/BusinessProfile.ts | 2 +-
src/lists/extensions/Namespace.ts | 99 ++++++++++++++++++-
src/nextapp/shared/types/query.types.ts | 14 +++
src/services/bceid/bceid.service.ts | 2 +-
src/services/{bceid => }/config.service.ts | 16 +--
src/services/keystone/types.ts | 14 +++
src/services/keystone/user.ts | 2 +-
.../notification/notification.service.ts | 2 +-
src/tsconfig.json | 56 ++++-------
10 files changed, 187 insertions(+), 107 deletions(-)
rename src/services/{bceid => }/config.service.ts (83%)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index c3ac659e3..8a9f368b4 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -21,7 +21,7 @@ const {
lookupUserByUsername,
} = require('../services/keystone');
-const { ConfigService } = require('../services/bceid/config.service');
+const { ConfigService } = require('../services/config.service');
const {
NotificationService,
} = require('../services/notification/notification.service');
@@ -139,65 +139,36 @@ module.exports = {
'This is awesome namespace: ' +
accessRequest.productEnvironment.product.namespace
);
- const productEnvironmentSlug = process.env.GWA_PROD_ENV_SLUG;
-
- const prodEnv = await lookupProductEnvironmentServicesBySlug(
- noauthContext,
- productEnvironmentSlug
- );
- const envCtx = await getEnvironmentContext(context, prodEnv.id, '');
-
- console.log('This is envCtx: ', JSON.stringify(envCtx));
-
- const resourceIds = await getResourceSets(envCtx);
- const resourcesApi = new UMAResourceRegistrationService(
- envCtx.issuerEnvConfig.issuerUrl,
- envCtx.accessToken
- );
- const namespaces = await resourcesApi.listResourcesByIdList(
- resourceIds
- );
- const matched = namespaces
- .filter(
- (ns) =>
- ns.name == accessRequest.productEnvironment.product.namespace
- )
- .map((ns) => ({
- id: ns.id,
- name: ns.name,
- scopes: ns.resource_scopes,
- prodEnvId: prodEnv.id,
- }));
- namespaceObj = matched[0];
- console.log(
- 'This is the same namespace: ' + JSON.stringify(namespaceObj)
- );
- const permissionApi = new KeycloakPermissionTicketService(
- envCtx.issuerEnvConfig.issuerUrl,
- envCtx.accessToken
- );
- const params = { resourceId: namespaceObj.id, returnNames: true };
- const permissions = await permissionApi.listPermissions(params);
- console.log('Permissions List: ' + JSON.stringify(permissions));
- const nc = new NotificationService(new ConfigService());
- permissions.forEach(async (perm) => {
- const userDetails = await lookupUserByUsername(
- noauthContext,
- perm.requesterName
- );
- nc.notify(
- { email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
- { template: 'email-template', subject: 'Yeah!' }
- )
- .then((answer) => {
- console.log('DONE!');
- console.log('ANSWER = ' + JSON.stringify(answer));
- })
- .catch((err) => {
- console.log('ERROR ! ' + err);
- });
+ const userContactList = await noauthContext.executeGraphQL({
+ query: `query ListUsersByNamespace($namespace: String!) {
+ usersByNamespace(namespace: $namespace) {
+ id
+ name
+ username
+ email
+ }
+ }`,
+ variables: {
+ namespace: accessRequest.productEnvironment.product.namespace,
+ },
});
+ console.log('userContactList: ' + JSON.stringify(userContactList));
}
+ const nc = new NotificationService(new ConfigService());
+ userContactList.data.usersByNamespace.forEach((contact) => {
+ nc.notify(
+ { email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
+ { template: 'email-template', subject: 'Yeah!' }
+ )
+ .then((info) => {
+ console.log(
+ `[SUCCESS][${info}] Notification sent to ${contact.email}`
+ );
+ })
+ .catch((err) => {
+ console.log('[ERROR] Sending notification failed!' + err);
+ });
+ });
},
},
};
diff --git a/src/lists/extensions/BusinessProfile.ts b/src/lists/extensions/BusinessProfile.ts
index 7553dcd66..9750fca56 100644
--- a/src/lists/extensions/BusinessProfile.ts
+++ b/src/lists/extensions/BusinessProfile.ts
@@ -2,7 +2,7 @@ import { EnforcementPoint } from '../../authz/enforcement';
import { lookupCredentialReferenceByServiceAccess } from '../../services/keystone';
-import { ConfigService } from '../../services/bceid/config.service';
+import { ConfigService } from '../../services/config.service';
import { BCeIDService } from '../../services/bceid/bceid.service';
const typeBusinessProfile = `
diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts
index 3c024e3fc..a9ea85559 100644
--- a/src/lists/extensions/Namespace.ts
+++ b/src/lists/extensions/Namespace.ts
@@ -6,13 +6,17 @@ import {
ResourceSet,
ResourceSetInput,
} from '../../services/uma2';
-import { lookupProductEnvironmentServicesBySlug } from '../../services/keystone';
+import {
+ lookupProductEnvironmentServicesBySlug,
+ lookupUserByUsername,
+} from '../../services/keystone';
import {
getSuitableOwnerToken,
getEnvironmentContext,
getResourceSets,
getNamespaceResourceSets,
isUserBasedResourceOwners,
+ doClientLoginForCredentialIssuer,
} from './Common';
import type { TokenExchangeResult } from './Common';
import {
@@ -24,6 +28,15 @@ import { Logger } from '../../logger';
const logger = Logger('ext.Namespace');
import { strict as assert } from 'assert';
+import { User } from '@/services/keystone/types';
+
+const typeUserContact = `
+ type UserContact {
+ id: ID!
+ name: String!
+ username: String!
+ email: String!
+ }`;
const typeNamespace = `
type Namespace {
@@ -44,7 +57,11 @@ module.exports = {
extensions: [
(keystone: any) => {
keystone.extendGraphQLSchema({
- types: [{ type: typeNamespace }, { type: typeNamespaceInput }],
+ types: [
+ { type: typeNamespace },
+ { type: typeNamespaceInput },
+ { type: typeUserContact },
+ ],
queries: [
{
schema: 'currentNamespace: Namespace',
@@ -97,7 +114,6 @@ module.exports = {
},
access: EnforcementPoint,
},
-
{
schema: 'allNamespaces: [Namespace]',
resolver: async (
@@ -138,6 +154,83 @@ module.exports = {
},
access: EnforcementPoint,
},
+ {
+ schema: 'usersByNamespace(namespace: String!): [UserContact]',
+ resolver: async (
+ item: any,
+ args: any,
+ context: any,
+ info: any,
+ { query, access }: any
+ ) => {
+ const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$';
+ const re = new RegExp(namespaceValidationRule);
+ assert.strictEqual(
+ re.test(args.namespace),
+ true,
+ 'Namespace name must be between 5 and 15 alpha-numeric lowercase characters and begin with an alphabet.'
+ );
+ const noauthContext = context.createContext({
+ skipAccessControl: true,
+ });
+
+ const prodEnv = await lookupProductEnvironmentServicesBySlug(
+ noauthContext,
+ process.env.GWA_PROD_ENV_SLUG
+ );
+
+ const tokenResult: TokenExchangeResult = await doClientLoginForCredentialIssuer(
+ noauthContext,
+ prodEnv.id
+ );
+
+ const kcprotectApi = new UMAResourceRegistrationService(
+ tokenResult.issuer,
+ tokenResult.accessToken
+ );
+ const resOwnerResourceIds = await kcprotectApi.listResources({
+ owner: tokenResult.clientUuid,
+ type: 'namespace',
+ } as ResourceSetQuery);
+
+ const namespaces = await kcprotectApi.listResourcesByIdList(
+ resOwnerResourceIds
+ );
+
+ const matched = namespaces
+ .filter((ns) => ns.name == args.namespace)
+ .map((ns) => ({
+ id: ns.id,
+ name: ns.name,
+ scopes: ns.resource_scopes,
+ prodEnvId: prodEnv.id,
+ }));
+ const namespaceObj = matched[0];
+ const permissionApi = new KeycloakPermissionTicketService(
+ tokenResult.issuer,
+ tokenResult.accessToken
+ );
+ const params = { resourceId: namespaceObj.id, returnNames: true };
+ const permissions = await permissionApi.listPermissions(params);
+ const listOfUsers: Array = [];
+ for (const perm of permissions) {
+ if (perm.granted) {
+ const user = await lookupUserByUsername(
+ noauthContext,
+ perm.requesterName
+ );
+ listOfUsers.push({
+ id: user[0].id,
+ name: user[0].name,
+ username: user[0].username,
+ email: user[0].email,
+ });
+ }
+ }
+ return listOfUsers;
+ },
+ access: EnforcementPoint,
+ },
],
mutations: [
{
diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts
index 13b110251..4d075d655 100644
--- a/src/nextapp/shared/types/query.types.ts
+++ b/src/nextapp/shared/types/query.types.ts
@@ -5875,6 +5875,14 @@ export type NamespaceInput = {
name: Scalars['String'];
};
+export type UserContact = {
+ __typename?: 'UserContact';
+ id: Scalars['String'];
+ name: Scalars['String'];
+ username: Scalars['String'];
+ email: Scalars['String'];
+};
+
export type ServiceAccount = {
__typename?: 'ServiceAccount';
id: Scalars['String'];
@@ -6164,6 +6172,7 @@ export type Query = {
consumerScopesAndRoles?: Maybe;
currentNamespace?: Maybe;
allNamespaces?: Maybe>>;
+ usersByNamespace?: Maybe>>;
getUmaPoliciesForResource?: Maybe>>;
allResourceSets?: Maybe>>;
getResourceSet?: Maybe;
@@ -6841,6 +6850,11 @@ export type QueryConsumerScopesAndRolesArgs = {
};
+export type QueryUsersByNamespaceArgs = {
+ namespace: Scalars['String'];
+};
+
+
export type QueryGetUmaPoliciesForResourceArgs = {
prodEnvId: Scalars['ID'];
resourceId: Scalars['String'];
diff --git a/src/services/bceid/bceid.service.ts b/src/services/bceid/bceid.service.ts
index dff98fe39..2d434bc49 100644
--- a/src/services/bceid/bceid.service.ts
+++ b/src/services/bceid/bceid.service.ts
@@ -2,7 +2,7 @@
import { BasicAuthSecurity, Client, createClientAsync } from 'soap';
import { BCeIDConfig } from './config';
// import { LoggerService } from "../../logger/logger.service";
-import { ConfigService } from './config.service';
+import { ConfigService } from '../config.service';
import { AccountDetails } from './account-details.model';
import {
BCeIDAccountTypeCodes,
diff --git a/src/services/bceid/config.service.ts b/src/services/config.service.ts
similarity index 83%
rename from src/services/bceid/config.service.ts
rename to src/services/config.service.ts
index e80b05ed4..66436f07b 100644
--- a/src/services/bceid/config.service.ts
+++ b/src/services/config.service.ts
@@ -1,4 +1,4 @@
-import { IConfig } from "./config";
+import { IConfig } from './bceid/config';
export class ConfigService {
getConfig(): IConfig {
@@ -33,21 +33,23 @@ export class ConfigService {
},
},
notification: {
- enabled: ['true','TRUE'].includes(process.env.EMAIL_ENABLED || 'false'),
- secure: ['true','TRUE'].includes(process.env.EMAIL_SECURE || 'false'),
+ enabled: ['true', 'TRUE'].includes(
+ process.env.EMAIL_ENABLED || 'false'
+ ),
+ secure: ['true', 'TRUE'].includes(process.env.EMAIL_SECURE || 'false'),
from: process.env.EMAIL_FROM || '',
host: process.env.EMAIL_HOST || '',
port: Number(process.env.EMAIL_PORT || 25),
user: process.env.EMAIL_USER || '',
- pass: process.env.EMAIL_PASS || ''
- }
+ pass: process.env.EMAIL_PASS || '',
+ },
};
}
private getOpenIdConfigurationUrl(): string {
return new URL(
`realms/${process.env.KEYCLOAK_REALM}/.well-known/openid-configuration`,
- process.env.KEYCLOAK_AUTH_URL,
+ process.env.KEYCLOAK_AUTH_URL
).href;
}
-}
\ No newline at end of file
+}
diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts
index 13b110251..4d075d655 100644
--- a/src/services/keystone/types.ts
+++ b/src/services/keystone/types.ts
@@ -5875,6 +5875,14 @@ export type NamespaceInput = {
name: Scalars['String'];
};
+export type UserContact = {
+ __typename?: 'UserContact';
+ id: Scalars['String'];
+ name: Scalars['String'];
+ username: Scalars['String'];
+ email: Scalars['String'];
+};
+
export type ServiceAccount = {
__typename?: 'ServiceAccount';
id: Scalars['String'];
@@ -6164,6 +6172,7 @@ export type Query = {
consumerScopesAndRoles?: Maybe;
currentNamespace?: Maybe;
allNamespaces?: Maybe>>;
+ usersByNamespace?: Maybe>>;
getUmaPoliciesForResource?: Maybe>>;
allResourceSets?: Maybe>>;
getResourceSet?: Maybe;
@@ -6841,6 +6850,11 @@ export type QueryConsumerScopesAndRolesArgs = {
};
+export type QueryUsersByNamespaceArgs = {
+ namespace: Scalars['String'];
+};
+
+
export type QueryGetUmaPoliciesForResourceArgs = {
prodEnvId: Scalars['ID'];
resourceId: Scalars['String'];
diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts
index 4ba0e27d2..3b07a2536 100644
--- a/src/services/keystone/user.ts
+++ b/src/services/keystone/user.ts
@@ -70,7 +70,7 @@ export async function updateUserLegalAccept(
export async function lookupUserByUsername(
context: any,
username: string
-): Promise {
+): Promise<[User]> {
const result = await context.executeGraphQL({
query: `query GetUserWithUsername($username: String!) {
allUsers(where: {username: $username}) {
diff --git a/src/services/notification/notification.service.ts b/src/services/notification/notification.service.ts
index a9e8df72f..1aa240840 100644
--- a/src/services/notification/notification.service.ts
+++ b/src/services/notification/notification.service.ts
@@ -7,7 +7,7 @@ import { Logger } from '../../logger';
import { NotificationConfig, EmailNotification, User } from './config';
-import { ConfigService } from '../bceid/config.service';
+import { ConfigService } from '../config.service';
export class NotificationService {
private notifyConfig: NotificationConfig;
diff --git a/src/tsconfig.json b/src/tsconfig.json
index 57062b095..9fc4f0a3d 100644
--- a/src/tsconfig.json
+++ b/src/tsconfig.json
@@ -1,36 +1,22 @@
{
- "compilerOptions": {
- "module": "commonjs",
- "experimentalDecorators": true,
- "emitDecoratorMetadata": true,
- "esModuleInterop": true,
- "target": "es6",
- "noImplicitAny": true,
- "moduleResolution": "node",
- "sourceMap": true,
- "outDir": "dist",
- "baseUrl": ".",
- "paths": {
- "@/logger": [
- "logger"
- ],
- "@/services/*": [
- "services/*"
- ],
- "@/controllers/*": [
- "controllers/*"
- ],
- "@/types": [
- "services/keystone/types.ts"
- ]
- },
- },
- "include": [
- "**/*.ts"
- ],
- "exclude": [
- "node_modules",
- "nextapp",
- "dist"
- ],
-}
\ No newline at end of file
+ "compilerOptions": {
+ "module": "commonjs",
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "esModuleInterop": true,
+ "target": "es6",
+ "noImplicitAny": true,
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "outDir": "dist",
+ "baseUrl": ".",
+ "paths": {
+ "@/logger": ["logger"],
+ "@/services/*": ["services/*"],
+ "@/controllers/*": ["controllers/*"],
+ "@/types": ["services/keystone/types.ts"]
+ }
+ },
+ "include": ["**/*.ts"],
+ "exclude": ["node_modules", "nextapp", "dist"]
+}
From a2577579e76e95aa9e60200e5abf8cd1cdc3d9c5 Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Sun, 8 Aug 2021 22:56:14 -0700
Subject: [PATCH 122/155] fixed undefined issue
---
src/lists/AccessRequest.js | 35 +++++++++++++++--------------------
1 file changed, 15 insertions(+), 20 deletions(-)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index 8a9f368b4..6ac24053b 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -135,10 +135,6 @@ module.exports = {
noauthContext,
updatedItem.id
);
- console.log(
- 'This is awesome namespace: ' +
- accessRequest.productEnvironment.product.namespace
- );
const userContactList = await noauthContext.executeGraphQL({
query: `query ListUsersByNamespace($namespace: String!) {
usersByNamespace(namespace: $namespace) {
@@ -152,23 +148,22 @@ module.exports = {
namespace: accessRequest.productEnvironment.product.namespace,
},
});
- console.log('userContactList: ' + JSON.stringify(userContactList));
+ const nc = new NotificationService(new ConfigService());
+ userContactList.data.usersByNamespace.forEach((contact) => {
+ nc.notify(
+ { email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
+ { template: 'email-template', subject: 'Yeah!' }
+ )
+ .then((info) => {
+ console.log(
+ `[SUCCESS][${info}] Notification sent to ${contact.email}`
+ );
+ })
+ .catch((err) => {
+ console.log('[ERROR] Sending notification failed!' + err);
+ });
+ });
}
- const nc = new NotificationService(new ConfigService());
- userContactList.data.usersByNamespace.forEach((contact) => {
- nc.notify(
- { email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
- { template: 'email-template', subject: 'Yeah!' }
- )
- .then((info) => {
- console.log(
- `[SUCCESS][${info}] Notification sent to ${contact.email}`
- );
- })
- .catch((err) => {
- console.log('[ERROR] Sending notification failed!' + err);
- });
- });
},
},
};
From fb216eacabffb6fad2a1a591ade9929f20cd88cb Mon Sep 17 00:00:00 2001
From: Nithin Shekar Kuruba
Date: Mon, 9 Aug 2021 18:19:08 -0700
Subject: [PATCH 123/155] added optional param to filter users by scope in a
namespace and made the application selection mandatory
---
src/lists/AccessRequest.js | 11 +++++++----
src/lists/extensions/Namespace.ts | 8 +++++++-
src/nextapp/pages/devportal/requests/new/[id].tsx | 2 +-
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/lists/AccessRequest.js b/src/lists/AccessRequest.js
index 6ac24053b..45b1769e4 100644
--- a/src/lists/AccessRequest.js
+++ b/src/lists/AccessRequest.js
@@ -136,8 +136,8 @@ module.exports = {
updatedItem.id
);
const userContactList = await noauthContext.executeGraphQL({
- query: `query ListUsersByNamespace($namespace: String!) {
- usersByNamespace(namespace: $namespace) {
+ query: `query ListUsersByNamespace($namespace: String!, $scopeName: String) {
+ usersByNamespace(namespace: $namespace, scopeName: $scopeName) {
id
name
username
@@ -146,6 +146,7 @@ module.exports = {
}`,
variables: {
namespace: accessRequest.productEnvironment.product.namespace,
+ scopeName: 'Access.Manage',
},
});
const nc = new NotificationService(new ConfigService());
@@ -154,9 +155,11 @@ module.exports = {
{ email: 'nithu.everyyear@gmail.com', name: 'Nithin Kuruba' },
{ template: 'email-template', subject: 'Yeah!' }
)
- .then((info) => {
+ .then((answer) => {
console.log(
- `[SUCCESS][${info}] Notification sent to ${contact.email}`
+ `[SUCCESS][${JSON.stringify(answer)}] Notification sent to ${
+ contact.email
+ }`
);
})
.catch((err) => {
diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts
index a9ea85559..be6f5291d 100644
--- a/src/lists/extensions/Namespace.ts
+++ b/src/lists/extensions/Namespace.ts
@@ -211,7 +211,13 @@ module.exports = {
tokenResult.accessToken
);
const params = { resourceId: namespaceObj.id, returnNames: true };
- const permissions = await permissionApi.listPermissions(params);
+ let permissions = await permissionApi.listPermissions(params);
+ if (args.scopeName) {
+ const updatedPermissions = permissions.filter((perm) => {
+ return perm.scope == args.scopeName;
+ });
+ permissions = updatedPermissions;
+ }
const listOfUsers: Array = [];
for (const perm of permissions) {
if (perm.granted) {
diff --git a/src/nextapp/pages/devportal/requests/new/[id].tsx b/src/nextapp/pages/devportal/requests/new/[id].tsx
index 576fe23f1..983d912f7 100644
--- a/src/nextapp/pages/devportal/requests/new/[id].tsx
+++ b/src/nextapp/pages/devportal/requests/new/[id].tsx
@@ -191,7 +191,7 @@ const NewRequestsPage: React.FC<
Select an application to consume the API
-