[communication] Move @azure/communication-common to ESM/vitest (#31419)
### Packages impacted by this PR - @azure/communication-common ### Issues associated with this PR - https://github.com/Azure/azure-sdk-for-js/issues/31338 ### Describe the problem that is addressed by this PR Updates to ESM/vitest for @azure/communication-common ### What are the possible designs available to address the problem? If there are more than one possible design, why was the one in this PR chosen? ### Are there test cases added in this PR? _(If not, why?)_ ### Provide a list of related PRs _(if any)_ ### Command used to generate this PR:**_(Applicable only to SDK release request PRs)_ ### Checklists - [ ] Added impacted package name to the issue description - [ ] Does this PR needs any fixes in the SDK Generator?** _(If so, create an Issue in the [Autorest/typescript](https://github.com/Azure/autorest.typescript) repository and link it here)_ - [ ] Added a changelog (if necessary)
This commit is contained in:
Родитель
0cacd2113a
Коммит
fe7545b8bd
|
@ -19904,7 +19904,7 @@ packages:
|
|||
dev: false
|
||||
|
||||
file:projects/communication-common.tgz:
|
||||
resolution: {integrity: sha512-lWGXpp9xHaRFtOdJrZsv/5OrHYEAlT1diEen2KkDnO9udQ8XTDs9EGdRwnuprs7bAj/FzawXckFxj27gJ1C85Q==, tarball: file:projects/communication-common.tgz}
|
||||
resolution: {integrity: sha512-BoEaaH3sJLyt/JMQFr7Fw+iEtJ+73S+Ycef8OXgaLJZqUqrKFHONVPvT9PgnMKMm7Drv75jkfxY/yY18ZlOp8A==, tarball: file:projects/communication-common.tgz}
|
||||
name: '@rush-temp/communication-common'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
@ -19914,6 +19914,8 @@ packages:
|
|||
'@types/mocha': 10.0.9
|
||||
'@types/node': 18.19.55
|
||||
'@types/sinon': 17.0.3
|
||||
'@vitest/browser': 2.1.3(playwright@1.48.0)(typescript@5.6.3)(vitest@2.1.3)
|
||||
'@vitest/coverage-istanbul': 2.1.3(vitest@2.1.3)
|
||||
chai: 4.3.10
|
||||
chai-as-promised: 7.1.2(chai@4.3.10)
|
||||
cross-env: 7.0.3
|
||||
|
@ -19933,20 +19935,34 @@ packages:
|
|||
mocha: 10.7.3
|
||||
mockdate: 3.0.5
|
||||
nyc: 17.1.0
|
||||
playwright: 1.48.0
|
||||
rimraf: 5.0.10
|
||||
sinon: 17.0.1
|
||||
ts-node: 10.9.2(@types/node@18.19.55)(typescript@5.6.3)
|
||||
tslib: 2.7.0
|
||||
typescript: 5.6.3
|
||||
util: 0.12.5
|
||||
vitest: 2.1.3(@types/node@18.19.55)(@vitest/browser@2.1.3)
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
- '@swc/wasm'
|
||||
- '@edge-runtime/vm'
|
||||
- '@vitest/ui'
|
||||
- bufferutil
|
||||
- debug
|
||||
- happy-dom
|
||||
- jiti
|
||||
- jsdom
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- safaridriver
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- utf-8-validate
|
||||
- vite
|
||||
- webdriverio
|
||||
dev: false
|
||||
|
||||
file:projects/communication-email.tgz:
|
||||
|
@ -24257,7 +24273,7 @@ packages:
|
|||
dev: false
|
||||
|
||||
file:projects/storage-file-datalake.tgz:
|
||||
resolution: {integrity: sha512-SUsQnAA/geN3tUNpcVlFI+/vnrIcbnEYN/xfR5sWlu+qTJ6Hh0tqGofCusgJTlzfZyLSm/hv2GW6c3/Yj8iung==, tarball: file:projects/storage-file-datalake.tgz}
|
||||
resolution: {integrity: sha512-e+GSDtmAiZZkAHoCQZQAEWsR4wCqZTTbBfC85vnIBIVdlBTho8fI5YywC7VMtYylhd3J2SF/wWl7PGqbz/1MoA==, tarball: file:projects/storage-file-datalake.tgz}
|
||||
name: '@rush-temp/storage-file-datalake'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"include": ["dist-esm/src/**/*.js"],
|
||||
"exclude": ["**/*.d.ts", "dist-esm/src/generated/*"],
|
||||
"reporter": ["text-summary", "html", "cobertura"],
|
||||
"exclude-after-remap": false,
|
||||
"sourceMap": true,
|
||||
"produce-source-map": true,
|
||||
"instrument": true,
|
||||
"all": true
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "types/src/index.d.ts",
|
||||
"mainEntryPointFilePath": "dist/esm/index.d.ts",
|
||||
"docModel": {
|
||||
"enabled": true
|
||||
},
|
||||
|
@ -11,7 +11,7 @@
|
|||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "",
|
||||
"publicTrimmedFilePath": "./types/communication-common.d.ts"
|
||||
"publicTrimmedFilePath": "dist/communication-common.d.ts"
|
||||
},
|
||||
"messages": {
|
||||
"tsdocMessageReporting": {
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// https://github.com/karma-runner/karma-chrome-launcher
|
||||
process.env.CHROME_BIN = require("puppeteer").executablePath();
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: "./",
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ["mocha"],
|
||||
|
||||
plugins: [
|
||||
"karma-mocha",
|
||||
"karma-mocha-reporter",
|
||||
"karma-chrome-launcher",
|
||||
"karma-firefox-launcher",
|
||||
"karma-env-preprocessor",
|
||||
"karma-coverage",
|
||||
"karma-sourcemap-loader",
|
||||
"karma-junit-reporter",
|
||||
],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: ["dist-test/index.browser.js"],
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
"**/*.js": ["env"],
|
||||
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
|
||||
// Preprocess source file to calculate code coverage, however this will make source file unreadable
|
||||
//"dist-test/index.browser.js": ["coverage"]
|
||||
},
|
||||
|
||||
// inject following environment values into browser testing with window.__env__
|
||||
// environment values MUST be exported or set with same console running "karma start"
|
||||
// https://www.npmjs.com/package/karma-env-preprocessor
|
||||
envPreprocessor: ["ACCOUNT_NAME", "ACCOUNT_SAS"],
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ["mocha", "coverage", "junit"],
|
||||
|
||||
coverageReporter: {
|
||||
// specify a common output directory
|
||||
dir: "coverage-browser/",
|
||||
reporters: [
|
||||
{ type: "json", subdir: ".", file: "coverage.json" },
|
||||
{ type: "lcovonly", subdir: ".", file: "lcov.info" },
|
||||
{ type: "html", subdir: "html" },
|
||||
{ type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" },
|
||||
],
|
||||
},
|
||||
|
||||
junitReporter: {
|
||||
outputDir: "", // results will be saved as $outputDir/$browserName.xml
|
||||
outputFile: "test-results.browser.xml", // if included, results will be saved as $outputDir/$browserName/$outputFile
|
||||
suite: "", // suite will become the package name attribute in xml testsuite element
|
||||
useBrowserName: false, // add browser name to report and classes names
|
||||
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
|
||||
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
|
||||
properties: {}, // key value pair of properties to add to the <properties> section of the report
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
// 'ChromeHeadless', 'Chrome', 'Firefox', 'Edge', 'IE'
|
||||
browsers: ["HeadlessChrome"],
|
||||
|
||||
customLaunchers: {
|
||||
HeadlessChrome: {
|
||||
base: "ChromeHeadless",
|
||||
flags: ["--no-sandbox"],
|
||||
},
|
||||
},
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: true,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: 1,
|
||||
|
||||
browserNoActivityTimeout: 600000,
|
||||
browserDisconnectTimeout: 10000,
|
||||
browserDisconnectTolerance: 3,
|
||||
|
||||
client: {
|
||||
mocha: {
|
||||
// change Karma's debug.html to the mocha web reporter
|
||||
reporter: "html",
|
||||
timeout: "600000",
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
|
@ -3,28 +3,25 @@
|
|||
"version": "2.3.2",
|
||||
"description": "Common package for Azure Communication services.",
|
||||
"sdk-type": "client",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist-esm/src/index.js",
|
||||
"types": "types/communication-common.d.ts",
|
||||
"browser": {
|
||||
"./dist-esm/src/credential/cryptoUtils.js": "./dist-esm/src/credential/cryptoUtils.browser.js",
|
||||
"./dist-esm/src/credential/isNode.js": "./dist-esm/src/credential/isNode.browser.js"
|
||||
},
|
||||
"main": "./dist/commonjs/index.js",
|
||||
"module": "./dist/esm/index.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"browser": "./dist/browser/index.js",
|
||||
"scripts": {
|
||||
"audit": "node ../../../common/scripts/rush-audit.js && rimraf node_modules package-lock.json && npm i --package-lock-only 2>&1 && npm audit",
|
||||
"build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api",
|
||||
"build:browser": "tsc -p . && dev-tool run bundle",
|
||||
"build:node": "tsc -p . && dev-tool run bundle",
|
||||
"build": "npm run clean && dev-tool run build-package && dev-tool run extract-api",
|
||||
"build:browser": "dev-tool run build-package && dev-tool run bundle",
|
||||
"build:node": "dev-tool run build-package && dev-tool run bundle",
|
||||
"build:samples": "echo Skipped.",
|
||||
"build:test": "tsc -p . && dev-tool run bundle",
|
||||
"build:test": "dev-tool run build-package && dev-tool run bundle",
|
||||
"check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
|
||||
"clean": "rimraf --glob dist dist-* temp types *.tgz *.log",
|
||||
"execute:samples": "echo skipped",
|
||||
"extract-api": "tsc -p . && dev-tool run extract-api",
|
||||
"extract-api": "dev-tool run build-package && dev-tool run extract-api",
|
||||
"format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
|
||||
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
|
||||
"integration-test:browser": "karma start --single-run",
|
||||
"integration-test:node": "dev-tool run test:node-js-input -- --timeout 5000000 'dist-esm/test/**/*.spec.js'",
|
||||
"integration-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --no-test-proxy --browser",
|
||||
"integration-test:node": "dev-tool run test:vitest --no-test-proxy",
|
||||
"lint": "eslint package.json api-extractor.json README.md src test",
|
||||
"lint:fix": "eslint package.json api-extractor.json README.md src test --fix --fix-type [problem,suggestion]",
|
||||
"pack": "npm pack 2>&1",
|
||||
|
@ -32,14 +29,12 @@
|
|||
"test:browser": "npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
|
||||
"test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node",
|
||||
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
|
||||
"unit-test:browser": "karma start --single-run",
|
||||
"unit-test:node": "dev-tool run test:node-ts-input --no-test-proxy",
|
||||
"unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --no-test-proxy --browser",
|
||||
"unit-test:node": "dev-tool run test:vitest --no-test-proxy",
|
||||
"update-snippets": "echo skipped"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"dist-esm/src",
|
||||
"types/communication-common.d.ts",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
|
@ -63,45 +58,68 @@
|
|||
"sideEffects": false,
|
||||
"prettier": "@azure/eslint-plugin-azure-sdk/prettier.json",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.0.0",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
"@azure/core-rest-pipeline": "^1.3.2",
|
||||
"@azure/core-tracing": "^1.0.0",
|
||||
"@azure/core-util": "^1.0.0",
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-auth": "^1.8.0",
|
||||
"@azure/core-rest-pipeline": "^1.17.0",
|
||||
"@azure/core-tracing": "^1.2.0",
|
||||
"@azure/core-util": "^1.10.0",
|
||||
"events": "^3.0.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"tslib": "^2.2.0"
|
||||
"tslib": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure-tools/test-utils-vitest": "^1.0.0",
|
||||
"@azure/dev-tool": "^1.0.0",
|
||||
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
||||
"@microsoft/api-extractor": "^7.31.1",
|
||||
"@types/chai": "^4.1.6",
|
||||
"@types/chai-as-promised": "^7.1.0",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/sinon": "^17.0.0",
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"@vitest/browser": "^2.1.3",
|
||||
"@vitest/coverage-istanbul": "^2.1.3",
|
||||
"cross-env": "^7.0.2",
|
||||
"eslint": "^9.9.0",
|
||||
"inherits": "^2.0.3",
|
||||
"karma": "^6.2.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-coverage": "^2.0.0",
|
||||
"karma-env-preprocessor": "^0.1.1",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-junit-reporter": "^2.0.1",
|
||||
"karma-mocha": "^2.0.1",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-sourcemap-loader": "^0.3.8",
|
||||
"mocha": "^10.0.0",
|
||||
"mockdate": "^3.0.5",
|
||||
"nyc": "^17.0.0",
|
||||
"playwright": "^1.48.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"sinon": "^17.0.0",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "~5.6.2",
|
||||
"util": "^0.12.1"
|
||||
"util": "^0.12.1",
|
||||
"vitest": "^2.1.3"
|
||||
},
|
||||
"type": "module",
|
||||
"tshy": {
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"dialects": [
|
||||
"esm",
|
||||
"commonjs"
|
||||
],
|
||||
"esmDialects": [
|
||||
"browser",
|
||||
"react-native"
|
||||
],
|
||||
"selfLink": false
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"browser": {
|
||||
"types": "./dist/browser/index.d.ts",
|
||||
"default": "./dist/browser/index.js"
|
||||
},
|
||||
"react-native": {
|
||||
"types": "./dist/react-native/index.d.ts",
|
||||
"default": "./dist/react-native/index.js"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
```ts
|
||||
|
||||
import { AbortSignalLike } from '@azure/abort-controller';
|
||||
import { AccessToken } from '@azure/core-auth';
|
||||
import type { AbortSignalLike } from '@azure/abort-controller';
|
||||
import type { AccessToken } from '@azure/core-auth';
|
||||
import { KeyCredential } from '@azure/core-auth';
|
||||
import { PipelinePolicy } from '@azure/core-rest-pipeline';
|
||||
import { TokenCredential } from '@azure/core-auth';
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { CommunicationGetTokenOptions, TokenCredential } from "./communicationTokenCredential";
|
||||
import { AbortSignalLike } from "@azure/abort-controller";
|
||||
import { AccessToken } from "@azure/core-auth";
|
||||
import { parseToken } from "./tokenParser";
|
||||
import type {
|
||||
CommunicationGetTokenOptions,
|
||||
TokenCredential,
|
||||
} from "./communicationTokenCredential.js";
|
||||
import type { AbortSignalLike } from "@azure/abort-controller";
|
||||
import type { AccessToken } from "@azure/core-auth";
|
||||
import { parseToken } from "./tokenParser.js";
|
||||
|
||||
/**
|
||||
* Options for auto-refreshing a Communication Token credential.
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
|
||||
import {
|
||||
AutoRefreshTokenCredential,
|
||||
CommunicationTokenRefreshOptions,
|
||||
} from "./autoRefreshTokenCredential";
|
||||
import {
|
||||
type CommunicationTokenRefreshOptions,
|
||||
} from "./autoRefreshTokenCredential.js";
|
||||
import type {
|
||||
CommunicationGetTokenOptions,
|
||||
CommunicationTokenCredential,
|
||||
TokenCredential,
|
||||
} from "./communicationTokenCredential";
|
||||
import { AccessToken } from "@azure/core-auth";
|
||||
import { StaticTokenCredential } from "./staticTokenCredential";
|
||||
import { parseToken } from "./tokenParser";
|
||||
} from "./communicationTokenCredential.js";
|
||||
import type { AccessToken } from "@azure/core-auth";
|
||||
import { StaticTokenCredential } from "./staticTokenCredential.js";
|
||||
import { parseToken } from "./tokenParser.js";
|
||||
|
||||
/**
|
||||
* The CommunicationTokenCredential implementation with support for proactive token refresh.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { AbortSignalLike } from "@azure/abort-controller";
|
||||
import { AccessToken } from "@azure/core-auth";
|
||||
import type { AbortSignalLike } from "@azure/abort-controller";
|
||||
import type { AccessToken } from "@azure/core-auth";
|
||||
|
||||
export type TokenCredential = Pick<CommunicationTokenCredential, "getToken" | "dispose">;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { KeyCredential, TokenCredential, isTokenCredential } from "@azure/core-auth";
|
||||
import { parseConnectionString } from "./connectionString";
|
||||
import { type KeyCredential, type TokenCredential, isTokenCredential } from "@azure/core-auth";
|
||||
import { parseConnectionString } from "./connectionString.js";
|
||||
|
||||
const isValidEndpoint = (host: string): boolean => {
|
||||
const url = new URL(host);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
import type {
|
||||
PipelinePolicy,
|
||||
PipelineRequest,
|
||||
PipelineResponse,
|
||||
SendRequest,
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import { shaHMAC, shaHash } from "./cryptoUtils";
|
||||
import { KeyCredential } from "@azure/core-auth";
|
||||
import { isNode } from "@azure/core-util";
|
||||
import { shaHMAC, shaHash } from "./cryptoUtils.js";
|
||||
import type { KeyCredential } from "@azure/core-auth";
|
||||
import { isNodeLike } from "@azure/core-util";
|
||||
|
||||
/**
|
||||
* CommunicationKeyCredentialPolicy provides a means of signing requests made through
|
||||
|
@ -44,7 +44,7 @@ export function createCommunicationAccessKeyCredentialPolicy(
|
|||
const stringToSign = `${verb}\n${urlPathAndQuery}\n${utcNow};${hostAndPort};${contentHash}`;
|
||||
const signature = await shaHMAC(credential.key, stringToSign);
|
||||
|
||||
if (isNode) {
|
||||
if (isNodeLike) {
|
||||
request.headers.set("Host", hostAndPort || "");
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
BearerTokenAuthenticationPolicyOptions,
|
||||
PipelinePolicy,
|
||||
type BearerTokenAuthenticationPolicyOptions,
|
||||
type PipelinePolicy,
|
||||
bearerTokenAuthenticationPolicy,
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import { KeyCredential, TokenCredential, isTokenCredential } from "@azure/core-auth";
|
||||
import { createCommunicationAccessKeyCredentialPolicy } from "./communicationAccessKeyCredentialPolicy";
|
||||
import { type KeyCredential, type TokenCredential, isTokenCredential } from "@azure/core-auth";
|
||||
import { createCommunicationAccessKeyCredentialPolicy } from "./communicationAccessKeyCredentialPolicy.js";
|
||||
/**
|
||||
* Creates a pipeline policy to authenticate request based
|
||||
* on the credential passed in.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { AzureKeyCredential, KeyCredential } from "@azure/core-auth";
|
||||
import { AzureKeyCredential, type KeyCredential } from "@azure/core-auth";
|
||||
/**
|
||||
* Represents different properties of connection string
|
||||
* using format "/endpoint=(.*);accesskey=(.*)".
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
/// <reference lib="dom" />
|
||||
|
||||
import { encodeBase64, encodeUTF8, encodeUTF8fromBase64 } from "./encodeUtils.browser";
|
||||
import { encodeBase64, encodeUTF8, encodeUTF8fromBase64 } from "./encodeUtils.browser.js";
|
||||
|
||||
const subtle = (globalThis as any)?.crypto?.subtle as SubtleCrypto;
|
||||
const subtleCrypto = globalThis.crypto.subtle;
|
||||
|
||||
export const shaHash = async (content: string): Promise<string> => {
|
||||
const data = encodeUTF8(content);
|
||||
const hash = await subtle.digest("SHA-256", data);
|
||||
const hash = await subtleCrypto.digest("SHA-256", data);
|
||||
return encodeBase64(hash);
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,7 @@ export const shaHMAC = async (secret: string, content: string): Promise<string>
|
|||
const importParams: HmacImportParams = { name: "HMAC", hash: { name: "SHA-256" } };
|
||||
const encodedMessage = encodeUTF8(content);
|
||||
const encodedKey = encodeUTF8fromBase64(secret);
|
||||
const crypto = subtle;
|
||||
const cryptoKey = await crypto.importKey("raw", encodedKey, importParams, false, ["sign"]);
|
||||
const signature = await crypto.sign(importParams, cryptoKey, encodedMessage);
|
||||
const cryptoKey = await subtleCrypto.importKey("raw", encodedKey, importParams, false, ["sign"]);
|
||||
const signature = await subtleCrypto.sign(importParams, cryptoKey, encodedMessage);
|
||||
return encodeBase64(signature);
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { createHash, createHmac } from "crypto";
|
||||
import { createHash, createHmac } from "node:crypto";
|
||||
|
||||
export const shaHash = async (content: string): Promise<string> =>
|
||||
createHash("sha256").update(content).digest("base64");
|
||||
|
|
|
@ -8,11 +8,7 @@ export function encodeUTF8fromBase64(str: string): Uint8Array {
|
|||
throw new Error("Your browser environment is missing the global `atob` function");
|
||||
}
|
||||
const binary = atob(str);
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
||||
}
|
||||
|
||||
export function encodeBase64(value: ArrayBuffer): string {
|
||||
|
@ -20,9 +16,6 @@ export function encodeBase64(value: ArrayBuffer): string {
|
|||
throw new Error("Your browser environment is missing the global `btoa` function");
|
||||
}
|
||||
const bytes = new Uint8Array(value);
|
||||
let binary = "";
|
||||
for (const byte of bytes) {
|
||||
binary += String.fromCharCode(byte);
|
||||
}
|
||||
const binary = String.fromCharCode.apply(null, [...bytes]);
|
||||
return btoa(binary);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
export * from "./communicationAccessKeyCredentialPolicy";
|
||||
export * from "./communicationAuthPolicy";
|
||||
export * from "./clientArguments";
|
||||
export * from "./connectionString";
|
||||
export * from "./communicationAccessKeyCredentialPolicy.js";
|
||||
export * from "./communicationAuthPolicy.js";
|
||||
export * from "./clientArguments.js";
|
||||
export * from "./connectionString.js";
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
CommunicationIdentifier,
|
||||
CommunicationIdentifierKind,
|
||||
type CommunicationIdentifier,
|
||||
type CommunicationIdentifierKind,
|
||||
getIdentifierKind,
|
||||
getIdentifierRawId,
|
||||
} from "./identifierModels";
|
||||
} from "./identifierModels.js";
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
export {
|
||||
CommunicationTokenCredential,
|
||||
CommunicationGetTokenOptions,
|
||||
} from "./communicationTokenCredential";
|
||||
export { AzureCommunicationTokenCredential } from "./azureCommunicationTokenCredential";
|
||||
export * from "./credential";
|
||||
export { CommunicationTokenRefreshOptions } from "./autoRefreshTokenCredential";
|
||||
export * from "./credential";
|
||||
export * from "./identifierModels";
|
||||
export * from "./identifierModelSerializer";
|
||||
} from "./communicationTokenCredential.js";
|
||||
export { AzureCommunicationTokenCredential } from "./azureCommunicationTokenCredential.js";
|
||||
export * from "./credential/index.js";
|
||||
export { CommunicationTokenRefreshOptions } from "./autoRefreshTokenCredential.js";
|
||||
export * from "./credential/index.js";
|
||||
export * from "./identifierModels.js";
|
||||
export * from "./identifierModelSerializer.js";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { AccessToken } from "@azure/core-auth";
|
||||
import { TokenCredential } from "./communicationTokenCredential";
|
||||
import type { AccessToken } from "@azure/core-auth";
|
||||
import type { TokenCredential } from "./communicationTokenCredential.js";
|
||||
|
||||
/**
|
||||
* StaticTokenCredential
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { AccessToken } from "@azure/core-auth";
|
||||
import type { AccessToken } from "@azure/core-auth";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
|
||||
interface JwtToken {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { shaHMAC, shaHash } from "../../src/credential/cryptoUtils";
|
||||
import { assert } from "chai";
|
||||
import { shaHMAC, shaHash } from "../../src/credential/cryptoUtils.js";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
describe("CryptoUtils", function () {
|
||||
it("calculates correct hash", async function () {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import { AzureKeyCredential } from "@azure/core-auth";
|
||||
import { assert } from "chai";
|
||||
import { parseClientArguments } from "../../src";
|
||||
import { parseConnectionString } from "../../src";
|
||||
import { assertPropertyNames } from "./utils/credentialUtils";
|
||||
import { parseClientArguments } from "../../src/index.js";
|
||||
import { parseConnectionString } from "../../src/index.js";
|
||||
import { assertPropertyNames } from "./utils/credentialUtils.js";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
const mockCredential = new AzureKeyCredential("secret");
|
||||
const host = "https://contoso.communicationservices.azure.com";
|
||||
|
|
|
@ -9,10 +9,10 @@ import {
|
|||
createPipelineRequest,
|
||||
} from "@azure/core-rest-pipeline";
|
||||
import { KeyCredential } from "@azure/core-auth";
|
||||
import { assert } from "chai";
|
||||
import { createCommunicationAccessKeyCredentialPolicy } from "../../src";
|
||||
import { isNode } from "@azure/core-util";
|
||||
import { createCommunicationAccessKeyCredentialPolicy } from "../../src/index.js";
|
||||
import { isNodeLike } from "@azure/core-util";
|
||||
import { set } from "mockdate";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
const date = "2022-04-13T18:09:12.451Z";
|
||||
set(date); // Any request to Date will return this date
|
||||
|
@ -84,7 +84,7 @@ async function verifyHeadersForUrlReturnAuthHeader(urlToTest: string): Promise<s
|
|||
|
||||
assert.equal(dateHeader, "Wed, 13 Apr 2022 18:09:12 GMT");
|
||||
assert.equal(hashHeader, "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=");
|
||||
if (isNode) {
|
||||
if (isNodeLike) {
|
||||
assert.isNotEmpty(hostHeader);
|
||||
}
|
||||
return authHeader;
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { assert, use } from "chai";
|
||||
import { AzureCommunicationTokenCredential } from "../../src";
|
||||
import chaiAsPromised from "chai-as-promised";
|
||||
import { isNode } from "@azure/core-util";
|
||||
import sinon from "sinon";
|
||||
|
||||
use(chaiAsPromised);
|
||||
import { AzureCommunicationTokenCredential } from "../../src/index.js";
|
||||
import { isNodeLike } from "@azure/core-util";
|
||||
import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
|
||||
declare function btoa(stringToEncode: string): string;
|
||||
|
||||
const generateToken = (validForMinutes: number): string => {
|
||||
const expiresOn = (Date.now() + validForMinutes * 60 * 1000) / 1000;
|
||||
const tokenString = JSON.stringify({ exp: expiresOn });
|
||||
const base64Token = isNode ? Buffer.from(tokenString).toString("base64") : btoa(tokenString);
|
||||
const base64Token = isNodeLike ? Buffer.from(tokenString).toString("base64") : btoa(tokenString);
|
||||
return `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${base64Token}.adM-ddBZZlQ1WlN3pdPBOF5G4Wh9iZpxNP_fSvpF4cWs`;
|
||||
};
|
||||
|
||||
|
@ -34,14 +29,12 @@ const exposeInternalUpdatePromise = async (
|
|||
};
|
||||
|
||||
describe("CommunicationTokenCredential", function () {
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("handles valid JWT strings", async function () {
|
||||
|
@ -53,11 +46,11 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
|
||||
it("throws if non-JWT passed as lambda", async function () {
|
||||
await assert.isRejected(
|
||||
await expect(() =>
|
||||
new AzureCommunicationTokenCredential({
|
||||
tokenRefresher: async () => "IAmNotAToken",
|
||||
}).getToken(),
|
||||
);
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("returns token as expected", async function () {
|
||||
|
@ -69,18 +62,18 @@ describe("CommunicationTokenCredential", function () {
|
|||
|
||||
it("returns token as expected when using lambda", async function () {
|
||||
const token = generateToken(60);
|
||||
const tokenRefresher = sinon.stub().resolves(token);
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(token);
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
});
|
||||
const tokenResult = (await tokenCredential.getToken()).token;
|
||||
assert.strictEqual(tokenResult, token);
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("uses initial token as expected", async function () {
|
||||
const token = generateToken(60);
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(120));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(120));
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
token,
|
||||
|
@ -88,42 +81,39 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
const tokenResult = (await tokenCredential.getToken()).token;
|
||||
assert.strictEqual(tokenResult, token);
|
||||
sinon.assert.notCalled(tokenRefresher);
|
||||
expect(tokenRefresher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("no proactive refresh, accepts expired token", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(-1));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(-1));
|
||||
new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
});
|
||||
clock.tick(5 * 60 * 1000);
|
||||
sinon.assert.notCalled(tokenRefresher);
|
||||
vi.advanceTimersByTime(5 * 60 * 1000);
|
||||
expect(tokenRefresher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("with proactive refresh, passing an expired token to constructor triggers immediate refresh", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(30));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(30));
|
||||
new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
token: generateToken(-1),
|
||||
});
|
||||
clock.tick(5 * 60 * 1000);
|
||||
vi.advanceTimersByTime(5 * 60 * 1000);
|
||||
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("throws if tokenRefresher returns an expired token", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(-1));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(-1));
|
||||
const credential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher: tokenRefresher,
|
||||
});
|
||||
clock.tick(5 * 60 * 1000);
|
||||
await assert.isRejected(
|
||||
credential.getToken(),
|
||||
Error,
|
||||
"The token returned from the tokenRefresher is expired.",
|
||||
);
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
vi.advanceTimersByTime(5 * 60 * 1000);
|
||||
|
||||
await expect(credential.getToken()).rejects.toThrow(Error);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("returns expired token when not using a lambda", async function () {
|
||||
|
@ -134,14 +124,14 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
|
||||
it("passes abortSignal through to tokenRefresher", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(60));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(60));
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
});
|
||||
const aborter = new AbortController();
|
||||
const options = { abortSignal: aborter.signal };
|
||||
tokenCredential.getToken(options);
|
||||
sinon.assert.calledOnceWithExactly(tokenRefresher, options.abortSignal);
|
||||
expect(tokenRefresher).toHaveBeenCalledWith(options.abortSignal);
|
||||
});
|
||||
|
||||
it("throws if disposed", async function () {
|
||||
|
@ -151,46 +141,48 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
withStatic.dispose();
|
||||
withLambda.dispose();
|
||||
await assert.isRejected(withStatic.getToken());
|
||||
await assert.isRejected(withLambda.getToken());
|
||||
await expect(() => withStatic.getToken()).rejects.toThrow();
|
||||
await expect(() => withLambda.getToken()).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("doesn't swallow error from tokenRefresher", async function () {
|
||||
const tokenRefresher = sinon.stub().throws(new Error("No token for you!"));
|
||||
const tokenRefresher = vi.fn().mockImplementation(() => {
|
||||
new Error("No token for you!");
|
||||
});
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
});
|
||||
await assert.isRejected(tokenCredential.getToken());
|
||||
await expect(() => tokenCredential.getToken()).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("requests new token when token is about to expire", async function () {
|
||||
const token = generateToken(20);
|
||||
const newToken = generateToken(60);
|
||||
const tokenRefresher = sinon.stub().resolves(token);
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(token);
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher });
|
||||
|
||||
const tokenResult = await tokenCredential.getToken();
|
||||
assert.strictEqual(tokenResult.token, token);
|
||||
|
||||
tokenRefresher.resolves(newToken);
|
||||
tokenRefresher.mockResolvedValue(newToken);
|
||||
// go into the soon-to-expire window
|
||||
clock.tick(19 * 60 * 1000);
|
||||
vi.advanceTimersByTime(19 * 60 * 1000);
|
||||
const secondTokenResult = await tokenCredential.getToken();
|
||||
|
||||
// returns old token because it's still valid
|
||||
assert.strictEqual(secondTokenResult.token, token);
|
||||
|
||||
clock.tick(5 * 60 * 1000);
|
||||
vi.advanceTimersByTime(5 * 60 * 1000);
|
||||
// now it returns new token
|
||||
const thirdTokenResult = await tokenCredential.getToken();
|
||||
assert.strictEqual(thirdTokenResult.token, newToken);
|
||||
|
||||
sinon.assert.calledTwice(tokenRefresher);
|
||||
expect(tokenRefresher).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("proactively refreshes token when it is about to expire", async function () {
|
||||
const token = (): string => generateToken(20);
|
||||
const tokenRefresher = sinon.stub().resolves(token());
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(token());
|
||||
new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
|
@ -198,13 +190,13 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
|
||||
// go into the soon-to-expire window
|
||||
clock.tick(19 * 60 * 1000);
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
vi.advanceTimersByTime(19 * 60 * 1000);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("repeats proactive refreshing", async function () {
|
||||
const token = (): string => generateToken(20);
|
||||
const tokenRefresher = sinon.stub().resolves(token());
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(token());
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
|
@ -213,7 +205,7 @@ describe("CommunicationTokenCredential", function () {
|
|||
|
||||
const internalTimeout = exposeInternalTimeout(tokenCredential);
|
||||
// go into the soon-to-expire window
|
||||
clock.tick(19 * 60 * 1000);
|
||||
vi.advanceTimersByTime(19 * 60 * 1000);
|
||||
|
||||
await exposeInternalUpdatePromise(tokenCredential);
|
||||
const newInternalTimeout = exposeInternalTimeout(tokenCredential);
|
||||
|
@ -225,7 +217,7 @@ describe("CommunicationTokenCredential", function () {
|
|||
|
||||
it("dispose cancels timer", async function () {
|
||||
const token = (): string => generateToken(20);
|
||||
const tokenRefresher = sinon.stub().resolves(token());
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(token());
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
|
@ -233,33 +225,34 @@ describe("CommunicationTokenCredential", function () {
|
|||
});
|
||||
|
||||
tokenCredential.dispose();
|
||||
|
||||
// go into the soon-to-expire window
|
||||
clock.tick(19 * 60 * 1000);
|
||||
sinon.assert.notCalled(tokenRefresher);
|
||||
vi.advanceTimersByTimeAsync(19 * 60 * 1000);
|
||||
expect(tokenRefresher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("multiple calls to getToken call tokenRefresher only once", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(60));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(60));
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({ tokenRefresher });
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await tokenCredential.getToken();
|
||||
}
|
||||
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("calls tokenRefresher only once when proactive refreshing is in progress", async function () {
|
||||
const tokenRefresher = sinon.stub().resolves(generateToken(20));
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(generateToken(20));
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
});
|
||||
|
||||
// go into the soon-to-expire window
|
||||
clock.tick(19 * 60 * 1000);
|
||||
vi.advanceTimersByTime(19 * 60 * 1000);
|
||||
await tokenCredential.getToken();
|
||||
sinon.assert.calledOnce(tokenRefresher);
|
||||
expect(tokenRefresher).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("applies fractional backoff when the token is about to expire", async function () {
|
||||
|
@ -270,7 +263,7 @@ describe("CommunicationTokenCredential", function () {
|
|||
Math.log(tokenExpirationMinutes * 60) / Math.log(1 / defaultRefreshAfterLifetimePercentage),
|
||||
);
|
||||
const staticToken = generateToken(tokenExpirationMinutes);
|
||||
const tokenRefresher = sinon.stub().resolves(((): string => staticToken)()); // keep returning the same token for the duration of the test
|
||||
const tokenRefresher = vi.fn().mockResolvedValue(((): string => staticToken)()); // keep returning the same token for the duration of the test
|
||||
const tokenCredential = new AzureCommunicationTokenCredential({
|
||||
tokenRefresher,
|
||||
refreshProactively: true,
|
||||
|
@ -283,21 +276,21 @@ describe("CommunicationTokenCredential", function () {
|
|||
for (let i = 0; i < 10 * 60; i++) {
|
||||
// perform token refreshing & scheduling
|
||||
await exposeInternalUpdatePromise(tokenCredential);
|
||||
clock.tick(1000);
|
||||
vi.advanceTimersByTime(1000);
|
||||
}
|
||||
|
||||
// expect the token to be refreshed only once within the first 10 minutes
|
||||
sinon.assert.callCount(tokenRefresher, expectedPreBackOffCallCount);
|
||||
expect(tokenRefresher).toHaveBeenCalledTimes(expectedPreBackOffCallCount);
|
||||
|
||||
// iterate until the penultimate second of the token expiration
|
||||
// to prevent an exception being thrown due to the token being expired
|
||||
while (Math.floor((newToken.expiresOnTimestamp - Date.now()) / 1000) > 1) {
|
||||
// perform token refreshing & scheduling
|
||||
await exposeInternalUpdatePromise(tokenCredential);
|
||||
clock.tick(1000);
|
||||
vi.advanceTimersByTime(1000);
|
||||
}
|
||||
|
||||
// expect the token to be refreshed with an increasing frequency in the remaining 10 minutes
|
||||
sinon.assert.callCount(tokenRefresher, expectedTotalCallCount);
|
||||
expect(tokenRefresher).toHaveBeenCalledTimes(expectedTotalCallCount);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import { AzureKeyCredential } from "@azure/core-auth";
|
||||
import { assert } from "chai";
|
||||
import { parseConnectionString } from "../../src";
|
||||
import { assertPropertyNames } from "./utils/credentialUtils";
|
||||
import { parseConnectionString } from "../../src/index.js";
|
||||
import { assertPropertyNames } from "./utils/credentialUtils.js";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
const CONNECTION_STRING =
|
||||
"endpoint=https://contoso.communicationservices.azure.com:443/;accesskey=secret";
|
||||
|
|
|
@ -7,8 +7,8 @@ import {
|
|||
SerializedCommunicationIdentifier,
|
||||
deserializeCommunicationIdentifier,
|
||||
serializeCommunicationIdentifier,
|
||||
} from "../../src";
|
||||
import { assert } from "chai";
|
||||
} from "../../src/index.js";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
const assertSerialize = (
|
||||
identifier: CommunicationIdentifier,
|
||||
|
|
|
@ -12,8 +12,8 @@ import {
|
|||
isMicrosoftTeamsUserIdentifier,
|
||||
isPhoneNumberIdentifier,
|
||||
isUnknownIdentifier,
|
||||
} from "../../src";
|
||||
import { assert } from "chai";
|
||||
} from "../../src/index.js";
|
||||
import { describe, it, assert } from "vitest";
|
||||
|
||||
describe("Identifier models", function () {
|
||||
it("type guards", function () {
|
||||
|
@ -35,7 +35,7 @@ describe("Identifier models", function () {
|
|||
});
|
||||
|
||||
it("get raw id of identifier", function () {
|
||||
const assertRawId = (identifier: CommunicationIdentifier, expectedRawId: string) =>
|
||||
const assertRawId = (identifier: CommunicationIdentifier, expectedRawId: string): void =>
|
||||
assert.strictEqual(getIdentifierRawId(identifier), expectedRawId);
|
||||
|
||||
assertRawId(
|
||||
|
@ -159,8 +159,10 @@ describe("Identifier models", function () {
|
|||
});
|
||||
|
||||
it("create identifier from raw id", function () {
|
||||
const assertIdentifier = (rawId: string, expectedIdentifier: CommunicationIdentifierKind) =>
|
||||
assert.deepStrictEqual(createIdentifierFromRawId(rawId), expectedIdentifier);
|
||||
const assertIdentifier = (
|
||||
rawId: string,
|
||||
expectedIdentifier: CommunicationIdentifierKind,
|
||||
): void => assert.deepStrictEqual(createIdentifierFromRawId(rawId), expectedIdentifier);
|
||||
|
||||
assertIdentifier(
|
||||
"8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130",
|
||||
|
@ -302,7 +304,7 @@ describe("Identifier models", function () {
|
|||
});
|
||||
|
||||
it("rawId stays the same after conversion to identifier and back", function () {
|
||||
const assertRoundtrip = (rawId: string) =>
|
||||
const assertRoundtrip = (rawId: string): void =>
|
||||
assert.strictEqual(getIdentifierRawId(createIdentifierFromRawId(rawId)), rawId);
|
||||
|
||||
assertRoundtrip(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import { AzureKeyCredential } from "@azure/core-auth";
|
||||
import { assert } from "chai";
|
||||
import { assert } from "vitest";
|
||||
|
||||
export const assertPropertyNames = <T>(
|
||||
expectedInstance: AzureKeyCredential,
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "./.tshy/build.json",
|
||||
"include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts"],
|
||||
"exclude": ["./test/**/node/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist-test/browser",
|
||||
"rootDir": ".",
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"extends": "../../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist-esm",
|
||||
"declarationDir": "./types"
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"rootDir": "."
|
||||
},
|
||||
"exclude": ["node_modules", "types", "temp", "browser", "dist", "dist-esm", "./samples/**/*.ts"]
|
||||
"exclude": ["node_modules", "types", "temp", "browser", "dist", "dist-esm", "./samples/**/*.ts"],
|
||||
"include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { defineConfig, mergeConfig } from "vitest/config";
|
||||
import viteConfig from "../../../vitest.browser.base.config.ts";
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
include: ["dist-test/browser/test/**/*.spec.js"],
|
||||
},
|
||||
}),
|
||||
);
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { defineConfig, mergeConfig } from "vitest/config";
|
||||
import viteConfig from "../../../vitest.shared.config.ts";
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
include: ["test/**/*.spec.ts"],
|
||||
},
|
||||
}),
|
||||
);
|
Загрузка…
Ссылка в новой задаче