From dad9ac9171ea9d044a78b56366b45974a2703585 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Fri, 1 Apr 2022 21:15:02 +0000 Subject: [PATCH 1/2] wip --- sdk/identity/identity/package.json | 7 +- sdk/identity/identity/rollup.config.js | 22 +++++ .../identity/test/playwright/index.html | 10 ++ sdk/identity/identity/test/playwright/page.ts | 21 ++++ .../identity/test/playwright/popup.spec.ts | 95 +++++++++++++++++++ .../identity/test/playwright/redirect.spec.ts | 91 ++++++++++++++++++ .../test/playwright/rollup/src/index.js | 4 + .../identity/test/playwright/server.ts | 80 ++++++++++++++++ 8 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 sdk/identity/identity/rollup.config.js create mode 100644 sdk/identity/identity/test/playwright/index.html create mode 100644 sdk/identity/identity/test/playwright/page.ts create mode 100644 sdk/identity/identity/test/playwright/popup.spec.ts create mode 100644 sdk/identity/identity/test/playwright/redirect.spec.ts create mode 100644 sdk/identity/identity/test/playwright/rollup/src/index.js create mode 100644 sdk/identity/identity/test/playwright/server.ts diff --git a/sdk/identity/identity/package.json b/sdk/identity/identity/package.json index 59acd672369a..ad27ecca96b2 100644 --- a/sdk/identity/identity/package.json +++ b/sdk/identity/identity/package.json @@ -52,7 +52,9 @@ "check-format": "prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "echo skipped", "integration-test:node": "dev-tool run test:node-js-input -- --timeout 180000 'dist-esm/test/public/node/*.spec.js' 'dist-esm/test/internal/node/*.spec.js'", - "integration-test": "npm run integration-test:node && npm run integration-test:browser", + "preintegration-test:playwright": "npm run build:test && rollup --config", + "integration-test:playwright": "playwright test -c dist-esm/test/playwright", + "integration-test": "npm run integration-test:node && npm run integration-test:browser && npm run integration-test:playwright", "lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]", "lint": "eslint package.json api-extractor.json src test --ext .ts", "pack": "npm pack 2>&1", @@ -126,16 +128,19 @@ "@azure/test-utils": "^1.0.0", "@azure-tools/test-recorder": "^2.0.0", "@microsoft/api-extractor": "^7.18.11", + "@playwright/test": "^1.19.2", "@types/jws": "^3.2.2", "@types/mocha": "^7.0.2", "@types/node": "^12.0.0", "@types/uuid": "^8.0.0", "@types/chai": "^4.1.6", + "@types/express": "^4.17.13", "@types/stoppable": "^1.1.0", "chai": "^4.2.0", "cross-env": "^7.0.2", "dotenv": "^8.2.0", "eslint": "^7.15.0", + "express": "^4.17.3", "inherits": "^2.0.3", "karma": "^6.2.0", "karma-chrome-launcher": "^3.0.0", diff --git a/sdk/identity/identity/rollup.config.js b/sdk/identity/identity/rollup.config.js new file mode 100644 index 000000000000..016d48b31aa4 --- /dev/null +++ b/sdk/identity/identity/rollup.config.js @@ -0,0 +1,22 @@ +import resolve from "@rollup/plugin-node-resolve"; +import cjs from "@rollup/plugin-commonjs"; +import json from "@rollup/plugin-json"; +import shim from "rollup-plugin-shim"; + +export default { + input: "./test/playwright/rollup/src/index.js", + output: { + file: "test/playwright/rollup/dist/index.js", + format: "umd", + name: "main", + }, + plugins: [ + shim({}), + resolve({ + preferBuiltins: false, + mainFields: ["module", "browser"], + }), + cjs(), + json(), + ], +}; diff --git a/sdk/identity/identity/test/playwright/index.html b/sdk/identity/identity/test/playwright/index.html new file mode 100644 index 000000000000..3102a1371d79 --- /dev/null +++ b/sdk/identity/identity/test/playwright/index.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sdk/identity/identity/test/playwright/page.ts b/sdk/identity/identity/test/playwright/page.ts new file mode 100644 index 000000000000..775f8df661fc --- /dev/null +++ b/sdk/identity/identity/test/playwright/page.ts @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Page } from "@playwright/test"; + +export async function preparePage(page: Page): Promise { + // Log and continue all network requests + await page.route("**", (route) => { + console.log("PLAYWRIGHT PAGE ROUTE:", route.request().url()); + route.continue(); + }); + + // Logging the page's console.logs + page.on("console", async (msg) => { + const values = []; + for (const arg of msg.args()) { + values.push(await arg.jsonValue()); + } + console.log(...values); + }); +} diff --git a/sdk/identity/identity/test/playwright/popup.spec.ts b/sdk/identity/identity/test/playwright/popup.spec.ts new file mode 100644 index 000000000000..9e864a5367e0 --- /dev/null +++ b/sdk/identity/identity/test/playwright/popup.spec.ts @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as dotenv from "dotenv"; +import { test } from "@playwright/test"; +import { isLiveMode } from "@azure-tools/test-recorder"; +import { prepareServer } from "./server"; +import { preparePage } from "./page"; + +dotenv.config(); + +const tenantId = process.env.AZURE_TENANT_ID || process.env.AZURE_IDENTITY_TEST_TENANTID; +const clientId = process.env.AZURE_CLIENT_ID || process.env.AZURE_IDENTITY_BROWSER_CLIENT_ID; +const azureUsername = process.env.AZURE_USERNAME || process.env.AZURE_IDENTITY_TEST_USERNAME; +const azurePassword = process.env.AZURE_PASSWORD || process.env.AZURE_IDENTITY_TEST_PASSWORD; +const protocol = process.env.PROTOCOL || "http"; +const host = process.env.HOST || "localhost"; +const port = process.env.PORT || "8080"; +const scope = "https://graph.microsoft.com/.default"; +const authorizeHost = + process.env.AUTHORIZE_HOST || `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0`; + +// The Azure Active Directory app registration should be of the type +// "spa" and the redirect endpoint should point to: +const homeUri = `http://localhost:${port}/`; + +const credentialOptions = { redirectUri: homeUri }; + +test("Authenticates with a popup", async ({ page }) => { + test.skip(!isLiveMode(), "Playwright tests can only run on live mode"); + + const { app, start, stop } = await prepareServer({ port }); + await preparePage(page); + await start(); + + // THE TEST BEGINS + + // We go to the home page + await page.goto(homeUri); + + const firstAuthentication = async ({ clientId, scope, credentialOptions }) => { + const { InteractiveBrowserCredential } = (window as any).main; + + const credential = new InteractiveBrowserCredential({ + clientId, + ...credentialOptions, + }); + + // The redirection to Azure happens here... + credential.getToken(scope); + }; + + const [popup] = await Promise.all([ + page.waitForEvent("popup"), + page.evaluate(firstAuthentication, { + clientId, + scope, + credentialOptions, + }), + ]); + + // Interactive popup login with Playwright + await popup.waitForNavigation(); + await popup.waitForSelector(`input[type="email"]`); + await popup.fill(`input[type="email"]`, azureUsername); + await popup.waitForSelector(`input[type="submit"]`); + await popup.click(`input[type="submit"]`); + await popup.waitForLoadState("networkidle"); + await popup.waitForSelector(`input[type="password"]`); + await popup.fill(`input[type="password"]`, azurePassword); + await popup.waitForSelector(`input[type="submit"]`); + await popup.click(`input[type="submit"]`); + await popup.waitForSelector(`input[type="submit"]`); + await popup.click(`input[type="submit"]`); + await popup.waitForEvent("close"); + + await page.evaluate( + async ({ clientId, scope, credentialOptions }) => { + const { InteractiveBrowserCredential } = (window as any).main; + + const credential = new InteractiveBrowserCredential({ + clientId, + ...credentialOptions, + }); + + const token = await credential.getToken(scope); + expect(token).toBeTruthy(); + expect(token.token).toBeTruthy(); + expect(token.expiresOnTimestamp).toBeTruthy(); + }, + { clientId, scope, credentialOptions } + ); + + await stop(); +}); diff --git a/sdk/identity/identity/test/playwright/redirect.spec.ts b/sdk/identity/identity/test/playwright/redirect.spec.ts new file mode 100644 index 000000000000..9bf7b3088349 --- /dev/null +++ b/sdk/identity/identity/test/playwright/redirect.spec.ts @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as dotenv from "dotenv"; +import { test } from "@playwright/test"; +import { isLiveMode } from "@azure-tools/test-recorder"; +import { prepareServer } from "./server"; +import { preparePage } from "./page"; + +dotenv.config(); + +const tenantId = process.env.AZURE_TENANT_ID || process.env.AZURE_IDENTITY_TEST_TENANTID; +const clientId = process.env.AZURE_CLIENT_ID || process.env.AZURE_IDENTITY_BROWSER_CLIENT_ID; +const azureUsername = process.env.AZURE_USERNAME || process.env.AZURE_IDENTITY_TEST_USERNAME; +const azurePassword = process.env.AZURE_PASSWORD || process.env.AZURE_IDENTITY_TEST_PASSWORD; +const protocol = process.env.PROTOCOL || "http"; +const host = process.env.HOST || "localhost"; +const port = process.env.PORT || "8080"; +const scope = "https://graph.microsoft.com/.default"; +const authorizeHost = + process.env.AUTHORIZE_HOST || `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0`; + +// The Azure Active Directory app registration should be of the type +// "spa" and the redirect endpoint should point to: +const homeUri = `http://localhost:${port}/`; + +const credentialOptions = { redirectUri: homeUri }; + +test("Authenticates", async ({ page }) => { + test.skip(!isLiveMode(), "Playwright tests can only run on live mode"); + + const { app, start, stop } = await prepareServer({ port }); + await preparePage(page); + await start(); + + // THE TEST BEGINS + + // We go to the home page + await page.goto(homeUri); + + await page.evaluate( + async ({ clientId, scope, credentialOptions }) => { + const { InteractiveBrowserCredential } = (window as any).main; + + const credential = new InteractiveBrowserCredential({ + clientId, + ...credentialOptions, + loginStyle: "redirect", + }); + + // The redirection to Azure happens here... + credential.getToken(scope); + }, + { clientId, scope, credentialOptions } + ); + + // Interactive login with Playwright + await page.waitForNavigation(); + await page.waitForSelector(`input[type="email"]`); + await page.fill(`input[type="email"]`, azureUsername); + await page.waitForSelector(`input[type="submit"]`); + await page.click(`input[type="submit"]`); + await page.waitForLoadState("networkidle"); + await page.waitForSelector(`input[type="password"]`); + await page.fill(`input[type="password"]`, azurePassword); + await page.waitForSelector(`input[type="submit"]`); + await page.click(`input[type="submit"]`); + await page.waitForSelector(`input[type="submit"]`); + await page.click(`input[type="submit"]`); + await page.waitForURL(`${homeUri}**`); + + await page.evaluate( + async ({ clientId, scope, credentialOptions }) => { + const { InteractiveBrowserCredential } = (window as any).main; + + const credential = new InteractiveBrowserCredential({ + clientId, + ...credentialOptions, + loginStyle: "redirect", + }); + + const token = await credential.getToken(scope); + expect(token).toBeTruthy(); + expect(token.token).toBeTruthy(); + expect(token.expiresOnTimestamp).toBeTruthy(); + }, + { clientId, scope, credentialOptions } + ); + + await stop(); +}); diff --git a/sdk/identity/identity/test/playwright/rollup/src/index.js b/sdk/identity/identity/test/playwright/rollup/src/index.js new file mode 100644 index 000000000000..3dd1abf56ba3 --- /dev/null +++ b/sdk/identity/identity/test/playwright/rollup/src/index.js @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +export { InteractiveBrowserCredential } from "../../../../src"; diff --git a/sdk/identity/identity/test/playwright/server.ts b/sdk/identity/identity/test/playwright/server.ts new file mode 100644 index 000000000000..e6811ab8bfae --- /dev/null +++ b/sdk/identity/identity/test/playwright/server.ts @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { AccessToken, TokenCredential } from "@azure/core-auth"; +import * as express from "express"; +import { readFileSync } from "fs"; +import { Server } from "http"; + +// A simple web server that allows passing configuration and behavioral parameters. +// This file should be thought as the archetypicall representation of a web server, +// whereas the test file will include the nuance specific to testing the desired behavior. + +/** + * Options to the server. + * With the intent to make the server parametrizable! + */ +export interface ServerOptions { + /** + * Port number as a string + */ + port: string; +} + +/** + * Result of the prepareServer function. + */ +export interface PepareServerResult { + app: express.Application; + start: () => Promise; + stop: () => Promise; +} + +/** + * Sets up a parametrizable Express server. + */ +export async function prepareServer(serverOptions: ServerOptions): Promise { + const app = express(); + const database: Record = {}; + const { port, serverSecret } = serverOptions; + + /** + * Logging calls. + */ + app.use((req: express.Request, res: express.Response, next: express.NextFunction) => { + console.log("Playwright Express test server:", req.url); + next(); + }); + + /** + * Endpoint that loads the index.js + */ + app.get("/index.js", async (req: express.Request, res: express.Response) => { + const indexContent = readFileSync("./test/playwright/rollup/dist/index.js", { + encoding: "utf8", + }); + res.send(indexContent); + }); + + /** + * Home URI + */ + app.get("/", async (req: express.Request, res: express.Response) => { + const indexContent = readFileSync("./test/playwright/index.html", { encoding: "utf8" }); + res.send(indexContent); + }); + + let server: Server | undefined = undefined; + + return { + app, + async start() { + server = app.listen(serverOptions.port, () => { + console.log(`Authorization code redirect server listening on port ${serverOptions.port}`); + }); + }, + async stop() { + server.close(); + }, + }; +} From 28ed0a5b73a65c9f1a1d9be7f53ba73537245cd8 Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Sat, 2 Apr 2022 01:33:00 +0000 Subject: [PATCH 2/2] two first playwright tests --- common/config/rush/pnpm-lock.yaml | 708 +++++++++++++++++- sdk/identity/identity/package.json | 9 +- .../identity/playwright.tsconfig.json | 10 + sdk/identity/identity/rollup.config.js | 4 +- .../identity/test/playwright/popup.spec.ts | 62 +- .../identity/test/playwright/redirect.spec.ts | 31 +- .../test/playwright/rollup/src/index.js | 4 - .../test/playwright/rollup/src/index.ts | 4 + .../identity/test/playwright/server.ts | 13 +- sdk/identity/identity/tests.yml | 1 + sdk/identity/identity/tsconfig.json | 2 +- 11 files changed, 785 insertions(+), 63 deletions(-) create mode 100644 sdk/identity/identity/playwright.tsconfig.json delete mode 100644 sdk/identity/identity/test/playwright/rollup/src/index.js create mode 100644 sdk/identity/identity/test/playwright/rollup/src/index.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 550e70ceb9f9..43b2960eef23 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1260,6 +1260,29 @@ packages: engines: {node: '>=6.9.0'} dev: false + /@babel/core/7.16.12: + resolution: {integrity: sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.7 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.16.12 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helpers': 7.17.8 + '@babel/parser': 7.17.8 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + convert-source-map: 1.8.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/core/7.17.8: resolution: {integrity: sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==} engines: {node: '>=6.9.0'} @@ -1292,6 +1315,26 @@ packages: source-map: 0.5.7 dev: false + /@babel/helper-annotate-as-pure/7.16.7: + resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: false + + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.16.12: + resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.17.7 + '@babel/core': 7.16.12 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.20.2 + semver: 6.3.0 + dev: false + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.17.8: resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} engines: {node: '>=6.9.0'} @@ -1305,6 +1348,24 @@ packages: semver: 6.3.0 dev: false + /@babel/helper-create-class-features-plugin/7.17.6_@babel+core@7.16.12: + resolution: {integrity: sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.17.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/helper-environment-visitor/7.16.7: resolution: {integrity: sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==} engines: {node: '>=6.9.0'} @@ -1335,6 +1396,13 @@ packages: '@babel/types': 7.17.0 dev: false + /@babel/helper-member-expression-to-functions/7.17.7: + resolution: {integrity: sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: false + /@babel/helper-module-imports/7.16.7: resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} engines: {node: '>=6.9.0'} @@ -1358,6 +1426,31 @@ packages: - supports-color dev: false + /@babel/helper-optimise-call-expression/7.16.7: + resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: false + + /@babel/helper-plugin-utils/7.16.7: + resolution: {integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-replace-supers/7.16.7: + resolution: {integrity: sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.17.7 + '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/helper-simple-access/7.17.7: resolution: {integrity: sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==} engines: {node: '>=6.9.0'} @@ -1365,6 +1458,13 @@ packages: '@babel/types': 7.17.0 dev: false + /@babel/helper-skip-transparent-expression-wrappers/7.16.0: + resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: false + /@babel/helper-split-export-declaration/7.16.7: resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} engines: {node: '>=6.9.0'} @@ -1408,6 +1508,267 @@ packages: hasBin: true dev: false + /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.12 + dev: false + + /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.16.12: + resolution: {integrity: sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.12 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.16.12: + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.16.12: + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.16.12: + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.16.12: + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.16.12: + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-transform-modules-commonjs/7.16.8_@babel+core@7.16.12: + resolution: {integrity: sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-simple-access': 7.17.7 + babel-plugin-dynamic-import-node: 2.3.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.16.12: + resolution: {integrity: sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.16.12 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/preset-typescript/7.16.7_@babel+core@7.16.12: + resolution: {integrity: sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-validator-option': 7.16.7 + '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.16.12 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/runtime/7.17.8: resolution: {integrity: sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==} engines: {node: '>=6.9.0'} @@ -1515,6 +1876,17 @@ packages: engines: {node: '>=8'} dev: false + /@jest/types/27.5.1: + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 17.0.23 + '@types/yargs': 16.0.4 + chalk: 4.1.2 + dev: false + /@jridgewell/resolve-uri/3.0.5: resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==} engines: {node: '>=6.0.0'} @@ -1887,6 +2259,51 @@ packages: lodash.merge: 4.6.2 dev: false + /@playwright/test/1.20.2: + resolution: {integrity: sha512-unkLa+xe/lP7MVC0qpgadc9iSG1+LEyGBzlXhGS/vLGAJaSFs8DNfI89hNd5shHjWfNzb34JgPVnkRKCSNo5iw==} + engines: {node: '>=12'} + hasBin: true + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/core': 7.16.12 + '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.12 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.12 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.12 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.12 + '@babel/plugin-transform-modules-commonjs': 7.16.8_@babel+core@7.16.12 + '@babel/preset-typescript': 7.16.7_@babel+core@7.16.12 + colors: 1.4.0 + commander: 8.3.0 + debug: 4.3.3 + expect: 27.2.5 + jest-matcher-utils: 27.2.5 + json5: 2.2.1 + mime: 3.0.0 + minimatch: 3.0.4 + ms: 2.1.3 + open: 8.4.0 + pirates: 4.0.4 + playwright-core: 1.20.2 + rimraf: 3.0.2 + source-map-support: 0.4.18 + stack-utils: 2.0.5 + yazl: 2.5.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@rollup/plugin-commonjs/11.0.2_rollup@1.32.1: resolution: {integrity: sha512-MPYGZr0qdbV5zZj8/2AuomVpnRVXRU5XKXb3HVniwRoRCreGlf5kOE081isNWeiLIi6IYkwTX9zE0/c7V8g81g==} engines: {node: '>= 8.0.0'} @@ -2048,6 +2465,21 @@ packages: rollup: 2.70.1 dev: false + /@rollup/plugin-typescript/8.3.1_2440efe631074d82b9217924bf1ae787: + resolution: {integrity: sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==} + engines: {node: '>=8.0.0'} + peerDependencies: + rollup: ^2.14.0 + tslib: '*' + typescript: '>=3.7.0' + dependencies: + '@rollup/pluginutils': 3.1.0_rollup@2.70.1 + resolve: 1.22.0 + rollup: 2.70.1 + tslib: 2.3.1 + typescript: 4.2.4 + dev: false + /@rollup/plugin-virtual/2.1.0_rollup@2.70.1: resolution: {integrity: sha512-CPPAtlKT53HFqC8jFHb/V5WErpU8Hrq2TyCR0A7kPQMlF2wNUf0o1xuAc+Qxj8NCZM0Z3Yvl+FbUXfJjVWqDwA==} engines: {node: '>=8.0.0'} @@ -2318,6 +2750,22 @@ packages: '@types/node': 17.0.23 dev: false + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: false + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: false + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: false + /@types/json-schema/7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: false @@ -2468,6 +2916,10 @@ packages: resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==} dev: false + /@types/stack-utils/2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: false + /@types/stoppable/1.1.1: resolution: {integrity: sha512-b8N+fCADRIYYrGZOcmOR8ZNBOqhktWTB/bMUl5LvGtT201QKJZOOH5UsFyI3qtteM6ZAJbJqZoBcLqqxKIwjhw==} dependencies: @@ -2520,6 +2972,16 @@ packages: '@types/node': 17.0.23 dev: false + /@types/yargs-parser/21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: false + + /@types/yargs/16.0.4: + resolution: {integrity: sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: false + /@types/yauzl/2.9.2: resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} requiresBuild: true @@ -2753,6 +3215,11 @@ packages: color-convert: 2.0.1 dev: false + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: false + /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} @@ -2960,6 +3427,12 @@ packages: - supports-color dev: false + /babel-plugin-dynamic-import-node/2.3.3: + resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} + dependencies: + object.assign: 4.1.2 + dev: false + /backbone/1.4.1: resolution: {integrity: sha512-ADy1ztN074YkWbHi8ojJVFe3vAanO/lrzMGZWUClIP7oDD/Pjy2vrASraUP+2EVCfIiTtCW4FChVow01XneivA==} dependencies: @@ -3290,6 +3763,11 @@ packages: engines: {node: '>=0.1.90'} dev: false + /colors/1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + dev: false + /combined-stream/1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3301,6 +3779,11 @@ packages: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: false + /commander/8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + /commondir/1.0.1: resolution: {integrity: sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=} dev: false @@ -3617,6 +4100,11 @@ packages: resolution: {integrity: sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=} dev: false + /diff-sequences/27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: false + /diff/3.5.0: resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} engines: {node: '>=0.3.1'} @@ -3826,6 +4314,11 @@ packages: engines: {node: '>=0.8.0'} dev: false + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: false + /escape-string-regexp/4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -4132,6 +4625,18 @@ packages: homedir-polyfill: 1.0.3 dev: false + /expect/27.2.5: + resolution: {integrity: sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.5.1 + ansi-styles: 5.2.0 + jest-get-type: 27.5.1 + jest-matcher-utils: 27.2.5 + jest-message-util: 27.5.1 + jest-regex-util: 27.5.1 + dev: false + /express/4.17.3: resolution: {integrity: sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==} engines: {node: '>= 0.10.0'} @@ -4899,6 +5404,10 @@ packages: engines: {node: '>=4'} dev: false + /ip/1.1.5: + resolution: {integrity: sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=} + dev: false + /ipaddr.js/1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -5293,6 +5802,51 @@ packages: istanbul-lib-report: 3.0.0 dev: false + /jest-diff/27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: false + + /jest-get-type/27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: false + + /jest-matcher-utils/27.2.5: + resolution: {integrity: sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: false + + /jest-message-util/27.5.1: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@babel/code-frame': 7.16.7 + '@jest/types': 27.5.1 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.9 + micromatch: 4.0.5 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.5 + dev: false + + /jest-regex-util/27.5.1: + resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: false + /jest-worker/24.9.0: resolution: {integrity: sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==} engines: {node: '>= 6'} @@ -5305,6 +5859,10 @@ packages: resolution: {integrity: sha1-o6vicYryQaKykE+EpiWXDzia4yo=} dev: false + /jpeg-js/0.4.3: + resolution: {integrity: sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==} + dev: false + /jquery/3.6.0: resolution: {integrity: sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==} dev: false @@ -5963,6 +6521,12 @@ packages: hasBin: true dev: false + /mime/3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: false + /mimic-fn/2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -6686,6 +7250,18 @@ packages: engines: {node: '>=6'} dev: false + /pirates/4.0.4: + resolution: {integrity: sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==} + engines: {node: '>= 6'} + dev: false + + /pixelmatch/5.2.1: + resolution: {integrity: sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==} + hasBin: true + dependencies: + pngjs: 4.0.1 + dev: false + /pkg-dir/3.0.0: resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} engines: {node: '>=6'} @@ -6700,6 +7276,45 @@ packages: find-up: 4.1.0 dev: false + /playwright-core/1.20.2: + resolution: {integrity: sha512-iV6+HftSPalynkq0CYJala1vaTOq7+gU9BRfKCdM9bAxNq/lFLrwbluug2Wt5OoUwbMABcnTThIEm3/qUhCdJQ==} + engines: {node: '>=12'} + hasBin: true + dependencies: + colors: 1.4.0 + commander: 8.3.0 + debug: 4.3.3 + extract-zip: 2.0.1 + https-proxy-agent: 5.0.0 + jpeg-js: 0.4.3 + mime: 3.0.0 + pixelmatch: 5.2.1 + pngjs: 6.0.0 + progress: 2.0.3 + proper-lockfile: 4.1.2 + proxy-from-env: 1.1.0 + rimraf: 3.0.2 + socks-proxy-agent: 6.1.1 + stack-utils: 2.0.5 + ws: 8.4.2 + yauzl: 2.10.0 + yazl: 2.5.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /pngjs/4.0.1: + resolution: {integrity: sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==} + engines: {node: '>=8.0.0'} + dev: false + + /pngjs/6.0.0: + resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} + engines: {node: '>=12.13.0'} + dev: false + /prebuild-install/7.0.1: resolution: {integrity: sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg==} engines: {node: '>=10'} @@ -6749,6 +7364,15 @@ packages: hasBin: true dev: false + /pretty-format/27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: false + /priorityqueuejs/1.0.0: resolution: {integrity: sha1-LuTyPCVgkT4IwHzlzN1t498sWvg=} dev: false @@ -6785,6 +7409,14 @@ packages: engines: {node: '>= 8'} dev: false + /proper-lockfile/4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + dependencies: + graceful-fs: 4.2.9 + retry: 0.12.0 + signal-exit: 3.0.7 + dev: false + /proxy-addr/2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -6909,6 +7541,10 @@ packages: strip-json-comments: 2.0.1 dev: false + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: false + /read-pkg-up/4.0.0: resolution: {integrity: sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==} engines: {node: '>=6'} @@ -7073,6 +7709,11 @@ packages: path-parse: 1.0.7 dev: false + /retry/0.12.0: + resolution: {integrity: sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=} + engines: {node: '>= 4'} + dev: false + /reusify/1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -7466,6 +8107,11 @@ packages: is-fullwidth-code-point: 3.0.0 dev: false + /smart-buffer/4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + /socket.io-adapter/2.3.3: resolution: {integrity: sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==} dev: false @@ -7497,6 +8143,25 @@ packages: - utf-8-validate dev: false + /socks-proxy-agent/6.1.1: + resolution: {integrity: sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.6.2 + transitivePeerDependencies: + - supports-color + dev: false + + /socks/2.6.2: + resolution: {integrity: sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 1.1.5 + smart-buffer: 4.2.0 + dev: false + /source-map-resolve/0.5.3: resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} deprecated: See https://github.com/lydell/source-map-resolve#deprecated @@ -7516,6 +8181,12 @@ packages: decode-uri-component: 0.2.0 dev: false + /source-map-support/0.4.18: + resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} + dependencies: + source-map: 0.5.7 + dev: false + /source-map-support/0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -7600,6 +8271,13 @@ packages: resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=} dev: false + /stack-utils/2.0.5: + resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: false + /statuses/1.5.0: resolution: {integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=} engines: {node: '>= 0.6'} @@ -8443,6 +9121,19 @@ packages: optional: true dev: false + /ws/8.4.2: + resolution: {integrity: sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws/8.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} @@ -8606,6 +9297,12 @@ packages: fd-slicer: 1.1.0 dev: false + /yazl/2.5.1: + resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + dependencies: + buffer-crc32: 0.2.13 + dev: false + /yn/3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -15086,7 +15783,7 @@ packages: dev: false file:projects/identity.tgz: - resolution: {integrity: sha512-c5Qkc5SAHq5kIU71uO6rdV7Eq5Qd4kkhDi0v6QnHwn/dWFoAywZtepUOeW+mPpTZiaoqApQmUHc5NTtUUIwzaw==, tarball: file:projects/identity.tgz} + resolution: {integrity: sha512-aFiit1F56m0bKaT9ZBG05/GJ7lIR76UU8psMLIy7YLw6P7BXXsSIuLXvjGIqG68Yk5cxbW6Mr1JJkt5njJ8cuA==, tarball: file:projects/identity.tgz} name: '@rush-temp/identity' version: 0.0.0 dependencies: @@ -15096,7 +15793,13 @@ packages: '@azure/msal-common': 4.5.1 '@azure/msal-node': 1.7.0 '@microsoft/api-extractor': 7.19.5 + '@playwright/test': 1.20.2 + '@rollup/plugin-commonjs': 21.0.3_rollup@2.70.1 + '@rollup/plugin-json': 4.1.0_rollup@2.70.1 + '@rollup/plugin-node-resolve': 13.1.3_rollup@2.70.1 + '@rollup/plugin-typescript': 8.3.1_2440efe631074d82b9217924bf1ae787 '@types/chai': 4.3.0 + '@types/express': 4.17.13 '@types/jws': 3.2.4 '@types/mocha': 7.0.2 '@types/node': 12.20.47 @@ -15108,6 +15811,7 @@ packages: dotenv: 8.6.0 eslint: 7.32.0 events: 3.3.0 + express: 4.17.3 inherits: 2.0.4 jws: 4.0.0 karma: 6.3.17 @@ -15125,6 +15829,8 @@ packages: prettier: 2.6.1 puppeteer: 13.5.1 rimraf: 3.0.2 + rollup: 2.70.1 + rollup-plugin-shim: 1.0.0 sinon: 9.2.4 stoppable: 1.1.0 tslib: 2.3.1 diff --git a/sdk/identity/identity/package.json b/sdk/identity/identity/package.json index ad27ecca96b2..4dffa5c03dc6 100644 --- a/sdk/identity/identity/package.json +++ b/sdk/identity/identity/package.json @@ -52,8 +52,7 @@ "check-format": "prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "echo skipped", "integration-test:node": "dev-tool run test:node-js-input -- --timeout 180000 'dist-esm/test/public/node/*.spec.js' 'dist-esm/test/internal/node/*.spec.js'", - "preintegration-test:playwright": "npm run build:test && rollup --config", - "integration-test:playwright": "playwright test -c dist-esm/test/playwright", + "integration-test:playwright": "rimraf dist-playwright && npx playwright install && tsc -p playwright.tsconfig.json && rollup --config && playwright test -c dist-playwright", "integration-test": "npm run integration-test:node && npm run integration-test:browser && npm run integration-test:playwright", "lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]", "lint": "eslint package.json api-extractor.json src test --ext .ts", @@ -129,6 +128,10 @@ "@azure-tools/test-recorder": "^2.0.0", "@microsoft/api-extractor": "^7.18.11", "@playwright/test": "^1.19.2", + "@rollup/plugin-commonjs": "^21.0.2", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.1.3", + "@rollup/plugin-typescript": "^8.3.1", "@types/jws": "^3.2.2", "@types/mocha": "^7.0.2", "@types/node": "^12.0.0", @@ -156,6 +159,8 @@ "prettier": "^2.5.1", "puppeteer": "^13.5.1", "rimraf": "^3.0.0", + "rollup": "^2.70.1", + "rollup-plugin-shim": "^1.0.0", "typescript": "~4.2.0", "util": "^0.12.1", "sinon": "^9.0.2", diff --git a/sdk/identity/identity/playwright.tsconfig.json b/sdk/identity/identity/playwright.tsconfig.json new file mode 100644 index 000000000000..861462ccd121 --- /dev/null +++ b/sdk/identity/identity/playwright.tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "Node", + "sourceMap": true, + "outDir": "./dist-playwright" + }, + "include": ["test/playwright"] +} diff --git a/sdk/identity/identity/rollup.config.js b/sdk/identity/identity/rollup.config.js index 016d48b31aa4..18147365734e 100644 --- a/sdk/identity/identity/rollup.config.js +++ b/sdk/identity/identity/rollup.config.js @@ -1,10 +1,11 @@ import resolve from "@rollup/plugin-node-resolve"; import cjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; +import typescript from "@rollup/plugin-typescript"; import shim from "rollup-plugin-shim"; export default { - input: "./test/playwright/rollup/src/index.js", + input: "./test/playwright/rollup/src/index.ts", output: { file: "test/playwright/rollup/dist/index.js", format: "umd", @@ -18,5 +19,6 @@ export default { }), cjs(), json(), + typescript(), ], }; diff --git a/sdk/identity/identity/test/playwright/popup.spec.ts b/sdk/identity/identity/test/playwright/popup.spec.ts index 9e864a5367e0..f7ec547ef13e 100644 --- a/sdk/identity/identity/test/playwright/popup.spec.ts +++ b/sdk/identity/identity/test/playwright/popup.spec.ts @@ -2,23 +2,18 @@ // Licensed under the MIT license. import * as dotenv from "dotenv"; -import { test } from "@playwright/test"; +import { test, expect } from "@playwright/test"; import { isLiveMode } from "@azure-tools/test-recorder"; import { prepareServer } from "./server"; import { preparePage } from "./page"; dotenv.config(); -const tenantId = process.env.AZURE_TENANT_ID || process.env.AZURE_IDENTITY_TEST_TENANTID; const clientId = process.env.AZURE_CLIENT_ID || process.env.AZURE_IDENTITY_BROWSER_CLIENT_ID; const azureUsername = process.env.AZURE_USERNAME || process.env.AZURE_IDENTITY_TEST_USERNAME; const azurePassword = process.env.AZURE_PASSWORD || process.env.AZURE_IDENTITY_TEST_PASSWORD; -const protocol = process.env.PROTOCOL || "http"; -const host = process.env.HOST || "localhost"; const port = process.env.PORT || "8080"; const scope = "https://graph.microsoft.com/.default"; -const authorizeHost = - process.env.AUTHORIZE_HOST || `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0`; // The Azure Active Directory app registration should be of the type // "spa" and the redirect endpoint should point to: @@ -28,8 +23,11 @@ const credentialOptions = { redirectUri: homeUri }; test("Authenticates with a popup", async ({ page }) => { test.skip(!isLiveMode(), "Playwright tests can only run on live mode"); + test.skip(!clientId, "Client ID environment variable required"); + test.skip(!azureUsername, "Username environment variable required"); + test.skip(!azurePassword, "Password environment variable required"); - const { app, start, stop } = await prepareServer({ port }); + const { start, stop } = await prepareServer({ port }); await preparePage(page); await start(); @@ -38,43 +36,44 @@ test("Authenticates with a popup", async ({ page }) => { // We go to the home page await page.goto(homeUri); - const firstAuthentication = async ({ clientId, scope, credentialOptions }) => { - const { InteractiveBrowserCredential } = (window as any).main; - - const credential = new InteractiveBrowserCredential({ - clientId, - ...credentialOptions, - }); - - // The redirection to Azure happens here... - credential.getToken(scope); - }; - const [popup] = await Promise.all([ page.waitForEvent("popup"), - page.evaluate(firstAuthentication, { - clientId, - scope, - credentialOptions, - }), + page.evaluate( + async ({ clientId, scope, credentialOptions }) => { + const { InteractiveBrowserCredential } = (window as any).main; + + const credential = new InteractiveBrowserCredential({ + ...credentialOptions, + clientId, + }); + + // The redirection to Azure happens here... + credential.getToken(scope); + }, + { + clientId, + scope, + credentialOptions, + } + ), ]); // Interactive popup login with Playwright await popup.waitForNavigation(); await popup.waitForSelector(`input[type="email"]`); - await popup.fill(`input[type="email"]`, azureUsername); + await popup.fill(`input[type="email"]`, azureUsername!); await popup.waitForSelector(`input[type="submit"]`); await popup.click(`input[type="submit"]`); await popup.waitForLoadState("networkidle"); await popup.waitForSelector(`input[type="password"]`); - await popup.fill(`input[type="password"]`, azurePassword); + await popup.fill(`input[type="password"]`, azurePassword!); await popup.waitForSelector(`input[type="submit"]`); await popup.click(`input[type="submit"]`); await popup.waitForSelector(`input[type="submit"]`); await popup.click(`input[type="submit"]`); await popup.waitForEvent("close"); - await page.evaluate( + const token = await page.evaluate( async ({ clientId, scope, credentialOptions }) => { const { InteractiveBrowserCredential } = (window as any).main; @@ -83,13 +82,14 @@ test("Authenticates with a popup", async ({ page }) => { ...credentialOptions, }); - const token = await credential.getToken(scope); - expect(token).toBeTruthy(); - expect(token.token).toBeTruthy(); - expect(token.expiresOnTimestamp).toBeTruthy(); + return await credential.getToken(scope); }, { clientId, scope, credentialOptions } ); + expect(token).toBeTruthy(); + expect(token.token).toBeTruthy(); + expect(token.expiresOnTimestamp).toBeTruthy(); + await stop(); }); diff --git a/sdk/identity/identity/test/playwright/redirect.spec.ts b/sdk/identity/identity/test/playwright/redirect.spec.ts index 9bf7b3088349..90fe6548cdd5 100644 --- a/sdk/identity/identity/test/playwright/redirect.spec.ts +++ b/sdk/identity/identity/test/playwright/redirect.spec.ts @@ -2,23 +2,18 @@ // Licensed under the MIT license. import * as dotenv from "dotenv"; -import { test } from "@playwright/test"; +import { test, expect } from "@playwright/test"; import { isLiveMode } from "@azure-tools/test-recorder"; import { prepareServer } from "./server"; import { preparePage } from "./page"; dotenv.config(); -const tenantId = process.env.AZURE_TENANT_ID || process.env.AZURE_IDENTITY_TEST_TENANTID; const clientId = process.env.AZURE_CLIENT_ID || process.env.AZURE_IDENTITY_BROWSER_CLIENT_ID; const azureUsername = process.env.AZURE_USERNAME || process.env.AZURE_IDENTITY_TEST_USERNAME; const azurePassword = process.env.AZURE_PASSWORD || process.env.AZURE_IDENTITY_TEST_PASSWORD; -const protocol = process.env.PROTOCOL || "http"; -const host = process.env.HOST || "localhost"; const port = process.env.PORT || "8080"; const scope = "https://graph.microsoft.com/.default"; -const authorizeHost = - process.env.AUTHORIZE_HOST || `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0`; // The Azure Active Directory app registration should be of the type // "spa" and the redirect endpoint should point to: @@ -28,8 +23,11 @@ const credentialOptions = { redirectUri: homeUri }; test("Authenticates", async ({ page }) => { test.skip(!isLiveMode(), "Playwright tests can only run on live mode"); + test.skip(!clientId, "Client ID environment variable required"); + test.skip(!azureUsername, "Username environment variable required"); + test.skip(!azurePassword, "Password environment variable required"); - const { app, start, stop } = await prepareServer({ port }); + const { start, stop } = await prepareServer({ port }); await preparePage(page); await start(); @@ -43,8 +41,8 @@ test("Authenticates", async ({ page }) => { const { InteractiveBrowserCredential } = (window as any).main; const credential = new InteractiveBrowserCredential({ - clientId, ...credentialOptions, + clientId, loginStyle: "redirect", }); @@ -57,35 +55,36 @@ test("Authenticates", async ({ page }) => { // Interactive login with Playwright await page.waitForNavigation(); await page.waitForSelector(`input[type="email"]`); - await page.fill(`input[type="email"]`, azureUsername); + await page.fill(`input[type="email"]`, azureUsername!); await page.waitForSelector(`input[type="submit"]`); await page.click(`input[type="submit"]`); await page.waitForLoadState("networkidle"); await page.waitForSelector(`input[type="password"]`); - await page.fill(`input[type="password"]`, azurePassword); + await page.fill(`input[type="password"]`, azurePassword!); await page.waitForSelector(`input[type="submit"]`); await page.click(`input[type="submit"]`); await page.waitForSelector(`input[type="submit"]`); await page.click(`input[type="submit"]`); await page.waitForURL(`${homeUri}**`); - await page.evaluate( + const token = await page.evaluate( async ({ clientId, scope, credentialOptions }) => { const { InteractiveBrowserCredential } = (window as any).main; const credential = new InteractiveBrowserCredential({ - clientId, ...credentialOptions, + clientId, loginStyle: "redirect", }); - const token = await credential.getToken(scope); - expect(token).toBeTruthy(); - expect(token.token).toBeTruthy(); - expect(token.expiresOnTimestamp).toBeTruthy(); + return await credential.getToken(scope); }, { clientId, scope, credentialOptions } ); + expect(token).toBeTruthy(); + expect(token.token).toBeTruthy(); + expect(token.expiresOnTimestamp).toBeTruthy(); + await stop(); }); diff --git a/sdk/identity/identity/test/playwright/rollup/src/index.js b/sdk/identity/identity/test/playwright/rollup/src/index.js deleted file mode 100644 index 3dd1abf56ba3..000000000000 --- a/sdk/identity/identity/test/playwright/rollup/src/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -export { InteractiveBrowserCredential } from "../../../../src"; diff --git a/sdk/identity/identity/test/playwright/rollup/src/index.ts b/sdk/identity/identity/test/playwright/rollup/src/index.ts new file mode 100644 index 000000000000..c57052284139 --- /dev/null +++ b/sdk/identity/identity/test/playwright/rollup/src/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +export { InteractiveBrowserCredential } from "../../../../src/credentials/interactiveBrowserCredential.browser"; diff --git a/sdk/identity/identity/test/playwright/server.ts b/sdk/identity/identity/test/playwright/server.ts index e6811ab8bfae..bd75d314458e 100644 --- a/sdk/identity/identity/test/playwright/server.ts +++ b/sdk/identity/identity/test/playwright/server.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { AccessToken, TokenCredential } from "@azure/core-auth"; import * as express from "express"; import { readFileSync } from "fs"; import { Server } from "http"; @@ -35,13 +34,11 @@ export interface PepareServerResult { */ export async function prepareServer(serverOptions: ServerOptions): Promise { const app = express(); - const database: Record = {}; - const { port, serverSecret } = serverOptions; /** * Logging calls. */ - app.use((req: express.Request, res: express.Response, next: express.NextFunction) => { + app.use((req: express.Request, _res: express.Response, next: express.NextFunction) => { console.log("Playwright Express test server:", req.url); next(); }); @@ -49,7 +46,7 @@ export async function prepareServer(serverOptions: ServerOptions): Promise { + app.get("/index.js", async (_req: express.Request, res: express.Response) => { const indexContent = readFileSync("./test/playwright/rollup/dist/index.js", { encoding: "utf8", }); @@ -59,7 +56,7 @@ export async function prepareServer(serverOptions: ServerOptions): Promise { + app.get("/", async (_req: express.Request, res: express.Response) => { const indexContent = readFileSync("./test/playwright/index.html", { encoding: "utf8" }); res.send(indexContent); }); @@ -74,7 +71,9 @@ export async function prepareServer(serverOptions: ServerOptions): Promise