From c5775053802567b33c691cdd0610dce21157a83c Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Mon, 24 Jan 2022 17:27:06 -0500 Subject: [PATCH 01/11] moves routing apps to samples --- .eslintignore | 1 + .gitignore | 1 + .../samples/config/new/bs-config.js.t | 18 + .../samples/config/new/package.json.t | 6 + .../samples/config/new/vite.config.js.t | 2 +- generator/config.js | 46 + generator/gulpfile.js/samples.js | 4 +- package.json | 4 +- samples/custom-login/bs-config.js | 2 +- samples/custom-login/vite.config.js | 2 +- samples/doc-direct-auth/bs-config.js | 2 +- samples/doc-direct-auth/vite.config.js | 2 +- samples/doc-embedded-widget/bs-config.js | 2 +- samples/doc-embedded-widget/vite.config.js | 2 +- samples/okta-hosted-login/bs-config.js | 2 +- samples/okta-hosted-login/vite.config.js | 2 +- samples/routing/reach-router/README.md | 26 + .../reach-router}/bs-config.js | 2 +- .../reach-router}/env/index.js | 0 .../reach-router}/env/okta-env.js | 0 .../reach-router}/index.html | 2 +- samples/routing/reach-router/package.json | 28 + samples/routing/reach-router/src/App.tsx | 49 + .../reach-router}/src/assets/logo.svg | 0 .../reach-router/src/components/Footer.tsx | 44 + .../reach-router}/src/components/Loading.tsx | 0 .../reach-router/src/components/Nav.tsx | 25 + .../reach-router/src/components/Routes.tsx | 36 + .../src/components/SecureRoutes.tsx | 70 + .../reach-router}/src/index.css | 0 samples/routing/reach-router/src/index.tsx | 24 + .../routing/reach-router/src/pages/Home.tsx | 27 + .../reach-router/src/pages/Protected.tsx | 27 + .../reach-router/src/react-app-env.d.ts | 13 + .../reach-router}/tsconfig.json | 0 .../reach-router}/tsconfig.node.json | 0 .../reach-router}/vite.config.js | 2 +- .../react-router-dom-v5-hash/README.md | 26 + .../react-router-dom-v5-hash/bs-config.js | 14 + .../react-router-dom-v5-hash/env/index.js | 18 + .../react-router-dom-v5-hash/env/okta-env.js | 51 + .../react-router-dom-v5-hash/index.html | 13 + .../react-router-dom-v5-hash/package.json | 26 + .../react-router-dom-v5-hash/src/App.tsx | 56 + .../src/assets/logo.svg | 1 + .../src/components/Footer.tsx | 44 + .../src/components/Loading.tsx | 21 + .../src/components/LoginCallback.tsx | 55 + .../src/components/Nav.tsx | 25 + .../src/components/Routes.tsx | 34 + .../src/components/SecureRoute.tsx | 77 + .../react-router-dom-v5-hash/src/index.css | 54 + .../react-router-dom-v5-hash/src/index.tsx | 27 + .../src/pages/Home.tsx | 0 .../src/pages/Protected.tsx | 0 .../src/react-app-env.d.ts | 13 + .../react-router-dom-v5-hash/tsconfig.json | 21 + .../tsconfig.node.json | 8 + .../react-router-dom-v5-hash/vite.config.js | 54 + samples/routing/react-router-dom-v5/README.md | 26 + .../routing/react-router-dom-v5/bs-config.js | 14 + .../routing/react-router-dom-v5/env/index.js | 18 + .../react-router-dom-v5/env/okta-env.js | 51 + .../routing/react-router-dom-v5/index.html | 13 + .../routing/react-router-dom-v5/package.json | 26 + .../routing/react-router-dom-v5/src/App.tsx | 50 + .../react-router-dom-v5/src/assets/logo.svg | 1 + .../src/components/Footer.tsx | 44 + .../src/components/Loading.tsx | 21 + .../src/components/Nav.tsx | 25 + .../src/components/Routes.tsx | 32 + .../src/components/SecureRoute.tsx | 77 + .../routing/react-router-dom-v5/src/index.css | 54 + .../react-router-dom-v5}/src/index.tsx | 0 .../react-router-dom-v5/src/pages/Home.tsx | 25 + .../src/pages/Protected.tsx | 25 + .../src/react-app-env.d.ts | 13 + .../routing/react-router-dom-v5/tsconfig.json | 21 + .../react-router-dom-v5/tsconfig.node.json | 8 + .../react-router-dom-v5/vite.config.js | 54 + .../react-router-dom-v6-hash/README.md | 28 + .../react-router-dom-v6-hash/bs-config.js | 14 + .../react-router-dom-v6-hash/env/index.js | 18 + .../react-router-dom-v6-hash/env/okta-env.js | 51 + .../react-router-dom-v6-hash/index.html | 13 + .../react-router-dom-v6-hash/package.json | 26 + .../react-router-dom-v6-hash/src/App.tsx | 56 + .../src/assets/logo.svg | 1 + .../src/components/Footer.tsx | 0 .../src/components/Loading.tsx | 21 + .../src/components/LoginCallback.tsx | 46 + .../src/components/Nav.tsx | 25 + .../src/components/Routes.tsx | 36 + .../src/components/SecureRoute.tsx | 36 + .../react-router-dom-v6-hash/src/index.css | 54 + .../react-router-dom-v6-hash/src/index.tsx | 27 + .../src/pages/Home.tsx | 25 + .../src/pages/Protected.tsx | 25 + .../src/react-app-env.d.ts | 13 + .../react-router-dom-v6-hash/tsconfig.json | 21 + .../tsconfig.node.json | 8 + .../react-router-dom-v6-hash/vite.config.js | 54 + .../react-router-dom-v6/.gitignore | 0 .../react-router-dom-v6/README.md | 0 .../routing/react-router-dom-v6/bs-config.js | 14 + .../routing/react-router-dom-v6/env/index.js | 18 + .../react-router-dom-v6/env/okta-env.js | 51 + .../routing/react-router-dom-v6/index.html | 13 + .../react-router-dom-v6/package.json | 0 .../react-router-dom-v6/src/App.tsx | 0 .../react-router-dom-v6/src/assets/logo.svg | 1 + .../src/components/Footer.tsx | 45 + .../src/components/Loading.tsx | 21 + .../src/components/Nav.tsx | 0 .../src/components/Routes.tsx | 0 .../src/components/SecureRoute.tsx | 0 .../react-router-dom-v6/src/config.ts | 0 .../routing/react-router-dom-v6/src/index.css | 54 + .../routing/react-router-dom-v6/src/index.tsx | 27 + .../react-router-dom-v6/src/pages/Home.tsx | 25 + .../src/pages/Protected.tsx | 25 + .../react-router-dom-v6/src/vite-env.d.ts | 0 .../routing/react-router-dom-v6/tsconfig.json | 21 + .../react-router-dom-v6/tsconfig.node.json | 8 + .../react-router-dom-v6/vite.config.js | 54 + test/routing-samples/babel.config.js | 24 + test/routing-samples/package-lock.json | 3431 +++++++++++++++++ test/routing-samples/package.json | 18 + .../page-objects/RouterTestAppPage.js | 59 + test/routing-samples/runner.js | 107 + test/routing-samples/specs/router.e2e.js | 111 + test/routing-samples/utils/waitForLoad.js | 16 + test/routing-samples/wdio.conf.js | 341 ++ util/maintain-banners.js | 2 +- 134 files changed, 6777 insertions(+), 16 deletions(-) create mode 100644 generator/_templates/samples/config/new/bs-config.js.t create mode 100644 samples/routing/reach-router/README.md rename samples/{react-router-dom-v6 => routing/reach-router}/bs-config.js (88%) rename samples/{react-router-dom-v6 => routing/reach-router}/env/index.js (100%) rename samples/{react-router-dom-v6 => routing/reach-router}/env/okta-env.js (100%) rename samples/{react-router-dom-v6 => routing/reach-router}/index.html (89%) create mode 100644 samples/routing/reach-router/package.json create mode 100644 samples/routing/reach-router/src/App.tsx rename samples/{react-router-dom-v6 => routing/reach-router}/src/assets/logo.svg (100%) create mode 100644 samples/routing/reach-router/src/components/Footer.tsx rename samples/{react-router-dom-v6 => routing/reach-router}/src/components/Loading.tsx (100%) create mode 100644 samples/routing/reach-router/src/components/Nav.tsx create mode 100644 samples/routing/reach-router/src/components/Routes.tsx create mode 100644 samples/routing/reach-router/src/components/SecureRoutes.tsx rename samples/{react-router-dom-v6 => routing/reach-router}/src/index.css (100%) create mode 100644 samples/routing/reach-router/src/index.tsx create mode 100644 samples/routing/reach-router/src/pages/Home.tsx create mode 100644 samples/routing/reach-router/src/pages/Protected.tsx create mode 100644 samples/routing/reach-router/src/react-app-env.d.ts rename samples/{react-router-dom-v6 => routing/reach-router}/tsconfig.json (100%) rename samples/{react-router-dom-v6 => routing/reach-router}/tsconfig.node.json (100%) rename samples/{react-router-dom-v6 => routing/reach-router}/vite.config.js (97%) create mode 100644 samples/routing/react-router-dom-v5-hash/README.md create mode 100644 samples/routing/react-router-dom-v5-hash/bs-config.js create mode 100644 samples/routing/react-router-dom-v5-hash/env/index.js create mode 100644 samples/routing/react-router-dom-v5-hash/env/okta-env.js create mode 100644 samples/routing/react-router-dom-v5-hash/index.html create mode 100644 samples/routing/react-router-dom-v5-hash/package.json create mode 100644 samples/routing/react-router-dom-v5-hash/src/App.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/assets/logo.svg create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/Footer.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/Loading.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/LoginCallback.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/Nav.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/Routes.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/components/SecureRoute.tsx create mode 100644 samples/routing/react-router-dom-v5-hash/src/index.css create mode 100644 samples/routing/react-router-dom-v5-hash/src/index.tsx rename samples/{react-router-dom-v6 => routing/react-router-dom-v5-hash}/src/pages/Home.tsx (100%) rename samples/{react-router-dom-v6 => routing/react-router-dom-v5-hash}/src/pages/Protected.tsx (100%) create mode 100644 samples/routing/react-router-dom-v5-hash/src/react-app-env.d.ts create mode 100644 samples/routing/react-router-dom-v5-hash/tsconfig.json create mode 100644 samples/routing/react-router-dom-v5-hash/tsconfig.node.json create mode 100644 samples/routing/react-router-dom-v5-hash/vite.config.js create mode 100644 samples/routing/react-router-dom-v5/README.md create mode 100644 samples/routing/react-router-dom-v5/bs-config.js create mode 100644 samples/routing/react-router-dom-v5/env/index.js create mode 100644 samples/routing/react-router-dom-v5/env/okta-env.js create mode 100644 samples/routing/react-router-dom-v5/index.html create mode 100644 samples/routing/react-router-dom-v5/package.json create mode 100644 samples/routing/react-router-dom-v5/src/App.tsx create mode 100644 samples/routing/react-router-dom-v5/src/assets/logo.svg create mode 100644 samples/routing/react-router-dom-v5/src/components/Footer.tsx create mode 100644 samples/routing/react-router-dom-v5/src/components/Loading.tsx create mode 100644 samples/routing/react-router-dom-v5/src/components/Nav.tsx create mode 100644 samples/routing/react-router-dom-v5/src/components/Routes.tsx create mode 100644 samples/routing/react-router-dom-v5/src/components/SecureRoute.tsx create mode 100644 samples/routing/react-router-dom-v5/src/index.css rename samples/{react-router-dom-v6 => routing/react-router-dom-v5}/src/index.tsx (100%) create mode 100644 samples/routing/react-router-dom-v5/src/pages/Home.tsx create mode 100644 samples/routing/react-router-dom-v5/src/pages/Protected.tsx create mode 100644 samples/routing/react-router-dom-v5/src/react-app-env.d.ts create mode 100644 samples/routing/react-router-dom-v5/tsconfig.json create mode 100644 samples/routing/react-router-dom-v5/tsconfig.node.json create mode 100644 samples/routing/react-router-dom-v5/vite.config.js create mode 100644 samples/routing/react-router-dom-v6-hash/README.md create mode 100644 samples/routing/react-router-dom-v6-hash/bs-config.js create mode 100644 samples/routing/react-router-dom-v6-hash/env/index.js create mode 100644 samples/routing/react-router-dom-v6-hash/env/okta-env.js create mode 100644 samples/routing/react-router-dom-v6-hash/index.html create mode 100644 samples/routing/react-router-dom-v6-hash/package.json create mode 100644 samples/routing/react-router-dom-v6-hash/src/App.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/assets/logo.svg rename samples/{react-router-dom-v6 => routing/react-router-dom-v6-hash}/src/components/Footer.tsx (100%) create mode 100644 samples/routing/react-router-dom-v6-hash/src/components/Loading.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/components/LoginCallback.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/components/Nav.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/components/Routes.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/components/SecureRoute.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/index.css create mode 100644 samples/routing/react-router-dom-v6-hash/src/index.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/pages/Home.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/pages/Protected.tsx create mode 100644 samples/routing/react-router-dom-v6-hash/src/react-app-env.d.ts create mode 100644 samples/routing/react-router-dom-v6-hash/tsconfig.json create mode 100644 samples/routing/react-router-dom-v6-hash/tsconfig.node.json create mode 100644 samples/routing/react-router-dom-v6-hash/vite.config.js rename samples/{ => routing}/react-router-dom-v6/.gitignore (100%) rename samples/{ => routing}/react-router-dom-v6/README.md (100%) create mode 100644 samples/routing/react-router-dom-v6/bs-config.js create mode 100644 samples/routing/react-router-dom-v6/env/index.js create mode 100644 samples/routing/react-router-dom-v6/env/okta-env.js create mode 100644 samples/routing/react-router-dom-v6/index.html rename samples/{ => routing}/react-router-dom-v6/package.json (100%) rename samples/{ => routing}/react-router-dom-v6/src/App.tsx (100%) create mode 100644 samples/routing/react-router-dom-v6/src/assets/logo.svg create mode 100644 samples/routing/react-router-dom-v6/src/components/Footer.tsx create mode 100644 samples/routing/react-router-dom-v6/src/components/Loading.tsx rename samples/{ => routing}/react-router-dom-v6/src/components/Nav.tsx (100%) rename samples/{ => routing}/react-router-dom-v6/src/components/Routes.tsx (100%) rename samples/{ => routing}/react-router-dom-v6/src/components/SecureRoute.tsx (100%) rename samples/{ => routing}/react-router-dom-v6/src/config.ts (100%) create mode 100644 samples/routing/react-router-dom-v6/src/index.css create mode 100644 samples/routing/react-router-dom-v6/src/index.tsx create mode 100644 samples/routing/react-router-dom-v6/src/pages/Home.tsx create mode 100644 samples/routing/react-router-dom-v6/src/pages/Protected.tsx rename samples/{ => routing}/react-router-dom-v6/src/vite-env.d.ts (100%) create mode 100644 samples/routing/react-router-dom-v6/tsconfig.json create mode 100644 samples/routing/react-router-dom-v6/tsconfig.node.json create mode 100644 samples/routing/react-router-dom-v6/vite.config.js create mode 100644 test/routing-samples/babel.config.js create mode 100644 test/routing-samples/package-lock.json create mode 100644 test/routing-samples/package.json create mode 100644 test/routing-samples/page-objects/RouterTestAppPage.js create mode 100644 test/routing-samples/runner.js create mode 100644 test/routing-samples/specs/router.e2e.js create mode 100644 test/routing-samples/utils/waitForLoad.js create mode 100644 test/routing-samples/wdio.conf.js diff --git a/.eslintignore b/.eslintignore index 8c93705b..f94e4a92 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ node_modules dist /scripts build +test/apps/react-routing/e2e \ No newline at end of file diff --git a/.gitignore b/.gitignore index bfc0422d..0391f997 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ testenv yalc.lock .yarnrc .yarn +.env \ No newline at end of file diff --git a/generator/_templates/samples/config/new/bs-config.js.t b/generator/_templates/samples/config/new/bs-config.js.t new file mode 100644 index 00000000..f5cd4d9e --- /dev/null +++ b/generator/_templates/samples/config/new/bs-config.js.t @@ -0,0 +1,18 @@ +--- +to: ../samples/<%= dest %>/bs-config.js +force: true +--- +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +module.exports = { + port: process.env.PORT || 8080, + logLevel: 'silent', + files: ['./dist/**/*.{html,htm,css,js}'], + server: { + baseDir: './dist', + middleware: { + 0: null + } + }, + open: false +}; diff --git a/generator/_templates/samples/config/new/package.json.t b/generator/_templates/samples/config/new/package.json.t index 2dd0d5b0..ae47e149 100644 --- a/generator/_templates/samples/config/new/package.json.t +++ b/generator/_templates/samples/config/new/package.json.t @@ -17,7 +17,9 @@ force: true "dependencies": { "react": "^17.0.2", "react-dom": "^17.0.2", +<% if (reactRouterDomVersion !== 'false') { -%> "react-router-dom": "<%= reactRouterDomVersion %>", +<% } -%> "@okta/okta-auth-js": "^<%= oktaAuthJsVersion %>", <% if (useSiw === 'true') { -%> "@okta/okta-signin-widget": "^<%= siwVersion %>", @@ -28,6 +30,10 @@ force: true <% } -%> <% if (usePolyfill === 'true') { -%> "text-encoding": "0.7.0", +<% } -%> +<% if (reachRouterVersion !== 'false') { -%> + "@reach/router":"<%= reachRouterVersion %>", + "@types/reach__router": "<%= reachRouterVersion %>", <% } -%> "@okta/okta-react": "*" }, diff --git a/generator/_templates/samples/config/new/vite.config.js.t b/generator/_templates/samples/config/new/vite.config.js.t index 44ee8b81..946cb84c 100644 --- a/generator/_templates/samples/config/new/vite.config.js.t +++ b/generator/_templates/samples/config/new/vite.config.js.t @@ -44,7 +44,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/generator/config.js b/generator/config.js index 764658a1..1e9b609d 100644 --- a/generator/config.js +++ b/generator/config.js @@ -17,6 +17,7 @@ module.exports = [ useSemanticUi: true, usePolyfill: true, reactRouterDomVersion: '5.2.0', + reachRouterVersion: false, specs: [ 'okta-hosted-login' ] @@ -27,6 +28,7 @@ module.exports = [ useSemanticUi: true, usePolyfill: true, reactRouterDomVersion: '5.2.0', + reachRouterVersion: false, specs: [ 'custom-login' ] @@ -37,6 +39,7 @@ module.exports = [ useSemanticUi: false, usePolyfill: false, reactRouterDomVersion: '5.2.0', + reachRouterVersion: false, specs: [ 'doc-embedded-widget' ] @@ -47,16 +50,59 @@ module.exports = [ useSemanticUi: false, usePolyfill: false, reactRouterDomVersion: '5.2.0', + reachRouterVersion: false, specs: [ 'doc-direct-auth' ] }, { name: '@okta/samples.react.react-router-dom-v6', + nested: 'routing/', useSiw: false, useSemanticUi: false, usePolyfill: false, reactRouterDomVersion: '6.2.1', + reachRouterVersion: false, + specs: [] + }, + { + name: '@okta/samples.react.react-router-dom-v6-hash', + nested: 'routing/', + useSiw: false, + useSemanticUi: false, + usePolyfill: false, + reactRouterDomVersion: '6.2.1', + reachRouterVersion: false, + specs: [] + }, + { + name: '@okta/samples.react.react-router-dom-v5', + nested: 'routing/', + useSiw: false, + useSemanticUi: false, + usePolyfill: false, + reactRouterDomVersion: '5.3.0', + reachRouterVersion: false, + specs: [] + }, + { + name: '@okta/samples.react.react-router-dom-v5-hash', + nested: 'routing/', + useSiw: false, + useSemanticUi: false, + usePolyfill: false, + reactRouterDomVersion: '5.3.0', + reachRouterVersion: false, + specs: [] + }, + { + name: '@okta/samples.react.reach-router', + nested: 'routing/', + useSiw: false, + useSemanticUi: false, + usePolyfill: false, + reactRouterDomVersion: '5.3.0', + reachRouterVersion: "^1.3.4", specs: [] } ]; diff --git a/generator/gulpfile.js/samples.js b/generator/gulpfile.js/samples.js index fe999c79..e1a30143 100644 --- a/generator/gulpfile.js/samples.js +++ b/generator/gulpfile.js/samples.js @@ -23,8 +23,8 @@ const samplesConfig = (() => { return configs.map(config => { const nameParts = config.name.split('.'); const name = nameParts[nameParts.length - 1]; - const dest = `${name}`; - return { + const dest = `${config.nested || ''}${name}`; + return { ...config, ...versions, name, diff --git a/package.json b/package.json index b9a12c46..aba6f5d7 100644 --- a/package.json +++ b/package.json @@ -120,9 +120,11 @@ "env", "generator", "samples/**/*", + "samples/routing/**/*", "test/apps/*", "test/e2e/harness", - "test/e2e-samples" + "test/e2e-samples", + "test/routing-samples" ], "nohoist": [ "**/@okta/okta-auth-js", diff --git a/samples/custom-login/bs-config.js b/samples/custom-login/bs-config.js index e64ae278..18e0ef15 100644 --- a/samples/custom-login/bs-config.js +++ b/samples/custom-login/bs-config.js @@ -1,7 +1,7 @@ // "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" module.exports = { - port: 8080, + port: process.env.PORT || 8080, logLevel: 'silent', files: ['./dist/**/*.{html,htm,css,js}'], server: { diff --git a/samples/custom-login/vite.config.js b/samples/custom-login/vite.config.js index 3d008069..88f8a134 100644 --- a/samples/custom-login/vite.config.js +++ b/samples/custom-login/vite.config.js @@ -40,7 +40,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/samples/doc-direct-auth/bs-config.js b/samples/doc-direct-auth/bs-config.js index e64ae278..18e0ef15 100644 --- a/samples/doc-direct-auth/bs-config.js +++ b/samples/doc-direct-auth/bs-config.js @@ -1,7 +1,7 @@ // "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" module.exports = { - port: 8080, + port: process.env.PORT || 8080, logLevel: 'silent', files: ['./dist/**/*.{html,htm,css,js}'], server: { diff --git a/samples/doc-direct-auth/vite.config.js b/samples/doc-direct-auth/vite.config.js index 3d008069..88f8a134 100644 --- a/samples/doc-direct-auth/vite.config.js +++ b/samples/doc-direct-auth/vite.config.js @@ -40,7 +40,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/samples/doc-embedded-widget/bs-config.js b/samples/doc-embedded-widget/bs-config.js index e64ae278..18e0ef15 100644 --- a/samples/doc-embedded-widget/bs-config.js +++ b/samples/doc-embedded-widget/bs-config.js @@ -1,7 +1,7 @@ // "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" module.exports = { - port: 8080, + port: process.env.PORT || 8080, logLevel: 'silent', files: ['./dist/**/*.{html,htm,css,js}'], server: { diff --git a/samples/doc-embedded-widget/vite.config.js b/samples/doc-embedded-widget/vite.config.js index 3d008069..88f8a134 100644 --- a/samples/doc-embedded-widget/vite.config.js +++ b/samples/doc-embedded-widget/vite.config.js @@ -40,7 +40,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/samples/okta-hosted-login/bs-config.js b/samples/okta-hosted-login/bs-config.js index e64ae278..18e0ef15 100644 --- a/samples/okta-hosted-login/bs-config.js +++ b/samples/okta-hosted-login/bs-config.js @@ -1,7 +1,7 @@ // "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" module.exports = { - port: 8080, + port: process.env.PORT || 8080, logLevel: 'silent', files: ['./dist/**/*.{html,htm,css,js}'], server: { diff --git a/samples/okta-hosted-login/vite.config.js b/samples/okta-hosted-login/vite.config.js index 3d008069..88f8a134 100644 --- a/samples/okta-hosted-login/vite.config.js +++ b/samples/okta-hosted-login/vite.config.js @@ -40,7 +40,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/samples/routing/reach-router/README.md b/samples/routing/reach-router/README.md new file mode 100644 index 00000000..86c42e12 --- /dev/null +++ b/samples/routing/reach-router/README.md @@ -0,0 +1,26 @@ +# Okta Reach Router Sample App + +Sample app to demonstrate how to use `reach-router` with `@okta/okta-react`. + +## Install +```bash +$ git clone https://github.com/okta/okta-react.git +$ yarn +``` + +## Configure +Add an `testenv` file with the following fields +``` +SPA_CLIENT_ID= +ISSUER= +``` + +## Start +```bash +$ yarn workspace @okta/samples.react.reach-router start +``` +OR +```bash +$ cd ./samples/reach-router +$ yarn start +``` diff --git a/samples/react-router-dom-v6/bs-config.js b/samples/routing/reach-router/bs-config.js similarity index 88% rename from samples/react-router-dom-v6/bs-config.js rename to samples/routing/reach-router/bs-config.js index e64ae278..18e0ef15 100644 --- a/samples/react-router-dom-v6/bs-config.js +++ b/samples/routing/reach-router/bs-config.js @@ -1,7 +1,7 @@ // "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" module.exports = { - port: 8080, + port: process.env.PORT || 8080, logLevel: 'silent', files: ['./dist/**/*.{html,htm,css,js}'], server: { diff --git a/samples/react-router-dom-v6/env/index.js b/samples/routing/reach-router/env/index.js similarity index 100% rename from samples/react-router-dom-v6/env/index.js rename to samples/routing/reach-router/env/index.js diff --git a/samples/react-router-dom-v6/env/okta-env.js b/samples/routing/reach-router/env/okta-env.js similarity index 100% rename from samples/react-router-dom-v6/env/okta-env.js rename to samples/routing/reach-router/env/okta-env.js diff --git a/samples/react-router-dom-v6/index.html b/samples/routing/reach-router/index.html similarity index 89% rename from samples/react-router-dom-v6/index.html rename to samples/routing/reach-router/index.html index 13267ed5..f14fdec4 100644 --- a/samples/react-router-dom-v6/index.html +++ b/samples/routing/reach-router/index.html @@ -4,7 +4,7 @@ - Vite App + Reach Router Sample
diff --git a/samples/routing/reach-router/package.json b/samples/routing/reach-router/package.json new file mode 100644 index 00000000..dd129b14 --- /dev/null +++ b/samples/routing/reach-router/package.json @@ -0,0 +1,28 @@ +{ + "comment": "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'", + "name": "@okta/samples.react.reach-router", + "private": true, + "version": "0.3.0", + "scripts": { + "prestart": "vite build", + "start": "lite-server", + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-router-dom": "5.3.0", + "@okta/okta-auth-js": "^6.2.0", + "@reach/router":"^1.3.4", + "@types/reach__router": "^1.3.4", + "@okta/okta-react": "*" + }, + "devDependencies": { + "@vitejs/plugin-react": "^1.0.7", + "vite": "^2.8.0", + "lite-server": "^2.6.1", + "dotenv": "^16.0.0" + } +} \ No newline at end of file diff --git a/samples/routing/reach-router/src/App.tsx b/samples/routing/reach-router/src/App.tsx new file mode 100644 index 00000000..fb9a741d --- /dev/null +++ b/samples/routing/reach-router/src/App.tsx @@ -0,0 +1,49 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { navigate } from '@reach/router'; +import { Security } from '@okta/okta-react'; +import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js'; + +import Footer from './components/Footer'; +import Nav from './components/Nav'; +import Routes from './components/Routes'; + +function App() { + const oktaAuth = new OktaAuth({ + issuer: process.env.ISSUER, + clientId: process.env.SPA_CLIENT_ID, + redirectUri: window.location.origin + '/login/callback' + }); + + const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => { + navigate(toRelativeUrl(originalUri || '/', window.location.origin), { replace: true }); + }; + + return ( + +
+
+
+
+ +
+
+
+
+ ); +} + +export default App; diff --git a/samples/react-router-dom-v6/src/assets/logo.svg b/samples/routing/reach-router/src/assets/logo.svg similarity index 100% rename from samples/react-router-dom-v6/src/assets/logo.svg rename to samples/routing/reach-router/src/assets/logo.svg diff --git a/samples/routing/reach-router/src/components/Footer.tsx b/samples/routing/reach-router/src/components/Footer.tsx new file mode 100644 index 00000000..f475b215 --- /dev/null +++ b/samples/routing/reach-router/src/components/Footer.tsx @@ -0,0 +1,44 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; + +function Footer() { + const { authState, oktaAuth } = useOktaAuth(); + + const handleLogin = () => oktaAuth.signInWithRedirect(); + const handleLogout = () => oktaAuth.signOut(); + + return ( +
+
+ { + !authState || !authState?.isAuthenticated ? + ( + <> +

Please log in

+ + + ) : + ( + <> +

You're logged in!

+ + + ) + } +
+ ); +} + +export default Footer; diff --git a/samples/react-router-dom-v6/src/components/Loading.tsx b/samples/routing/reach-router/src/components/Loading.tsx similarity index 100% rename from samples/react-router-dom-v6/src/components/Loading.tsx rename to samples/routing/reach-router/src/components/Loading.tsx diff --git a/samples/routing/reach-router/src/components/Nav.tsx b/samples/routing/reach-router/src/components/Nav.tsx new file mode 100644 index 00000000..9fad980f --- /dev/null +++ b/samples/routing/reach-router/src/components/Nav.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Link } from '@reach/router'; + +const Nav = () => { + return ( + + ); +} + +export default Nav; diff --git a/samples/routing/reach-router/src/components/Routes.tsx b/samples/routing/reach-router/src/components/Routes.tsx new file mode 100644 index 00000000..8f6f1b74 --- /dev/null +++ b/samples/routing/reach-router/src/components/Routes.tsx @@ -0,0 +1,36 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Router, RouteComponentProps } from '@reach/router'; +import { LoginCallback } from '@okta/okta-react'; +import { SecureRoutes } from './SecureRoutes'; + +import Home from '../pages/Home'; +import Protected from '../pages/Protected'; +import Loading from './Loading'; + +const OktaLoginCallback: React.FC = () => (} />); + +const AppRoutes = () => { + return ( + + + + + + + + ); +}; + +export default AppRoutes; diff --git a/samples/routing/reach-router/src/components/SecureRoutes.tsx b/samples/routing/reach-router/src/components/SecureRoutes.tsx new file mode 100644 index 00000000..fc3f33d4 --- /dev/null +++ b/samples/routing/reach-router/src/components/SecureRoutes.tsx @@ -0,0 +1,70 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; +import { toRelativeUrl } from '@okta/okta-auth-js'; +import { RouteComponentProps } from '@reach/router'; +import Loading from './Loading'; + + +export type SecureRoutesChildProps = React.Component; + +export type SecureRoutesProps = { + children: React.ReactElement; + path: string; + errorComponent?: React.ComponentType<{ error: Error }>; +} & RouteComponentProps; + +export const SecureRoutes: React.FC = ({ errorComponent, children }) => { + const { oktaAuth, authState } = useOktaAuth(); + const isPending = React.useRef(false); + const [ error, setError ] = React.useState(null); + + React.useEffect(() => { + const login = async () => { + if (isPending.current) { + return; + } + + isPending.current = true; + + const originalUri = toRelativeUrl(window.location.href, window.location.origin); + oktaAuth.setOriginalUri(originalUri); + await oktaAuth.signInWithRedirect(); + }; + + if (authState?.isAuthenticated) { + isPending.current = false; + return; + } + + if (!authState || !authState.isAuthenticated) { + login().catch(err => { + setError(err); + }); + } + }, [authState, oktaAuth, isPending, setError]); + + if (error && errorComponent) { + const ErrorComponent = errorComponent; + return + } + + if (!authState || !authState?.isAuthenticated) { + return (); + } + + return (children); +}; + +export default SecureRoutes; \ No newline at end of file diff --git a/samples/react-router-dom-v6/src/index.css b/samples/routing/reach-router/src/index.css similarity index 100% rename from samples/react-router-dom-v6/src/index.css rename to samples/routing/reach-router/src/index.css diff --git a/samples/routing/reach-router/src/index.tsx b/samples/routing/reach-router/src/index.tsx new file mode 100644 index 00000000..9a9240b0 --- /dev/null +++ b/samples/routing/reach-router/src/index.tsx @@ -0,0 +1,24 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; + + +ReactDOM.render( + + + , + document.getElementById('root') +); diff --git a/samples/routing/reach-router/src/pages/Home.tsx b/samples/routing/reach-router/src/pages/Home.tsx new file mode 100644 index 00000000..c83f7022 --- /dev/null +++ b/samples/routing/reach-router/src/pages/Home.tsx @@ -0,0 +1,27 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { RouteComponentProps } from '@reach/router'; + +import logo from '../assets/logo.svg'; + +const Home: React.FC = () => { + return ( + <> +

Home

+ logo + + ); +}; + +export default Home; \ No newline at end of file diff --git a/samples/routing/reach-router/src/pages/Protected.tsx b/samples/routing/reach-router/src/pages/Protected.tsx new file mode 100644 index 00000000..5dacab5e --- /dev/null +++ b/samples/routing/reach-router/src/pages/Protected.tsx @@ -0,0 +1,27 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { RouteComponentProps } from '@reach/router'; + +import logo from '../assets/logo.svg'; + +const Protected: React.FC = () => { + return ( + <> +

Protected

+ logo + + ); +}; + +export default Protected; \ No newline at end of file diff --git a/samples/routing/reach-router/src/react-app-env.d.ts b/samples/routing/reach-router/src/react-app-env.d.ts new file mode 100644 index 00000000..e37d0a97 --- /dev/null +++ b/samples/routing/reach-router/src/react-app-env.d.ts @@ -0,0 +1,13 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/// diff --git a/samples/react-router-dom-v6/tsconfig.json b/samples/routing/reach-router/tsconfig.json similarity index 100% rename from samples/react-router-dom-v6/tsconfig.json rename to samples/routing/reach-router/tsconfig.json diff --git a/samples/react-router-dom-v6/tsconfig.node.json b/samples/routing/reach-router/tsconfig.node.json similarity index 100% rename from samples/react-router-dom-v6/tsconfig.node.json rename to samples/routing/reach-router/tsconfig.node.json diff --git a/samples/react-router-dom-v6/vite.config.js b/samples/routing/reach-router/vite.config.js similarity index 97% rename from samples/react-router-dom-v6/vite.config.js rename to samples/routing/reach-router/vite.config.js index 3d008069..88f8a134 100644 --- a/samples/react-router-dom-v6/vite.config.js +++ b/samples/routing/reach-router/vite.config.js @@ -40,7 +40,7 @@ export default defineConfig({ } }, server: { - port: 8080 + port: process.env.PORT || 8080 }, build: { rollupOptions: { diff --git a/samples/routing/react-router-dom-v5-hash/README.md b/samples/routing/react-router-dom-v5-hash/README.md new file mode 100644 index 00000000..af8a441a --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/README.md @@ -0,0 +1,26 @@ +# Okta React Router DOM v5 HashRouter Sample App + +Sample app to demonstrate how to use `react-router-dom` v5 with `@okta/okta-react`. + +## Install +```bash +$ git clone https://github.com/okta/okta-react.git +$ yarn +``` + +## Configure +Add an `testenv` file with the following fields +``` +SPA_CLIENT_ID= +ISSUER= +``` + +## Start +```bash +$ yarn workspace @okta/samples.react.react-router-dom-v5-hash start +``` +OR +```bash +$ cd ./samples/react-router-dom-v5-hash +$ yarn start +``` diff --git a/samples/routing/react-router-dom-v5-hash/bs-config.js b/samples/routing/react-router-dom-v5-hash/bs-config.js new file mode 100644 index 00000000..18e0ef15 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/bs-config.js @@ -0,0 +1,14 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +module.exports = { + port: process.env.PORT || 8080, + logLevel: 'silent', + files: ['./dist/**/*.{html,htm,css,js}'], + server: { + baseDir: './dist', + middleware: { + 0: null + } + }, + open: false +}; diff --git a/samples/routing/react-router-dom-v5-hash/env/index.js b/samples/routing/react-router-dom-v5-hash/env/index.js new file mode 100644 index 00000000..e9e83b30 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/env/index.js @@ -0,0 +1,18 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +export default function () { + let oktaEnv; + try { + oktaEnv = require('@okta/env'); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + // try local env module + oktaEnv = require('./okta-env'); + return oktaEnv; + } + + throw err; + } + + return oktaEnv; +} diff --git a/samples/routing/react-router-dom-v5-hash/env/okta-env.js b/samples/routing/react-router-dom-v5-hash/env/okta-env.js new file mode 100644 index 00000000..e5b0bc95 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/env/okta-env.js @@ -0,0 +1,51 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" +/*! + * Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +const dotenv = require('dotenv'); +const fs = require('fs'); +const path = require('path'); + +const TESTENV_FILE = 'testenv'; + +function setEnvironmentVars(envConfig) { + Object.keys(envConfig).forEach((k) => { + if (process.env[k] !== envConfig[k]) { + console.log(`Setting a new value for environment variable "${k}"`); + } + process.env[k] = envConfig[k]; + }); +} + +function getPath(currDir = __dirname) { + let res, prevDir; + // stop when find testenv file or reach to root dir + while (!fs.existsSync(res) && currDir !== prevDir) { + prevDir = currDir; + res = path.resolve(currDir, TESTENV_FILE); + currDir = path.resolve(currDir, '..'); + } + return fs.existsSync(res) ? res : null; +} + +function setEnvironmentVarsFromTestEnv(currDir) { + const testEnvPath = getPath(currDir); + if (!testEnvPath) { + return; + } + const envConfig = dotenv.parse(fs.readFileSync(testEnvPath)); + setEnvironmentVars(envConfig); +} + +module.exports = { + setEnvironmentVarsFromTestEnv +}; diff --git a/samples/routing/react-router-dom-v5-hash/index.html b/samples/routing/react-router-dom-v5-hash/index.html new file mode 100644 index 00000000..fc5dc837 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/index.html @@ -0,0 +1,13 @@ + + + + + + + React Router v5 HashRouter Sample + + +
+ + + diff --git a/samples/routing/react-router-dom-v5-hash/package.json b/samples/routing/react-router-dom-v5-hash/package.json new file mode 100644 index 00000000..61d89b96 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/package.json @@ -0,0 +1,26 @@ +{ + "comment": "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'", + "name": "@okta/samples.react.react-router-dom-v5-hash", + "private": true, + "version": "0.3.0", + "scripts": { + "prestart": "vite build", + "start": "lite-server", + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-router-dom": "5.3.0", + "@okta/okta-auth-js": "^6.2.0", + "@okta/okta-react": "*" + }, + "devDependencies": { + "@vitejs/plugin-react": "^1.0.7", + "vite": "^2.8.0", + "lite-server": "^2.6.1", + "dotenv": "^16.0.0" + } +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5-hash/src/App.tsx b/samples/routing/react-router-dom-v5-hash/src/App.tsx new file mode 100644 index 00000000..208e807d --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/App.tsx @@ -0,0 +1,56 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { useHistory } from 'react-router-dom'; +import { Security } from '@okta/okta-react'; +import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js'; + +import Footer from './components/Footer'; +import Nav from './components/Nav'; +import Routes from './components/Routes'; + + +function App() { + const oktaAuth = new OktaAuth({ + issuer: process.env.ISSUER, + clientId: process.env.SPA_CLIENT_ID, + redirectUri: window.location.origin + }); + + const history = useHistory(); + const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => { + let uri = '/'; + if (originalUri) { + // strip the lead '/#' from the uri + uri = originalUri.startsWith('/#') ? originalUri.slice(2) : originalUri; + } + history.replace(toRelativeUrl(uri, window.location.origin)); + }; + + return ( + +
+
+
+
+ +
+
+
+
+ ); +} + +export default App; diff --git a/samples/routing/react-router-dom-v5-hash/src/assets/logo.svg b/samples/routing/react-router-dom-v5-hash/src/assets/logo.svg new file mode 100644 index 00000000..9dfc1c05 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5-hash/src/components/Footer.tsx b/samples/routing/react-router-dom-v5-hash/src/components/Footer.tsx new file mode 100644 index 00000000..92210e0e --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/Footer.tsx @@ -0,0 +1,44 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; + +function Footer() { + const { authState, oktaAuth } = useOktaAuth(); + + const handleLogin = () => oktaAuth.signInWithRedirect(); + const handleLogout = () => oktaAuth.signOut(); + + return ( +
+
+ { + !authState || !authState.isAuthenticated ? + ( + <> +

Please log in

+ + + ) : + ( + <> +

You're logged in!

+ + + ) + } +
+ ); +} + +export default Footer; diff --git a/samples/routing/react-router-dom-v5-hash/src/components/Loading.tsx b/samples/routing/react-router-dom-v5-hash/src/components/Loading.tsx new file mode 100644 index 00000000..aac8ab35 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/Loading.tsx @@ -0,0 +1,21 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +const Loading: React.FC = () => { + return ( +

Loading...

+ ); +}; + +export default Loading; diff --git a/samples/routing/react-router-dom-v5-hash/src/components/LoginCallback.tsx b/samples/routing/react-router-dom-v5-hash/src/components/LoginCallback.tsx new file mode 100644 index 00000000..db7c3d43 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/LoginCallback.tsx @@ -0,0 +1,55 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { useHistory } from 'react-router-dom'; +import { useOktaAuth } from '@okta/okta-react'; + +const LoginCallback: React.FC<{ + homePath: string, + loadingElement: React.ReactElement +}> = ({ homePath, loadingElement }) => { + const { oktaAuth } = useOktaAuth(); + const history = useHistory(); + + React.useEffect(() => { + const handleLoginRedirect = async () => { + await oktaAuth.handleLoginRedirect(); + }; + + if (oktaAuth.token.isLoginRedirect()) { + // store redirectUri, it's cleared after `handleLoginRedirect` call + const redirectUri = oktaAuth.getOriginalUri(); + handleLoginRedirect() + .then(() => { + if (!redirectUri) { + // manual redirect when redirectUri is not set + // otherwise allow default behavior + history.replace(homePath); + } + }) + .catch(e => { + // TODO: handle error state(s) + console.error(e); + }); + } + else { + // we landed on root path, but do not have login callback params in url query string + history.replace(homePath); + } + }, [oktaAuth, history, homePath]); + + return loadingElement; +}; + +export default LoginCallback; diff --git a/samples/routing/react-router-dom-v5-hash/src/components/Nav.tsx b/samples/routing/react-router-dom-v5-hash/src/components/Nav.tsx new file mode 100644 index 00000000..b8a5b906 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/Nav.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Nav = () => { + return ( + + ); +} + +export default Nav; diff --git a/samples/routing/react-router-dom-v5-hash/src/components/Routes.tsx b/samples/routing/react-router-dom-v5-hash/src/components/Routes.tsx new file mode 100644 index 00000000..b4af4119 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/Routes.tsx @@ -0,0 +1,34 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { SecureRoute } from './SecureRoute'; + +import Home from '../pages/Home'; +import Protected from '../pages/Protected'; +import LoginCallback from './LoginCallback'; +import Loading from './Loading'; + + +// NOTE: `loginCallback` *must* be mounted on '/', as it matches the signIn redirect url +const AppRoutes = () => { + return ( + + (} />)} /> + + + + ); +}; + +export default AppRoutes; diff --git a/samples/routing/react-router-dom-v5-hash/src/components/SecureRoute.tsx b/samples/routing/react-router-dom-v5-hash/src/components/SecureRoute.tsx new file mode 100644 index 00000000..ba62e4b3 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/components/SecureRoute.tsx @@ -0,0 +1,77 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; +import { toRelativeUrl } from '@okta/okta-auth-js'; +import { Route, RouteProps, useRouteMatch } from 'react-router-dom'; +import Loading from './Loading'; + +export const SecureRoute: React.FC<{ + errorComponent?: React.ComponentType<{ error: Error }>; +} & RouteProps> = ({ errorComponent, ...routeProps }) => { + const { oktaAuth, authState } = useOktaAuth(); + const match = useRouteMatch(); + const isPending = React.useRef(false); + const [ error, setError ] = React.useState(null); + + React.useEffect(() => { + const login = async () => { + if (isPending.current) { + return; + } + + isPending.current = true; + + const originalUri = toRelativeUrl(window.location.href, window.location.origin); + oktaAuth.setOriginalUri(originalUri); + await oktaAuth.signInWithRedirect(); + }; + + // Only process logic if the route matches + if (!match) { + return; + } + + if (!authState) { + return; + } + + if (authState.isAuthenticated) { + isPending.current = false; + return; + } + + if (!authState.isAuthenticated) { + login().catch(err => { + setError(err); + }); + } + }, [authState, oktaAuth, match, isPending, setError]); + + if (error && errorComponent) { + const ErrorComponent = errorComponent; + return + } + + if (!authState || !authState?.isAuthenticated) { + return (); + } + + return ( + + ); +}; + +export default SecureRoute; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5-hash/src/index.css b/samples/routing/react-router-dom-v5-hash/src/index.css new file mode 100644 index 00000000..f746ef8c --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/index.css @@ -0,0 +1,54 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-link, a { + color: #61dafb; + padding: 0 5px; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +form label { + margin: 0 5px; +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5-hash/src/index.tsx b/samples/routing/react-router-dom-v5-hash/src/index.tsx new file mode 100644 index 00000000..9306f7b0 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/index.tsx @@ -0,0 +1,27 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import { HashRouter } from "react-router-dom"; + + +ReactDOM.render( + + + + + , + document.getElementById('root') +); diff --git a/samples/react-router-dom-v6/src/pages/Home.tsx b/samples/routing/react-router-dom-v5-hash/src/pages/Home.tsx similarity index 100% rename from samples/react-router-dom-v6/src/pages/Home.tsx rename to samples/routing/react-router-dom-v5-hash/src/pages/Home.tsx diff --git a/samples/react-router-dom-v6/src/pages/Protected.tsx b/samples/routing/react-router-dom-v5-hash/src/pages/Protected.tsx similarity index 100% rename from samples/react-router-dom-v6/src/pages/Protected.tsx rename to samples/routing/react-router-dom-v5-hash/src/pages/Protected.tsx diff --git a/samples/routing/react-router-dom-v5-hash/src/react-app-env.d.ts b/samples/routing/react-router-dom-v5-hash/src/react-app-env.d.ts new file mode 100644 index 00000000..e37d0a97 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/src/react-app-env.d.ts @@ -0,0 +1,13 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/// diff --git a/samples/routing/react-router-dom-v5-hash/tsconfig.json b/samples/routing/react-router-dom-v5-hash/tsconfig.json new file mode 100644 index 00000000..c8bdc640 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/samples/routing/react-router-dom-v5-hash/tsconfig.node.json b/samples/routing/react-router-dom-v5-hash/tsconfig.node.json new file mode 100644 index 00000000..e993792c --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": ["vite.config.ts"] +} diff --git a/samples/routing/react-router-dom-v5-hash/vite.config.js b/samples/routing/react-router-dom-v5-hash/vite.config.js new file mode 100644 index 00000000..88f8a134 --- /dev/null +++ b/samples/routing/react-router-dom-v5-hash/vite.config.js @@ -0,0 +1,54 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path'; +import getEnvModule from './env' + +getEnvModule().setEnvironmentVarsFromTestEnv(__dirname); + +process.env.CLIENT_ID = process.env.SPA_CLIENT_ID || process.env.CLIENT_ID; +process.env.OKTA_TESTING_DISABLEHTTPSCHECK = process.env.OKTA_TESTING_DISABLEHTTPSCHECK || false; +process.env.USE_INTERACTION_CODE = process.env.USE_INTERACTION_CODE || false; + +const env = {}; + +// List of environment variables made available to the app +[ + 'ISSUER', + 'CLIENT_ID', + 'SPA_CLIENT_ID', + 'OKTA_TESTING_DISABLEHTTPSCHECK', + 'USE_INTERACTION_CODE', +].forEach((key) => { + if (!process.env[key]) { + throw new Error(`Environment variable ${key} must be set. See README.md`); + } + env[key] = process.env[key]; +}); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + define: { + 'process.env': env + }, + resolve: { + alias: { + '@okta/okta-auth-js': path.resolve(__dirname, 'node_modules/@okta/okta-auth-js/dist/okta-auth-js.umd.js'), + 'react-router-dom': path.resolve(__dirname, 'node_modules/react-router-dom') + } + }, + server: { + port: process.env.PORT || 8080 + }, + build: { + rollupOptions: { + // always throw with build warnings + onwarn (warning, warn) { + warn('\nBuild warning happened, customize "onwarn" callback in vite.config.js to handle this error.'); + throw new Error(warning); + } + } + } +}) diff --git a/samples/routing/react-router-dom-v5/README.md b/samples/routing/react-router-dom-v5/README.md new file mode 100644 index 00000000..0d53e303 --- /dev/null +++ b/samples/routing/react-router-dom-v5/README.md @@ -0,0 +1,26 @@ +# Okta React Router DOM v5 Sample App + +Sample app to demonstrate how to use `react-router-dom` v5 with `@okta/okta-react`. + +## Install +```bash +$ git clone https://github.com/okta/okta-react.git +$ yarn +``` + +## Configure +Add an `testenv` file with the following fields +``` +SPA_CLIENT_ID= +ISSUER= +``` + +## Start +```bash +$ yarn workspace @okta/samples.react.react-router-dom-v5 start +``` +OR +```bash +$ cd ./samples/react-router-dom-v5 +$ yarn start +``` diff --git a/samples/routing/react-router-dom-v5/bs-config.js b/samples/routing/react-router-dom-v5/bs-config.js new file mode 100644 index 00000000..18e0ef15 --- /dev/null +++ b/samples/routing/react-router-dom-v5/bs-config.js @@ -0,0 +1,14 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +module.exports = { + port: process.env.PORT || 8080, + logLevel: 'silent', + files: ['./dist/**/*.{html,htm,css,js}'], + server: { + baseDir: './dist', + middleware: { + 0: null + } + }, + open: false +}; diff --git a/samples/routing/react-router-dom-v5/env/index.js b/samples/routing/react-router-dom-v5/env/index.js new file mode 100644 index 00000000..e9e83b30 --- /dev/null +++ b/samples/routing/react-router-dom-v5/env/index.js @@ -0,0 +1,18 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +export default function () { + let oktaEnv; + try { + oktaEnv = require('@okta/env'); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + // try local env module + oktaEnv = require('./okta-env'); + return oktaEnv; + } + + throw err; + } + + return oktaEnv; +} diff --git a/samples/routing/react-router-dom-v5/env/okta-env.js b/samples/routing/react-router-dom-v5/env/okta-env.js new file mode 100644 index 00000000..e5b0bc95 --- /dev/null +++ b/samples/routing/react-router-dom-v5/env/okta-env.js @@ -0,0 +1,51 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" +/*! + * Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +const dotenv = require('dotenv'); +const fs = require('fs'); +const path = require('path'); + +const TESTENV_FILE = 'testenv'; + +function setEnvironmentVars(envConfig) { + Object.keys(envConfig).forEach((k) => { + if (process.env[k] !== envConfig[k]) { + console.log(`Setting a new value for environment variable "${k}"`); + } + process.env[k] = envConfig[k]; + }); +} + +function getPath(currDir = __dirname) { + let res, prevDir; + // stop when find testenv file or reach to root dir + while (!fs.existsSync(res) && currDir !== prevDir) { + prevDir = currDir; + res = path.resolve(currDir, TESTENV_FILE); + currDir = path.resolve(currDir, '..'); + } + return fs.existsSync(res) ? res : null; +} + +function setEnvironmentVarsFromTestEnv(currDir) { + const testEnvPath = getPath(currDir); + if (!testEnvPath) { + return; + } + const envConfig = dotenv.parse(fs.readFileSync(testEnvPath)); + setEnvironmentVars(envConfig); +} + +module.exports = { + setEnvironmentVarsFromTestEnv +}; diff --git a/samples/routing/react-router-dom-v5/index.html b/samples/routing/react-router-dom-v5/index.html new file mode 100644 index 00000000..1cadbcc7 --- /dev/null +++ b/samples/routing/react-router-dom-v5/index.html @@ -0,0 +1,13 @@ + + + + + + + React Router v5 Sample + + +
+ + + diff --git a/samples/routing/react-router-dom-v5/package.json b/samples/routing/react-router-dom-v5/package.json new file mode 100644 index 00000000..d8685d3e --- /dev/null +++ b/samples/routing/react-router-dom-v5/package.json @@ -0,0 +1,26 @@ +{ + "comment": "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'", + "name": "@okta/samples.react.react-router-dom-v5", + "private": true, + "version": "0.3.0", + "scripts": { + "prestart": "vite build", + "start": "lite-server", + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-router-dom": "5.3.0", + "@okta/okta-auth-js": "^6.2.0", + "@okta/okta-react": "*" + }, + "devDependencies": { + "@vitejs/plugin-react": "^1.0.7", + "vite": "^2.8.0", + "lite-server": "^2.6.1", + "dotenv": "^16.0.0" + } +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5/src/App.tsx b/samples/routing/react-router-dom-v5/src/App.tsx new file mode 100644 index 00000000..67ee0d7b --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/App.tsx @@ -0,0 +1,50 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { useHistory } from 'react-router-dom'; +import { Security } from '@okta/okta-react'; +import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js'; + +import Footer from './components/Footer'; +import Nav from './components/Nav'; +import Routes from './components/Routes'; + +function App() { + const oktaAuth = new OktaAuth({ + issuer: process.env.ISSUER, + clientId: process.env.SPA_CLIENT_ID, + redirectUri: window.location.origin + '/login/callback' + }); + + const history = useHistory(); + const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => { + history.replace(toRelativeUrl(originalUri || '/', window.location.origin)); + }; + + return ( + +
+
+
+
+ +
+
+
+
+ ); +} + +export default App; diff --git a/samples/routing/react-router-dom-v5/src/assets/logo.svg b/samples/routing/react-router-dom-v5/src/assets/logo.svg new file mode 100644 index 00000000..9dfc1c05 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5/src/components/Footer.tsx b/samples/routing/react-router-dom-v5/src/components/Footer.tsx new file mode 100644 index 00000000..92210e0e --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/components/Footer.tsx @@ -0,0 +1,44 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; + +function Footer() { + const { authState, oktaAuth } = useOktaAuth(); + + const handleLogin = () => oktaAuth.signInWithRedirect(); + const handleLogout = () => oktaAuth.signOut(); + + return ( +
+
+ { + !authState || !authState.isAuthenticated ? + ( + <> +

Please log in

+ + + ) : + ( + <> +

You're logged in!

+ + + ) + } +
+ ); +} + +export default Footer; diff --git a/samples/routing/react-router-dom-v5/src/components/Loading.tsx b/samples/routing/react-router-dom-v5/src/components/Loading.tsx new file mode 100644 index 00000000..aac8ab35 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/components/Loading.tsx @@ -0,0 +1,21 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +const Loading: React.FC = () => { + return ( +

Loading...

+ ); +}; + +export default Loading; diff --git a/samples/routing/react-router-dom-v5/src/components/Nav.tsx b/samples/routing/react-router-dom-v5/src/components/Nav.tsx new file mode 100644 index 00000000..5621a555 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/components/Nav.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Nav = () => { + return ( + + ); +} + +export default Nav; diff --git a/samples/routing/react-router-dom-v5/src/components/Routes.tsx b/samples/routing/react-router-dom-v5/src/components/Routes.tsx new file mode 100644 index 00000000..5fbe0a8e --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/components/Routes.tsx @@ -0,0 +1,32 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { LoginCallback } from '@okta/okta-react'; +import { SecureRoute } from './SecureRoute'; + +import Home from '../pages/Home'; +import Protected from '../pages/Protected'; +import Loading from './Loading'; + +const AppRoutes = () => { + return ( + + + (} />)} /> + + + ); +}; + +export default AppRoutes; diff --git a/samples/routing/react-router-dom-v5/src/components/SecureRoute.tsx b/samples/routing/react-router-dom-v5/src/components/SecureRoute.tsx new file mode 100644 index 00000000..ba62e4b3 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/components/SecureRoute.tsx @@ -0,0 +1,77 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; +import { toRelativeUrl } from '@okta/okta-auth-js'; +import { Route, RouteProps, useRouteMatch } from 'react-router-dom'; +import Loading from './Loading'; + +export const SecureRoute: React.FC<{ + errorComponent?: React.ComponentType<{ error: Error }>; +} & RouteProps> = ({ errorComponent, ...routeProps }) => { + const { oktaAuth, authState } = useOktaAuth(); + const match = useRouteMatch(); + const isPending = React.useRef(false); + const [ error, setError ] = React.useState(null); + + React.useEffect(() => { + const login = async () => { + if (isPending.current) { + return; + } + + isPending.current = true; + + const originalUri = toRelativeUrl(window.location.href, window.location.origin); + oktaAuth.setOriginalUri(originalUri); + await oktaAuth.signInWithRedirect(); + }; + + // Only process logic if the route matches + if (!match) { + return; + } + + if (!authState) { + return; + } + + if (authState.isAuthenticated) { + isPending.current = false; + return; + } + + if (!authState.isAuthenticated) { + login().catch(err => { + setError(err); + }); + } + }, [authState, oktaAuth, match, isPending, setError]); + + if (error && errorComponent) { + const ErrorComponent = errorComponent; + return + } + + if (!authState || !authState?.isAuthenticated) { + return (); + } + + return ( + + ); +}; + +export default SecureRoute; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5/src/index.css b/samples/routing/react-router-dom-v5/src/index.css new file mode 100644 index 00000000..f746ef8c --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/index.css @@ -0,0 +1,54 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-link, a { + color: #61dafb; + padding: 0 5px; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +form label { + margin: 0 5px; +} \ No newline at end of file diff --git a/samples/react-router-dom-v6/src/index.tsx b/samples/routing/react-router-dom-v5/src/index.tsx similarity index 100% rename from samples/react-router-dom-v6/src/index.tsx rename to samples/routing/react-router-dom-v5/src/index.tsx diff --git a/samples/routing/react-router-dom-v5/src/pages/Home.tsx b/samples/routing/react-router-dom-v5/src/pages/Home.tsx new file mode 100644 index 00000000..a6523f0b --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/pages/Home.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Home = () => { + return ( + <> +

Home

+ logo + + ); +}; + +export default Home; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5/src/pages/Protected.tsx b/samples/routing/react-router-dom-v5/src/pages/Protected.tsx new file mode 100644 index 00000000..f86f4eb3 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/pages/Protected.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Protected = () => { + return ( + <> +

Protected

+ logo + + ); +}; + +export default Protected; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v5/src/react-app-env.d.ts b/samples/routing/react-router-dom-v5/src/react-app-env.d.ts new file mode 100644 index 00000000..e37d0a97 --- /dev/null +++ b/samples/routing/react-router-dom-v5/src/react-app-env.d.ts @@ -0,0 +1,13 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/// diff --git a/samples/routing/react-router-dom-v5/tsconfig.json b/samples/routing/react-router-dom-v5/tsconfig.json new file mode 100644 index 00000000..c8bdc640 --- /dev/null +++ b/samples/routing/react-router-dom-v5/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/samples/routing/react-router-dom-v5/tsconfig.node.json b/samples/routing/react-router-dom-v5/tsconfig.node.json new file mode 100644 index 00000000..e993792c --- /dev/null +++ b/samples/routing/react-router-dom-v5/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": ["vite.config.ts"] +} diff --git a/samples/routing/react-router-dom-v5/vite.config.js b/samples/routing/react-router-dom-v5/vite.config.js new file mode 100644 index 00000000..88f8a134 --- /dev/null +++ b/samples/routing/react-router-dom-v5/vite.config.js @@ -0,0 +1,54 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path'; +import getEnvModule from './env' + +getEnvModule().setEnvironmentVarsFromTestEnv(__dirname); + +process.env.CLIENT_ID = process.env.SPA_CLIENT_ID || process.env.CLIENT_ID; +process.env.OKTA_TESTING_DISABLEHTTPSCHECK = process.env.OKTA_TESTING_DISABLEHTTPSCHECK || false; +process.env.USE_INTERACTION_CODE = process.env.USE_INTERACTION_CODE || false; + +const env = {}; + +// List of environment variables made available to the app +[ + 'ISSUER', + 'CLIENT_ID', + 'SPA_CLIENT_ID', + 'OKTA_TESTING_DISABLEHTTPSCHECK', + 'USE_INTERACTION_CODE', +].forEach((key) => { + if (!process.env[key]) { + throw new Error(`Environment variable ${key} must be set. See README.md`); + } + env[key] = process.env[key]; +}); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + define: { + 'process.env': env + }, + resolve: { + alias: { + '@okta/okta-auth-js': path.resolve(__dirname, 'node_modules/@okta/okta-auth-js/dist/okta-auth-js.umd.js'), + 'react-router-dom': path.resolve(__dirname, 'node_modules/react-router-dom') + } + }, + server: { + port: process.env.PORT || 8080 + }, + build: { + rollupOptions: { + // always throw with build warnings + onwarn (warning, warn) { + warn('\nBuild warning happened, customize "onwarn" callback in vite.config.js to handle this error.'); + throw new Error(warning); + } + } + } +}) diff --git a/samples/routing/react-router-dom-v6-hash/README.md b/samples/routing/react-router-dom-v6-hash/README.md new file mode 100644 index 00000000..182c9640 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/README.md @@ -0,0 +1,28 @@ +# Okta React Router DOM v6 HashRouter Sample App + +Sample app to demonstrate how to use `react-router-dom` v6 with `@okta/okta-react`. + +**NOTE:** This sample is not runnable before fixing issue [#187](https://github.com/okta/okta-react/issues/187). See [this comment](https://github.com/okta/okta-react/issues/187#issuecomment-1043059092) for potential workaround. + +## Install +```bash +$ git clone https://github.com/okta/okta-react.git +$ yarn +``` + +## Configure +Add an `testenv` file with the following fields +``` +SPA_CLIENT_ID= +ISSUER= +``` + +## Start +```bash +$ yarn workspace @okta/samples.react.react-router-dom-v6-hash start +``` +OR +```bash +$ cd ./samples/react-router-dom-v6-hash +$ yarn start +``` diff --git a/samples/routing/react-router-dom-v6-hash/bs-config.js b/samples/routing/react-router-dom-v6-hash/bs-config.js new file mode 100644 index 00000000..18e0ef15 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/bs-config.js @@ -0,0 +1,14 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +module.exports = { + port: process.env.PORT || 8080, + logLevel: 'silent', + files: ['./dist/**/*.{html,htm,css,js}'], + server: { + baseDir: './dist', + middleware: { + 0: null + } + }, + open: false +}; diff --git a/samples/routing/react-router-dom-v6-hash/env/index.js b/samples/routing/react-router-dom-v6-hash/env/index.js new file mode 100644 index 00000000..e9e83b30 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/env/index.js @@ -0,0 +1,18 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +export default function () { + let oktaEnv; + try { + oktaEnv = require('@okta/env'); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + // try local env module + oktaEnv = require('./okta-env'); + return oktaEnv; + } + + throw err; + } + + return oktaEnv; +} diff --git a/samples/routing/react-router-dom-v6-hash/env/okta-env.js b/samples/routing/react-router-dom-v6-hash/env/okta-env.js new file mode 100644 index 00000000..e5b0bc95 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/env/okta-env.js @@ -0,0 +1,51 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" +/*! + * Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +const dotenv = require('dotenv'); +const fs = require('fs'); +const path = require('path'); + +const TESTENV_FILE = 'testenv'; + +function setEnvironmentVars(envConfig) { + Object.keys(envConfig).forEach((k) => { + if (process.env[k] !== envConfig[k]) { + console.log(`Setting a new value for environment variable "${k}"`); + } + process.env[k] = envConfig[k]; + }); +} + +function getPath(currDir = __dirname) { + let res, prevDir; + // stop when find testenv file or reach to root dir + while (!fs.existsSync(res) && currDir !== prevDir) { + prevDir = currDir; + res = path.resolve(currDir, TESTENV_FILE); + currDir = path.resolve(currDir, '..'); + } + return fs.existsSync(res) ? res : null; +} + +function setEnvironmentVarsFromTestEnv(currDir) { + const testEnvPath = getPath(currDir); + if (!testEnvPath) { + return; + } + const envConfig = dotenv.parse(fs.readFileSync(testEnvPath)); + setEnvironmentVars(envConfig); +} + +module.exports = { + setEnvironmentVarsFromTestEnv +}; diff --git a/samples/routing/react-router-dom-v6-hash/index.html b/samples/routing/react-router-dom-v6-hash/index.html new file mode 100644 index 00000000..718703dd --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/index.html @@ -0,0 +1,13 @@ + + + + + + + React Router v6 HashRouter Sample + + +
+ + + diff --git a/samples/routing/react-router-dom-v6-hash/package.json b/samples/routing/react-router-dom-v6-hash/package.json new file mode 100644 index 00000000..a5fa9211 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/package.json @@ -0,0 +1,26 @@ +{ + "comment": "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'", + "name": "@okta/samples.react.react-router-dom-v6-hash", + "private": true, + "version": "0.3.0", + "scripts": { + "prestart": "vite build", + "start": "lite-server", + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-router-dom": "6.2.1", + "@okta/okta-auth-js": "^6.2.0", + "@okta/okta-react": "*" + }, + "devDependencies": { + "@vitejs/plugin-react": "^1.0.7", + "vite": "^2.8.0", + "lite-server": "^2.6.1", + "dotenv": "^16.0.0" + } +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6-hash/src/App.tsx b/samples/routing/react-router-dom-v6-hash/src/App.tsx new file mode 100644 index 00000000..96341890 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/App.tsx @@ -0,0 +1,56 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { useNavigate } from 'react-router-dom'; +import { Security } from '@okta/okta-react'; +import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js'; + +import Footer from './components/Footer'; +import Nav from './components/Nav'; +import Routes from './components/Routes'; + + +function App() { + const oktaAuth = new OktaAuth({ + issuer: process.env.ISSUER, + clientId: process.env.SPA_CLIENT_ID, + redirectUri: window.location.origin + }); + + const navigate = useNavigate(); + const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => { + let uri = '/'; + if (originalUri) { + // strip the lead '/#' from the uri + uri = originalUri.startsWith('/#') ? originalUri.slice(2) : originalUri; + } + navigate(toRelativeUrl(uri, window.location.origin)); + }; + + return ( + +
+
+
+
+ +
+
+
+
+ ); +} + +export default App; diff --git a/samples/routing/react-router-dom-v6-hash/src/assets/logo.svg b/samples/routing/react-router-dom-v6-hash/src/assets/logo.svg new file mode 100644 index 00000000..9dfc1c05 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/react-router-dom-v6/src/components/Footer.tsx b/samples/routing/react-router-dom-v6-hash/src/components/Footer.tsx similarity index 100% rename from samples/react-router-dom-v6/src/components/Footer.tsx rename to samples/routing/react-router-dom-v6-hash/src/components/Footer.tsx diff --git a/samples/routing/react-router-dom-v6-hash/src/components/Loading.tsx b/samples/routing/react-router-dom-v6-hash/src/components/Loading.tsx new file mode 100644 index 00000000..aac8ab35 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/components/Loading.tsx @@ -0,0 +1,21 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +const Loading: React.FC = () => { + return ( +

Loading...

+ ); +}; + +export default Loading; diff --git a/samples/routing/react-router-dom-v6-hash/src/components/LoginCallback.tsx b/samples/routing/react-router-dom-v6-hash/src/components/LoginCallback.tsx new file mode 100644 index 00000000..3c8910b1 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/components/LoginCallback.tsx @@ -0,0 +1,46 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +import { useNavigate } from 'react-router-dom'; +import { useOktaAuth } from '@okta/okta-react'; + +const LoginCallback: React.FC<{ + homePath: string, + loadingElement: React.ReactElement +}> = ({ homePath, loadingElement }) => { + const { oktaAuth } = useOktaAuth(); + const navigate = useNavigate(); + + React.useEffect(() => { + const handleLoginRedirect = async () => { + await oktaAuth.handleLoginRedirect(); + }; + + if (oktaAuth.token.isLoginRedirect()) { + handleLoginRedirect() + .catch(e => { + // TODO: handle error state(s) + console.error(e); + }); + } + else { + // we landed on root path, but do not have login callback params in url query string + navigate(homePath, { replace: true }); + } + }, [oktaAuth, navigate, homePath]); + + return loadingElement; +}; + +export default LoginCallback; diff --git a/samples/routing/react-router-dom-v6-hash/src/components/Nav.tsx b/samples/routing/react-router-dom-v6-hash/src/components/Nav.tsx new file mode 100644 index 00000000..06ce91b2 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/components/Nav.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Nav = () => { + return ( + + ); +}; + +export default Nav; diff --git a/samples/routing/react-router-dom-v6-hash/src/components/Routes.tsx b/samples/routing/react-router-dom-v6-hash/src/components/Routes.tsx new file mode 100644 index 00000000..f6eba1ab --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/components/Routes.tsx @@ -0,0 +1,36 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { Routes, Route } from 'react-router-dom'; +import { RequiredAuth } from './SecureRoute'; + +import Home from '../pages/Home'; +import Protected from '../pages/Protected'; +import LoginCallback from './LoginCallback'; +import Loading from './Loading'; + + +// NOTE: `loginCallback` *must* be mounted on '/', as it matches the signIn redirect url +const AppRoutes = () => { + return ( + + } />} /> + } /> + }> + } /> + + + ); +}; + +export default AppRoutes; diff --git a/samples/routing/react-router-dom-v6-hash/src/components/SecureRoute.tsx b/samples/routing/react-router-dom-v6-hash/src/components/SecureRoute.tsx new file mode 100644 index 00000000..b1b0ebee --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/components/SecureRoute.tsx @@ -0,0 +1,36 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; +import { toRelativeUrl } from '@okta/okta-auth-js'; +import { Outlet } from 'react-router-dom'; +import Loading from './Loading'; + + +export const RequiredAuth: React.FC = () => { + const { oktaAuth, authState } = useOktaAuth(); + + if (oktaAuth.token.isLoginRedirect()) { + return (); + } + + if (!authState || !authState?.isAuthenticated) { + const originalUri = toRelativeUrl(window.location.href, window.location.origin); + oktaAuth.setOriginalUri(originalUri); + oktaAuth.signInWithRedirect(); + + return (); + } + + return (); +} diff --git a/samples/routing/react-router-dom-v6-hash/src/index.css b/samples/routing/react-router-dom-v6-hash/src/index.css new file mode 100644 index 00000000..f746ef8c --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/index.css @@ -0,0 +1,54 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-link, a { + color: #61dafb; + padding: 0 5px; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +form label { + margin: 0 5px; +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6-hash/src/index.tsx b/samples/routing/react-router-dom-v6-hash/src/index.tsx new file mode 100644 index 00000000..9306f7b0 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/index.tsx @@ -0,0 +1,27 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import { HashRouter } from "react-router-dom"; + + +ReactDOM.render( + + + + + , + document.getElementById('root') +); diff --git a/samples/routing/react-router-dom-v6-hash/src/pages/Home.tsx b/samples/routing/react-router-dom-v6-hash/src/pages/Home.tsx new file mode 100644 index 00000000..a6523f0b --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/pages/Home.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Home = () => { + return ( + <> +

Home

+ logo + + ); +}; + +export default Home; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6-hash/src/pages/Protected.tsx b/samples/routing/react-router-dom-v6-hash/src/pages/Protected.tsx new file mode 100644 index 00000000..f86f4eb3 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/pages/Protected.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Protected = () => { + return ( + <> +

Protected

+ logo + + ); +}; + +export default Protected; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6-hash/src/react-app-env.d.ts b/samples/routing/react-router-dom-v6-hash/src/react-app-env.d.ts new file mode 100644 index 00000000..e37d0a97 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/src/react-app-env.d.ts @@ -0,0 +1,13 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/// diff --git a/samples/routing/react-router-dom-v6-hash/tsconfig.json b/samples/routing/react-router-dom-v6-hash/tsconfig.json new file mode 100644 index 00000000..c8bdc640 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/samples/routing/react-router-dom-v6-hash/tsconfig.node.json b/samples/routing/react-router-dom-v6-hash/tsconfig.node.json new file mode 100644 index 00000000..e993792c --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": ["vite.config.ts"] +} diff --git a/samples/routing/react-router-dom-v6-hash/vite.config.js b/samples/routing/react-router-dom-v6-hash/vite.config.js new file mode 100644 index 00000000..88f8a134 --- /dev/null +++ b/samples/routing/react-router-dom-v6-hash/vite.config.js @@ -0,0 +1,54 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path'; +import getEnvModule from './env' + +getEnvModule().setEnvironmentVarsFromTestEnv(__dirname); + +process.env.CLIENT_ID = process.env.SPA_CLIENT_ID || process.env.CLIENT_ID; +process.env.OKTA_TESTING_DISABLEHTTPSCHECK = process.env.OKTA_TESTING_DISABLEHTTPSCHECK || false; +process.env.USE_INTERACTION_CODE = process.env.USE_INTERACTION_CODE || false; + +const env = {}; + +// List of environment variables made available to the app +[ + 'ISSUER', + 'CLIENT_ID', + 'SPA_CLIENT_ID', + 'OKTA_TESTING_DISABLEHTTPSCHECK', + 'USE_INTERACTION_CODE', +].forEach((key) => { + if (!process.env[key]) { + throw new Error(`Environment variable ${key} must be set. See README.md`); + } + env[key] = process.env[key]; +}); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + define: { + 'process.env': env + }, + resolve: { + alias: { + '@okta/okta-auth-js': path.resolve(__dirname, 'node_modules/@okta/okta-auth-js/dist/okta-auth-js.umd.js'), + 'react-router-dom': path.resolve(__dirname, 'node_modules/react-router-dom') + } + }, + server: { + port: process.env.PORT || 8080 + }, + build: { + rollupOptions: { + // always throw with build warnings + onwarn (warning, warn) { + warn('\nBuild warning happened, customize "onwarn" callback in vite.config.js to handle this error.'); + throw new Error(warning); + } + } + } +}) diff --git a/samples/react-router-dom-v6/.gitignore b/samples/routing/react-router-dom-v6/.gitignore similarity index 100% rename from samples/react-router-dom-v6/.gitignore rename to samples/routing/react-router-dom-v6/.gitignore diff --git a/samples/react-router-dom-v6/README.md b/samples/routing/react-router-dom-v6/README.md similarity index 100% rename from samples/react-router-dom-v6/README.md rename to samples/routing/react-router-dom-v6/README.md diff --git a/samples/routing/react-router-dom-v6/bs-config.js b/samples/routing/react-router-dom-v6/bs-config.js new file mode 100644 index 00000000..18e0ef15 --- /dev/null +++ b/samples/routing/react-router-dom-v6/bs-config.js @@ -0,0 +1,14 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +module.exports = { + port: process.env.PORT || 8080, + logLevel: 'silent', + files: ['./dist/**/*.{html,htm,css,js}'], + server: { + baseDir: './dist', + middleware: { + 0: null + } + }, + open: false +}; diff --git a/samples/routing/react-router-dom-v6/env/index.js b/samples/routing/react-router-dom-v6/env/index.js new file mode 100644 index 00000000..e9e83b30 --- /dev/null +++ b/samples/routing/react-router-dom-v6/env/index.js @@ -0,0 +1,18 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +export default function () { + let oktaEnv; + try { + oktaEnv = require('@okta/env'); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + // try local env module + oktaEnv = require('./okta-env'); + return oktaEnv; + } + + throw err; + } + + return oktaEnv; +} diff --git a/samples/routing/react-router-dom-v6/env/okta-env.js b/samples/routing/react-router-dom-v6/env/okta-env.js new file mode 100644 index 00000000..e5b0bc95 --- /dev/null +++ b/samples/routing/react-router-dom-v6/env/okta-env.js @@ -0,0 +1,51 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" +/*! + * Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +const dotenv = require('dotenv'); +const fs = require('fs'); +const path = require('path'); + +const TESTENV_FILE = 'testenv'; + +function setEnvironmentVars(envConfig) { + Object.keys(envConfig).forEach((k) => { + if (process.env[k] !== envConfig[k]) { + console.log(`Setting a new value for environment variable "${k}"`); + } + process.env[k] = envConfig[k]; + }); +} + +function getPath(currDir = __dirname) { + let res, prevDir; + // stop when find testenv file or reach to root dir + while (!fs.existsSync(res) && currDir !== prevDir) { + prevDir = currDir; + res = path.resolve(currDir, TESTENV_FILE); + currDir = path.resolve(currDir, '..'); + } + return fs.existsSync(res) ? res : null; +} + +function setEnvironmentVarsFromTestEnv(currDir) { + const testEnvPath = getPath(currDir); + if (!testEnvPath) { + return; + } + const envConfig = dotenv.parse(fs.readFileSync(testEnvPath)); + setEnvironmentVars(envConfig); +} + +module.exports = { + setEnvironmentVarsFromTestEnv +}; diff --git a/samples/routing/react-router-dom-v6/index.html b/samples/routing/react-router-dom-v6/index.html new file mode 100644 index 00000000..b4bcd0ec --- /dev/null +++ b/samples/routing/react-router-dom-v6/index.html @@ -0,0 +1,13 @@ + + + + + + + React Router v6 Sample + + +
+ + + diff --git a/samples/react-router-dom-v6/package.json b/samples/routing/react-router-dom-v6/package.json similarity index 100% rename from samples/react-router-dom-v6/package.json rename to samples/routing/react-router-dom-v6/package.json diff --git a/samples/react-router-dom-v6/src/App.tsx b/samples/routing/react-router-dom-v6/src/App.tsx similarity index 100% rename from samples/react-router-dom-v6/src/App.tsx rename to samples/routing/react-router-dom-v6/src/App.tsx diff --git a/samples/routing/react-router-dom-v6/src/assets/logo.svg b/samples/routing/react-router-dom-v6/src/assets/logo.svg new file mode 100644 index 00000000..9dfc1c05 --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6/src/components/Footer.tsx b/samples/routing/react-router-dom-v6/src/components/Footer.tsx new file mode 100644 index 00000000..893bd899 --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/components/Footer.tsx @@ -0,0 +1,45 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; + + +function Footer() { + const { authState, oktaAuth } = useOktaAuth(); + + const handleLogin = () => oktaAuth.signInWithRedirect(); + const handleLogout = () => oktaAuth.signOut(); + + return ( +
+
+ { + !authState || !authState.isAuthenticated ? + ( + <> +

Please log in

+ + + ) : + ( + <> +

You're logged in!

+ + + ) + } +
+ ); +} + +export default Footer; diff --git a/samples/routing/react-router-dom-v6/src/components/Loading.tsx b/samples/routing/react-router-dom-v6/src/components/Loading.tsx new file mode 100644 index 00000000..aac8ab35 --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/components/Loading.tsx @@ -0,0 +1,21 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; + +const Loading: React.FC = () => { + return ( +

Loading...

+ ); +}; + +export default Loading; diff --git a/samples/react-router-dom-v6/src/components/Nav.tsx b/samples/routing/react-router-dom-v6/src/components/Nav.tsx similarity index 100% rename from samples/react-router-dom-v6/src/components/Nav.tsx rename to samples/routing/react-router-dom-v6/src/components/Nav.tsx diff --git a/samples/react-router-dom-v6/src/components/Routes.tsx b/samples/routing/react-router-dom-v6/src/components/Routes.tsx similarity index 100% rename from samples/react-router-dom-v6/src/components/Routes.tsx rename to samples/routing/react-router-dom-v6/src/components/Routes.tsx diff --git a/samples/react-router-dom-v6/src/components/SecureRoute.tsx b/samples/routing/react-router-dom-v6/src/components/SecureRoute.tsx similarity index 100% rename from samples/react-router-dom-v6/src/components/SecureRoute.tsx rename to samples/routing/react-router-dom-v6/src/components/SecureRoute.tsx diff --git a/samples/react-router-dom-v6/src/config.ts b/samples/routing/react-router-dom-v6/src/config.ts similarity index 100% rename from samples/react-router-dom-v6/src/config.ts rename to samples/routing/react-router-dom-v6/src/config.ts diff --git a/samples/routing/react-router-dom-v6/src/index.css b/samples/routing/react-router-dom-v6/src/index.css new file mode 100644 index 00000000..f746ef8c --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/index.css @@ -0,0 +1,54 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-link, a { + color: #61dafb; + padding: 0 5px; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +form label { + margin: 0 5px; +} \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6/src/index.tsx b/samples/routing/react-router-dom-v6/src/index.tsx new file mode 100644 index 00000000..94f7f6e3 --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/index.tsx @@ -0,0 +1,27 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import { BrowserRouter } from "react-router-dom"; + + +ReactDOM.render( + + + + + , + document.getElementById('root') +); diff --git a/samples/routing/react-router-dom-v6/src/pages/Home.tsx b/samples/routing/react-router-dom-v6/src/pages/Home.tsx new file mode 100644 index 00000000..a6523f0b --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/pages/Home.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Home = () => { + return ( + <> +

Home

+ logo + + ); +}; + +export default Home; \ No newline at end of file diff --git a/samples/routing/react-router-dom-v6/src/pages/Protected.tsx b/samples/routing/react-router-dom-v6/src/pages/Protected.tsx new file mode 100644 index 00000000..f86f4eb3 --- /dev/null +++ b/samples/routing/react-router-dom-v6/src/pages/Protected.tsx @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import React from 'react'; +import logo from '../assets/logo.svg'; + +const Protected = () => { + return ( + <> +

Protected

+ logo + + ); +}; + +export default Protected; \ No newline at end of file diff --git a/samples/react-router-dom-v6/src/vite-env.d.ts b/samples/routing/react-router-dom-v6/src/vite-env.d.ts similarity index 100% rename from samples/react-router-dom-v6/src/vite-env.d.ts rename to samples/routing/react-router-dom-v6/src/vite-env.d.ts diff --git a/samples/routing/react-router-dom-v6/tsconfig.json b/samples/routing/react-router-dom-v6/tsconfig.json new file mode 100644 index 00000000..c8bdc640 --- /dev/null +++ b/samples/routing/react-router-dom-v6/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/samples/routing/react-router-dom-v6/tsconfig.node.json b/samples/routing/react-router-dom-v6/tsconfig.node.json new file mode 100644 index 00000000..e993792c --- /dev/null +++ b/samples/routing/react-router-dom-v6/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": ["vite.config.ts"] +} diff --git a/samples/routing/react-router-dom-v6/vite.config.js b/samples/routing/react-router-dom-v6/vite.config.js new file mode 100644 index 00000000..88f8a134 --- /dev/null +++ b/samples/routing/react-router-dom-v6/vite.config.js @@ -0,0 +1,54 @@ +// "IMPORTANT: THIS FILE IS GENERATED, CHANGES SHOULD BE MADE WITHIN '@okta/generator'" + +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path'; +import getEnvModule from './env' + +getEnvModule().setEnvironmentVarsFromTestEnv(__dirname); + +process.env.CLIENT_ID = process.env.SPA_CLIENT_ID || process.env.CLIENT_ID; +process.env.OKTA_TESTING_DISABLEHTTPSCHECK = process.env.OKTA_TESTING_DISABLEHTTPSCHECK || false; +process.env.USE_INTERACTION_CODE = process.env.USE_INTERACTION_CODE || false; + +const env = {}; + +// List of environment variables made available to the app +[ + 'ISSUER', + 'CLIENT_ID', + 'SPA_CLIENT_ID', + 'OKTA_TESTING_DISABLEHTTPSCHECK', + 'USE_INTERACTION_CODE', +].forEach((key) => { + if (!process.env[key]) { + throw new Error(`Environment variable ${key} must be set. See README.md`); + } + env[key] = process.env[key]; +}); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + define: { + 'process.env': env + }, + resolve: { + alias: { + '@okta/okta-auth-js': path.resolve(__dirname, 'node_modules/@okta/okta-auth-js/dist/okta-auth-js.umd.js'), + 'react-router-dom': path.resolve(__dirname, 'node_modules/react-router-dom') + } + }, + server: { + port: process.env.PORT || 8080 + }, + build: { + rollupOptions: { + // always throw with build warnings + onwarn (warning, warn) { + warn('\nBuild warning happened, customize "onwarn" callback in vite.config.js to handle this error.'); + throw new Error(warning); + } + } + } +}) diff --git a/test/routing-samples/babel.config.js b/test/routing-samples/babel.config.js new file mode 100644 index 00000000..224e651a --- /dev/null +++ b/test/routing-samples/babel.config.js @@ -0,0 +1,24 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +module.exports = { + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "14" + } + } + ] + ] +} \ No newline at end of file diff --git a/test/routing-samples/package-lock.json b/test/routing-samples/package-lock.json new file mode 100644 index 00000000..b344ba7b --- /dev/null +++ b/test/routing-samples/package-lock.json @@ -0,0 +1,3431 @@ +{ + "name": "webdriverio-tests", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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==", + "dev": true, + "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=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@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==", + "dev": true, + "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==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@testim/chrome-version": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.2.tgz", + "integrity": "sha512-1c4ZOETSRpI0iBfIFUqU4KqwBAB2lHUAlBjZz/YqOHqwM9dTTzjV6Km0ZkiEiSCx/tLr1BtESIKyWWMww+RUqw==", + "dev": true + }, + "@types/aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-P+dkdFu0n08PDIvw+9nT9ByQnd+Udc8DaWPb9HKfaPwCvWvQpC5XaMRx2xLWECm9x1VKNps6vEAlirjA6+uNrQ==", + "dev": true + }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/diff": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.0.2.tgz", + "integrity": "sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==", + "dev": true + }, + "@types/easy-table": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/easy-table/-/easy-table-0.0.33.tgz", + "integrity": "sha512-/vvqcJPmZUfQwCgemL0/34G7bIQnCuvgls379ygRlcC1FqNqk3n+VZ15dAO51yl6JNDoWd8vsk+kT8zfZ1VZSw==", + "dev": true + }, + "@types/ejs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.0.tgz", + "integrity": "sha512-DCg+Ka+uDQ31lJ/UtEXVlaeV3d6t81gifaVWKJy4MYVVgvJttyX/viREy+If7fz+tK/gVxTGMtyrFPnm4gjrVA==", + "dev": true + }, + "@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "@types/inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-BNoMetRf3gmkpAlV5we+kxyZTle7YibdOntIZbU5pyIfMdcwy784KfeZDAcuyMznkh5OLa17RVXZOGA5LTlkgQ==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jasmine": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.3.tgz", + "integrity": "sha512-SWyMrjgdAUHNQmutvDcKablrJhkDLy4wunTme8oYLjKp41GnHGxMRXr2MQMvy/qy8H3LdzwQk9gH4hZ6T++H8g==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", + "dev": true + }, + "@types/lodash.flattendeep": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/lodash.flattendeep/-/lodash.flattendeep-4.4.6.tgz", + "integrity": "sha512-uLm2MaRVlqJSGsMK0RZpP5T3KqReq+9WbYDHCUhBhp98v56hMG/Yht52bsoTSui9xz2mUvQ9NfG3LrNGDL92Ng==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.pickby": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.pickby/-/lodash.pickby-4.6.6.tgz", + "integrity": "sha512-NFa13XxlMd9eFi0UFZFWIztpMpXhozbijrx3Yb1viYZphT7jyopIFVoIRF4eYMjruWNEG1rnyrRmg/8ej9T8Iw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.union": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.6.tgz", + "integrity": "sha512-Wu0ZEVNcyCz8eAn6TlUbYWZoGbH9E+iOHxAZbwUoCEXdUiy6qpcz5o44mMXViM4vlPLLCPlkAubEP1gokoSZaw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz", + "integrity": "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA==", + "dev": true + }, + "@types/object-inspect": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@types/object-inspect/-/object-inspect-1.8.1.tgz", + "integrity": "sha512-0JTdf3CGV0oWzE6Wa40Ayv2e2GhpP3pEJMcrlM74vBSJPuuNkVwfDnl0SZxyFCXETcB4oKA/MpTVfuYSMOelBg==", + "dev": true + }, + "@types/recursive-readdir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.0.tgz", + "integrity": "sha512-HGk753KRu2N4mWduovY4BLjYq4jTOL29gV2OfGdGxHcPSWGFkC5RRIdk+VTs5XmYd7MVAD+JwKrcb5+5Y7FOCg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/stream-buffers": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/stream-buffers/-/stream-buffers-3.0.4.tgz", + "integrity": "sha512-qU/K1tb2yUdhXkLIATzsIPwbtX6BpZk0l3dPW6xqWyhfzzM1ECaQ/8faEnu3CNraLiQ9LHyQQPBGp7N9Fbs25w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", + "dev": true + }, + "@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-dDZH/tXzwjutnuk4UacGgFRwV+JSLaXL1ikvidfJprkb7L9Nx1njcRHHmi3Dsvt7pgqqTEeucQuOrWHPFgzVHA==", + "dev": true + }, + "@types/ua-parser-js": { + "version": "0.7.36", + "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", + "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", + "dev": true + }, + "@types/which": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", + "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==", + "dev": true + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "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": "*" + } + }, + "@wdio/cli": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-7.16.14.tgz", + "integrity": "sha512-eWo+/QCFqBHjFdbKEnywSDZk98XIyaYXV8fYfjBpr4aS752I+tV9KpaM1dHFIiafuWzwE614ifJTMa4iZ6pDNA==", + "dev": true, + "requires": { + "@types/ejs": "^3.0.5", + "@types/fs-extra": "^9.0.4", + "@types/inquirer": "^8.1.2", + "@types/lodash.flattendeep": "^4.4.6", + "@types/lodash.pickby": "^4.6.6", + "@types/lodash.union": "^4.6.6", + "@types/node": "^17.0.4", + "@types/recursive-readdir": "^2.2.0", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "async-exit-hook": "^2.0.1", + "chalk": "^4.0.0", + "chokidar": "^3.0.0", + "cli-spinners": "^2.1.0", + "ejs": "^3.0.1", + "fs-extra": "^10.0.0", + "inquirer": "8.1.5", + "lodash.flattendeep": "^4.4.0", + "lodash.pickby": "^4.6.0", + "lodash.union": "^4.6.0", + "mkdirp": "^1.0.4", + "recursive-readdir": "^2.2.2", + "webdriverio": "7.16.14", + "yargs": "^17.0.0", + "yarn-install": "^1.0.0" + } + }, + "@wdio/config": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.16.14.tgz", + "integrity": "sha512-CdB8F4XFbuH9W3JaLYQoJMPRzM+GQirg9Ay1dW4xNcmJk7m3TJbk3/L78oz8ey1TpCLjQTG8aNqI4SZlFO4JRg==", + "dev": true, + "requires": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "deepmerge": "^4.0.0", + "glob": "^7.1.2" + } + }, + "@wdio/jasmine-framework": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/jasmine-framework/-/jasmine-framework-7.16.14.tgz", + "integrity": "sha512-p0v71sQzd5jDomq+S5Z1JXRibIEwecD2zvwTCmRdb5LwhUM14pTZI9HIhiqGtVUS1+Dmg9IKI809GyljuMP81w==", + "dev": true, + "requires": { + "@types/jasmine": "3.10.3", + "@types/node": "^17.0.4", + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "expect-webdriverio": "^3.0.0", + "jasmine": "3.10.0" + } + }, + "@wdio/local-runner": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-7.16.14.tgz", + "integrity": "sha512-kEJjQHV5Avdv0fra6KvWUgCa5aLDUhgxWZP6y/tj2okCAJtD4AKmsfCHZ3+YId11vn2hgDnn1RN7ie//IxAGmA==", + "dev": true, + "requires": { + "@types/stream-buffers": "^3.0.3", + "@wdio/logger": "7.16.0", + "@wdio/repl": "7.16.14", + "@wdio/runner": "7.16.14", + "@wdio/types": "7.16.14", + "async-exit-hook": "^2.0.1", + "split2": "^4.0.0", + "stream-buffers": "^3.0.2" + } + }, + "@wdio/logger": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.16.0.tgz", + "integrity": "sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "strip-ansi": "^6.0.0" + } + }, + "@wdio/protocols": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.16.7.tgz", + "integrity": "sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==", + "dev": true + }, + "@wdio/repl": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.16.14.tgz", + "integrity": "sha512-Ezih0Y+lsGkKv3H3U56hdWgZiQGA3VaAYguSLd9+g1xbQq+zMKqSmfqECD9bAy+OgCCiVTRstES6lHZxJVPhAg==", + "dev": true, + "requires": { + "@wdio/utils": "7.16.14" + } + }, + "@wdio/reporter": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-7.16.14.tgz", + "integrity": "sha512-e/I2oGfqjx9+zI4NT/garqxm7Afnos1EcrGSNu75WmP3PNJt4i+9DKkROu4PM6XWcpUB4v2UF7Mv/NrL3TU9aA==", + "dev": true, + "requires": { + "@types/diff": "^5.0.0", + "@types/node": "^17.0.4", + "@types/object-inspect": "^1.8.0", + "@types/supports-color": "^8.1.0", + "@types/tmp": "^0.2.0", + "@wdio/types": "7.16.14", + "diff": "^5.0.0", + "fs-extra": "^10.0.0", + "object-inspect": "^1.10.3", + "supports-color": "8.1.1" + }, + "dependencies": { + "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" + } + } + } + }, + "@wdio/runner": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-7.16.14.tgz", + "integrity": "sha512-FX/OURrUyBDPbLAeLUKCMXIpzDyz7h3wZkQbnfO1g4Cr3+1SSd8mh0C0NeqTmzufen1oUmLu0jhZer04WsCrTw==", + "dev": true, + "requires": { + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "deepmerge": "^4.0.0", + "gaze": "^1.1.2", + "webdriver": "7.16.14", + "webdriverio": "7.16.14" + } + }, + "@wdio/spec-reporter": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-7.16.14.tgz", + "integrity": "sha512-hpS2rLXo91lfrit5/pjDSbff2lqQe+k07/JPOJ48W+ZPSI+ib7rSldI4JFYU4YuKN1TnhkbhxRBMib3bF3Fs+Q==", + "dev": true, + "requires": { + "@types/easy-table": "^0.0.33", + "@wdio/reporter": "7.16.14", + "@wdio/types": "7.16.14", + "chalk": "^4.0.0", + "easy-table": "^1.1.1", + "pretty-ms": "^7.0.0" + } + }, + "@wdio/types": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.16.14.tgz", + "integrity": "sha512-AyNI9iBSos9xWBmiFAF3sBs6AJXO/55VppU/eeF4HRdbZMtMarnvMuahM+jlUrA3vJSmDW+ufelG0MT//6vrnw==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "got": "^11.8.1" + } + }, + "@wdio/utils": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.16.14.tgz", + "integrity": "sha512-wwin8nVpIlhmXJkq6GJw9aDDzgLOJKgXTcEua0T2sdXjoW78u5Ly/GZrFXTjMGhacFvoZfitTrjyfyy4CxMVvw==", + "dev": true, + "requires": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "p-iteration": "^1.1.8" + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "dependencies": { + "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==", + "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" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "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" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true + }, + "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==", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "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==", + "dev": true + }, + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dev": true, + "requires": { + "follow-redirects": "^1.14.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "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 + }, + "cac": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cac/-/cac-3.0.4.tgz", + "integrity": "sha1-bSTO7Dcu/lybeYgIvH9JtHJCpO8=", + "dev": true, + "requires": { + "camelcase-keys": "^3.0.0", + "chalk": "^1.1.3", + "indent-string": "^3.0.0", + "minimist": "^1.2.0", + "read-pkg-up": "^1.0.1", + "suffix": "^0.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "camelcase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-3.0.0.tgz", + "integrity": "sha1-/AxsNgNj9zd+N5O5oWvM8QcMHKQ=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "map-obj": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-launcher": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", + "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", + "dev": true, + "requires": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + } + } + }, + "chromedriver": { + "version": "97.0.4", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-97.0.4.tgz", + "integrity": "sha512-mAOH1QSCaeYgniNOqceAzC8BVORQtWxsmgSOBuy8TV/CyyDTllLmKtNNORsxdqrDtefVlxRVQkEzYrlKiJsfFw==", + "dev": true, + "requires": { + "@testim/chrome-version": "^1.1.2", + "axios": "^0.24.0", + "del": "^6.0.0", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.1.0", + "tcp-port-used": "^1.0.1" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "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-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "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 + }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "crc-32": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "dev": true, + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.3.1" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "css-shorthand-properties": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", + "integrity": "sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==", + "dev": true + }, + "css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true + }, + "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" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "devtools": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.16.14.tgz", + "integrity": "sha512-cmTl4D/4BgKFf4ceaUB4CTd8uqFZrBT/9IU81bx/dasX+YmkJIjQpECYo+uHspyQLW6AdjZPPv39eG4YFpaLIw==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "@types/ua-parser-js": "^0.7.33", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "chrome-launcher": "^0.15.0", + "edge-paths": "^2.1.0", + "puppeteer-core": "^13.0.0", + "query-selector-shadow-dom": "^1.0.0", + "ua-parser-js": "^1.0.1", + "uuid": "^8.0.0" + } + }, + "devtools-protocol": { + "version": "0.0.964462", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.964462.tgz", + "integrity": "sha512-8rv6vWn+v0eYLTJKMlb3L2I3XT8jpbx3H3OmpD6e1W4QwbnOd0VrPXr/kr+U5vGLqTTRVGW7wePOJnikHN4bGw==", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, + "easy-table": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", + "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "wcwidth": "^1.0.1" + } + }, + "edge-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.2.1.tgz", + "integrity": "sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw==", + "dev": true, + "requires": { + "@types/which": "^1.3.2", + "which": "^2.0.2" + } + }, + "ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "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" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "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=", + "dev": true + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "expect-webdriverio": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-3.1.4.tgz", + "integrity": "sha512-65FTS3bmxcIp0cq6fLb/72TrCQXBCpwPLC7SwMWdpPlLq461mXcK1BPKJJjnIC587aXSKD+3E4hvnlCtwDmXfg==", + "dev": true, + "requires": { + "expect": "^27.0.2", + "jest-matcher-utils": "^27.0.2" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "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" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "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" + } + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "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" + } + }, + "filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "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==", + "dev": true + }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "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": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globule": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", + "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "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" + } + } + } + }, + "got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "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 + }, + "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 + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "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==", + "dev": true + }, + "inquirer": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.5.tgz", + "integrity": "sha512-G6/9xUqmt/r+UvufSyrPpt84NYwhKZ9jLsgMbQzlx804XErNupor8WQdBnBRrXmBfTPpuwf1sV+ss2ovjgdXIg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true + }, + "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-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "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==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "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-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-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "is2": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz", + "integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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==", + "dev": true, + "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=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jasmine": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.10.0.tgz", + "integrity": "sha512-2Y42VsC+3CQCTzTwJezOvji4qLORmKIE0kwowWC+934Krn6ZXNQYljiwK5st9V3PVx96BSiDYXSB60VVah3IlQ==", + "dev": true, + "requires": { + "glob": "^7.1.6", + "jasmine-core": "~3.10.0" + } + }, + "jasmine-core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.10.1.tgz", + "integrity": "sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==", + "dev": true + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "keyv": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz", + "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "ky": { + "version": "0.28.7", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.28.7.tgz", + "integrity": "sha512-a23i6qSr/ep15vdtw/zyEQIDLoUaKDg9Jf04CYl/0ns/wXNYna26zJpI+MeIFaPeDvkrjLPrKtKOiiI3IE53RQ==", + "dev": true + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "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==", + "dev": true, + "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" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "lighthouse-logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", + "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "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==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "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=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.pickby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", + "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "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" + } + }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true + }, + "loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "marky": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", + "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "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==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "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==", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "p-iteration": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.8.tgz", + "integrity": "sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "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==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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" + } + }, + "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==", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "dev": true + }, + "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==", + "dev": true + }, + "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=", + "dev": true + }, + "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==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "pretty-ms": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", + "dev": true, + "requires": { + "parse-ms": "^2.1.0" + } + }, + "printj": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", + "dev": true + }, + "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==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "puppeteer-core": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.2.0.tgz", + "integrity": "sha512-EfQlh6osciVLf9dY0a/rLNE4DzaxfK+T97mYyd5opY9u2MyBrr8NbayBhK1NEDoUC1w+FYnNI1oZg2ybEF3MNQ==", + "dev": true, + "requires": { + "debug": "4.3.3", + "devtools-protocol": "0.0.960912", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.0", + "node-fetch": "2.6.7", + "pkg-dir": "4.2.0", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "rimraf": "3.0.2", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.2.3" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "devtools-protocol": { + "version": "0.0.960912", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz", + "integrity": "sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "query-selector-shadow-dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz", + "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "dev": true, + "requires": { + "minimatch": "3.0.4" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "resq": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.2.tgz", + "integrity": "sha512-HmgVS3j+FLrEDBTDYysPdPVF9/hioDMJ/otOiQDKqk77YfZeeLOj0qi34yObumcud1gBpk+wpBTEg4kMicD++A==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1" + } + }, + "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" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rgb2hex": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", + "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.3.tgz", + "integrity": "sha512-6162iC/N7L7K8q3UvdOMWix1ju+esADGrDaPrTu5XJmCv69YNdYoUaop/iatN8GHK+YHOdszPP+qygA0yi04zQ==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "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==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "stream-buffers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", + "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "suffix": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/suffix/-/suffix-0.1.1.tgz", + "integrity": "sha1-zFgjFkag7xEC95R47zqSSP2chC8=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "requires": { + "debug": "4.3.1", + "is2": "^2.0.6" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "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==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "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 + }, + "ua-parser-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", + "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", + "dev": true + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "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" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "wdio-chromedriver-service": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/wdio-chromedriver-service/-/wdio-chromedriver-service-7.2.6.tgz", + "integrity": "sha512-nepyo50jXfkLjRPdVmnZ55+YcPI6xSzYJ6ReAfHEGbwQcIqx6G+8zyynvBM7BIjWGdCwEpX6dbyVTTnt1xh/Kw==", + "dev": true, + "requires": { + "@wdio/logger": "^7.5.3", + "fs-extra": "^9.1.0", + "split2": "^3.2.2", + "tcp-port-used": "^1.0.1" + }, + "dependencies": { + "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" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + } + } + } + }, + "webdriver": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.14.tgz", + "integrity": "sha512-wfD3Okv+XJVMzrFVSTkhU381pJn2HlbKyURC7uY4E2QLaalhJLrrqekofBOUsr7WMf9nqoQwiVHQygnyt0afFw==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "got": "^11.0.2", + "ky": "^0.28.5", + "lodash.merge": "^4.6.1" + } + }, + "webdriverio": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.16.14.tgz", + "integrity": "sha512-uzGGT0vXkkm5WKFwdr3MuzrKaqKERlikoaoO57bSFiwM3uBIQQqQPdwbwOMtwDaDH9Vjy+qEMtLvtTZEmp3oEg==", + "dev": true, + "requires": { + "@types/aria-query": "^5.0.0", + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/repl": "7.16.14", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "archiver": "^5.0.0", + "aria-query": "^5.0.0", + "css-shorthand-properties": "^1.1.1", + "css-value": "^0.0.1", + "devtools": "7.16.14", + "devtools-protocol": "^0.0.964462", + "fs-extra": "^10.0.0", + "get-port": "^5.1.1", + "grapheme-splitter": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "lodash.isobject": "^3.0.2", + "lodash.isplainobject": "^4.0.6", + "lodash.zip": "^4.2.0", + "minimatch": "^3.0.4", + "puppeteer-core": "^13.0.0", + "query-selector-shadow-dom": "^1.0.0", + "resq": "^1.9.1", + "rgb2hex": "0.2.5", + "serialize-error": "^8.0.0", + "webdriver": "7.16.14" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.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" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", + "dev": true + }, + "yarn-install": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yarn-install/-/yarn-install-1.0.0.tgz", + "integrity": "sha1-V/RQULgu/VcYKzlzxUqgXLXSUjA=", + "dev": true, + "requires": { + "cac": "^3.0.3", + "chalk": "^1.1.3", + "cross-spawn": "^4.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "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" + } + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } + } + } +} diff --git a/test/routing-samples/package.json b/test/routing-samples/package.json new file mode 100644 index 00000000..63dc3984 --- /dev/null +++ b/test/routing-samples/package.json @@ -0,0 +1,18 @@ +{ + "name": "@okta/routing-samples.e2e", + "version": "0.1.0", + "private": true, + "devDependencies": { + "@wdio/cli": "^7.16.14", + "@wdio/jasmine-framework": "^7.16.14", + "@wdio/local-runner": "^7.16.14", + "@wdio/selenium-standalone-service": "^7.16.14", + "@wdio/spec-reporter": "^7.16.14", + "cross-spawn-with-kill": "^1.0.0", + "wait-on": "^6.0.0" + }, + "scripts": { + "wdio": "wdio run wdio.conf.js", + "test": "node ./runner.js" + } +} diff --git a/test/routing-samples/page-objects/RouterTestAppPage.js b/test/routing-samples/page-objects/RouterTestAppPage.js new file mode 100644 index 00000000..c376b0ff --- /dev/null +++ b/test/routing-samples/page-objects/RouterTestAppPage.js @@ -0,0 +1,59 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/* eslint-disable */ +import { waitForLoad } from '../utils/waitForLoad'; + +/** +* main page object containing all methods, selectors and functionality +* that is shared across all page objects +*/ +class RouterTestAppPage { + + // Router App selectors + get header () { return $('main h1.page-header'); } + get homeNavLink () { return $('#home-nav-link'); } + get protectedNavLink () { return $('#protected-nav-link'); } + get loadingIcon () { return $('#loading-icon'); } + get footerBtn () { return $('footer > button[type="button"]'); } + + // Widget selectors + get widget () { return $('#okta-sign-in'); } + get usernameInput () { return $('#okta-sign-in form input[type="text"][name="identifier"]'); } + get nextBtn () { return $('#okta-sign-in form input[type="submit"][value="Next"]'); } + get passwordInput () { return $('#okta-sign-in form input[type="password"][name="credentials.passcode"]'); } + get verifyBtn () { return $('#okta-sign-in form input[type="submit"][value="Verify"]'); } + + async login (username, password) { + await this.usernameInput.setValue(username); + await this.nextBtn.click(); + await waitForLoad(this.passwordInput); + await this.passwordInput.setValue(password); + await this.verifyBtn.click(); + } + + async logout () { + await expect(this.footerBtn).toHaveText('Logout'); + await this.footerBtn.click(); + await browser.waitUntil(async () => await this.footerBtn.getText() === 'Login'); + } + + /** + * Opens a sub page of the page + * @param path path of the sub page (e.g. /path/to/page.html) + */ + open (path='/') { + return browser.url(`http://localhost:4440${path}`); + } +} + +export default new RouterTestAppPage(); diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js new file mode 100644 index 00000000..a549f1e4 --- /dev/null +++ b/test/routing-samples/runner.js @@ -0,0 +1,107 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/* eslint-disable */ +const path = require('path'); +const spawn = require('cross-spawn-with-kill'); +const waitOn = require('wait-on'); + +// will load environment vars from testenv file and set on process.env +require('@okta/env').setEnvironmentVarsFromTestEnv(__dirname); + +const ROUTER_APPS = [ + 'reach-router', + 'react-router-dom-v5', + 'react-router-dom-v5-hash', + 'react-router-dom-v6', + 'react-router-dom-v6-hash', +]; + +const runTestsOnApp = (app) => { + return new Promise((resolve) => { + // extend `process.env` so variables like PATH are included + const env = { ...(process.env), PORT: 4440 }; + // start react router app dev server + const routerApp = spawn('yarn', ['workspace', `@okta/samples.react.${app}`, 'start'], { env }); + console.log(`## ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ ## + Running e2e tests on ${app} +## ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ ##` + ); + const stdErrHandler = data => console.error('FATAL ERROR: ', data.toString()); + routerApp.stderr.on('data', stdErrHandler); + + let returnCode = 0; + routerApp.on('exit', function(code) { + console.log('Server exited with code: ' + code); + resolve(returnCode); + }); + + let routerAppError = null; + routerApp.on('error', function (err) { + console.log('error handler'); + console.log(err); + routerAppError = err; + }); + if (routerAppError) return routerApp.kill(); + + // only listen for errors during initialization. `routerApp.kill` will end the process with an error code + // un-binding listeners prevents false errors from being reported + routerApp.stderr.off('data', stdErrHandler); + waitOn({ + resources: [ + 'http-get://localhost:4440' + ], + delay: 100, + timeout: 10000 + }) + .then(() => { + const wdioConfig = path.resolve(__dirname, 'wdio.conf.js'); + + const runner = spawn('yarn', ['wdio', 'run', wdioConfig], { stdio: 'inherit' }); + + runner.on('exit', function(code) { + console.log('Test runner exited with code: ' + code); + returnCode = code; + routerApp.stderr.pause(); + routerApp.kill(code); + }); + runner.on('error', function(err) { + routerApp.kill(); + throw err; + }); + }) + .catch(err => { + console.error(err.message); + routerApp.kill(); + }); + }); +}; + +const runTests = async (apps) => { + for (app of apps) { + await runTestsOnApp(app); + console.log(`${app} app test run complete!\n`); + } +}; + +const appName = process.env.SAMPLE_APP; +if (appName) { + if (!ROUTER_APPS.includes(appName)) { + console.log(`Error: ${appName} not a valid router app`); + return; + } + + runTests([appName]).catch(console.error); +} +else { + runTests(ROUTER_APPS).catch(console.error); +} diff --git a/test/routing-samples/specs/router.e2e.js b/test/routing-samples/specs/router.e2e.js new file mode 100644 index 00000000..ba997325 --- /dev/null +++ b/test/routing-samples/specs/router.e2e.js @@ -0,0 +1,111 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/* eslint-disable */ +import TestApp from '../page-objects/RouterTestAppPage'; +import { waitForLoad } from '../utils/waitForLoad'; + +const { ISSUER, USERNAME, PASSWORD } = process.env; + +describe('React router test app', () => { + let isAuthenticated = false; + + const testLogin = async (elemToClick) => { + await elemToClick.click(); + + await waitForLoad(TestApp.widget); + await expect(browser).toHaveUrlContaining(`${ISSUER}/v1/authorize`); + + await TestApp.login(USERNAME, PASSWORD); + isAuthenticated = true; + await waitForLoad(TestApp.loadingIcon); + await waitForLoad(TestApp.header); + }; + + beforeEach(async () => { + await TestApp.open(); + }); + + afterEach(async () => { + if (isAuthenticated) { + await TestApp.logout(); + isAuthenticated = false; + } + }); + + it('should load home page', async () => { + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Home'); + }); + + it('should navigate to login when accessing protected route while unauthenticated', async () => { + await TestApp.protectedNavLink.click(); + await expect(TestApp.loadingIcon).toExist(); + await expect(TestApp.loadingIcon).toHaveTextContaining('Loading...'); + + await waitForLoad(TestApp.widget); + await expect(browser).toHaveUrlContaining(`${ISSUER}/v1/authorize`); + }); + + it('should login user after redirect from ', async () => { + await testLogin(TestApp.protectedNavLink); + await expect(browser).toHaveUrlContaining('/protected'); + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Protected'); + }); + + it('should login user after redirect from Login button', async () => { + await expect(TestApp.footerBtn).toHaveText('Login'); + await testLogin(TestApp.footerBtn); + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Home'); + await expect(TestApp.footerBtn).toHaveText('Logout'); + }); + + it('should navigate user to Home Page after logout on Protected Page', async () => { + await testLogin(TestApp.protectedNavLink); + await expect(browser).toHaveUrlContaining('/protected'); + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Protected'); + await TestApp.logout(); + isAuthenticated = false; + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Home'); + }); + + it('can toggle between tabs once authenticated', async () => { + await expect(TestApp.footerBtn).toHaveText('Login'); + await testLogin(TestApp.footerBtn); + await expect(TestApp.footerBtn).toHaveText('Logout'); + + // on Home Page + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Home'); + + // navigate to Protected Page + await TestApp.protectedNavLink.click(); + await waitForLoad(TestApp.header); + + // on Protected Page + await expect(browser).toHaveUrlContaining('/protected'); + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Protected'); + + // navigate to Home Page + await TestApp.homeNavLink.click(); + await waitForLoad(TestApp.header); + + // on Home Page + await expect(TestApp.header).toExist(); + await expect(TestApp.header).toHaveTextContaining('Home'); + }); +}); diff --git a/test/routing-samples/utils/waitForLoad.js b/test/routing-samples/utils/waitForLoad.js new file mode 100644 index 00000000..5e3a2cc9 --- /dev/null +++ b/test/routing-samples/utils/waitForLoad.js @@ -0,0 +1,16 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/* eslint-disable */ +export const waitForLoad = async (element) => { + await browser.waitUntil(async () => element.then(el => el.isDisplayed()), 5000, 'wait for element to load'); +}; diff --git a/test/routing-samples/wdio.conf.js b/test/routing-samples/wdio.conf.js new file mode 100644 index 00000000..ebaf7d6f --- /dev/null +++ b/test/routing-samples/wdio.conf.js @@ -0,0 +1,341 @@ +/*! + * Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +/* eslint-disable */ + +const logLevel = 'warn'; +const browserOptions = { + args: [] +}; + +if (process.env.CHROMIUM_BINARY) { + browserOptions.binary = process.env.CHROMIUM_BINARY; +} + +if (process.env.CI || process.env.CHROME_HEADLESS) { + browserOptions.args = browserOptions.args.concat([ + '--headless', + '--disable-gpu', + '--window-size=1600x1200', + '--no-sandbox', + '--whitelisted-ips', + '--disable-extensions', + '--verbose', + '--disable-dev-shm-usage' + ]); +} + +const CHROMEDRIVER_VERSION = process.env.CHROMEDRIVER_VERSION || '97.0.4692.36'; +const drivers = { + chrome: { version: CHROMEDRIVER_VERSION } +}; + +exports.config = { + // + // ==================== + // Runner Configuration + // ==================== + // + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + specs: [ + './specs/*.js' + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // First, you can define how many instances should be started at the same time. Let's + // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have + // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec + // files and you set maxInstances to 10, all spec files will get tested at the same time + // and 30 processes will get spawned. The property handles how many capabilities + // from the same test should run tests. + // + maxInstances: 10, + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://saucelabs.com/platform/platform-configurator + // + capabilities: [{ + + // maxInstances can get overwritten per capability. So if you have an in-house Selenium + // grid with only 5 firefox instances available you can make sure that not more than + // 5 instances get started at a time. + maxInstances: 5, + // + browserName: 'chrome', + acceptInsecureCerts: true + // If outputDir is provided WebdriverIO can capture driver session logs + // it is possible to configure which logTypes to include/exclude. + // excludeDriverLogs: ['*'], // pass '*' to exclude all driver session logs + // excludeDriverLogs: ['bugreport', 'server'], + }], + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + // Level of logging verbosity: trace | debug | info | warn | error | silent + logLevel, + // + // Set specific log levels per logger + // loggers: + // - webdriver, webdriverio + // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service + // - @wdio/mocha-framework, @wdio/jasmine-framework + // - @wdio/local-runner + // - @wdio/sumologic-reporter + // - @wdio/cli, @wdio/config, @wdio/utils + // Level of logging verbosity: trace | debug | info | warn | error | silent + // logLevels: { + // webdriver: 'info', + // '@wdio/appium-service': 'info' + // }, + // + // If you only want to run your tests until a specific amount of tests have failed use + // bail (default is 0 - don't bail, run all tests). + bail: 0, + // + // Set a base URL in order to shorten url command calls. If your `url` parameter starts + // with `/`, the base url gets prepended, not including the path portion of your baseUrl. + // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url + // gets prepended directly. + baseUrl: 'http://localhost:4440', + // + // Default timeout for all waitFor* commands. + waitforTimeout: 10000, + // + // Default timeout in milliseconds for request + // if browser driver or grid doesn't send response + connectionRetryTimeout: 120000, + // + // Default request retries count + connectionRetryCount: 3, + // + // Test runner services + // Services take over a specific job you don't want to take care of. They enhance + // your test setup with almost no effort. Unlike plugins, they don't add new + // commands. Instead, they hook themselves up into the test process. + services: [ + ['selenium-standalone', { + installArgs: { + drivers + }, + args: { + drivers + } + }] + ], + + // Framework you want to run your specs with. + // The following are supported: Mocha, Jasmine, and Cucumber + // see also: https://webdriver.io/docs/frameworks + // + // Make sure you have the wdio adapter package for the specific framework installed + // before running any tests. + framework: 'jasmine', + // + // The number of times to retry the entire specfile when it fails as a whole + // specFileRetries: 1, + // + // Delay in seconds between the spec file retry attempts + // specFileRetriesDelay: 0, + // + // Whether or not retried specfiles should be retried immediately or deferred to the end of the queue + // specFileRetriesDeferred: false, + // + // Test reporter for stdout. + // The only one supported by default is 'dot' + // see also: https://webdriver.io/docs/dot-reporter + reporters: ['spec'], + + + + // + // Options to be passed to Jasmine. + jasmineOpts: { + // Jasmine default timeout + defaultTimeoutInterval: 60000, + // + // The Jasmine framework allows interception of each assertion in order to log the state of the application + // or website depending on the result. For example, it is pretty handy to take a screenshot every time + // an assertion fails. + expectationResultHandler: function(passed, assertion) { + // do something + } + }, + + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + /** + * Gets executed once before all workers get launched. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + */ + // onPrepare: function (config, capabilities) { + // }, + /** + * Gets executed before a worker process is spawned and can be used to initialise specific service + * for that worker as well as modify runtime environments in an async fashion. + * @param {String} cid capability id (e.g 0-0) + * @param {[type]} caps object containing capabilities for session that will be spawn in the worker + * @param {[type]} specs specs to be run in the worker process + * @param {[type]} args object that will be merged with the main configuration once worker is initialised + * @param {[type]} execArgv list of string arguments passed to the worker process + */ + // onWorkerStart: function (cid, caps, specs, args, execArgv) { + // }, + /** + * Gets executed just before initialising the webdriver session and test framework. It allows you + * to manipulate configurations depending on the capability or spec. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {String} cid worker id (e.g. 0-0) + */ + // beforeSession: function (config, capabilities, specs, cid) { + // }, + /** + * Gets executed before test execution begins. At this point you can access to all global + * variables like `browser`. It is the perfect place to define custom commands. + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {Object} browser instance of created browser/device session + */ + // before: function (capabilities, specs) { + // }, + /** + * Runs before a WebdriverIO command gets executed. + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + */ + // beforeCommand: function (commandName, args) { + // }, + /** + * Hook that gets executed before the suite starts + * @param {Object} suite suite details + */ + // beforeSuite: function (suite) { + // }, + /** + * Function to be executed before a test (in Mocha/Jasmine) starts. + */ + // beforeTest: function (test, context) { + // }, + /** + * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling + * beforeEach in Mocha) + */ + // beforeHook: function (test, context) { + // }, + /** + * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling + * afterEach in Mocha) + */ + // afterHook: function (test, context, { error, result, duration, passed, retries }) { + // }, + /** + * Function to be executed after a test (in Mocha/Jasmine only) + * @param {Object} test test object + * @param {Object} context scope object the test was executed with + * @param {Error} result.error error object in case the test fails, otherwise `undefined` + * @param {Any} result.result return object of test function + * @param {Number} result.duration duration of test + * @param {Boolean} result.passed true if test has passed, otherwise false + * @param {Object} result.retries informations to spec related retries, e.g. `{ attempts: 0, limit: 0 }` + */ + // afterTest: function(test, context, { error, result, duration, passed, retries }) { + // }, + + + /** + * Hook that gets executed after the suite has ended + * @param {Object} suite suite details + */ + // afterSuite: function (suite) { + // }, + /** + * Runs after a WebdriverIO command gets executed + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + * @param {Number} result 0 - command success, 1 - command error + * @param {Object} error error object if any + */ + // afterCommand: function (commandName, args, result, error) { + // }, + /** + * Gets executed after all tests are done. You still have access to all global variables from + * the test. + * @param {Number} result 0 - test pass, 1 - test fail + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // after: function (result, capabilities, specs) { + // }, + /** + * Gets executed right after terminating the webdriver session. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // afterSession: function (config, capabilities, specs) { + // }, + /** + * Gets executed after all workers got shut down and the process is about to exit. An error + * thrown in the onComplete hook will result in the test run failing. + * @param {Object} exitCode 0 - success, 1 - fail + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {} results object containing test results + */ + // onComplete: function(exitCode, config, capabilities, results) { + // }, + /** + * Gets executed when a refresh happens. + * @param {String} oldSessionId session ID of the old session + * @param {String} newSessionId session ID of the new session + */ + //onReload: function(oldSessionId, newSessionId) { + //} +} diff --git a/util/maintain-banners.js b/util/maintain-banners.js index 14c08c52..4d77f639 100755 --- a/util/maintain-banners.js +++ b/util/maintain-banners.js @@ -10,7 +10,7 @@ const filePatterns = [ 'generated/**/*.{js,jsx,ts,tsx}', 'dist/bundles/*.{js,jsx,ts,tsx}' ]; -const files = globby.sync(path.join(__dirname, '..',`{${filePatterns.join(',')}}`)); +const files = globby.sync([path.join(__dirname, '..',`{${filePatterns.join(',')}}`), '!**/node_modules/**']); const bannerSource = fs.readFileSync(bannerSourcePath).toString(); const copyrightRegex = /(Copyright \(c\) )([0-9]+)-?([0-9]+)?/; From c0755ab4ec001e1cbb4dafc8d87e86f6987aeec0 Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 12:36:04 -0500 Subject: [PATCH 02/11] moves e2e test port to 8080 --- test/routing-samples/page-objects/RouterTestAppPage.js | 2 +- test/routing-samples/runner.js | 4 ++-- test/routing-samples/wdio.conf.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/routing-samples/page-objects/RouterTestAppPage.js b/test/routing-samples/page-objects/RouterTestAppPage.js index c376b0ff..ee2951ed 100644 --- a/test/routing-samples/page-objects/RouterTestAppPage.js +++ b/test/routing-samples/page-objects/RouterTestAppPage.js @@ -52,7 +52,7 @@ class RouterTestAppPage { * @param path path of the sub page (e.g. /path/to/page.html) */ open (path='/') { - return browser.url(`http://localhost:4440${path}`); + return browser.url(`http://localhost:8080${path}`); } } diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index a549f1e4..348aeddb 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -29,7 +29,7 @@ const ROUTER_APPS = [ const runTestsOnApp = (app) => { return new Promise((resolve) => { // extend `process.env` so variables like PATH are included - const env = { ...(process.env), PORT: 4440 }; + const env = { ...(process.env), PORT: 8080 }; // start react router app dev server const routerApp = spawn('yarn', ['workspace', `@okta/samples.react.${app}`, 'start'], { env }); console.log(`## ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ ## @@ -58,7 +58,7 @@ const runTestsOnApp = (app) => { routerApp.stderr.off('data', stdErrHandler); waitOn({ resources: [ - 'http-get://localhost:4440' + 'http-get://localhost:8080' ], delay: 100, timeout: 10000 diff --git a/test/routing-samples/wdio.conf.js b/test/routing-samples/wdio.conf.js index ebaf7d6f..cbbd8e9b 100644 --- a/test/routing-samples/wdio.conf.js +++ b/test/routing-samples/wdio.conf.js @@ -135,7 +135,7 @@ exports.config = { // with `/`, the base url gets prepended, not including the path portion of your baseUrl. // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url // gets prepended directly. - baseUrl: 'http://localhost:4440', + baseUrl: 'http://localhost:8080', // // Default timeout for all waitFor* commands. waitforTimeout: 10000, From dcad94af8eea037d6fa951ef421c491154bd406d Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 12:39:33 -0500 Subject: [PATCH 03/11] adding routing samples tests to bacon --- package.json | 2 +- test/routing-samples/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index aba6f5d7..b30744c1 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "start": "yarn workspace @okta/test.app.test-harness-app start", "test": "yarn lint && yarn test:unit && yarn test:e2e", "test:e2e": "yarn workspace @okta/test.e2e test", - "test:e2e:samples": "yarn workspace @okta/test.e2e-samples test", + "test:e2e:samples": "yarn workspace @okta/test.e2e-samples test && yarn workspace @okta/test.e2e.routing-samples test", "test:unit": "jest", "bundle": "rollup -c", "dev": "yarn bundle --watch", diff --git a/test/routing-samples/package.json b/test/routing-samples/package.json index 63dc3984..9a566f74 100644 --- a/test/routing-samples/package.json +++ b/test/routing-samples/package.json @@ -1,5 +1,5 @@ { - "name": "@okta/routing-samples.e2e", + "name": "@okta/test.e2e.routing-samples", "version": "0.1.0", "private": true, "devDependencies": { From 29ef9a6fc890777a41d1e31c6fba9d7f622554fd Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 12:42:15 -0500 Subject: [PATCH 04/11] lint fix --- test/routing-samples/runner.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index 348aeddb..774a5a17 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -97,10 +97,10 @@ const appName = process.env.SAMPLE_APP; if (appName) { if (!ROUTER_APPS.includes(appName)) { console.log(`Error: ${appName} not a valid router app`); - return; } - - runTests([appName]).catch(console.error); + else { + runTests([appName]).catch(console.error); + } } else { runTests(ROUTER_APPS).catch(console.error); From 3ea55598efcfceaf10fe015a44c4217069cb4ec8 Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 13:04:16 -0500 Subject: [PATCH 05/11] throw error if test fails --- test/routing-samples/runner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index 774a5a17..2755134a 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -99,9 +99,9 @@ if (appName) { console.log(`Error: ${appName} not a valid router app`); } else { - runTests([appName]).catch(console.error); + runTests([appName]); } } else { - runTests(ROUTER_APPS).catch(console.error); + runTests(ROUTER_APPS); } From 319d7a07b01ebe47532969accd0b6b39bda40a7e Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 13:18:08 -0500 Subject: [PATCH 06/11] bacon fix --- test/routing-samples/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/routing-samples/package.json b/test/routing-samples/package.json index 9a566f74..fc5fcb18 100644 --- a/test/routing-samples/package.json +++ b/test/routing-samples/package.json @@ -6,7 +6,7 @@ "@wdio/cli": "^7.16.14", "@wdio/jasmine-framework": "^7.16.14", "@wdio/local-runner": "^7.16.14", - "@wdio/selenium-standalone-service": "^7.16.14", + "@wdio/selenium-standalone-service": "^7.14.1", "@wdio/spec-reporter": "^7.16.14", "cross-spawn-with-kill": "^1.0.0", "wait-on": "^6.0.0" From 52b7e15bd2ea5fc8bb99717ca1b6fa144529a0af Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 13:33:27 -0500 Subject: [PATCH 07/11] bacon fixes --- package.json | 1 + scripts/setup.sh | 2 +- test/routing-samples/package.json | 2 +- test/routing-samples/runner.js | 4 ---- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b30744c1..0e3def13 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "test/routing-samples" ], "nohoist": [ + "**/@wdio/**", "**/@okta/okta-auth-js", "**/react", "**/react/**", diff --git a/scripts/setup.sh b/scripts/setup.sh index 14799369..df978ce6 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -5,7 +5,7 @@ export PATH="${PATH}:$(yarn global bin)" # Install required node version export NVM_DIR="/root/.nvm" -NODE_VERSION="${1:-v12.13.0}" +NODE_VERSION="${1:-v12.20.0}" setup_service node $NODE_VERSION cd ${OKTA_HOME}/${REPO} diff --git a/test/routing-samples/package.json b/test/routing-samples/package.json index fc5fcb18..9a566f74 100644 --- a/test/routing-samples/package.json +++ b/test/routing-samples/package.json @@ -6,7 +6,7 @@ "@wdio/cli": "^7.16.14", "@wdio/jasmine-framework": "^7.16.14", "@wdio/local-runner": "^7.16.14", - "@wdio/selenium-standalone-service": "^7.14.1", + "@wdio/selenium-standalone-service": "^7.16.14", "@wdio/spec-reporter": "^7.16.14", "cross-spawn-with-kill": "^1.0.0", "wait-on": "^6.0.0" diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index 2755134a..bf8040d3 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -78,10 +78,6 @@ const runTestsOnApp = (app) => { routerApp.kill(); throw err; }); - }) - .catch(err => { - console.error(err.message); - routerApp.kill(); }); }); }; From 8a654dc155203bc4e3d837144e685f8444a56802 Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 15:22:58 -0500 Subject: [PATCH 08/11] bacon fixes --- test/routing-samples/runner.js | 5 ++++- test/routing-samples/wdio.conf.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index bf8040d3..75129ffb 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -83,10 +83,13 @@ const runTestsOnApp = (app) => { }; const runTests = async (apps) => { + let exitCode = 0; for (app of apps) { - await runTestsOnApp(app); + const testRun = await runTestsOnApp(app); + exitCode = Math.max(exitCode, testRun); console.log(`${app} app test run complete!\n`); } + process.exit(exitCode); }; const appName = process.env.SAMPLE_APP; diff --git a/test/routing-samples/wdio.conf.js b/test/routing-samples/wdio.conf.js index cbbd8e9b..37ea7877 100644 --- a/test/routing-samples/wdio.conf.js +++ b/test/routing-samples/wdio.conf.js @@ -34,7 +34,7 @@ if (process.env.CI || process.env.CHROME_HEADLESS) { ]); } -const CHROMEDRIVER_VERSION = process.env.CHROMEDRIVER_VERSION || '97.0.4692.36'; +const CHROMEDRIVER_VERSION = process.env.CHROMEDRIVER_VERSION || '89.0.4389.23'; const drivers = { chrome: { version: CHROMEDRIVER_VERSION } }; From f5aa1cb06e0b3c4bb37b1f51d445a3ac3d0e7818 Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 15:38:07 -0500 Subject: [PATCH 09/11] bacon fix --- scripts/e2e-samples.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/e2e-samples.sh b/scripts/e2e-samples.sh index df3a1cb6..662531d0 100755 --- a/scripts/e2e-samples.sh +++ b/scripts/e2e-samples.sh @@ -4,6 +4,7 @@ source ${OKTA_HOME}/${REPO}/scripts/setup.sh "v14.18.0" setup_service google-chrome-stable 83.0.4103.61-1 +export CI=true export TEST_SUITE_TYPE="junit" export TEST_RESULT_FILE_DIR="${REPO}/test-reports/e2e-samples" From e4269abaaeedcac8aa5cdbbe1e7c63b62298f1e6 Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 16:03:32 -0500 Subject: [PATCH 10/11] bacon fixes --- test/routing-samples/runner.js | 1 - test/routing-samples/wdio.conf.js | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/routing-samples/runner.js b/test/routing-samples/runner.js index 75129ffb..137e233f 100644 --- a/test/routing-samples/runner.js +++ b/test/routing-samples/runner.js @@ -71,7 +71,6 @@ const runTestsOnApp = (app) => { runner.on('exit', function(code) { console.log('Test runner exited with code: ' + code); returnCode = code; - routerApp.stderr.pause(); routerApp.kill(code); }); runner.on('error', function(err) { diff --git a/test/routing-samples/wdio.conf.js b/test/routing-samples/wdio.conf.js index 37ea7877..08fa197e 100644 --- a/test/routing-samples/wdio.conf.js +++ b/test/routing-samples/wdio.conf.js @@ -11,6 +11,9 @@ */ /* eslint-disable */ +// will load environment vars from testenv file and set on process.env +require('@okta/env').setEnvironmentVarsFromTestEnv(__dirname); + const logLevel = 'warn'; const browserOptions = { @@ -95,9 +98,10 @@ exports.config = { // maxInstances can get overwritten per capability. So if you have an in-house Selenium // grid with only 5 firefox instances available you can make sure that not more than // 5 instances get started at a time. - maxInstances: 5, + maxInstances: 1, // browserName: 'chrome', + 'goog:chromeOptions': browserOptions, acceptInsecureCerts: true // If outputDir is provided WebdriverIO can capture driver session logs // it is possible to configure which logTypes to include/exclude. From 1fe4b05c17aab3ed93bd4333997101c944dc313e Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 11 Mar 2022 16:14:29 -0500 Subject: [PATCH 11/11] bacon fix --- scripts/e2e-samples.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/e2e-samples.sh b/scripts/e2e-samples.sh index 662531d0..d1193817 100755 --- a/scripts/e2e-samples.sh +++ b/scripts/e2e-samples.sh @@ -2,7 +2,8 @@ source ${OKTA_HOME}/${REPO}/scripts/setup.sh "v14.18.0" -setup_service google-chrome-stable 83.0.4103.61-1 +setup_service java 1.8.222 +setup_service google-chrome-stable 89.0.4389.72-1 export CI=true export TEST_SUITE_TYPE="junit"