diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000000..b2bee0cadf71 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "test:vitest", + "type": "node", + "request": "launch", + "runtimeExecutable": "npx", + "runtimeArgs": ["dev-tool", "run", "test:vitest"], + "args": ["--", "--inspect-brk", "--no-file-parallelism", "${input:filename}"], + "autoAttachChildProcesses": false, + "skipFiles": ["/**"], + "console": "integratedTerminal", + "attachSimplePort": 9229, + "cwd": "${workspaceFolder}/sdk/${input:package-directory}" + } + ], + "inputs": [ + { + "id": "filename", + "type": "promptString", + "description": "(Optional) Enter a part of the test file name (e.g. 'foo' will run 'foo.spec.ts', 'notfoo.spec.ts', 'test.foo.spec.ts', etc.)", + "default": "" + }, + { + "id": "package-directory", + "type": "promptString", + "description": "Enter the package directory (e.g., 'identity/identity', 'keyvault/keyvault-keys', etc.)" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 103f8e1f7892..d4b308085e08 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,8 +10,7 @@ "files.exclude": { "**/.git": true, "**/.svn": true, - "**/.DS_Store": true, - "**/node_modules": true + "**/.DS_Store": true }, "files.insertFinalNewline": true, "files.trimFinalNewlines": true, diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 6c748c6bb487..c60fdcd776ca 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1655,6 +1655,11 @@ packages: engines: {node: '>=0.8.0'} dev: false + /@azure/msal-common@14.16.0: + resolution: {integrity: sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==} + engines: {node: '>=0.8.0'} + dev: false + /@azure/msal-node-extensions@1.3.0: resolution: {integrity: sha512-7rXN+9hDm3NncIfNnMyoFtsnz2AlUtmK5rsY3P+fhhbH+GOk0W5Y1BASvAB6RCcKdO+qSIK3ZA6VHQYy4iS/1w==} engines: {node: '>=16'} @@ -1679,6 +1684,15 @@ packages: uuid: 8.3.2 dev: false + /@azure/msal-node@2.16.1: + resolution: {integrity: sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg==} + engines: {node: '>=16'} + dependencies: + '@azure/msal-common': 14.16.0 + jsonwebtoken: 9.0.2 + uuid: 8.3.2 + dev: false + /@azure/openai@1.0.0-beta.12: resolution: {integrity: sha512-qKblxr6oVa8GsyNzY+/Ub9VmEsPYKhBrUrPaNEQiM+qrxnBPVm9kaeqGFFb/U78Q2zOabmhF9ctYt3xBW0nWnQ==} engines: {node: '>=18.0.0'} @@ -1962,6 +1976,12 @@ packages: cookie: 0.5.0 dev: false + /@bundled-es-modules/cookie@2.0.1: + resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} + dependencies: + cookie: 0.7.2 + dev: false + /@bundled-es-modules/statuses@1.0.1: resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} dependencies: @@ -3711,6 +3731,12 @@ packages: '@sinonjs/commons': 3.0.1 dev: false + /@sinonjs/fake-timers@13.0.5: + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + dependencies: + '@sinonjs/commons': 3.0.1 + dev: false + /@sinonjs/samsam@8.0.2: resolution: {integrity: sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==} dependencies: @@ -4508,6 +4534,40 @@ packages: - vite dev: false + /@vitest/browser@2.1.5(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.5): + resolution: {integrity: sha512-JrpnxvkrjlBrF7oXbK/YytWVYfJIzWYeDKppANlUaisBKwDso+yXlWocAJrANx8gUxyirF355Yx80S+SKQqayg==} + peerDependencies: + playwright: '*' + safaridriver: '*' + vitest: 2.1.5 + webdriverio: '*' + peerDependenciesMeta: + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@testing-library/dom': 10.4.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/mocker': 2.1.5(msw@2.6.4) + '@vitest/utils': 2.1.5 + magic-string: 0.30.12 + msw: 2.6.4(@types/node@18.19.64)(typescript@5.6.3) + playwright: 1.48.2 + sirv: 3.0.0 + tinyrainbow: 1.2.0 + vitest: 2.1.5(@types/node@18.19.64)(@vitest/browser@2.1.5) + ws: 8.18.0 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - typescript + - utf-8-validate + - vite + dev: false + /@vitest/coverage-istanbul@1.6.0(vitest@1.6.0): resolution: {integrity: sha512-h/BwpXehkkS0qsNCS00QxiupAqVkNi0WT19BR0dQvlge5oHghoSVLx63fABYFoKxVb7Ue7+k6V2KokmQ1zdMpg==} peerDependencies: @@ -4547,6 +4607,26 @@ packages: - supports-color dev: false + /@vitest/coverage-istanbul@2.1.5(vitest@2.1.5): + resolution: {integrity: sha512-jJsS5jeHncmSvzMNE03F1pk8F9etmjzGmGyQnGMkdHdVek/bxK/3vo8Qr3e9XmVuDM3UZKOy1ObeQHgC2OxvHg==} + peerDependencies: + vitest: 2.1.5 + dependencies: + '@istanbuljs/schema': 0.1.3 + debug: 4.3.7(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magicast: 0.3.5 + test-exclude: 7.0.1 + tinyrainbow: 1.2.0 + vitest: 2.1.5(@types/node@18.19.64)(@vitest/browser@2.1.5) + transitivePeerDependencies: + - supports-color + dev: false + /@vitest/expect@1.6.0: resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} dependencies: @@ -4564,6 +4644,15 @@ packages: tinyrainbow: 1.2.0 dev: false + /@vitest/expect@2.1.5: + resolution: {integrity: sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==} + dependencies: + '@vitest/spy': 2.1.5 + '@vitest/utils': 2.1.5 + chai: 5.1.2 + tinyrainbow: 1.2.0 + dev: false + /@vitest/mocker@2.1.4(msw@2.6.0): resolution: {integrity: sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==} peerDependencies: @@ -4598,12 +4687,52 @@ packages: vite: 5.4.10(@types/node@18.19.64) dev: false + /@vitest/mocker@2.1.5(msw@2.6.4): + resolution: {integrity: sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + dependencies: + '@vitest/spy': 2.1.5 + estree-walker: 3.0.3 + magic-string: 0.30.12 + msw: 2.6.4(@types/node@18.19.64)(typescript@5.6.3) + dev: false + + /@vitest/mocker@2.1.5(vite@5.4.10): + resolution: {integrity: sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + dependencies: + '@vitest/spy': 2.1.5 + estree-walker: 3.0.3 + magic-string: 0.30.12 + vite: 5.4.10(@types/node@18.19.64) + dev: false + /@vitest/pretty-format@2.1.4: resolution: {integrity: sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==} dependencies: tinyrainbow: 1.2.0 dev: false + /@vitest/pretty-format@2.1.5: + resolution: {integrity: sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==} + dependencies: + tinyrainbow: 1.2.0 + dev: false + /@vitest/runner@1.6.0: resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} dependencies: @@ -4619,6 +4748,13 @@ packages: pathe: 1.1.2 dev: false + /@vitest/runner@2.1.5: + resolution: {integrity: sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==} + dependencies: + '@vitest/utils': 2.1.5 + pathe: 1.1.2 + dev: false + /@vitest/snapshot@1.6.0: resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} dependencies: @@ -4635,6 +4771,14 @@ packages: pathe: 1.1.2 dev: false + /@vitest/snapshot@2.1.5: + resolution: {integrity: sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==} + dependencies: + '@vitest/pretty-format': 2.1.5 + magic-string: 0.30.12 + pathe: 1.1.2 + dev: false + /@vitest/spy@1.6.0: resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} dependencies: @@ -4647,6 +4791,12 @@ packages: tinyspy: 3.0.2 dev: false + /@vitest/spy@2.1.5: + resolution: {integrity: sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==} + dependencies: + tinyspy: 3.0.2 + dev: false + /@vitest/utils@1.6.0: resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} dependencies: @@ -4664,6 +4814,14 @@ packages: tinyrainbow: 1.2.0 dev: false + /@vitest/utils@2.1.5: + resolution: {integrity: sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==} + dependencies: + '@vitest/pretty-format': 2.1.5 + loupe: 3.1.2 + tinyrainbow: 1.2.0 + dev: false + /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -5124,6 +5282,13 @@ packages: engines: {node: '>=6'} dev: false + /bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + dependencies: + run-applescript: 7.0.0 + dev: false + /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -5771,6 +5936,19 @@ packages: engines: {node: '>=0.10.0'} dev: false + /default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + dev: false + + /default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + dev: false + /default-require-extensions@3.0.1: resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==} engines: {node: '>=8'} @@ -5798,6 +5976,11 @@ packages: engines: {node: '>=8'} dev: false + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false + /degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} @@ -5855,6 +6038,11 @@ packages: engines: {node: '>=0.3.1'} dev: false + /diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -6001,6 +6189,10 @@ packages: engines: {node: '>= 0.4'} dev: false + /es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + dev: false + /es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} dev: false @@ -7335,6 +7527,12 @@ packages: hasBin: true dev: false + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -7363,6 +7561,14 @@ packages: resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} dev: false + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -7449,6 +7655,13 @@ packages: is-docker: 2.2.1 dev: false + /is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + dependencies: + is-inside-container: 1.0.0 + dev: false + /isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} dev: false @@ -8512,6 +8725,40 @@ packages: - '@types/node' dev: false + /msw@2.6.4(@types/node@18.19.64)(typescript@5.6.3): + resolution: {integrity: sha512-Pm4LmWQeytDsNCR+A7gt39XAdtH6zQb6jnIKRig0FlvYOn8eksn3s1nXxUfz5KYUjbckof7Z4p2ewzgffPoCbg==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@bundled-es-modules/cookie': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.0.1(@types/node@18.19.64) + '@mswjs/interceptors': 0.36.9 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.5 + chalk: 4.1.2 + graphql: 16.9.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + strict-event-emitter: 0.5.1 + type-fest: 4.26.1 + typescript: 5.6.3 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + dev: false + /mustache@4.2.0: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true @@ -8565,6 +8812,16 @@ packages: path-to-regexp: 6.3.0 dev: false + /nise@6.1.1: + resolution: {integrity: sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==} + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 13.0.5 + '@sinonjs/text-encoding': 0.7.3 + just-extend: 6.2.0 + path-to-regexp: 8.2.0 + dev: false + /nock@13.5.5: resolution: {integrity: sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA==} engines: {node: '>= 10.13'} @@ -8731,6 +8988,16 @@ packages: mimic-fn: 4.0.0 dev: false + /open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + dev: false + /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -9010,6 +9277,11 @@ packages: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} dev: false + /path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + dev: false + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -9721,6 +9993,11 @@ packages: fsevents: 2.3.3 dev: false + /run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + dev: false + /run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} @@ -9907,6 +10184,17 @@ packages: supports-color: 7.2.0 dev: false + /sinon@19.0.2: + resolution: {integrity: sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==} + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 13.0.5 + '@sinonjs/samsam': 8.0.2 + diff: 7.0.0 + nise: 6.1.1 + supports-color: 7.2.0 + dev: false + /sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} @@ -10087,6 +10375,10 @@ packages: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} dev: false + /std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + dev: false + /stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} engines: {node: '>=4', npm: '>=6'} @@ -11036,6 +11328,28 @@ packages: - terser dev: false + /vite-node@2.1.5(@types/node@18.19.64): + resolution: {integrity: sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.7(supports-color@8.1.1) + es-module-lexer: 1.5.4 + pathe: 1.1.2 + vite: 5.4.10(@types/node@18.19.64) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + dev: false + /vite@5.4.10(@types/node@18.19.64): resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} engines: {node: ^18.0.0 || >=20.0.0} @@ -11289,6 +11603,65 @@ packages: - terser dev: false + /vitest@2.1.5(@types/node@18.19.64)(@vitest/browser@2.1.5): + resolution: {integrity: sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.5 + '@vitest/ui': 2.1.5 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 18.19.64 + '@vitest/browser': 2.1.5(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.5) + '@vitest/expect': 2.1.5 + '@vitest/mocker': 2.1.5(vite@5.4.10) + '@vitest/pretty-format': 2.1.5 + '@vitest/runner': 2.1.5 + '@vitest/snapshot': 2.1.5 + '@vitest/spy': 2.1.5 + '@vitest/utils': 2.1.5 + chai: 5.1.2 + debug: 4.3.7(supports-color@8.1.1) + expect-type: 1.1.0 + magic-string: 0.30.12 + pathe: 1.1.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.1 + tinypool: 1.0.1 + tinyrainbow: 1.2.0 + vite: 5.4.10(@types/node@18.19.64) + vite-node: 2.1.5(@types/node@18.19.64) + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + dev: false + /void-elements@2.0.1: resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} engines: {node: '>=0.10.0'} @@ -18601,7 +18974,7 @@ packages: dev: false file:projects/communication-chat.tgz: - resolution: {integrity: sha512-skckUOVlwJEksKTKnfz6C+gSMGDH9OSD5hqIk8Xe778C4oVgYmAxt5Ca06odu4sPxGg9ltSUnDtx4XBaW8PqYA==, tarball: file:projects/communication-chat.tgz} + resolution: {integrity: sha512-J1sRuvQkiaeWZtnBmgo0F7yz38gSppMo/+b42TnKyPoRq+Es1UaUXkdo8CMpQfOW79FtH0Oo95HLKs43eq/rgw==, tarball: file:projects/communication-chat.tgz} name: '@rush-temp/communication-chat' version: 0.0.0 dependencies: @@ -18631,7 +19004,7 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 - sinon: 17.0.1 + sinon: 19.0.2 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 @@ -18688,7 +19061,7 @@ packages: dev: false file:projects/communication-email.tgz: - resolution: {integrity: sha512-ZOPSfMCI6uWwWm9OUsw6AHSJzn7SAMKxJOFFDbrj1jkvcQ9f1V+m2qa1NwV7FywuGMuKjN7wumpI284OIjxSxg==, tarball: file:projects/communication-email.tgz} + resolution: {integrity: sha512-QhLsLLokYOq6xNcg5alwSd7zmjUr5iul+3/p1yq7jzXk2vDsxGU32Wq5S1ALu5jX+eTLPpxjm8WPdCFc37UtIg==, tarball: file:projects/communication-email.tgz} name: '@rush-temp/communication-email' version: 0.0.0 dependencies: @@ -18697,6 +19070,8 @@ packages: '@types/chai': 4.3.20 '@types/mocha': 10.0.9 '@types/node': 18.19.64 + '@vitest/browser': 2.1.5(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.5) + '@vitest/coverage-istanbul': 2.1.5(vitest@2.1.5) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -18713,32 +19088,48 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) - tslib: 1.14.1 + tslib: 2.8.1 typescript: 5.6.3 + vitest: 2.1.5(@types/node@18.19.64)(@vitest/browser@2.1.5) 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-identity.tgz: - resolution: {integrity: sha512-qhM0Ig2VTC6fRQ0sjCP+8aYlz1m4yr+uC5vlhm/pXop87s6MyIIpZzHZH6MTijaIKKlTzZt+3dxYs/4XwqKVhA==, tarball: file:projects/communication-identity.tgz} + resolution: {integrity: sha512-cHCdd2LiWjg4jftWNnziaCV9uNSMfkhoUDFlKBymYkvmj4dbrgoobwpuPOkqJ4zoB9r86aiRDNP/E0YmMF2RFw==, tarball: file:projects/communication-identity.tgz} name: '@rush-temp/communication-identity' version: 0.0.0 dependencies: '@azure-tools/test-credential': 1.3.1 '@azure-tools/test-recorder': 3.5.2 '@azure/core-lro': 2.7.2 - '@azure/msal-node': 2.15.0 + '@azure/msal-node': 2.16.1 '@types/chai': 4.3.20 '@types/mocha': 10.0.9 '@types/node': 18.19.64 '@types/sinon': 17.0.3 + '@vitest/browser': 2.1.5(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.5) + '@vitest/coverage-istanbul': 2.1.5(vitest@2.1.5) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -18755,23 +19146,37 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 process: 0.11.10 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 + vitest: 2.1.5(@types/node@18.19.64)(@vitest/browser@2.1.5) 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-job-router-1.tgz: - resolution: {integrity: sha512-RZbsUhQkZUx5IKP0bXznxjTXhgPuBwPUEKVgusXlHstCp2/Qlo0Gj28SFhFxRIccGikPKPoTcLvspMSRJ/oQNg==, tarball: file:projects/communication-job-router-1.tgz} + resolution: {integrity: sha512-7NGs1l8E3JJ5oW9FXr+0jZnJyJkaCWcNqd/iA2rE1PqlEPv1bJ1GkPY+vh6cmDoZUSodOmWK4kn7Un4S5nsinw==, tarball: file:projects/communication-job-router-1.tgz} name: '@rush-temp/communication-job-router-1' version: 0.0.0 dependencies: @@ -18781,6 +19186,8 @@ packages: '@types/node': 18.19.64 '@types/sinon': 17.0.3 '@types/uuid': 8.3.4 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -18799,20 +19206,34 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 util: 0.12.5 uuid: 8.3.2 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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-job-router.tgz: @@ -18898,7 +19319,7 @@ packages: dev: false file:projects/communication-phone-numbers.tgz: - resolution: {integrity: sha512-TFOWK46fB+Xt/4wne7rUVXbFOJLR6FWn9+hUo1Q09WA/LTL5CyTfC1fPK7dpdGPR2OA/+ebefNQjguLcLvR2BQ==, tarball: file:projects/communication-phone-numbers.tgz} + resolution: {integrity: sha512-24JG0UquvqCfpD2fHYVg31EE7Zu+1LadlqbxK1oIhPj3dnaQ152m8T++HHMAkFzfbNdaH/1yqWjLTpBVotKMXA==, tarball: file:projects/communication-phone-numbers.tgz} name: '@rush-temp/communication-phone-numbers' version: 0.0.0 dependencies: @@ -18909,6 +19330,8 @@ packages: '@types/mocha': 10.0.9 '@types/node': 18.19.64 '@types/sinon': 17.0.3 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -18925,22 +19348,36 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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-recipient-verification.tgz: - resolution: {integrity: sha512-EJ/L18WNgHvJpQIzFUPd4+srCdToi/A/urtL2S9Rsh9TVrJpJsBgW42B8c1IXOVbvVr6WahdceA2JME1xz1eZw==, tarball: file:projects/communication-recipient-verification.tgz} + resolution: {integrity: sha512-cpVMuIbO+tSFbjQSjDB1yOL3QgqBKppbLvWuYCe2JoY10LBIu+a5SWMTSk9DbjlN+DfUCQ8gQN01zbizH0BBhw==, tarball: file:projects/communication-recipient-verification.tgz} name: '@rush-temp/communication-recipient-verification' version: 0.0.0 dependencies: @@ -18951,6 +19388,8 @@ packages: '@types/node': 18.19.64 '@types/sinon': 17.0.3 '@types/uuid': 8.3.4 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -18967,19 +19406,33 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 uuid: 8.3.2 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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-rooms.tgz: @@ -19015,7 +19468,7 @@ packages: dev: false file:projects/communication-short-codes.tgz: - resolution: {integrity: sha512-u4yftj8OtAnnZP1tzyGPOuPCdjNg97D572Hp+KrktonP7AqemRnAsWGPQyi/iMuR8qAED6pSRc9c682XrVXrEA==, tarball: file:projects/communication-short-codes.tgz} + resolution: {integrity: sha512-4Bh0DOycDYo2hEz+Yj2Z1IJ+BrRhHj3PLWrEPEBRS61LJqNcFHxyROmdSniFzPFMccdLftvLeekkq34WbBcMuw==, tarball: file:projects/communication-short-codes.tgz} name: '@rush-temp/communication-short-codes' version: 0.0.0 dependencies: @@ -19026,6 +19479,8 @@ packages: '@types/node': 18.19.64 '@types/sinon': 17.0.3 '@types/uuid': 8.3.4 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -19042,23 +19497,37 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 uuid: 8.3.2 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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-sms.tgz: - resolution: {integrity: sha512-f8eTqf+KRIWZBnOqr83aQRxIMmkLI2fBOGFzm0pJCVUTEWmEAOA+a+MWb096r8BWsABpOnQ5GbNW4YxHXwbGIA==, tarball: file:projects/communication-sms.tgz} + resolution: {integrity: sha512-haVPGnQ12Pl0W69/eg2MhmTpiF+DTrxGi+y1TMCm736KXUIeNrW87yhASdKXOOM15k2n3LJC2qi/KBKH0T9j7w==, tarball: file:projects/communication-sms.tgz} name: '@rush-temp/communication-sms' version: 0.0.0 dependencies: @@ -19068,8 +19537,6 @@ packages: '@types/mocha': 10.0.9 '@types/node': 18.19.64 '@types/sinon': 17.0.3 - '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) - '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -19086,37 +19553,23 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 - playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 util: 0.12.5 - vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitest/ui' + - '@swc/core' + - '@swc/wasm' - bufferutil - - happy-dom + - debug - jiti - - jsdom - - less - - lightningcss - - msw - - safaridriver - - sass - - sass-embedded - - stylus - - sugarss - supports-color - - terser - utf-8-validate - - vite - - webdriverio dev: false file:projects/communication-tiering.tgz: - resolution: {integrity: sha512-nDoqnFBea7fbl3xKZpetYRo4tdp0rw5rDRLrhjprDsgSrCOBoKrioCzzIWQ8Jr9VJ8bRHvhvc7m56jihYGDe7g==, tarball: file:projects/communication-tiering.tgz} + resolution: {integrity: sha512-rz1BR/nFh76ye4xr8Y7ma9rk7L5MdY/OvQzCHdccWUqJtna7thL+3dBEzfugUV3+3x25rHJ6QTwpj6VFz8P6Pg==, tarball: file:projects/communication-tiering.tgz} name: '@rush-temp/communication-tiering' version: 0.0.0 dependencies: @@ -19127,6 +19580,8 @@ packages: '@types/node': 18.19.64 '@types/sinon': 17.0.3 '@types/uuid': 8.3.4 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -19143,19 +19598,33 @@ packages: karma-sourcemap-loader: 0.3.8 mocha: 10.8.2 nyc: 17.1.0 + playwright: 1.48.2 sinon: 17.0.1 ts-node: 10.9.2(@types/node@18.19.64)(typescript@5.6.3) tslib: 2.8.1 typescript: 5.6.3 uuid: 8.3.2 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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-toll-free-verification.tgz: @@ -20568,7 +21037,7 @@ packages: dev: false file:projects/identity-broker.tgz: - resolution: {integrity: sha512-gzFe7YDnt2jSDsfkIgkTeOuF6P4OngqRlIw3j/EkmucdPoIRLI+Qk0JsWlL4buy9PqwgsioHm+CKIWAeJYm+GQ==, tarball: file:projects/identity-broker.tgz} + resolution: {integrity: sha512-vq3L3DyNQvVXqYonnD5vweOxzUQrulNdo7115ZCAV7e1y7Q0GfwvwC5k5LyeCY0F5TT3iQuUwHBDIE15/EMYpg==, tarball: file:projects/identity-broker.tgz} name: '@rush-temp/identity-broker' version: 0.0.0 dependencies: @@ -20579,17 +21048,36 @@ packages: '@types/mocha': 10.0.9 '@types/node': 18.19.64 '@types/sinon': 17.0.3 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) eslint: 9.14.0 mocha: 10.8.2 + playwright: 1.48.2 puppeteer: 23.7.0(typescript@5.6.3) sinon: 17.0.1 tslib: 2.8.1 typescript: 5.6.3 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) transitivePeerDependencies: + - '@edge-runtime/vm' + - '@vitest/ui' - bufferutil + - 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/identity-cache-persistence.tgz: @@ -20658,7 +21146,7 @@ packages: dev: false file:projects/identity.tgz: - resolution: {integrity: sha512-+dh1fu1N+pQDI4kqEYbQNKheyktQ47Buez8cgYnHaXf/gmPivfBdqOJbzqY4ERdUllHdhYTQIgdIN4yjx506Yg==, tarball: file:projects/identity.tgz} + resolution: {integrity: sha512-P0HbQwwg1mF2aczzbJ5iXPm+nf8N/iWXqAupzCtVBFQ+VC1OrVIQhL987fdKgpl/3c2LD4KdEm0rf9IoqO9/lQ==, tarball: file:projects/identity.tgz} name: '@rush-temp/identity' version: 0.0.0 dependencies: @@ -20675,6 +21163,8 @@ packages: '@types/sinon': 17.0.3 '@types/stoppable': 1.1.3 '@types/uuid': 8.3.4 + '@vitest/browser': 2.1.4(@types/node@18.19.64)(playwright@1.48.2)(typescript@5.6.3)(vitest@2.1.4) + '@vitest/coverage-istanbul': 2.1.4(vitest@2.1.4) chai: 4.3.10 dotenv: 16.4.5 eslint: 9.14.0 @@ -20693,7 +21183,8 @@ packages: mocha: 10.8.2 ms: 2.1.3 nyc: 17.1.0 - open: 8.4.2 + open: 10.1.0 + playwright: 1.48.2 puppeteer: 23.7.0(typescript@5.6.3) sinon: 17.0.1 stoppable: 1.1.0 @@ -20701,14 +21192,27 @@ packages: tslib: 2.8.1 typescript: 5.6.3 util: 0.12.5 + vitest: 2.1.4(@types/node@18.19.64)(@vitest/browser@2.1.4) 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/iot-device-update.tgz: @@ -21092,7 +21596,7 @@ packages: dev: false file:projects/maps-geolocation.tgz: - resolution: {integrity: sha512-ySfkp5wDGj+DQd49810Knq6uM5KLIgM2sD3THKJJhFe7Tp+7Y1d9nR3m3JErYhrGoMQ+N7iH2wUOjUndgWMGgQ==, tarball: file:projects/maps-geolocation.tgz} + resolution: {integrity: sha512-hQNWWAB2csKwDQitJWjwgAIBiFBEpmBFX82U1x9CGNkoXy7MNi/O7u880S2Hbarm+WI7UyuxSIF27KLBEH8C2Q==, tarball: file:projects/maps-geolocation.tgz} name: '@rush-temp/maps-geolocation' version: 0.0.0 dependencies: @@ -21134,7 +21638,7 @@ packages: dev: false file:projects/maps-render.tgz: - resolution: {integrity: sha512-DrEwi8UQP65AkDO5eQx9LbwzEGtngMa8+aoOuoEZ3XdfLM5te0RH2g1B2ugosRq7lbjmRpuex6xBKZE3tQw7Yw==, tarball: file:projects/maps-render.tgz} + resolution: {integrity: sha512-UsWhK4PLe8c4SueDX/MzVuOtEwAHCNrHYZHGSwEJ8nFvkT5qBQS0E6v0p87R+7dNE+2hUrXoXV2pYwTbM7NeMg==, tarball: file:projects/maps-render.tgz} name: '@rush-temp/maps-render' version: 0.0.0 dependencies: diff --git a/common/tools/dev-tool/src/commands/admin/migrate-package.ts b/common/tools/dev-tool/src/commands/admin/migrate-package.ts index 54ca58057aad..dd05ed6c9f32 100644 --- a/common/tools/dev-tool/src/commands/admin/migrate-package.ts +++ b/common/tools/dev-tool/src/commands/admin/migrate-package.ts @@ -85,12 +85,14 @@ export default leafCommand(commandInfo, async ({ "package-name": packageName, br await prepareFiles(projectFolder, { browser }); await applyCodemods(projectFolder); - log.info("Running `rush update`"); - await run(["rush", "update"], { cwd: projectFolder }); log.info("Formatting files"); await run(["rushx", "format"], { cwd: projectFolder }); await commitChanges(projectFolder, "rushx format"); + log.info( + "Done. Please run `rush update`, `rush build -t `, and run tests to verify the changes.", + ); + return true; }); diff --git a/common/tools/dev-tool/src/commands/run/extract-api.ts b/common/tools/dev-tool/src/commands/run/extract-api.ts index d35bdc717ab7..22861a8000be 100644 --- a/common/tools/dev-tool/src/commands/run/extract-api.ts +++ b/common/tools/dev-tool/src/commands/run/extract-api.ts @@ -8,7 +8,6 @@ import { ExtractorResult, IConfigApiReport, IConfigDocModel, - IConfigDtsRollup, IConfigFile, } from "@microsoft/api-extractor"; import { leafCommand, makeCommandInfo } from "../../framework/command"; @@ -123,9 +122,11 @@ export default leafCommand(commandInfo, async () => { const apiExtractorJsonPath: string = path.join(projectInfo.path, "api-extractor.json"); const extractorConfigObject = ExtractorConfig.loadFile(apiExtractorJsonPath); + // sub path exports extraction + const exports = buildExportConfiguration(packageJson); if ( !extractorConfigObject.mainEntryPointFilePath || - !extractorConfigObject?.dtsRollup?.publicTrimmedFilePath + (exports === undefined && !extractorConfigObject?.dtsRollup?.publicTrimmedFilePath) ) { log.error("Unexpected api-extractor configuration"); return false; @@ -138,21 +139,11 @@ export default leafCommand(commandInfo, async () => { log.debug(` reportTempFolder: ${extractorConfigObject.apiReport?.reportTempFolder}`); let succeed = true; - // sub path exports extraction - const exports = buildExportConfiguration(packageJson); + if (exports !== undefined) { log.info("Detected subpath exports, extracting markdown for each subpath."); for (const exportEntry of exports) { log.info(`Extracting api for export: ${exportEntry.path}`); - // Place the subpath export rollup file in the directory from which it is exported - const publicTrimmedFilePath = path.parse( - extractorConfigObject.dtsRollup.publicTrimmedFilePath, - ); - const newPublicTrimmedPath = path.join( - publicTrimmedFilePath.dir, - exportEntry.path, - publicTrimmedFilePath.base, - ); // Leave filenames unchanged for the root export let newApiJsonPath = extractorConfigObject.docModel?.apiJsonFilePath; @@ -172,10 +163,6 @@ export default leafCommand(commandInfo, async () => { ); } - const newDtsRollupOptions: IConfigDtsRollup = { - ...extractorConfigObject.dtsRollup, - publicTrimmedFilePath: newPublicTrimmedPath, - }; const newDocModel: IConfigDocModel = { ...extractorConfigObject.docModel, enabled: true, @@ -190,7 +177,6 @@ export default leafCommand(commandInfo, async () => { const updatedConfigObject: IConfigFile = { ...extractorConfigObject, - dtsRollup: newDtsRollupOptions, docModel: newDocModel, apiReport: newApiReport, mainEntryPointFilePath: exportEntry.mainEntryPointFilePath, diff --git a/eng/common/pipelines/templates/archetype-typespec-emitter.yml b/eng/common/pipelines/templates/archetype-typespec-emitter.yml index 5192ea22900d..fd725b3bc7d5 100644 --- a/eng/common/pipelines/templates/archetype-typespec-emitter.yml +++ b/eng/common/pipelines/templates/archetype-typespec-emitter.yml @@ -62,6 +62,11 @@ parameters: type: boolean default: false +# Paths to sparse checkout +- name: SparseCheckoutPaths + type: object + default: [] + extends: template: /eng/pipelines/templates/stages/1es-redirect.yml parameters: @@ -79,6 +84,8 @@ extends: - job: Build steps: - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml + parameters: + Paths: ${{ parameters.SparseCheckoutPaths }} - ${{ parameters.InitializationSteps }} @@ -411,7 +418,9 @@ extends: buildArtifactsPath: $(Pipeline.Workspace)/build_artifacts steps: - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml - + parameters: + Paths: ${{ parameters.SparseCheckoutPaths }} + - download: current artifact: build_artifacts displayName: Download build artifacts diff --git a/eng/common/pipelines/templates/steps/save-package-properties.yml b/eng/common/pipelines/templates/steps/save-package-properties.yml index 3714c0264388..172191c272dc 100644 --- a/eng/common/pipelines/templates/steps/save-package-properties.yml +++ b/eng/common/pipelines/templates/steps/save-package-properties.yml @@ -32,6 +32,19 @@ steps: -ArtifactPath '${{ parameters.DiffDirectory }}' pwsh: true + # When running in PR mode, we want the detected changed services to be attached to the build as tags. + # However, the public identity does not have the permissions to attach tags to the build. + # Instead, we will save the changed services to a file, attach it as an attachment for PiplineWitness to pick up and utilize. + - pwsh: | + $changedServices = (Get-Content -Path '${{ parameters.DiffDirectory }}/diff.json' -Raw | ConvertFrom-Json).ChangedServices + + if ($changedServices) { + Write-Host "Attaching changed service names to the build for additional tag generation." + $changedServices | ConvertTo-Json -AsArray | Out-File -FilePath $(System.DefaultWorkingDirectory)/tags.json -Encoding utf8 + Write-Host '##vso[task.addattachment type=AdditionalTags;name=AdditionalTags;]$(System.DefaultWorkingDirectory)/tags.json' + } + displayName: Upload tags.json with changed services + - task: Powershell@2 displayName: Save package properties filtered for PR inputs: diff --git a/eng/common/scripts/Generate-PR-Diff.ps1 b/eng/common/scripts/Generate-PR-Diff.ps1 index 5c3d764009fe..355ef612540f 100644 --- a/eng/common/scripts/Generate-PR-Diff.ps1 +++ b/eng/common/scripts/Generate-PR-Diff.ps1 @@ -28,9 +28,9 @@ function Get-ChangedServices [string[]] $ChangedFiles ) - $changedServices = $ChangedFiles | Foreach-Object { if ($_ -match "sdk/([^/]+)") { $matches[1] } } | Sort-Object -Unique + [string[]] $changedServices = $ChangedFiles | Foreach-Object { if ($_ -match "sdk/([^/]+)") { $matches[1] } } | Sort-Object -Unique - return $changedServices + return , $changedServices } if (!(Test-Path $ArtifactPath)) diff --git a/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 b/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 index 7cf55c758487..48bab2c49ebe 100644 --- a/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 +++ b/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 @@ -155,8 +155,9 @@ function DeployStressTests( -filters $filters ` -CI:$CI ` -namespaceOverride $Namespace ` - -MatrixSelection $MatrixSelection ` -MatrixFileName $MatrixFileName ` + -MatrixSelection $MatrixSelection ` + -MatrixDisplayNameFilter $MatrixDisplayNameFilter ` -MatrixFilters $MatrixFilters ` -MatrixReplace $MatrixReplace ` -MatrixNonSparseParameters $MatrixNonSparseParameters) diff --git a/eng/emitter-package-lock.json b/eng/emitter-package-lock.json index 13017234cde2..d51a53252449 100644 --- a/eng/emitter-package-lock.json +++ b/eng/emitter-package-lock.json @@ -6,22 +6,22 @@ "": { "name": "typescript-emitter-package", "dependencies": { - "@azure-tools/typespec-autorest": "0.45.0", - "@azure-tools/typespec-azure-core": "0.45.0", - "@azure-tools/typespec-azure-resource-manager": "0.45.0", - "@azure-tools/typespec-azure-rulesets": "0.45.0", - "@azure-tools/typespec-client-generator-core": "0.45.4", - "@azure-tools/typespec-ts": "0.33.0", - "@typespec/compiler": "0.59.1", - "@typespec/http": "0.59.1", - "@typespec/rest": "0.59.1", - "@typespec/versioning": "0.59.0" + "@azure-tools/typespec-autorest": "0.47.0", + "@azure-tools/typespec-azure-core": "0.47.0", + "@azure-tools/typespec-azure-resource-manager": "0.47.0", + "@azure-tools/typespec-azure-rulesets": "0.47.0", + "@azure-tools/typespec-client-generator-core": "0.47.4", + "@azure-tools/typespec-ts": "0.34.0", + "@typespec/compiler": "0.61.2", + "@typespec/http": "0.61.0", + "@typespec/rest": "0.61.0", + "@typespec/versioning": "0.61.0" } }, "node_modules/@azure-tools/rlc-common": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/@azure-tools/rlc-common/-/rlc-common-0.33.0.tgz", - "integrity": "sha512-x0+URxuvtFAA8GtlNTqr/R2/hnShfT0HISBYr8q8mWP2l8bxaCZm/EdyBYkZ98G9vJHlkKO70mVOK9zUOvFIvw==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@azure-tools/rlc-common/-/rlc-common-0.34.0.tgz", + "integrity": "sha512-mLbNypmvm77ZzOrAMjoYKsWTb4sNdFD43eFEG13yVX+k2mgvRppfBM1DQdli8QN3FfZsMDFYM+YpfdcL/rQiiw==", "dependencies": { "handlebars": "^4.7.7", "lodash": "^4.17.21", @@ -29,40 +29,40 @@ } }, "node_modules/@azure-tools/typespec-autorest": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-autorest/-/typespec-autorest-0.45.0.tgz", - "integrity": "sha512-6ycZ0bEfXC0U26FHHEt9smAhxh78SACIDY+u7zLAopRzmxjTuthDdGgYSShuRDu3J+vEBi1fOKpz4cYQkgRkBQ==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-autorest/-/typespec-autorest-0.47.0.tgz", + "integrity": "sha512-uYkk8mnzekSMhJKU3RS0cXvKPH0vbkonthYoPe7/vxZ7tWv4xJLSglV2v3m3QElFgvNebNVoBOEWSY8Kz/ip2Q==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": "~0.45.0", - "@azure-tools/typespec-azure-resource-manager": "~0.45.0", - "@azure-tools/typespec-client-generator-core": "~0.45.0", - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.0", - "@typespec/openapi": "~0.59.0", - "@typespec/rest": "~0.59.0", - "@typespec/versioning": "~0.59.0" + "@azure-tools/typespec-azure-core": "~0.47.0", + "@azure-tools/typespec-azure-resource-manager": "~0.47.0", + "@azure-tools/typespec-client-generator-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" } }, "node_modules/@azure-tools/typespec-azure-core": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.45.0.tgz", - "integrity": "sha512-GycGMCmaIVSN+TftPtlPJLyeOrglbLmH08ZiZaVMjSih/TQEJM21RGR6d8QdjlkQWN61ntNDRD+RP2uv9tHmqw==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.47.0.tgz", + "integrity": "sha512-RcBC5+dE1BVXTrUkkKULTImGxzM/ea3P3IL2kr9pk7r1uqF7D4CGqEKHFTg5L6QUtqc1f+zgTgQTNn6t4gI92w==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.0", - "@typespec/rest": "~0.59.0" + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/rest": "~0.61.0" } }, "node_modules/@azure-tools/typespec-azure-resource-manager": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-resource-manager/-/typespec-azure-resource-manager-0.45.0.tgz", - "integrity": "sha512-PdhB03P8PoOlUoUWd+CF5WipGzu2Q3ZjT0EAzgQe878DmXvxMq+zYaPJQtvkq9R6jCxFauDSr5gG7Yd4NINAuA==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-resource-manager/-/typespec-azure-resource-manager-0.47.0.tgz", + "integrity": "sha512-pe9XhHJezTZtVlSVKIMhL1kRATMg6QSaXUZQhQmQKSuozVRsRBxI4IAhK3RU4p6SA8A2CoCpPeJpRhQTvdt73Q==", "dependencies": { "change-case": "~5.4.4", "pluralize": "^8.0.0" @@ -71,32 +71,32 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": "~0.45.0", - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.0", - "@typespec/openapi": "~0.59.0", - "@typespec/rest": "~0.59.0", - "@typespec/versioning": "~0.59.0" + "@azure-tools/typespec-azure-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" } }, "node_modules/@azure-tools/typespec-azure-rulesets": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-rulesets/-/typespec-azure-rulesets-0.45.0.tgz", - "integrity": "sha512-OpMYYc0ElxnswABud22GSqE24ZoJCRGh9fwSA8SoqsJr0uXRX7D6D5pA1FHFT3b5uBVHy0l+FFHvjz9wxfsbUw==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-rulesets/-/typespec-azure-rulesets-0.47.0.tgz", + "integrity": "sha512-CG6sGYc/9qKAQIWtauzH6yEoTdugfz4DEmiWcytJMhgw1tQ2bqmcJuar01ctDKuaD5F1PKZ0X3oAxPu84pIlqw==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": "~0.45.0", - "@azure-tools/typespec-azure-resource-manager": "~0.45.0", - "@azure-tools/typespec-client-generator-core": "~0.45.0", - "@typespec/compiler": "~0.59.0" + "@azure-tools/typespec-azure-core": "~0.47.0", + "@azure-tools/typespec-azure-resource-manager": "~0.47.0", + "@azure-tools/typespec-client-generator-core": "~0.47.0", + "@typespec/compiler": "~0.61.0" } }, "node_modules/@azure-tools/typespec-client-generator-core": { - "version": "0.45.4", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.45.4.tgz", - "integrity": "sha512-QJygwMqhEtBi2tPYs/HAfs0QTowXAwp6QpP/Vd2pHnJAncTV1BN17n/9LLAlMu2CnLimqvTuIN+FfliM28AX9w==", + "version": "0.47.4", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.47.4.tgz", + "integrity": "sha512-oXA8rHzBsoofzSXvGLGohj6VDYegtgAfGMWo2o4ubew1bS4cvl3CYl9DJ54blqafxtJXnNh4SdjadeHTsCz2mw==", "dependencies": { "change-case": "~5.4.4", "pluralize": "^8.0.0" @@ -105,33 +105,33 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": "~0.45.0", - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.0", - "@typespec/openapi": "~0.59.0", - "@typespec/rest": "~0.59.0", - "@typespec/versioning": "~0.59.0" + "@azure-tools/typespec-azure-core": "~0.47.0", + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0", + "@typespec/openapi": "~0.61.0", + "@typespec/rest": "~0.61.0", + "@typespec/versioning": "~0.61.0" } }, "node_modules/@azure-tools/typespec-ts": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-ts/-/typespec-ts-0.33.0.tgz", - "integrity": "sha512-q81iMQtQSpj//krqXQUG/eselh2cpOTqlLkC0z+5Vr1MhLCGNATUu906NnPRoYuT3gfEkA2uHL30AkDDZH8/+Q==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-ts/-/typespec-ts-0.34.0.tgz", + "integrity": "sha512-7wVi170xCm5sCXUlPIeJF4RCnqWyuUY61SoBQezcRo6DG0sVyRXC8jcp9WpN4AZR+uT1LULGaGZPGj5yUG3AvA==", "dependencies": { - "@azure-tools/rlc-common": "^0.33.0", + "@azure-tools/rlc-common": "^0.34.0", "fs-extra": "^11.1.0", "lodash": "^4.17.21", - "prettier": "^3.1.0", + "prettier": "^3.3.3", "ts-morph": "^23.0.0", "tslib": "^2.3.1" }, "peerDependencies": { - "@azure-tools/typespec-azure-core": ">=0.45.0 <1.0.0", - "@azure-tools/typespec-client-generator-core": ">=0.45.4 <1.0.0", - "@typespec/compiler": ">=0.59.0 <1.0.0", - "@typespec/http": ">=0.59.0 <1.0.0", - "@typespec/rest": ">=0.59.0 <1.0.0", - "@typespec/versioning": ">=0.59.0 <1.0.0" + "@azure-tools/typespec-azure-core": ">=0.47.0 <1.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.47.4 <1.0.0", + "@typespec/compiler": ">=0.61.2 <1.0.0", + "@typespec/http": ">=0.61.0 <1.0.0", + "@typespec/rest": ">=0.61.0 <1.0.0", + "@typespec/versioning": ">=0.61.0 <1.0.0" } }, "node_modules/@babel/code-frame": { @@ -147,19 +147,19 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -223,23 +223,23 @@ } }, "node_modules/@typespec/compiler": { - "version": "0.59.1", - "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.59.1.tgz", - "integrity": "sha512-O2ljgr6YoFaIH6a8lWc90/czdv4B2X6N9wz4WsnQnVvgO0Tj0s+3xkvp4Tv59RKMhT0f3fK6dL8oEGO32FYk1A==", + "version": "0.61.2", + "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.61.2.tgz", + "integrity": "sha512-6QxYJd09VWssd/BvY+8eBxTVv085s1UNK63FdPrgT2lgI+j8VMMcpNR9m5l1zWlgGDM7sniA/Or8VCdVA6jerg==", "dependencies": { "@babel/code-frame": "~7.24.7", "ajv": "~8.17.1", "change-case": "~5.4.4", "globby": "~14.0.2", "mustache": "~4.2.0", - "picocolors": "~1.0.1", + "picocolors": "~1.1.0", "prettier": "~3.3.3", "prompts": "~2.4.2", "semver": "^7.6.3", "temporal-polyfill": "^0.2.5", "vscode-languageserver": "~9.0.1", - "vscode-languageserver-textdocument": "~1.0.11", - "yaml": "~2.4.5", + "vscode-languageserver-textdocument": "~1.0.12", + "yaml": "~2.5.1", "yargs": "~17.7.2" }, "bin": { @@ -251,50 +251,56 @@ } }, "node_modules/@typespec/http": { - "version": "0.59.1", - "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.59.1.tgz", - "integrity": "sha512-Ai8oCAO+Bw1HMSZ9gOI5Od4fNn/ul4HrVtTB01xFuLK6FQj854pxhzao8ylPnr7gIRQ327FV12/QfXR87yCiYQ==", + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.61.0.tgz", + "integrity": "sha512-7+AYHkzkc+p652GY9BcEbXY4OZa1fTr03MVmZeafvmbQbXfyzUU9eJld13M3v6NaUWqXWZ7nBNMISyKiXp/kSw==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.59.0" + "@typespec/compiler": "~0.61.0", + "@typespec/streams": "~0.61.0" + }, + "peerDependenciesMeta": { + "@typespec/streams": { + "optional": true + } } }, "node_modules/@typespec/openapi": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.59.0.tgz", - "integrity": "sha512-do1Dm5w0MuK3994gYTBg6qMfgeIxmmsDqnz3zimYKMPpbnUBi4F6/o4iCfn0Fn9kaNl+H6UlOzZpsZW9xHui1Q==", + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.61.0.tgz", + "integrity": "sha512-3AF319Ae4yGVOscsCLQeedXUJJcL/NdGOR2/e/nFiL/AOVdgLfIRnpR0Ad9Zj9XAESh1fq9XSu4Mi7N1k4V7rw==", "peer": true, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.0" + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0" } }, "node_modules/@typespec/rest": { - "version": "0.59.1", - "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.59.1.tgz", - "integrity": "sha512-uKU431jBYL2tVQWG5THA75+OtXDa1e8cMAafYK/JJRRiVRd8D/Epd8fp07dzlB8tFGrhCaGlekRMqFPFrHh2/A==", + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.61.0.tgz", + "integrity": "sha512-L9Oyor+l42p6S8GE+UvaZTi+dcu6WubGZKmaBRpX8mCZGsa69EgIK8DQoyxrfMcxAO4I5U0sfkzCKwCVFtRr9g==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.59.0", - "@typespec/http": "~0.59.1" + "@typespec/compiler": "~0.61.0", + "@typespec/http": "~0.61.0" } }, "node_modules/@typespec/versioning": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.59.0.tgz", - "integrity": "sha512-aihO/ux0lLmsuYAdGVkiBflSudcZokYG42SELk1FtMFo609G3Pd7ep7hau6unBnMIceQZejB0ow5UGRupK4X5A==", + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.61.0.tgz", + "integrity": "sha512-PIIug6eg3zc7E+BBHyNHHQD+OBq3FU465nhKrLEp35iVji/sYFuPc1ywnELDuwJVRWm6nvqNL1vtnc+4lEk+oA==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.59.0" + "@typespec/compiler": "~0.61.0" } }, "node_modules/ajv": { @@ -387,9 +393,9 @@ } }, "node_modules/code-block-writer": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.2.tgz", - "integrity": "sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==" + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==" }, "node_modules/color-convert": { "version": "1.9.3", @@ -446,9 +452,9 @@ } }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==" }, "node_modules/fastq": { "version": "1.17.1", @@ -716,9 +722,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -935,9 +941,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/uglify-js": { "version": "3.19.3", @@ -1068,9 +1074,9 @@ } }, "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "bin": { "yaml": "bin.mjs" }, diff --git a/eng/emitter-package.json b/eng/emitter-package.json index 07c7e775a73e..52c5aaabfc7f 100644 --- a/eng/emitter-package.json +++ b/eng/emitter-package.json @@ -2,15 +2,15 @@ "name": "typescript-emitter-package", "main": "dist/src/index.js", "dependencies": { - "@azure-tools/typespec-ts": "0.33.0", - "@azure-tools/typespec-azure-core": "0.45.0", - "@azure-tools/typespec-autorest": "0.45.0", - "@azure-tools/typespec-client-generator-core": "0.45.4", - "@azure-tools/typespec-azure-resource-manager": "0.45.0", - "@azure-tools/typespec-azure-rulesets": "0.45.0", - "@typespec/compiler": "0.59.1", - "@typespec/http": "0.59.1", - "@typespec/rest": "0.59.1", - "@typespec/versioning": "0.59.0" + "@azure-tools/typespec-ts": "0.34.0", + "@azure-tools/typespec-azure-core": "0.47.0", + "@azure-tools/typespec-autorest": "0.47.0", + "@azure-tools/typespec-client-generator-core": "0.47.4", + "@azure-tools/typespec-azure-resource-manager": "0.47.0", + "@azure-tools/typespec-azure-rulesets": "0.47.0", + "@typespec/compiler": "0.61.2", + "@typespec/http": "0.61.0", + "@typespec/rest": "0.61.0", + "@typespec/versioning": "0.61.0" } } diff --git a/sdk/apimanagement/api-management-custom-widgets-scaffolder/package.json b/sdk/apimanagement/api-management-custom-widgets-scaffolder/package.json index 2c806bf990e8..1e1c4d65fa93 100644 --- a/sdk/apimanagement/api-management-custom-widgets-scaffolder/package.json +++ b/sdk/apimanagement/api-management-custom-widgets-scaffolder/package.json @@ -26,8 +26,7 @@ "files": [ "dist/", "bin/", - "LICENSE", - "dist-esm/src" + "LICENSE" ], "type": "module", "scripts": { diff --git a/sdk/communication/communication-call-automation/review/communication-call-automation.api.md b/sdk/communication/communication-call-automation/review/communication-call-automation.api.md index 0e9d28d0adb7..a366dac240bd 100644 --- a/sdk/communication/communication-call-automation/review/communication-call-automation.api.md +++ b/sdk/communication/communication-call-automation/review/communication-call-automation.api.md @@ -113,6 +113,7 @@ export class CallAutomationClient { // @public export interface CallAutomationClientOptions extends CommonClientOptions { + opsSourceIdentity?: MicrosoftTeamsAppIdentifier; sourceIdentity?: CommunicationUserIdentifier; } diff --git a/sdk/communication/communication-call-automation/src/callAutomationClient.ts b/sdk/communication/communication-call-automation/src/callAutomationClient.ts index 71b43e879940..a5cfb3ff7849 100644 --- a/sdk/communication/communication-call-automation/src/callAutomationClient.ts +++ b/sdk/communication/communication-call-automation/src/callAutomationClient.ts @@ -7,6 +7,7 @@ import type { InternalPipelineOptions } from "@azure/core-rest-pipeline"; import type { CommunicationIdentifier, CommunicationUserIdentifier, + MicrosoftTeamsAppIdentifier, } from "@azure/communication-common"; import { parseClientArguments, isKeyCredential } from "@azure/communication-common"; import { logger } from "./models/logger"; @@ -14,6 +15,7 @@ import type { AnswerCallRequest, CallAutomationApiClient, CommunicationUserIdentifierModel, + MicrosoftTeamsAppIdentifierModel, CreateCallRequest, RedirectCallRequest, RejectCallRequest, @@ -34,6 +36,7 @@ import { communicationIdentifierModelConverter, communicationUserIdentifierConverter, communicationUserIdentifierModelConverter, + microsoftTeamsAppIdentifierModelConverter, phoneNumberIdentifierConverter, PhoneNumberIdentifierModelConverter, } from "./utli/converters"; @@ -49,6 +52,11 @@ export interface CallAutomationClientOptions extends CommonClientOptions { * The identifier of the source of the call for call creating/answering/inviting operation. */ sourceIdentity?: CommunicationUserIdentifier; + /** + * The identifier of the One Phone System bot for call creating operation. + * Should be mutually exclusive with sourceIdentity. + */ + opsSourceIdentity?: MicrosoftTeamsAppIdentifier; } /** @@ -65,6 +73,7 @@ const isCallAutomationClientOptions = (options: any): options is CallAutomationC export class CallAutomationClient { private readonly callAutomationApiClient: CallAutomationApiClient; private readonly sourceIdentity?: CommunicationUserIdentifierModel; + private readonly opsSourceIdentity?: MicrosoftTeamsAppIdentifierModel; private readonly credential: TokenCredential | KeyCredential; private readonly internalPipelineOptions: InternalPipelineOptions; private readonly callAutomationEventProcessor: CallAutomationEventProcessor; @@ -127,6 +136,7 @@ export class CallAutomationClient { ); this.sourceIdentity = communicationUserIdentifierModelConverter(options.sourceIdentity); + this.opsSourceIdentity = microsoftTeamsAppIdentifierModelConverter(options.opsSourceIdentity); } /** @@ -245,6 +255,7 @@ export class CallAutomationClient { ): Promise { const request: CreateCallRequest = { source: this.sourceIdentity, + opsSource: this.opsSourceIdentity, targets: [communicationIdentifierModelConverter(targetParticipant.targetParticipant)], callbackUri: callbackUrl, operationContext: options.operationContext, @@ -277,6 +288,7 @@ export class CallAutomationClient { ): Promise { const request: CreateCallRequest = { source: this.sourceIdentity, + opsSource: this.opsSourceIdentity, targets: targetParticipants.map((target) => communicationIdentifierModelConverter(target)), callbackUri: callbackUrl, operationContext: options.operationContext, diff --git a/sdk/communication/communication-call-automation/src/generated/src/models/index.ts b/sdk/communication/communication-call-automation/src/generated/src/models/index.ts index 8033a147ae4d..ecc485f622b0 100644 --- a/sdk/communication/communication-call-automation/src/generated/src/models/index.ts +++ b/sdk/communication/communication-call-automation/src/generated/src/models/index.ts @@ -27,6 +27,8 @@ export interface CreateCallRequest { sourceDisplayName?: string; /** The identifier of the source of the call */ source?: CommunicationUserIdentifierModel; + /** The identifier of the source in an OPS call */ + opsSource?: MicrosoftTeamsAppIdentifierModel; /** A customer set value used to track the answering of a call. */ operationContext?: string; /** The callback URI. */ @@ -194,6 +196,8 @@ export interface AnswerCallRequest { incomingCallContext: string; /** The callback uri. */ callbackUri: string; + /** Used by customer to send custom calling context to targets when answering On-Behalf-Of call */ + customCallingContext?: CustomCallingContextInternal; /** A customer set value used to track the answering of a call. */ operationContext?: string; /** Media Streaming Configuration. */ @@ -711,7 +715,7 @@ export interface StartCallRecordingRequest { pauseOnStart?: boolean; } -/** The locator used for joining or taking action on a call. */ +/** The locator used for joining or taking action on a call */ export interface CallLocator { /** The group call id */ groupCallId?: string; @@ -3064,7 +3068,6 @@ export type CallDialogStartDialogResponse = DialogStateResponse; /** Optional parameters. */ export interface CallDialogStopDialogOptionalParams extends coreClient.OperationOptions { - /** Operation callback URI. */ operationCallbackUri?: string; } diff --git a/sdk/communication/communication-call-automation/src/generated/src/models/mappers.ts b/sdk/communication/communication-call-automation/src/generated/src/models/mappers.ts index 0e121e804a3f..d5b306a6efc6 100644 --- a/sdk/communication/communication-call-automation/src/generated/src/models/mappers.ts +++ b/sdk/communication/communication-call-automation/src/generated/src/models/mappers.ts @@ -46,6 +46,13 @@ export const CreateCallRequest: coreClient.CompositeMapper = { className: "CommunicationUserIdentifierModel", }, }, + opsSource: { + serializedName: "opsSource", + type: { + name: "Composite", + className: "MicrosoftTeamsAppIdentifierModel", + }, + }, operationContext: { serializedName: "operationContext", type: { @@ -522,6 +529,13 @@ export const AnswerCallRequest: coreClient.CompositeMapper = { name: "String", }, }, + customCallingContext: { + serializedName: "customCallingContext", + type: { + name: "Composite", + className: "CustomCallingContextInternal", + }, + }, operationContext: { serializedName: "operationContext", type: { diff --git a/sdk/communication/communication-call-automation/src/generated/src/operations/callDialog.ts b/sdk/communication/communication-call-automation/src/generated/src/operations/callDialog.ts index ed2a0cf76d98..02330c389d27 100644 --- a/sdk/communication/communication-call-automation/src/generated/src/operations/callDialog.ts +++ b/sdk/communication/communication-call-automation/src/generated/src/operations/callDialog.ts @@ -52,9 +52,8 @@ export class CallDialogImpl implements CallDialog { } /** - * Stop a dialog. - * @param callConnectionId The call connection id - * @param dialogId The dialog id + * @param callConnectionId + * @param dialogId * @param options The options parameters. */ stopDialog( diff --git a/sdk/communication/communication-call-automation/src/generated/src/operationsInterfaces/callDialog.ts b/sdk/communication/communication-call-automation/src/generated/src/operationsInterfaces/callDialog.ts index 731b8415380f..4fccc524812b 100644 --- a/sdk/communication/communication-call-automation/src/generated/src/operationsInterfaces/callDialog.ts +++ b/sdk/communication/communication-call-automation/src/generated/src/operationsInterfaces/callDialog.ts @@ -31,9 +31,8 @@ export interface CallDialog { options?: CallDialogStartDialogOptionalParams, ): Promise; /** - * Stop a dialog. - * @param callConnectionId The call connection id - * @param dialogId The dialog id + * @param callConnectionId + * @param dialogId * @param options The options parameters. */ stopDialog( diff --git a/sdk/communication/communication-call-automation/src/utli/converters.ts b/sdk/communication/communication-call-automation/src/utli/converters.ts index 7cc3187111df..e24a15b791e8 100644 --- a/sdk/communication/communication-call-automation/src/utli/converters.ts +++ b/sdk/communication/communication-call-automation/src/utli/converters.ts @@ -26,6 +26,7 @@ import type { KnownCommunicationCloudEnvironmentModel, PhoneNumberIdentifierModel, CommunicationUserIdentifierModel, + MicrosoftTeamsAppIdentifierModel, } from "../generated/src"; import { KnownCommunicationIdentifierModelKind } from "../generated/src"; import type { CallParticipant } from "../models/models"; @@ -221,3 +222,25 @@ export function communicationUserIdentifierConverter( return { communicationUserId: identifier.id }; } + +/** Convert MicrosoftTeamsAppIdentifier to MicrosoftTeamsAppIdentifierModel (Internal usage class) */ +export function microsoftTeamsAppIdentifierModelConverter( + identifier: MicrosoftTeamsAppIdentifier | undefined, +): MicrosoftTeamsAppIdentifierModel | undefined { + if (!identifier || !identifier.teamsAppId) { + return undefined; + } + + return { appId: identifier.teamsAppId }; +} + +/** Convert MicrosoftTeamsAppIdentifierModel to MicrosoftTeamsAppIdentifier (Public usage class) */ +export function microsoftTeamsAppIdentifierConverter( + identifier: MicrosoftTeamsAppIdentifierModel | undefined, +): MicrosoftTeamsAppIdentifier | undefined { + if (!identifier || !identifier.appId) { + return undefined; + } + + return { teamsAppId: identifier.appId }; +} diff --git a/sdk/communication/communication-call-automation/swagger/README.md b/sdk/communication/communication-call-automation/swagger/README.md index 951fc4ae04f0..8323c607fa9f 100644 --- a/sdk/communication/communication-call-automation/swagger/README.md +++ b/sdk/communication/communication-call-automation/swagger/README.md @@ -13,7 +13,7 @@ license-header: MICROSOFT_MIT_NO_VERSION output-folder: ../src/generated tag: package-2023-10-03-preview require: - - https://github.com/Azure/azure-rest-api-specs/blob/156ff363e44f764ddd8a0a6adcd371610240ba15/specification/communication/data-plane/CallAutomation/readme.md + - https://github.com/Azure/azure-rest-api-specs/blob/be2a0fa68829fcb15c4e6b47aa6bc4bdd566c1cf/specification/communication/data-plane/CallAutomation/readme.md package-version: 1.3.0-beta.1 model-date-time-as-string: false optional-response-headers: true diff --git a/sdk/communication/communication-call-automation/test/callAutomationClient.spec.ts b/sdk/communication/communication-call-automation/test/callAutomationClient.spec.ts index cb1f5db2fd64..dee7538a6561 100644 --- a/sdk/communication/communication-call-automation/test/callAutomationClient.spec.ts +++ b/sdk/communication/communication-call-automation/test/callAutomationClient.spec.ts @@ -15,6 +15,7 @@ import { import type { CommunicationIdentifier, CommunicationUserIdentifier, + MicrosoftTeamsAppIdentifier, } from "@azure/communication-common"; import { assert } from "chai"; import type { Context } from "mocha"; @@ -39,6 +40,17 @@ import type { CreateCallEventResult, } from "../src/eventprocessor/eventResponses"; import { randomUUID } from "@azure/core-util"; +import { KnownCommunicationCloudEnvironmentModel } from "../src/generated/src"; + +function createOPSCallAutomationClient( + oPSSourceIdentity: MicrosoftTeamsAppIdentifier, +): CallAutomationClient { + const connectionString = "endpoint=https://redacted.communication.azure.com/;accesskey=redacted"; + + return new CallAutomationClient(connectionString, { + opsSourceIdentity: oPSSourceIdentity, + }); +} describe("Call Automation Client Unit Tests", () => { let targets: CommunicationIdentifier[]; @@ -132,6 +144,57 @@ describe("Call Automation Client Unit Tests", () => { .catch((error) => console.error(error)); }); + it("CreateOPSCall", async () => { + // defined dummy variables + const appId = "28:acs:redacted"; + const appCloud = KnownCommunicationCloudEnvironmentModel.Public; + const oPSSouceStub = { + teamsAppId: appId, + cloud: appCloud, + }; + + // stub an OPS CallAutomationClient + const createOPSClientStub = Sinon.stub().callsFake(() => + createOPSCallAutomationClient(oPSSouceStub), + ); + + // Use the stubbed factory function to create the client + const oPSClient: SinonStubbedInstance & CallAutomationClient = + createOPSClientStub(); + + // Explicitly stub the createCall method + oPSClient.createCall = Sinon.stub(); + + // mocks + const createCallResultMock: CreateCallResult = { + callConnectionProperties: { + source: { + rawId: appId, + teamsAppId: appId, + cloud: appCloud, + } as MicrosoftTeamsAppIdentifier, + } as CallConnectionProperties, + callConnection: {} as CallConnection, + waitForEventProcessor: async () => { + return {} as CreateCallEventResult; + }, + }; + + (oPSClient.createCall as Sinon.SinonStub).returns(Promise.resolve(createCallResultMock)); + + const promiseResult = oPSClient.createCall(target, CALL_CALLBACK_URL); + + // asserts + promiseResult + .then((result: CreateCallResult) => { + assert.isNotNull(result); + assert.isTrue(oPSClient.createCall.calledWith(target, CALL_CALLBACK_URL)); + assert.equal(result, createCallResultMock); + return; + }) + .catch((error) => console.error(error)); + }); + it("AnswerCall", async () => { // mocks const answerCallResultMock: AnswerCallResult = { diff --git a/sdk/communication/communication-chat/package.json b/sdk/communication/communication-chat/package.json index bdb74d38b1b5..18ef9fb36904 100644 --- a/sdk/communication/communication-chat/package.json +++ b/sdk/communication/communication-chat/package.json @@ -85,7 +85,7 @@ "@types/chai": "^4.1.6", "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", + "@types/sinon": "^17.0.3", "@types/uuid": "^8.0.0", "chai": "^4.2.0", "dotenv": "^16.0.0", @@ -104,7 +104,7 @@ "karma-sourcemap-loader": "^0.3.8", "mocha": "^10.0.0", "nyc": "^17.0.0", - "sinon": "^17.0.0", + "sinon": "^19.0.2", "ts-node": "^10.0.0", "typescript": "~5.6.2", "util": "^0.12.1" diff --git a/sdk/communication/communication-email/api-extractor.json b/sdk/communication/communication-email/api-extractor.json index e27476cd788c..0d4fb29a2b04 100644 --- a/sdk/communication/communication-email/api-extractor.json +++ b/sdk/communication/communication-email/api-extractor.json @@ -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 }, @@ -12,7 +12,7 @@ "dtsRollup": { "enabled": true, "untrimmedFilePath": "", - "publicTrimmedFilePath": "./types/communication-email.d.ts" + "publicTrimmedFilePath": "dist/communication-email.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-email/karma.conf.js b/sdk/communication/communication-email/karma.conf.js deleted file mode 100644 index 64bb1597db5c..000000000000 --- a/sdk/communication/communication-email/karma.conf.js +++ /dev/null @@ -1,126 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -require("dotenv").config(); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); - -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": ["sourcemap", "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: [ - "COMMUNICATION_CONNECTION_STRING_EMAIL", - "RECIPIENT_ADDRESS", - "SENDER_ADDRESS", - "TEST_MODE", - "RECORDINGS_RELATIVE_PATH", - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-email/package.json b/sdk/communication/communication-email/package.json index 416b1188937c..46f6dbde9809 100644 --- a/sdk/communication/communication-email/package.json +++ b/sdk/communication/communication-email/package.json @@ -5,22 +5,22 @@ "author": "Microsoft Corporation", "license": "MIT", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-email.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle --browser-test=false && dev-tool run extract-api", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:samples": "dev-tool samples publish -f", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* temp types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "generate:client": "autorest --typescript ./swagger/README.md && rushx format", "integration-test": "npm run integration-test:node && npm run integration-test:browser", - "integration-test:browser": "dev-tool run test:browser", - "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 --browser", + "integration-test:node": "dev-tool run test:vitest", "lint": "eslint package.json api-extractor.json src test", "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]", "pack": "npm pack 2>&1", @@ -28,14 +28,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": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/", - "types/communication-email.d.ts", "README.md", "LICENSE" ], @@ -47,41 +45,28 @@ "email" ], "dependencies": { - "@azure/communication-common": "^2.2.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.3.2", + "@azure/communication-common": "^2.3.1", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", "@azure/core-lro": "^2.5.0", - "@azure/core-rest-pipeline": "^1.8.0", - "@azure/core-util": "^1.6.1", - "@azure/logger": "^1.0.0", - "tslib": "^1.9.3" + "@azure/core-rest-pipeline": "^1.18.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.1.4", + "tslib": "^2.8.1" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.5", + "@vitest/coverage-istanbul": "^2.1.5", "dotenv": "^16.0.0", "eslint": "^9.9.0", - "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-json-preprocessor": "^0.3.3", - "karma-json-to-file-reporter": "^1.0.1", - "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", - "nyc": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.5" }, "homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/communication/communication-email/", "bugs": { @@ -103,5 +88,43 @@ "Azure Communication Services Resource": "https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource", "Email Communication Services Resource": "https://aka.ms/acsemail/createemailresource" } + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-email/src/emailClient.ts b/sdk/communication/communication-email/src/emailClient.ts index b22fd75fc12d..7e2c071b0b98 100644 --- a/sdk/communication/communication-email/src/emailClient.ts +++ b/sdk/communication/communication-email/src/emailClient.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { EmailClientOptions, EmailMessage, EmailSendOptionalParams } from "./models"; +import type { EmailClientOptions, EmailMessage, EmailSendOptionalParams } from "./models.js"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; import type { PollerLike, PollOperationState } from "@azure/core-lro"; @@ -10,10 +10,10 @@ import { isKeyCredential, parseClientArguments, } from "@azure/communication-common"; -import { EmailRestApiClient } from "./generated/src/emailRestApiClient"; +import { EmailRestApiClient } from "./generated/src/emailRestApiClient.js"; import type { InternalPipelineOptions } from "@azure/core-rest-pipeline"; -import { logger } from "./logger"; -import type { EmailSendResponse } from "./generated/src"; +import { logger } from "./logger.js"; +import type { EmailSendResponse } from "./generated/src/index.js"; /** * Checks whether the type of a value is EmailClientOptions or not. diff --git a/sdk/communication/communication-email/src/generated/src/emailRestApiClient.ts b/sdk/communication/communication-email/src/generated/src/emailRestApiClient.ts index 477d93633021..856a2319bd43 100644 --- a/sdk/communication/communication-email/src/generated/src/emailRestApiClient.ts +++ b/sdk/communication/communication-email/src/generated/src/emailRestApiClient.ts @@ -12,9 +12,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { EmailImpl } from "./operations"; -import { Email } from "./operationsInterfaces"; -import { EmailRestApiClientOptionalParams } from "./models"; +import { EmailImpl } from "./operations/index.js"; +import { Email } from "./operationsInterfaces/index.js"; +import { EmailRestApiClientOptionalParams } from "./models/index.js"; export class EmailRestApiClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-email/src/generated/src/index.ts b/sdk/communication/communication-email/src/generated/src/index.ts index a824fdd2f59b..4a35a8d24f71 100644 --- a/sdk/communication/communication-email/src/generated/src/index.ts +++ b/sdk/communication/communication-email/src/generated/src/index.ts @@ -6,6 +6,6 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./models"; -export { EmailRestApiClient } from "./emailRestApiClient"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { EmailRestApiClient } from "./emailRestApiClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-email/src/generated/src/models/parameters.ts b/sdk/communication/communication-email/src/generated/src/models/parameters.ts index f136a47bda68..b753b729ec6f 100644 --- a/sdk/communication/communication-email/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-email/src/generated/src/models/parameters.ts @@ -11,7 +11,7 @@ import { OperationURLParameter, OperationQueryParameter } from "@azure/core-client"; -import { EmailMessage as EmailMessageMapper } from "../models/mappers"; +import { EmailMessage as EmailMessageMapper } from "../models/mappers.js"; export const accept: OperationParameter = { parameterPath: "accept", diff --git a/sdk/communication/communication-email/src/generated/src/operations/email.ts b/sdk/communication/communication-email/src/generated/src/operations/email.ts index a5a36f3d5683..b445a98e9fdd 100644 --- a/sdk/communication/communication-email/src/generated/src/operations/email.ts +++ b/sdk/communication/communication-email/src/generated/src/operations/email.ts @@ -6,20 +6,20 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { Email } from "../operationsInterfaces"; +import { Email } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { EmailRestApiClient } from "../emailRestApiClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { EmailRestApiClient } from "../emailRestApiClient.js"; import { PollerLike, PollOperationState, LroEngine } from "@azure/core-lro"; -import { LroImpl } from "../lroImpl"; +import { LroImpl } from "../lroImpl.js"; import { EmailGetSendResultOptionalParams, EmailGetSendResultResponse, EmailMessage, EmailSendOptionalParams, EmailSendResponse -} from "../models"; +} from "../models/index.js"; /** Class containing Email operations. */ export class EmailImpl implements Email { diff --git a/sdk/communication/communication-email/src/generated/src/operations/index.ts b/sdk/communication/communication-email/src/generated/src/operations/index.ts index b9bab2d9d16d..bac350e31d1b 100644 --- a/sdk/communication/communication-email/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-email/src/generated/src/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./email"; +export * from "./email.js"; diff --git a/sdk/communication/communication-email/src/generated/src/operationsInterfaces/email.ts b/sdk/communication/communication-email/src/generated/src/operationsInterfaces/email.ts index 1773ab6709ef..50dc30bdbdef 100644 --- a/sdk/communication/communication-email/src/generated/src/operationsInterfaces/email.ts +++ b/sdk/communication/communication-email/src/generated/src/operationsInterfaces/email.ts @@ -13,7 +13,7 @@ import { EmailMessage, EmailSendOptionalParams, EmailSendResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a Email. */ export interface Email { diff --git a/sdk/communication/communication-email/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-email/src/generated/src/operationsInterfaces/index.ts index b9bab2d9d16d..bac350e31d1b 100644 --- a/sdk/communication/communication-email/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-email/src/generated/src/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./email"; +export * from "./email.js"; diff --git a/sdk/communication/communication-email/src/index.ts b/sdk/communication/communication-email/src/index.ts index a0ff08fa82bb..4c0a82202a9f 100644 --- a/sdk/communication/communication-email/src/index.ts +++ b/sdk/communication/communication-email/src/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./emailClient"; -export * from "./models"; +export * from "./emailClient.js"; +export * from "./models.js"; diff --git a/sdk/communication/communication-email/src/models.ts b/sdk/communication/communication-email/src/models.ts index 867ac18fe968..dda30a61a786 100644 --- a/sdk/communication/communication-email/src/models.ts +++ b/sdk/communication/communication-email/src/models.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { CommonClientOptions, OperationOptions } from "@azure/core-client"; -import type { EmailRecipients, EmailAttachment, EmailAddress } from "./models"; +import type { EmailRecipients, EmailAttachment, EmailAddress } from "./models.js"; /** * Client options used to configure Email Client API requests. @@ -71,4 +71,4 @@ export { ErrorDetail, ErrorAdditionalInfo, KnownEmailSendStatus, -} from "./generated/src/models"; +} from "./generated/src/models/index.js"; diff --git a/sdk/communication/communication-email/test/public/emailClient.spec.ts b/sdk/communication/communication-email/test/public/emailClient.spec.ts index 29f32b827ed7..2a2c268eb4d4 100644 --- a/sdk/communication/communication-email/test/public/emailClient.spec.ts +++ b/sdk/communication/communication-email/test/public/emailClient.spec.ts @@ -1,29 +1,28 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { EmailClient, EmailMessage } from "../../src"; -import { KnownEmailSendStatus } from "../../src"; +import type { EmailClient, EmailMessage } from "../../src/index.js"; +import { KnownEmailSendStatus } from "../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "chai"; -import { createRecordedEmailClientWithConnectionString } from "./utils/recordedClient"; +import { createRecordedEmailClientWithConnectionString } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`EmailClient [Playback/Live]`, function () { +describe(`EmailClient [Playback/Live]`, () => { let recorder: Recorder; let client: EmailClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedEmailClientWithConnectionString(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedEmailClientWithConnectionString(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("successfully sends an email to a single recipient", async function () { + it("successfully sends an email to a single recipient", { timeout: 120000 }, async () => { const emailMessage: EmailMessage = { senderAddress: env.SENDER_ADDRESS || "", recipients: { @@ -45,49 +44,53 @@ describe(`EmailClient [Playback/Live]`, function () { const response = await poller.pollUntilDone(); assert.isTrue(response.status === KnownEmailSendStatus.Succeeded); - }).timeout(120000); + }); - it("successfully sends an email to multiple types of recipients", async function () { - const emailMessage: EmailMessage = { - senderAddress: env.SENDER_ADDRESS ?? "", - recipients: { - to: [ - { - address: env.RECIPIENT_ADDRESS ?? "", - displayName: "someRecipient", - }, - { - address: env.RECIPIENT_ADDRESS ?? "", - displayName: "someRecipient", - }, - ], - cc: [ - { - address: env.RECIPIENT_ADDRESS ?? "", - displayName: "someRecipient", - }, - ], - bcc: [ - { - address: env.RECIPIENT_ADDRESS ?? "", - displayName: "someRecipient", - }, - ], - }, - content: { - subject: "someSubject", - plainText: "somePlainTextBody", - html: "

someHtmlBody", - }, - }; + it( + "successfully sends an email to multiple types of recipients", + { timeout: 120000 }, + async () => { + const emailMessage: EmailMessage = { + senderAddress: env.SENDER_ADDRESS ?? "", + recipients: { + to: [ + { + address: env.RECIPIENT_ADDRESS ?? "", + displayName: "someRecipient", + }, + { + address: env.RECIPIENT_ADDRESS ?? "", + displayName: "someRecipient", + }, + ], + cc: [ + { + address: env.RECIPIENT_ADDRESS ?? "", + displayName: "someRecipient", + }, + ], + bcc: [ + { + address: env.RECIPIENT_ADDRESS ?? "", + displayName: "someRecipient", + }, + ], + }, + content: { + subject: "someSubject", + plainText: "somePlainTextBody", + html: "

someHtmlBody", + }, + }; - const poller = await client.beginSend(emailMessage); - const response = await poller.pollUntilDone(); + const poller = await client.beginSend(emailMessage); + const response = await poller.pollUntilDone(); - assert.isTrue(response.status === KnownEmailSendStatus.Succeeded); - }).timeout(120000); + assert.isTrue(response.status === KnownEmailSendStatus.Succeeded); + }, + ); - it("successfully sends an email with an attachment", async function () { + it("successfully sends an email with an attachment", { timeout: 120000 }, async () => { const emailMessage: EmailMessage = { senderAddress: env.SENDER_ADDRESS ?? "", recipients: { @@ -116,9 +119,9 @@ describe(`EmailClient [Playback/Live]`, function () { const response = await poller.pollUntilDone(); assert.isTrue(response.status === KnownEmailSendStatus.Succeeded); - }).timeout(120000); + }); - it("successfully sends an email with an inline attachment", async function () { + it("successfully sends an email with an inline attachment", { timeout: 120000 }, async () => { const emailMessage: EmailMessage = { senderAddress: env.SENDER_ADDRESS ?? "", recipients: { @@ -148,5 +151,5 @@ describe(`EmailClient [Playback/Live]`, function () { const response = await poller.pollUntilDone(); assert.isTrue(response.status === KnownEmailSendStatus.Succeeded); - }).timeout(120000); + }); }); diff --git a/sdk/communication/communication-email/test/public/utils/recordedClient.ts b/sdk/communication/communication-email/test/public/utils/recordedClient.ts index 5f6c0ce20a25..0365edf3b4cd 100644 --- a/sdk/communication/communication-email/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-email/test/public/utils/recordedClient.ts @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type { Context, Test } from "mocha"; -import type { SanitizerOptions } from "@azure-tools/test-recorder"; +import type { SanitizerOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, env } from "@azure-tools/test-recorder"; -import { EmailClient } from "../../../src"; +import { EmailClient } from "../../../src/index.js"; export interface RecordedEmailClient { client: EmailClient; @@ -47,7 +45,7 @@ const sanitizerOptions: SanitizerOptions = { ], }; -export async function createRecorder(context: Test | undefined): Promise { +export async function createRecorder(context: TestInfo | undefined): Promise { const recorder = new Recorder(context); await recorder.start({ envSetupForPlayback }); await recorder.addSanitizers(sanitizerOptions, ["record", "playback"]); @@ -61,9 +59,9 @@ export async function createRecorder(context: Test | undefined): Promise { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); const client = new EmailClient( env.COMMUNICATION_CONNECTION_STRING_EMAIL ?? "", diff --git a/sdk/communication/communication-email/tsconfig.browser.config.json b/sdk/communication/communication-email/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-email/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-email/tsconfig.json b/sdk/communication/communication-email/tsconfig.json index 2cd0ee859621..3a3ac9f7007e 100644 --- a/sdk/communication/communication-email/tsconfig.json +++ b/sdk/communication/communication-email/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure/communication-email": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-email/vitest.browser.config.ts b/sdk/communication/communication-email/vitest.browser.config.ts new file mode 100644 index 000000000000..50ec2d5489b0 --- /dev/null +++ b/sdk/communication/communication-email/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-email/vitest.config.ts b/sdk/communication/communication-email/vitest.config.ts new file mode 100644 index 000000000000..d01fdec8ac69 --- /dev/null +++ b/sdk/communication/communication-email/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-identity/.nycrc b/sdk/communication/communication-identity/.nycrc deleted file mode 100644 index 29174b423579..000000000000 --- a/sdk/communication/communication-identity/.nycrc +++ /dev/null @@ -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 -} diff --git a/sdk/communication/communication-identity/api-extractor.json b/sdk/communication/communication-identity/api-extractor.json index 373e39769308..4c6770d2fae1 100644 --- a/sdk/communication/communication-identity/api-extractor.json +++ b/sdk/communication/communication-identity/api-extractor.json @@ -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-identity.d.ts" + "publicTrimmedFilePath": "dist/communication-identity.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-identity/karma.conf.js b/sdk/communication/communication-identity/karma.conf.js deleted file mode 100644 index ddf5f8d0dae5..000000000000 --- a/sdk/communication/communication-identity/karma.conf.js +++ /dev/null @@ -1,128 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); - -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": ["sourcemap", "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: [ - "TEST_MODE", - "COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING", - "INCLUDE_PHONENUMBER_TESTS", - "COMMUNICATION_ENDPOINT", - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "RECORDINGS_RELATIVE_PATH", - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-identity/package.json b/sdk/communication/communication-identity/package.json index a07ee2b7c4d9..3200a1209378 100644 --- a/sdk/communication/communication-identity/package.json +++ b/sdk/communication/communication-identity/package.json @@ -3,27 +3,26 @@ "version": "1.3.2", "description": "SDK for Azure Communication service which facilitates user token administration.", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-identity.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api", - "build:browser": "tsc -p . && dev-tool run bundle", - "build:clean": "rush update --recheck && rush rebuild && npm run build", - "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 Obsolete.", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* temp types *.tgz *.log", "execute:js-samples": "dev-tool samples run dist-samples/javascript", "execute:samples": "dev-tool samples run samples-dev", "execute:ts-samples": "dev-tool samples run dist-samples/typescript/dist/dist-samples/typescript/src/", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "generate:client": "autorest --typescript ./swagger/README.md && rushx format", "integration-test": "npm run integration-test:node && npm run integration-test:browser", - "integration-test:browser": "dev-tool run test:browser", - "integration-test:node": "dev-tool run test:node-js-input -- --timeout 5000000 --exclude 'dist-esm/test/**/browser/*.spec.js' '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 --browser", + "integration-test:node": "dev-tool run test:vitest", "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,8 +31,8 @@ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node", "test:watch": "npm run test -- --watch --reporter min", "unit-test": "npm run unit-test:node && npm run unit-test:browser", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "//metadata": { @@ -71,8 +70,6 @@ }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-identity.d.ts", "README.md", "LICENSE" ], @@ -94,49 +91,72 @@ "sideEffects": false, "prettier": "@azure/eslint-plugin-azure-sdk/prettier.json", "dependencies": { - "@azure/abort-controller": "^2.0.0", + "@azure/abort-controller": "^2.1.2", "@azure/communication-common": "^2.3.1", - "@azure/core-auth": "^1.3.2", - "@azure/core-client": "^1.6.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.1.1", - "@azure/core-rest-pipeline": "^1.3.0", - "@azure/core-tracing": "^1.0.0", - "@azure/logger": "^1.0.0", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.18.0", + "@azure/core-tracing": "^1.2.0", + "@azure/logger": "^1.1.4", "events": "^3.0.0", "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-credential": "^1.0.0", - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-credential": "^2.0.0", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/core-util": "^1.6.1", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", - "@azure/identity": "^4.0.1", - "@azure/msal-node": "^2.9.2", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", + "@azure/identity": "^4.5.0", + "@azure/msal-node": "^2.16.1", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.5", + "@vitest/coverage-istanbul": "^2.1.5", "dotenv": "^16.0.0", "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", - "nyc": "^17.0.0", - "process": "^0.11.10", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.5" + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-identity/samples-dev/createUserAndToken.ts b/sdk/communication/communication-identity/samples-dev/createUserAndToken.ts index 861b5bc89769..fb53e84d40e7 100644 --- a/sdk/communication/communication-identity/samples-dev/createUserAndToken.ts +++ b/sdk/communication/communication-identity/samples-dev/createUserAndToken.ts @@ -6,7 +6,7 @@ */ import { CommunicationIdentityClient, TokenScope } from "@azure/communication-identity"; -import { CreateUserAndTokenOptions } from "../src"; +import { CreateUserAndTokenOptions } from "../src/index.js"; // Load the .env file if it exists import * as dotenv from "dotenv"; diff --git a/sdk/communication/communication-identity/samples-dev/issueToken.ts b/sdk/communication/communication-identity/samples-dev/issueToken.ts index d3e0ba0d2262..538db0499016 100644 --- a/sdk/communication/communication-identity/samples-dev/issueToken.ts +++ b/sdk/communication/communication-identity/samples-dev/issueToken.ts @@ -11,7 +11,7 @@ import { TokenScope, } from "@azure/communication-identity"; -import { GetTokenOptions } from "../src"; +import { GetTokenOptions } from "../src/index.js"; // Load the .env file if it exists import * as dotenv from "dotenv"; diff --git a/sdk/communication/communication-identity/src/communicationIdentityClient.ts b/sdk/communication/communication-identity/src/communicationIdentityClient.ts index 11ea37113735..3c3b0f13c77a 100644 --- a/sdk/communication/communication-identity/src/communicationIdentityClient.ts +++ b/sdk/communication/communication-identity/src/communicationIdentityClient.ts @@ -9,7 +9,7 @@ import type { CreateUserAndTokenOptions, GetTokenOptions, TokenScope, -} from "./models"; +} from "./models.js"; import type { CommunicationUserIdentifier } from "@azure/communication-common"; import { createCommunicationAuthPolicy, @@ -19,9 +19,9 @@ import { import type { InternalClientPipelineOptions, OperationOptions } from "@azure/core-client"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; -import { IdentityRestClient } from "./generated/src/identityRestClient"; -import { logger } from "./common/logger"; -import { tracingClient } from "./generated/src/tracing"; +import { IdentityRestClient } from "./generated/src/identityRestClient.js"; +import { logger } from "./common/logger.js"; +import { tracingClient } from "./generated/src/tracing.js"; const isCommunicationIdentityClientOptions = ( options: any, diff --git a/sdk/communication/communication-identity/src/generated/src/identityRestClient.ts b/sdk/communication/communication-identity/src/generated/src/identityRestClient.ts index 2694861084a4..1b8322501a74 100644 --- a/sdk/communication/communication-identity/src/generated/src/identityRestClient.ts +++ b/sdk/communication/communication-identity/src/generated/src/identityRestClient.ts @@ -12,9 +12,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { CommunicationIdentityOperationsImpl } from "./operations"; -import { CommunicationIdentityOperations } from "./operationsInterfaces"; -import { IdentityRestClientOptionalParams } from "./models"; +import { CommunicationIdentityOperationsImpl } from "./operations/index.js"; +import { CommunicationIdentityOperations } from "./operationsInterfaces/index.js"; +import { IdentityRestClientOptionalParams } from "./models/index.js"; export class IdentityRestClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-identity/src/generated/src/index.ts b/sdk/communication/communication-identity/src/generated/src/index.ts index 47655697cd93..8b271d84ad95 100644 --- a/sdk/communication/communication-identity/src/generated/src/index.ts +++ b/sdk/communication/communication-identity/src/generated/src/index.ts @@ -6,6 +6,6 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./models"; -export { IdentityRestClient } from "./identityRestClient"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { IdentityRestClient } from "./identityRestClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-identity/src/generated/src/models/parameters.ts b/sdk/communication/communication-identity/src/generated/src/models/parameters.ts index 76d37faa7914..7097302c040c 100644 --- a/sdk/communication/communication-identity/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-identity/src/generated/src/models/parameters.ts @@ -15,7 +15,7 @@ import { CommunicationIdentityCreateRequest as CommunicationIdentityCreateRequestMapper, TeamsUserExchangeTokenRequest as TeamsUserExchangeTokenRequestMapper, CommunicationIdentityAccessTokenRequest as CommunicationIdentityAccessTokenRequestMapper -} from "../models/mappers"; +} from "../models/mappers.js"; export const contentType: OperationParameter = { parameterPath: ["options", "contentType"], diff --git a/sdk/communication/communication-identity/src/generated/src/operations/communicationIdentityOperations.ts b/sdk/communication/communication-identity/src/generated/src/operations/communicationIdentityOperations.ts index f12d59c5f440..ad24671409f9 100644 --- a/sdk/communication/communication-identity/src/generated/src/operations/communicationIdentityOperations.ts +++ b/sdk/communication/communication-identity/src/generated/src/operations/communicationIdentityOperations.ts @@ -6,12 +6,12 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; -import { CommunicationIdentityOperations } from "../operationsInterfaces"; +import { tracingClient } from "../tracing.js"; +import { CommunicationIdentityOperations } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { IdentityRestClient } from "../identityRestClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { IdentityRestClient } from "../identityRestClient.js"; import { CommunicationIdentityCreateOptionalParams, CommunicationIdentityCreateResponse, @@ -22,7 +22,7 @@ import { CommunicationIdentityTokenScope, CommunicationIdentityIssueAccessTokenOptionalParams, CommunicationIdentityIssueAccessTokenResponse -} from "../models"; +} from "../models/index.js"; /** Class containing CommunicationIdentityOperations operations. */ export class CommunicationIdentityOperationsImpl diff --git a/sdk/communication/communication-identity/src/generated/src/operations/index.ts b/sdk/communication/communication-identity/src/generated/src/operations/index.ts index c0e3fc741e5a..2c4ebd08eebf 100644 --- a/sdk/communication/communication-identity/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-identity/src/generated/src/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./communicationIdentityOperations"; +export * from "./communicationIdentityOperations.js"; diff --git a/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/communicationIdentityOperations.ts b/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/communicationIdentityOperations.ts index 0f7afc177653..5f67f6e2fc12 100644 --- a/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/communicationIdentityOperations.ts +++ b/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/communicationIdentityOperations.ts @@ -16,7 +16,7 @@ import { CommunicationIdentityTokenScope, CommunicationIdentityIssueAccessTokenOptionalParams, CommunicationIdentityIssueAccessTokenResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a CommunicationIdentityOperations. */ export interface CommunicationIdentityOperations { diff --git a/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/index.ts index c0e3fc741e5a..2c4ebd08eebf 100644 --- a/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-identity/src/generated/src/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./communicationIdentityOperations"; +export * from "./communicationIdentityOperations.js"; diff --git a/sdk/communication/communication-identity/src/index.ts b/sdk/communication/communication-identity/src/index.ts index 7837fc8e0a34..8ab7b2c6ea6c 100644 --- a/sdk/communication/communication-identity/src/index.ts +++ b/sdk/communication/communication-identity/src/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./communicationIdentityClient"; -export * from "./models"; +export * from "./communicationIdentityClient.js"; +export * from "./models.js"; diff --git a/sdk/communication/communication-identity/test/public/communicationIdentityClient.mocked.spec.ts b/sdk/communication/communication-identity/test/public/communicationIdentityClient.mocked.spec.ts index 1fbc27f7fb36..1ada7d5d68de 100644 --- a/sdk/communication/communication-identity/test/public/communicationIdentityClient.mocked.spec.ts +++ b/sdk/communication/communication-identity/test/public/communicationIdentityClient.mocked.spec.ts @@ -3,38 +3,33 @@ import type { CommunicationUserIdentifier } from "@azure/communication-common"; import { isCommunicationUserIdentifier } from "@azure/communication-common"; -import { getTokenForTeamsUserHttpClient, getTokenHttpClient } from "./utils/mockHttpClients"; -import { CommunicationIdentityClient } from "../../src"; -import { TestCommunicationIdentityClient } from "./utils/testCommunicationIdentityClient"; -import { assert } from "chai"; -import { isNode } from "@azure/core-util"; -import sinon from "sinon"; - -describe("CommunicationIdentityClient [Mocked]", function () { +import { getTokenForTeamsUserHttpClient, getTokenHttpClient } from "./utils/mockHttpClients.js"; +import { CommunicationIdentityClient } from "../../src/index.js"; +import { TestCommunicationIdentityClient } from "./utils/testCommunicationIdentityClient.js"; +import { isNodeLike } from "@azure/core-util"; +import { describe, it, assert, expect, vi } from "vitest"; + +describe("CommunicationIdentityClient [Mocked]", () => { const dateHeader = "x-ms-date"; const user: CommunicationUserIdentifier = { communicationUserId: "ACS_ID" }; - afterEach(function () { - sinon.restore(); - }); - - it("creates instance of CommunicationIdentityClient", function () { + it("creates instance of CommunicationIdentityClient", () => { const client = new CommunicationIdentityClient( "endpoint=https://contoso.spool.azure.local;accesskey=banana", ); assert.instanceOf(client, CommunicationIdentityClient); }); - it("sets correct headers", async function () { + it("sets correct headers", async () => { const client = new TestCommunicationIdentityClient(); - const spy = sinon.spy(getTokenHttpClient, "sendRequest"); + const spy = vi.spyOn(getTokenHttpClient, "sendRequest"); await client.getTokenTest(user, ["chat"]); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - const request = spy.getCall(0).args[0]; + const request = spy.mock.calls[0][0]; - if (isNode) { + if (isNodeLike) { assert.equal(request.headers.get("host"), "contoso.spool.azure.local"); } @@ -46,27 +41,27 @@ describe("CommunicationIdentityClient [Mocked]", function () { ); }); - it("sends scopes in issue token request", async function () { + it("sends scopes in issue token request", async () => { const client = new TestCommunicationIdentityClient(); - const spy = sinon.spy(getTokenHttpClient, "sendRequest"); + const spy = vi.spyOn(getTokenHttpClient, "sendRequest"); const response = await client.getTokenTest(user, ["chat"]); assert.equal(response.token, "token"); assert.equal(response.expiresOn.toDateString(), new Date("2011/11/30").toDateString()); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - const request = spy.getCall(0).args[0]; + const request = spy.mock.calls[0][0]; assert.deepEqual(JSON.parse(request.body as string), { scopes: ["chat"] }); }); - it("[getToken] excludes _response from results", async function () { + it("[getToken] excludes _response from results", async () => { const client = new TestCommunicationIdentityClient(); const response = await client.getTokenTest(user, ["chat"]); assert.isFalse("_response" in response); }); - it("[createUser] excludes _response from results", async function () { + it("[createUser] excludes _response from results", async () => { const client = new TestCommunicationIdentityClient(); const newUser = await client.createUserTest(); @@ -75,17 +70,17 @@ describe("CommunicationIdentityClient [Mocked]", function () { assert.isFalse("_response" in newUser); }); - it("exchanges Teams token for ACS token", async function () { + it("exchanges Teams token for ACS token", async () => { const client = new TestCommunicationIdentityClient(); - const spy = sinon.spy(getTokenForTeamsUserHttpClient, "sendRequest"); + const spy = vi.spyOn(getTokenForTeamsUserHttpClient, "sendRequest"); const response = await client.getTokenForTeamsUserTest("TeamsToken", "appId", "userId"); assert.equal(response.token, "token"); assert.equal(response.expiresOn.toDateString(), new Date("2011/11/30").toDateString()); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); }); - it("[getTokenForTeamsUser] excludes _response from results", async function () { + it("[getTokenForTeamsUser] excludes _response from results", async () => { const client = new TestCommunicationIdentityClient(); const response = await client.getTokenForTeamsUserTest("TeamsToken", "appId", "userId"); diff --git a/sdk/communication/communication-identity/test/public/communicationIdentityClient.spec.ts b/sdk/communication/communication-identity/test/public/communicationIdentityClient.spec.ts index 31a5550d7821..b3c19a01f23c 100644 --- a/sdk/communication/communication-identity/test/public/communicationIdentityClient.spec.ts +++ b/sdk/communication/communication-identity/test/public/communicationIdentityClient.spec.ts @@ -8,14 +8,13 @@ import { isPlaybackMode } from "@azure-tools/test-recorder"; import { createRecordedCommunicationIdentityClient, createRecordedCommunicationIdentityClientWithToken, -} from "./utils/recordedClient"; -import type { CommunicationIdentityClient, TokenScope } from "../../src"; -import type { Context } from "mocha"; -import { assert } from "chai"; -import { matrix } from "@azure-tools/test-utils"; - -matrix([[true, false]], async function (useAad: boolean) { - describe(`CommunicationIdentityClient [Playback/Live]${useAad ? " [AAD]" : ""}`, function () { +} from "./utils/recordedClient.js"; +import type { CommunicationIdentityClient, TokenScope } from "../../src/index.js"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; + +matrix([[true, false]], async (useAad: boolean) => { + describe(`CommunicationIdentityClient [Playback/Live]${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: CommunicationIdentityClient; @@ -33,27 +32,27 @@ matrix([[true, false]], async function (useAad: boolean) { { scopes: ["chat.join", "voip.join"], description: "ChatJoinVoipJoinScopes" }, ]; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { if (useAad) { - ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(this)); + ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(ctx)); } else { - ({ client, recorder } = await createRecordedCommunicationIdentityClient(this)); + ({ client, recorder } = await createRecordedCommunicationIdentityClient(ctx)); } }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("successfully creates a user", async function () { + it("successfully creates a user", async () => { const user: CommunicationUserIdentifier = await client.createUser(); assert.isString(user.communicationUserId); }); tokenScopeScenarios.forEach((scenario) => - it(`successfully creates a user and token <${scenario.description}>`, async function () { + it(`successfully creates a user and token <${scenario.description}>`, async () => { const { user: newUser, token, @@ -67,7 +66,7 @@ matrix([[true, false]], async function (useAad: boolean) { ); tokenScopeScenarios.forEach((scenario) => - it(`successfully gets a token for a user <${scenario.description}>`, async function () { + it(`successfully gets a token for a user <${scenario.description}>`, async () => { const user: CommunicationUserIdentifier = await client.createUser(); const { token, expiresOn } = await client.getToken(user, scenario.scopes as TokenScope[]); assert.isString(token); @@ -75,24 +74,24 @@ matrix([[true, false]], async function (useAad: boolean) { }), ); - it("successfully revokes tokens issued for a user", async function () { + it("successfully revokes tokens issued for a user", async () => { const { user } = await client.createUserAndToken(scopes); await client.revokeTokens(user); }); - it("successfully deletes a user", async function () { + it("successfully deletes a user", async () => { const user: CommunicationUserIdentifier = await client.createUser(); await client.deleteUser(user); }); - describe("Error Cases: ", async function () { + describe("Error Cases: ", async () => { const fakeUser: CommunicationUserIdentifier = { communicationUserId: isPlaybackMode() ? "sanitized" : "8:acs:00000000-0000-0000-0000-000000000000_00000000-0000-0000-0000-000000000000", }; - it("throws an error when attempting to issue a token without any scopes", async function () { + it("throws an error when attempting to issue a token without any scopes", async () => { try { const user: CommunicationUserIdentifier = await client.createUser(); await client.getToken(user, []); @@ -103,7 +102,7 @@ matrix([[true, false]], async function (useAad: boolean) { } }); - it("throws an error when attempting to issue a token for an invalid user", async function () { + it("throws an error when attempting to issue a token for an invalid user", async () => { try { await client.getToken(fakeUser, scopes); assert.fail("Should have thrown an error"); @@ -112,7 +111,7 @@ matrix([[true, false]], async function (useAad: boolean) { } }); - it("throws an error when attempting to revoke a token from an invalid user", async function () { + it("throws an error when attempting to revoke a token from an invalid user", async () => { try { await client.revokeTokens(fakeUser); assert.fail("Should have thrown an error"); @@ -121,7 +120,7 @@ matrix([[true, false]], async function (useAad: boolean) { } }); - it("throws an error when attempting to delete an invalid user", async function () { + it("throws an error when attempting to delete an invalid user", async () => { try { await client.deleteUser(fakeUser); assert.fail("Should have thrown an error"); diff --git a/sdk/communication/communication-identity/test/public/node/getTokenForTeamsUser.node.spec.ts b/sdk/communication/communication-identity/test/public/node/getTokenForTeamsUser.node.spec.ts index 10c40a4bc280..83a2b0990a02 100644 --- a/sdk/communication/communication-identity/test/public/node/getTokenForTeamsUser.node.spec.ts +++ b/sdk/communication/communication-identity/test/public/node/getTokenForTeamsUser.node.spec.ts @@ -5,158 +5,162 @@ import type { CommunicationAccessToken, CommunicationIdentityClient, GetTokenForTeamsUserOptions, -} from "../../../src"; +} from "../../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isPlaybackMode } from "@azure-tools/test-recorder"; import { createRecordedCommunicationIdentityClient, createRecordedCommunicationIdentityClientWithToken, -} from "../utils/recordedClient"; +} from "../utils/recordedClient.js"; import { PublicClientApplication } from "@azure/msal-node"; -import { matrix } from "@azure-tools/test-utils"; -import type { Context } from "mocha"; -import { assert } from "chai"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`Get Token For Teams User [Playback/Live]${useAad ? " [AAD]" : ""}`, function () { - let recorder: Recorder; - let client: CommunicationIdentityClient; - const sanitizedValue = "sanitized"; - let options: GetTokenForTeamsUserOptions = { - teamsUserAadToken: sanitizedValue, - clientId: sanitizedValue, - userObjectId: sanitizedValue, - }; +matrix([[true, false]], async (useAad) => { + describe( + `Get Token For Teams User [Playback/Live]${useAad ? " [AAD]" : ""}`, + { skip: env.SKIP_INT_IDENTITY_EXCHANGE_TOKEN_TEST === "true" }, + () => { + let recorder: Recorder; + let client: CommunicationIdentityClient; + const sanitizedValue = "sanitized"; + let options: GetTokenForTeamsUserOptions = { + teamsUserAadToken: sanitizedValue, + clientId: sanitizedValue, + userObjectId: sanitizedValue, + }; - before(async function (this: Context) { - const skipTests = env.SKIP_INT_IDENTITY_EXCHANGE_TOKEN_TEST === "true"; - if (skipTests) { - this.skip(); - } - if (!isPlaybackMode()) { - options = await fetchParamsForGetTokenForTeamsUser(); - } - }); + beforeAll(async () => { + if (!isPlaybackMode()) { + options = await fetchParamsForGetTokenForTeamsUser(); + } + }); - beforeEach(async function (this: Context) { - if (useAad) { - ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(this)); - } else { - ({ client, recorder } = await createRecordedCommunicationIdentityClient(this)); - } - }); + beforeEach(async (ctx) => { + if (useAad) { + ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(ctx)); + } else { + ({ client, recorder } = await createRecordedCommunicationIdentityClient(ctx)); + } + }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } - }); + afterEach(async (ctx) => { + if (!ctx.task.pending) { + await recorder.stop(); + } + }); - async function fetchParamsForGetTokenForTeamsUser(): Promise { - const msalConfig = { - auth: { + async function fetchParamsForGetTokenForTeamsUser(): Promise { + const msalConfig = { + auth: { + clientId: env.COMMUNICATION_M365_APP_ID ?? "", + authority: + env.COMMUNICATION_M365_AAD_AUTHORITY + "/" + env.COMMUNICATION_M365_AAD_TENANT, + }, + }; + const msalInstance = new PublicClientApplication(msalConfig); + const usernamePasswordRequest = { + scopes: [ + "https://auth.msft.communication.azure.com/Teams.ManageCalls", + "https://auth.msft.communication.azure.com/Teams.ManageChats", + ], + username: env.COMMUNICATION_MSAL_USERNAME ?? "", + password: env.COMMUNICATION_MSAL_PASSWORD ?? "", + }; + const response = await msalInstance.acquireTokenByUsernamePassword(usernamePasswordRequest); + const getTokenForTeamsUserOptions: GetTokenForTeamsUserOptions = { + teamsUserAadToken: response!.accessToken, clientId: env.COMMUNICATION_M365_APP_ID ?? "", - authority: env.COMMUNICATION_M365_AAD_AUTHORITY + "/" + env.COMMUNICATION_M365_AAD_TENANT, - }, - }; - const msalInstance = new PublicClientApplication(msalConfig); - const usernamePasswordRequest = { - scopes: [ - "https://auth.msft.communication.azure.com/Teams.ManageCalls", - "https://auth.msft.communication.azure.com/Teams.ManageChats", - ], - username: env.COMMUNICATION_MSAL_USERNAME ?? "", - password: env.COMMUNICATION_MSAL_PASSWORD ?? "", - }; - const response = await msalInstance.acquireTokenByUsernamePassword(usernamePasswordRequest); - const getTokenForTeamsUserOptions: GetTokenForTeamsUserOptions = { - teamsUserAadToken: response!.accessToken, - clientId: env.COMMUNICATION_M365_APP_ID ?? "", - userObjectId: response!.uniqueId, - }; - return getTokenForTeamsUserOptions; - } + userObjectId: response!.uniqueId, + }; + return getTokenForTeamsUserOptions; + } - it("successfully exchanges a Teams User AAD token for a Communication access token", async function () { - const { token, expiresOn }: CommunicationAccessToken = - await client.getTokenForTeamsUser(options); - assert.isString(token); - assert.instanceOf(expiresOn, Date); - }).timeout(5000); + it( + "successfully exchanges a Teams User AAD token for a Communication access token", + { timeout: 5000 }, + async () => { + const { token, expiresOn }: CommunicationAccessToken = + await client.getTokenForTeamsUser(options); + assert.isString(token); + assert.instanceOf(expiresOn, Date); + }, + ); - [ - { teamsUserAadToken: "", description: "an empty teamsUserAadToken" }, - { teamsUserAadToken: "invalid", description: "an invalid teamsUserAadToken" }, - { - teamsUserAadToken: env.COMMUNICATION_EXPIRED_TEAMS_TOKEN ?? "", - description: "an expired teamsUserAadToken", - }, - ].forEach((input) => - it(`throws an error when attempting to exchange <${input.description}>`, async function () { - try { - if (isPlaybackMode()) { - input.teamsUserAadToken = sanitizedValue; + [ + { teamsUserAadToken: "", description: "an empty teamsUserAadToken" }, + { teamsUserAadToken: "invalid", description: "an invalid teamsUserAadToken" }, + { + teamsUserAadToken: env.COMMUNICATION_EXPIRED_TEAMS_TOKEN ?? "", + description: "an expired teamsUserAadToken", + }, + ].forEach((input) => + it(`throws an error when attempting to exchange <${input.description}>`, async () => { + try { + if (isPlaybackMode()) { + input.teamsUserAadToken = sanitizedValue; + } + await client.getTokenForTeamsUser({ + teamsUserAadToken: input.teamsUserAadToken, + clientId: options.clientId, + userObjectId: options.clientId, + }); + } catch (e: any) { + assert.equal(e.statusCode, 401); + return; } - await client.getTokenForTeamsUser({ - teamsUserAadToken: input.teamsUserAadToken, - clientId: options.clientId, - userObjectId: options.clientId, - }); - } catch (e: any) { - assert.equal(e.statusCode, 401); - return; - } - assert.fail("Should have thrown an error"); - }), - ); + assert.fail("Should have thrown an error"); + }), + ); - [ - { clientId: "", description: "an empty clientId" }, - { clientId: "invalid", description: "an invalid clientId" }, - { clientId: options.userObjectId, description: "a wrong clientId" }, - ].forEach((input) => - it(`throws an error when attempting to exchange <${input.description}>`, async function () { - try { - if (isPlaybackMode()) { - input.clientId = sanitizedValue; + [ + { clientId: "", description: "an empty clientId" }, + { clientId: "invalid", description: "an invalid clientId" }, + { clientId: options.userObjectId, description: "a wrong clientId" }, + ].forEach((input) => + it(`throws an error when attempting to exchange <${input.description}>`, async () => { + try { + if (isPlaybackMode()) { + input.clientId = sanitizedValue; + } + await client.getTokenForTeamsUser({ + teamsUserAadToken: options.teamsUserAadToken, + clientId: input.clientId, + userObjectId: options.userObjectId, + }); + } catch (e: any) { + assert.equal(e.statusCode, 400); + return; } - await client.getTokenForTeamsUser({ - teamsUserAadToken: options.teamsUserAadToken, - clientId: input.clientId, - userObjectId: options.userObjectId, - }); - } catch (e: any) { - assert.equal(e.statusCode, 400); - return; - } - assert.fail("Should have thrown an error"); - }), - ); + assert.fail("Should have thrown an error"); + }), + ); - [ - { userObjectId: "", description: "an empty userObjectId" }, - { userObjectId: "invalid", description: "an invalid userObjectId" }, - { userObjectId: options.clientId, description: "a wrong userObjectId" }, - ].forEach((input) => - it(`throws an error when attempting to exchange <${input.description}>`, async function () { - try { - if (isPlaybackMode()) { - input.userObjectId = sanitizedValue; + [ + { userObjectId: "", description: "an empty userObjectId" }, + { userObjectId: "invalid", description: "an invalid userObjectId" }, + { userObjectId: options.clientId, description: "a wrong userObjectId" }, + ].forEach((input) => + it(`throws an error when attempting to exchange <${input.description}>`, async () => { + try { + if (isPlaybackMode()) { + input.userObjectId = sanitizedValue; + } + await client.getTokenForTeamsUser({ + teamsUserAadToken: options.teamsUserAadToken, + clientId: options.clientId, + userObjectId: input.userObjectId, + }); + } catch (e: any) { + assert.equal(e.statusCode, 400); + return; } - await client.getTokenForTeamsUser({ - teamsUserAadToken: options.teamsUserAadToken, - clientId: options.clientId, - userObjectId: input.userObjectId, - }); - } catch (e: any) { - assert.equal(e.statusCode, 400); - return; - } - assert.fail("Should have thrown an error"); - }), - ); - }); + assert.fail("Should have thrown an error"); + }), + ); + }, + ); }); diff --git a/sdk/communication/communication-identity/test/public/node/tokenCustomExpiration.node.spec.ts b/sdk/communication/communication-identity/test/public/node/tokenCustomExpiration.node.spec.ts index 99da3a6303f4..a01841dfa34e 100644 --- a/sdk/communication/communication-identity/test/public/node/tokenCustomExpiration.node.spec.ts +++ b/sdk/communication/communication-identity/test/public/node/tokenCustomExpiration.node.spec.ts @@ -4,34 +4,31 @@ import type { CommunicationUserIdentifier } from "@azure/communication-common"; import type { Recorder } from "@azure-tools/test-recorder"; import { isLiveMode } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "chai"; -import { matrix } from "@azure-tools/test-utils"; -import type { CommunicationIdentityClient } from "../../../src/communicationIdentityClient"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import type { CommunicationIdentityClient } from "../../../src/communicationIdentityClient.js"; import { createRecordedCommunicationIdentityClient, createRecordedCommunicationIdentityClientWithToken, -} from "../utils/recordedClient"; -import type { CreateUserAndTokenOptions, GetTokenOptions } from "../../../src/models"; +} from "../utils/recordedClient.js"; +import type { CreateUserAndTokenOptions, GetTokenOptions } from "../../../src/models.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad: boolean) { - describe(`Get Token With Custom Expiration [Playback/Live]${ - useAad ? " [AAD]" : "" - }`, function () { +matrix([[true, false]], async (useAad: boolean) => { + describe(`Get Token With Custom Expiration [Playback/Live]${useAad ? " [AAD]" : ""}`, () => { const TOKEN_EXPIRATION_ALLOWED_DEVIATION: number = 0.05; let recorder: Recorder; let client: CommunicationIdentityClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { if (useAad) { - ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(this)); + ({ client, recorder } = await createRecordedCommunicationIdentityClientWithToken(ctx)); } else { - ({ client, recorder } = await createRecordedCommunicationIdentityClient(this)); + ({ client, recorder } = await createRecordedCommunicationIdentityClient(ctx)); } }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); @@ -40,7 +37,10 @@ matrix([[true, false]], async function (useAad: boolean) { expectedTokenExpiration: number, tokenExpiresIn: Date, allowedDeviation: number, - ) { + ): { + withinAllowedDeviation: boolean; + tokenExpirationInMinutes: number; + } { const timeNow = Date.now(); const expiration = tokenExpiresIn.getTime(); const tokenSeconds = (expiration - timeNow) / 1000; @@ -57,7 +57,7 @@ matrix([[true, false]], async function (useAad: boolean) { { tokenExpiresInMinutes: 60, description: "min valid" }, { tokenExpiresInMinutes: 1440, description: "max valid" }, ].forEach((input) => - it(`successfully gets a valid custom expiration token <${input.description}>`, async function () { + it(`successfully gets a valid custom expiration token <${input.description}>`, async () => { const user: CommunicationUserIdentifier = await client.createUser(); const tokenOptions: GetTokenOptions = { tokenExpiresInMinutes: input.tokenExpiresInMinutes, @@ -90,7 +90,7 @@ matrix([[true, false]], async function (useAad: boolean) { { tokenExpiresInMinutes: 60, description: "min valid" }, { tokenExpiresInMinutes: 1440, description: "max valid" }, ].forEach((input) => - it(`successfully gets user and valid custom expiration token <${input.description}>`, async function () { + it(`successfully gets user and valid custom expiration token <${input.description}>`, async () => { const tokenOptions: CreateUserAndTokenOptions = { tokenExpiresInMinutes: input.tokenExpiresInMinutes, }; @@ -122,7 +122,7 @@ matrix([[true, false]], async function (useAad: boolean) { { tokenExpiresInMinutes: 59, description: "lo inval" }, { tokenExpiresInMinutes: 1441, description: "hi inval" }, ].forEach((input) => - it(`throws error when attempting to issue an invalid expiration token <${input.description}>`, async function () { + it(`throws error when attempting to issue an invalid expiration token <${input.description}>`, async () => { const user: CommunicationUserIdentifier = await client.createUser(); const tokenOptions: GetTokenOptions = { tokenExpiresInMinutes: input.tokenExpiresInMinutes, @@ -140,7 +140,7 @@ matrix([[true, false]], async function (useAad: boolean) { { tokenExpiresInMinutes: 59, description: "lo inval" }, { tokenExpiresInMinutes: 1441, description: "hi inval" }, ].forEach((input) => - it(`throws error when attempting to issue user and invalid expiration token <${input.description}>`, async function () { + it(`throws error when attempting to issue user and invalid expiration token <${input.description}>`, async () => { const tokenOptions: CreateUserAndTokenOptions = { tokenExpiresInMinutes: input.tokenExpiresInMinutes, }; diff --git a/sdk/communication/communication-identity/test/public/utils/matrix.ts b/sdk/communication/communication-identity/test/public/utils/matrix.ts deleted file mode 100644 index 23c8f86591c9..000000000000 --- a/sdk/communication/communication-identity/test/public/utils/matrix.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @internal - * Takes a jagged 2D array and a function and runs the function with every - * possible combination of elements of each of the arrays - * - * For strong type-checking, it is important that the `matrix` have a strong - * type, such as a `const` literal. - * - * @param values - jagged 2D array specifying the arguments and their possible - * values - * @param handler - the function to run with the different argument combinations - * - * @example - * ```typescript - * matrix([ - * [true, false], - * [1, 2, 3] - * ] as const, - * (useLabels: boolean, attempts: number) => { - * // This body will run six times with the following parameters: - * // - true, 1 - * // - true, 2 - * // - true, 3 - * // - false, 1 - * // - false, 2 - * // - false, 3 - * }); - * ``` - */ -export function matrix>( - values: T, - handler: ( - ...args: { [idx in keyof T]: T[idx] extends ReadonlyArray ? U : never } - ) => Promise, -): void { - // Classic recursive approach - if (values.length === 0) { - (handler as () => Promise)(); - } else { - for (const v of values[0]) { - matrix(values.slice(1), (...args) => (handler as any)(v, ...args)); - } - } -} diff --git a/sdk/communication/communication-identity/test/public/utils/mockHttpClients.ts b/sdk/communication/communication-identity/test/public/utils/mockHttpClients.ts index 364ec845b24e..9151a2940d65 100644 --- a/sdk/communication/communication-identity/test/public/utils/mockHttpClients.ts +++ b/sdk/communication/communication-identity/test/public/utils/mockHttpClients.ts @@ -3,7 +3,7 @@ import type { HttpClient, PipelineRequest, PipelineResponse } from "@azure/core-rest-pipeline"; import { createHttpHeaders } from "@azure/core-rest-pipeline"; -import type { CommunicationAccessToken } from "../../../src"; +import type { CommunicationAccessToken } from "../../../src/index.js"; export const createMockHttpClient = >( status: number = 200, diff --git a/sdk/communication/communication-identity/test/public/utils/recordedClient.ts b/sdk/communication/communication-identity/test/public/utils/recordedClient.ts index a42dba769a4a..0c10ec6cbdae 100644 --- a/sdk/communication/communication-identity/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-identity/test/public/utils/recordedClient.ts @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type { Context, Test } from "mocha"; -import type { RecorderStartOptions, SanitizerOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, SanitizerOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { CommunicationIdentityClient } from "../../../src"; +import { CommunicationIdentityClient } from "../../../src/index.js"; import type { TokenCredential } from "@azure/core-auth"; import { createTestCredential } from "@azure-tools/test-credential"; import { parseConnectionString } from "@azure/communication-common"; @@ -63,7 +61,7 @@ const recorderOptions: RecorderStartOptions = { sanitizerOptions: sanitizerOptions, }; -export async function createRecorder(context: Test | undefined): Promise { +export async function createRecorder(context: TestInfo | undefined): Promise { const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { @@ -76,9 +74,9 @@ export async function createRecorder(context: Test | undefined): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); const client = new CommunicationIdentityClient( env.COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING ?? "", @@ -92,9 +90,9 @@ export async function createRecordedCommunicationIdentityClient( } export async function createRecordedCommunicationIdentityClientWithToken( - context: Context, + context: TestInfo, ): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); let credential: TokenCredential; const endpoint = parseConnectionString( diff --git a/sdk/communication/communication-identity/test/public/utils/testCommunicationIdentityClient.ts b/sdk/communication/communication-identity/test/public/utils/testCommunicationIdentityClient.ts index b676a4e94ac1..2a7c5d64269f 100644 --- a/sdk/communication/communication-identity/test/public/utils/testCommunicationIdentityClient.ts +++ b/sdk/communication/communication-identity/test/public/utils/testCommunicationIdentityClient.ts @@ -6,15 +6,15 @@ import type { CommunicationIdentityClientOptions, CommunicationUserToken, TokenScope, -} from "../../../src"; -import { CommunicationIdentityClient } from "../../../src"; +} from "../../../src/index.js"; +import { CommunicationIdentityClient } from "../../../src/index.js"; import { createUserAndTokenHttpClient, createUserHttpClient, getTokenForTeamsUserHttpClient, getTokenHttpClient, revokeTokensHttpClient, -} from "./mockHttpClients"; +} from "./mockHttpClients.js"; import type { CommunicationUserIdentifier } from "@azure/communication-common"; import type { OperationOptions } from "@azure/core-client"; diff --git a/sdk/communication/communication-identity/tsconfig.browser.config.json b/sdk/communication/communication-identity/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-identity/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-identity/tsconfig.json b/sdk/communication/communication-identity/tsconfig.json index d7b0722fc5b6..96edb1c3057b 100644 --- a/sdk/communication/communication-identity/tsconfig.json +++ b/sdk/communication/communication-identity/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure/communication-identity": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-identity/vitest.browser.config.ts b/sdk/communication/communication-identity/vitest.browser.config.ts new file mode 100644 index 000000000000..50ec2d5489b0 --- /dev/null +++ b/sdk/communication/communication-identity/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-identity/vitest.config.ts b/sdk/communication/communication-identity/vitest.config.ts new file mode 100644 index 000000000000..d01fdec8ac69 --- /dev/null +++ b/sdk/communication/communication-identity/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-job-router/.nycrc b/sdk/communication/communication-job-router/.nycrc deleted file mode 100644 index 29174b423579..000000000000 --- a/sdk/communication/communication-job-router/.nycrc +++ /dev/null @@ -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 -} diff --git a/sdk/communication/communication-job-router/api-extractor.json b/sdk/communication/communication-job-router/api-extractor.json index bb2541acad88..36ac0211cff7 100644 --- a/sdk/communication/communication-job-router/api-extractor.json +++ b/sdk/communication/communication-job-router/api-extractor.json @@ -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-job-router.d.ts" + "publicTrimmedFilePath": "dist/communication-job-router.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-job-router/karma.conf.js b/sdk/communication/communication-job-router/karma.conf.js deleted file mode 100644 index 8ec9c23acdcc..000000000000 --- a/sdk/communication/communication-job-router/karma.conf.js +++ /dev/null @@ -1,133 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -require("dotenv").config(); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); - -const { jsonRecordingFilterFunction, isRecordMode } = require("@azure-tools/test-recorder"); - -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", - "karma-json-to-file-reporter", - "karma-json-preprocessor", - ], - - // 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": ["sourcemap", "env"], - "recordings/browsers/**/*.json": ["json"], - // 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: ["TEST_MODE", "COMMUNICATION_CONNECTION_STRING", "RECORDINGS_RELATIVE_PATH"], - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ["mocha", "coverage", "junit", "json-to-file"], - - 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 section of the report - }, - - jsonToFileReporter: { - filter: jsonRecordingFilterFunction, - outputPath: ".", - }, - - // 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, - browserConsoleLogOptions: { - terminal: !isRecordMode(), - }, - - client: { - mocha: { - // change Karma's debug.html to the mocha web reporter - reporter: "html", - timeout: "600000", - }, - }, - }); -}; diff --git a/sdk/communication/communication-job-router/package.json b/sdk/communication/communication-job-router/package.json index b43ba6ca693b..9c619df2b353 100644 --- a/sdk/communication/communication-job-router/package.json +++ b/sdk/communication/communication-job-router/package.json @@ -3,24 +3,24 @@ "version": "1.0.0-beta.2", "description": "Azure client library for Azure Communication Job Router services", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-job-router.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api --verbose", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:autorest": "autorest ./swagger/README.md && rushx format", - "build:browser": "tsc -p . && dev-tool run bundle && dev-tool run vendored cross-env ONLY_BROWSER=true ", - "build:node": "tsc -p . && dev-tool run bundle && dev-tool run vendored cross-env ONLY_NODE=true ", + "build:browser": "dev-tool run build-package && dev-tool run bundle && dev-tool run vendored cross-env ONLY_BROWSER=true ", + "build:node": "dev-tool run build-package && dev-tool run bundle && dev-tool run vendored cross-env ONLY_NODE=true ", "build:samples": "dev-tool samples publish -f", - "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": "dev-tool run vendored rimraf --glob dist dist-* temp types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "extract-api": "tsc -p . && dev-tool run extract-api --verbose", + "extract-api": "dev-tool run build-package && dev-tool run extract-api --verbose", "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": "dev-tool run test:browser", - "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 --browser", + "integration-test:node": "dev-tool run test:vitest", "lint": "eslint package.json api-extractor.json src test", "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]", "pack": "npm pack 2>&1", @@ -28,21 +28,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-cpolicies:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/classificationPolicies.spec.ts'", - "unit-test-dpolicies:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/distributionPolicies.spec.ts'", - "unit-test-epolicies:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/exceptionPolicies.spec.ts'", - "unit-test-jobs:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/jobs.spec.ts'", - "unit-test-queues:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/queues.spec.ts'", - "unit-test-scenarios:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/scenarios/**.spec.ts'", - "unit-test-workers:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/workers.spec.ts'", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-job-router.d.ts", "README.md", "LICENSE" ], @@ -90,36 +81,60 @@ "uuid": "^8.3.0" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/communication-identity": "^1.0.0", "@azure/core-util": "^1.0.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", "@types/uuid": "^8.0.0", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "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-json-preprocessor": "^0.3.3", - "karma-json-to-file-reporter": "^1.0.1", - "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", - "nyc": "^17.0.0", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", + "playwright": "^1.48.2", "typescript": "~5.6.2", - "util": "^0.12.1" + "util": "^0.12.1", + "vitest": "^2.1.4" + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-job-router/samples-dev/ClassificationPolicy_List.ts b/sdk/communication/communication-job-router/samples-dev/ClassificationPolicy_List.ts index f3acbe603260..f8f8332dd18f 100644 --- a/sdk/communication/communication-job-router/samples-dev/ClassificationPolicy_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/ClassificationPolicy_List.ts @@ -11,7 +11,6 @@ import { // Load the .env file (you will need to set these environment variables) import * as dotenv from "dotenv"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/samples-dev/DistributionPolicy_List.ts b/sdk/communication/communication-job-router/samples-dev/DistributionPolicy_List.ts index ff440c0a1f55..619ab249a698 100644 --- a/sdk/communication/communication-job-router/samples-dev/DistributionPolicy_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/DistributionPolicy_List.ts @@ -9,7 +9,6 @@ import { DistributionPolicyItem, JobRouterAdministrationClient, } from "@azure/communication-job-router"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/samples-dev/ExceptionPolicy_List.ts b/sdk/communication/communication-job-router/samples-dev/ExceptionPolicy_List.ts index 6435ffe01707..7ebbd230b8ca 100644 --- a/sdk/communication/communication-job-router/samples-dev/ExceptionPolicy_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/ExceptionPolicy_List.ts @@ -10,7 +10,6 @@ import { ExceptionPolicyItem, JobRouterAdministrationClient, } from "@azure/communication-job-router"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/samples-dev/RouterJob_List.ts b/sdk/communication/communication-job-router/samples-dev/RouterJob_List.ts index 64453efcbe65..f842cd588c31 100644 --- a/sdk/communication/communication-job-router/samples-dev/RouterJob_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/RouterJob_List.ts @@ -7,7 +7,6 @@ import { RouterJobItem, JobRouterClient } from "@azure/communication-job-router" // Load the .env file (you will need to set these environment variables) import * as dotenv from "dotenv"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/samples-dev/RouterQueue_List.ts b/sdk/communication/communication-job-router/samples-dev/RouterQueue_List.ts index 8f5bb684a1aa..460e1c4cc170 100644 --- a/sdk/communication/communication-job-router/samples-dev/RouterQueue_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/RouterQueue_List.ts @@ -7,7 +7,6 @@ import { RouterQueueItem, JobRouterAdministrationClient } from "@azure/communica // Load the .env file (you will need to set these environment variables) import * as dotenv from "dotenv"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/samples-dev/RouterWorker_List.ts b/sdk/communication/communication-job-router/samples-dev/RouterWorker_List.ts index 4556eb81a091..a165875b6721 100644 --- a/sdk/communication/communication-job-router/samples-dev/RouterWorker_List.ts +++ b/sdk/communication/communication-job-router/samples-dev/RouterWorker_List.ts @@ -7,7 +7,6 @@ import { JobRouterClient, RouterWorkerItem } from "@azure/communication-job-rout // Load the .env file (you will need to set these environment variables) import * as dotenv from "dotenv"; -import { assert } from "chai"; dotenv.config(); const connectionString = process.env["COMMUNICATION_CONNECTION_STRING"] || ""; diff --git a/sdk/communication/communication-job-router/src/generated/src/index.ts b/sdk/communication/communication-job-router/src/generated/src/index.ts index 66969a8e7221..55ff0affdee2 100644 --- a/sdk/communication/communication-job-router/src/generated/src/index.ts +++ b/sdk/communication/communication-job-router/src/generated/src/index.ts @@ -7,7 +7,7 @@ */ /// -export { getContinuationToken } from "./pagingHelper"; -export * from "./models"; -export { JobRouterApiClient } from "./jobRouterApiClient"; -export * from "./operationsInterfaces"; +export { getContinuationToken } from "./pagingHelper.js"; +export * from "./models/index.js"; +export { JobRouterApiClient } from "./jobRouterApiClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-job-router/src/generated/src/jobRouterApiClient.ts b/sdk/communication/communication-job-router/src/generated/src/jobRouterApiClient.ts index 22474037868e..31a3e41248d3 100644 --- a/sdk/communication/communication-job-router/src/generated/src/jobRouterApiClient.ts +++ b/sdk/communication/communication-job-router/src/generated/src/jobRouterApiClient.ts @@ -12,9 +12,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { JobRouterAdministrationImpl, JobRouterImpl } from "./operations"; -import { JobRouterAdministration, JobRouter } from "./operationsInterfaces"; -import { JobRouterApiClientOptionalParams } from "./models"; +import { JobRouterAdministrationImpl, JobRouterImpl } from "./operations/index.js"; +import { JobRouterAdministration, JobRouter } from "./operationsInterfaces/index.js"; +import { JobRouterApiClientOptionalParams } from "./models/index.js"; export class JobRouterApiClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-job-router/src/generated/src/models/parameters.ts b/sdk/communication/communication-job-router/src/generated/src/models/parameters.ts index ff90c63678a2..f22ae9d4c4e7 100644 --- a/sdk/communication/communication-job-router/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-job-router/src/generated/src/models/parameters.ts @@ -23,7 +23,7 @@ import { UnassignJobRequest as UnassignJobRequestMapper, DeclineJobOfferRequest as DeclineJobOfferRequestMapper, RouterWorker as RouterWorkerMapper -} from "../models/mappers"; +} from "../models/mappers.js"; export const contentType: OperationParameter = { parameterPath: ["options", "contentType"], diff --git a/sdk/communication/communication-job-router/src/generated/src/operations/index.ts b/sdk/communication/communication-job-router/src/generated/src/operations/index.ts index 86c3dbb3e1bb..d78acdeb910f 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operations/index.ts @@ -6,5 +6,5 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./jobRouterAdministration"; -export * from "./jobRouter"; +export * from "./jobRouterAdministration.js"; +export * from "./jobRouter.js"; diff --git a/sdk/communication/communication-job-router/src/generated/src/operations/jobRouter.ts b/sdk/communication/communication-job-router/src/generated/src/operations/jobRouter.ts index a4786cec7af6..f290cdd09f3a 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operations/jobRouter.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operations/jobRouter.ts @@ -6,14 +6,14 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; +import { tracingClient } from "../tracing.js"; import { PagedAsyncIterableIterator, PageSettings } from "@azure/core-paging"; -import { setContinuationToken } from "../pagingHelper"; -import { JobRouter } from "../operationsInterfaces"; +import { setContinuationToken } from "../pagingHelper.js"; +import { JobRouter } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { JobRouterApiClient } from "../jobRouterApiClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { JobRouterApiClient } from "../jobRouterApiClient.js"; import { RouterJobItem, JobRouterListJobsNextOptionalParams, @@ -55,7 +55,7 @@ import { JobRouterDeleteWorkerOptionalParams, JobRouterListJobsNextResponse, JobRouterListWorkersNextResponse -} from "../models"; +} from "../models/index.js"; /// /** Class containing JobRouter operations. */ diff --git a/sdk/communication/communication-job-router/src/generated/src/operations/jobRouterAdministration.ts b/sdk/communication/communication-job-router/src/generated/src/operations/jobRouterAdministration.ts index 99aa87ef7ed8..3c7c22846a2f 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operations/jobRouterAdministration.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operations/jobRouterAdministration.ts @@ -6,14 +6,14 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; +import { tracingClient } from "../tracing.js"; import { PagedAsyncIterableIterator, PageSettings } from "@azure/core-paging"; -import { setContinuationToken } from "../pagingHelper"; -import { JobRouterAdministration } from "../operationsInterfaces"; +import { setContinuationToken } from "../pagingHelper.js"; +import { JobRouterAdministration } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { JobRouterApiClient } from "../jobRouterApiClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { JobRouterApiClient } from "../jobRouterApiClient.js"; import { ClassificationPolicyItem, JobRouterAdministrationListClassificationPoliciesNextOptionalParams, @@ -59,7 +59,7 @@ import { JobRouterAdministrationListDistributionPoliciesNextResponse, JobRouterAdministrationListExceptionPoliciesNextResponse, JobRouterAdministrationListQueuesNextResponse -} from "../models"; +} from "../models/index.js"; /// /** Class containing JobRouterAdministration operations. */ diff --git a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/index.ts index 86c3dbb3e1bb..d78acdeb910f 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/index.ts @@ -6,5 +6,5 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./jobRouterAdministration"; -export * from "./jobRouter"; +export * from "./jobRouterAdministration.js"; +export * from "./jobRouter.js"; diff --git a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouter.ts b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouter.ts index 28e7cfbc8c54..4c807264c793 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouter.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouter.ts @@ -42,7 +42,7 @@ import { JobRouterGetWorkerOptionalParams, JobRouterGetWorkerResponse, JobRouterDeleteWorkerOptionalParams -} from "../models"; +} from "../models/index.js"; /// /** Interface representing a JobRouter. */ diff --git a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouterAdministration.ts b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouterAdministration.ts index 245644ad3c44..f9bfff9dc761 100644 --- a/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouterAdministration.ts +++ b/sdk/communication/communication-job-router/src/generated/src/operationsInterfaces/jobRouterAdministration.ts @@ -40,7 +40,7 @@ import { JobRouterAdministrationGetQueueOptionalParams, JobRouterAdministrationGetQueueResponse, JobRouterAdministrationDeleteQueueOptionalParams -} from "../models"; +} from "../models/index.js"; /// /** Interface representing a JobRouterAdministration. */ diff --git a/sdk/communication/communication-job-router/src/index.ts b/sdk/communication/communication-job-router/src/index.ts index 6cc78628450b..f59cc68c786d 100644 --- a/sdk/communication/communication-job-router/src/index.ts +++ b/sdk/communication/communication-job-router/src/index.ts @@ -6,9 +6,9 @@ * JavaScript SDK for the Azure Communication Services Job Router Service. */ -export * from "./models"; -export * from "./options"; -export * from "./responses"; -export * from "./clientUtils"; -export * from "./jobRouterClient"; -export * from "./jobRouterAdministrationClient"; +export * from "./models.js"; +export * from "./options.js"; +export * from "./responses.js"; +export * from "./clientUtils.js"; +export * from "./jobRouterClient.js"; +export * from "./jobRouterAdministrationClient.js"; diff --git a/sdk/communication/communication-job-router/src/jobRouterAdministrationClient.ts b/sdk/communication/communication-job-router/src/jobRouterAdministrationClient.ts index ee3dfccaa167..42dd634f0b3b 100644 --- a/sdk/communication/communication-job-router/src/jobRouterAdministrationClient.ts +++ b/sdk/communication/communication-job-router/src/jobRouterAdministrationClient.ts @@ -18,8 +18,8 @@ import type { JobRouterAdministrationListDistributionPoliciesOptionalParams, JobRouterAdministrationListExceptionPoliciesOptionalParams, JobRouterAdministrationListQueuesOptionalParams, -} from "./generated/src"; -import { JobRouterApiClient } from "./generated/src"; +} from "./generated/src/index.js"; +import { JobRouterApiClient } from "./generated/src/index.js"; import type { ClassificationPolicyItem, DistributionPolicyItem, @@ -29,7 +29,7 @@ import type { ExceptionPolicy, RouterQueue, ClassificationPolicy, -} from "./models"; +} from "./models.js"; import type { CreateClassificationPolicyOptions, CreateDistributionPolicyOptions, @@ -44,15 +44,15 @@ import type { UpdateDistributionPolicyOptions, UpdateExceptionPolicyOptions, UpdateQueueOptions, -} from "./options"; +} from "./options.js"; import type { ClassificationPolicyResponse, DistributionPolicyResponse, ExceptionPolicyResponse, RouterQueueResponse, -} from "./responses"; -import { SDK_VERSION } from "./constants"; -import { logger } from "./logger"; +} from "./responses.js"; +import { SDK_VERSION } from "./constants.js"; +import { logger } from "./logger.js"; /** * Checks whether a value is of type {@link JobRouterAdministrationClientOptions}. diff --git a/sdk/communication/communication-job-router/src/jobRouterClient.ts b/sdk/communication/communication-job-router/src/jobRouterClient.ts index 745adf4deb43..17beda30ca7c 100644 --- a/sdk/communication/communication-job-router/src/jobRouterClient.ts +++ b/sdk/communication/communication-job-router/src/jobRouterClient.ts @@ -12,7 +12,7 @@ import { import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import type { OperationOptions } from "@azure/core-client"; import type { InternalPipelineOptions } from "@azure/core-rest-pipeline"; -import { SDK_VERSION } from "./constants"; +import { SDK_VERSION } from "./constants.js"; import type { JobRouterListJobsOptionalParams, JobRouterListWorkersOptionalParams, @@ -22,9 +22,9 @@ import type { RouterJobItem as RouterJobItemGenerated, RouterWorkerItem as RouterWorkerItemGenerated, JobMatchingMode, -} from "./generated/src"; -import { JobRouterApiClient, KnownJobMatchModeType } from "./generated/src"; -import { logger } from "./logger"; +} from "./generated/src/index.js"; +import { JobRouterApiClient, KnownJobMatchModeType } from "./generated/src/index.js"; +import { logger } from "./logger.js"; import type { RouterJobItem, RouterWorkerItem, @@ -33,7 +33,7 @@ import type { RouterWorkerSelector, RouterJobMatchingMode, RouterWorkerState, -} from "./models"; +} from "./models.js"; import type { JobRouterClientOptions, CreateJobOptions, @@ -48,7 +48,7 @@ import type { CreateWorkerOptions, UpdateWorkerOptions, ListWorkersOptions, -} from "./options"; +} from "./options.js"; import type { RouterJobResponse, CancelJobResponse, @@ -59,8 +59,8 @@ import type { AcceptJobOfferResponse, DeclineJobOfferResponse, RouterWorkerResponse, -} from "./responses"; -import { TransformingPagedAsyncIterableIterator } from "./clientUtils"; +} from "./responses.js"; +import { TransformingPagedAsyncIterableIterator } from "./clientUtils.js"; /** * Checks whether a value is of type {@link JobRouterClientOptions}. diff --git a/sdk/communication/communication-job-router/src/models.ts b/sdk/communication/communication-job-router/src/models.ts index 5766a681521b..3c465a8ba924 100644 --- a/sdk/communication/communication-job-router/src/models.ts +++ b/sdk/communication/communication-job-router/src/models.ts @@ -26,7 +26,7 @@ import type { WorkerSelectorAttachment, LongestIdleMode, RoundRobinMode, -} from "./generated/src"; +} from "./generated/src/index.js"; /** Safe type instead of 'any'. */ export type JSONValue = boolean | number | string | JSONArray | JSONObject; @@ -637,4 +637,4 @@ export { RouterWorkerState, RouterJobStatus, LabelOperator, -} from "./generated/src"; +} from "./generated/src/index.js"; diff --git a/sdk/communication/communication-job-router/src/options.ts b/sdk/communication/communication-job-router/src/options.ts index 015a65386691..dc5c64464f3e 100644 --- a/sdk/communication/communication-job-router/src/options.ts +++ b/sdk/communication/communication-job-router/src/options.ts @@ -13,7 +13,7 @@ import type { JobRouterUpsertWorkerOptionalParams, JobRouterUnassignJobActionOptionalParams, ChannelConfiguration, -} from "./generated/src"; +} from "./generated/src/index.js"; import type { CommonClientOptions, OperationOptions } from "@azure/core-client"; import type { JSONObject, @@ -27,7 +27,7 @@ import type { ExceptionRule, RouterJobStatusSelector, RouterWorkerStateSelector, -} from "./models"; +} from "./models.js"; /** * Options to create a job router administration client. @@ -391,4 +391,4 @@ export { JobRouterUpsertWorkerOptionalParams, DeclineJobOfferRequest, UnassignJobRequest, -} from "./generated/src"; +} from "./generated/src/index.js"; diff --git a/sdk/communication/communication-job-router/src/responses.ts b/sdk/communication/communication-job-router/src/responses.ts index e92f71cae659..d14e25cbb002 100644 --- a/sdk/communication/communication-job-router/src/responses.ts +++ b/sdk/communication/communication-job-router/src/responses.ts @@ -9,7 +9,7 @@ import type { RouterJob, RouterWorker, JSONValue, -} from "./models"; +} from "./models.js"; export interface RouterJobResponse extends RouterJob { readonly id: string; @@ -68,4 +68,4 @@ export type DeclineJobOfferResponse = { export { AcceptJobOfferResult as AcceptJobOfferResponse, UnassignJobResult as UnassignJobResponse, -} from "./generated/src"; +} from "./generated/src/index.js"; diff --git a/sdk/communication/communication-job-router/test/internal/jobRouterClient.mocked.spec.ts b/sdk/communication/communication-job-router/test/internal/jobRouterClient.mocked.spec.ts index da9c4621f262..22dd1572a9e3 100644 --- a/sdk/communication/communication-job-router/test/internal/jobRouterClient.mocked.spec.ts +++ b/sdk/communication/communication-job-router/test/internal/jobRouterClient.mocked.spec.ts @@ -1,17 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import sinon from "sinon"; import { AzureCommunicationTokenCredential } from "@azure/communication-common"; -import { JobRouterClient } from "../../src"; -import { baseUri, generateToken } from "../public/utils/connection"; - -describe("[Mocked] JobRouterClient", async function () { - afterEach(function () { - sinon.restore(); - }); +import { JobRouterClient } from "../../src/index.js"; +import { baseUri, generateToken } from "../public/utils/connection.js"; +import { describe, it } from "vitest"; - it("can instantiate", async function () { +describe("[Mocked] JobRouterClient", async () => { + it("can instantiate", async () => { new JobRouterClient(baseUri, new AzureCommunicationTokenCredential(generateToken())); }); }); diff --git a/sdk/communication/communication-job-router/test/internal/utils/mockClient.ts b/sdk/communication/communication-job-router/test/internal/utils/mockClient.ts index c8e78f06357a..3883c72398ee 100644 --- a/sdk/communication/communication-job-router/test/internal/utils/mockClient.ts +++ b/sdk/communication/communication-job-router/test/internal/utils/mockClient.ts @@ -2,15 +2,17 @@ // Licensed under the MIT License. import * as dotenv from "dotenv"; -import type { Recorder } from "@azure-tools/test-recorder"; +import type { Recorder, TestInfo } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import { JobRouterAdministrationClient, JobRouterClient } from "../../../src"; -import type { Context } from "mocha"; -import { isNode } from "@azure/core-util"; -import type { JobRouterAdministrationClientOptions, JobRouterClientOptions } from "../../../src"; -import { createRecorder } from "./recordedClient"; +import { JobRouterAdministrationClient, JobRouterClient } from "../../../src/index.js"; +import { isNodeLike } from "@azure/core-util"; +import type { + JobRouterAdministrationClientOptions, + JobRouterClientOptions, +} from "../../../src/index.js"; +import { createRecorder } from "./recordedClient.js"; -if (isNode) { +if (isNodeLike) { dotenv.config(); } @@ -21,9 +23,9 @@ export interface RecordedRouterClient { } export async function createRecordedRouterClientWithConnectionString( - context: Context, + context: TestInfo, ): Promise { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); return { client: new JobRouterClient( diff --git a/sdk/communication/communication-job-router/test/internal/utils/recordedClient.ts b/sdk/communication/communication-job-router/test/internal/utils/recordedClient.ts index e96d8ba6c3f3..0033ba86d9b7 100644 --- a/sdk/communication/communication-job-router/test/internal/utils/recordedClient.ts +++ b/sdk/communication/communication-job-router/test/internal/utils/recordedClient.ts @@ -2,13 +2,12 @@ // Licensed under the MIT License. import * as dotenv from "dotenv"; -import { isNode } from "@azure/core-util"; -import type { RecorderStartOptions } from "@azure-tools/test-recorder"; +import { isNodeLike } from "@azure/core-util"; +import type { RecorderStartOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder } from "@azure-tools/test-recorder"; -import type { Test } from "mocha"; -import { generateToken } from "../../public/utils/connection"; +import { generateToken } from "../../public/utils/connection.js"; -if (isNode) { +if (isNodeLike) { dotenv.config(); } @@ -28,7 +27,7 @@ export const recorderOptions: RecorderStartOptions = { ], }; -export async function createRecorder(context: Test | undefined): Promise { +export async function createRecorder(context: TestInfo | undefined): Promise { const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("HeaderlessMatcher"); diff --git a/sdk/communication/communication-job-router/test/public/methods/classificationPolicies.spec.ts b/sdk/communication/communication-job-router/test/public/methods/classificationPolicies.spec.ts index 7163573d9a73..1646f04b9023 100644 --- a/sdk/communication/communication-job-router/test/public/methods/classificationPolicies.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/classificationPolicies.spec.ts @@ -2,19 +2,18 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { ClassificationPolicy, JobRouterAdministrationClient } from "../../../src"; +import type { ClassificationPolicy, JobRouterAdministrationClient } from "../../../src/index.js"; import { getClassificationPolicyRequest, getDistributionPolicyRequest, getExceptionPolicyRequest, getQueueRequest, -} from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { timeoutMs } from "../utils/constants"; +} from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -27,10 +26,10 @@ describe("JobRouterClient", function () { const { classificationPolicyId, classificationPolicyRequest } = getClassificationPolicyRequest(testRunId); - describe("Classification Policy Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Classification Policy Operations", () => { + beforeEach(async (ctx) => { ({ administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -44,18 +43,18 @@ describe("JobRouterClient", function () { ); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await administrationClient.deleteClassificationPolicy(classificationPolicyId); await administrationClient.deleteQueue(queueId); await administrationClient.deleteExceptionPolicy(exceptionPolicyId); await administrationClient.deleteDistributionPolicy(distributionPolicyId); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create a classification policy", async function () { + it("should create a classification policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.createClassificationPolicy( classificationPolicyId, classificationPolicyRequest, @@ -64,16 +63,16 @@ describe("JobRouterClient", function () { assert.isDefined(result); assert.isDefined(result.id); assert.equal(result.name, classificationPolicyRequest.name); - }).timeout(timeoutMs); + }); - it("should get a classification policy", async function () { + it("should get a classification policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.getClassificationPolicy(classificationPolicyId); assert.equal(result.id, classificationPolicyId); assert.equal(result.name, classificationPolicyRequest.name); - }).timeout(timeoutMs); + }); - it("should update a classification policy", async function () { + it("should update a classification policy", { timeout: timeoutMs }, async () => { const updatePatch = { ...classificationPolicyRequest, name: "new name" }; const updateResult = await administrationClient.updateClassificationPolicy( classificationPolicyId, @@ -92,9 +91,9 @@ describe("JobRouterClient", function () { assert.isDefined(removeResult.id); assert.equal(updatePatch.name, updateResult.name); assert.isUndefined(removeResult.name); - }).timeout(timeoutMs); + }); - it("should list classification policies", async function () { + it("should list classification policies", async () => { const result: ClassificationPolicy[] = []; for await (const policy of administrationClient.listClassificationPolicies({ maxPageSize: 20, @@ -103,12 +102,12 @@ describe("JobRouterClient", function () { } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should delete a classification policy", async function () { + it("should delete a classification policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.deleteClassificationPolicy(classificationPolicyId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/methods/distributionPolicies.spec.ts b/sdk/communication/communication-job-router/test/public/methods/distributionPolicies.spec.ts index a92555393cda..386a0b38bda0 100644 --- a/sdk/communication/communication-job-router/test/public/methods/distributionPolicies.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/distributionPolicies.spec.ts @@ -2,14 +2,13 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { DistributionPolicy, JobRouterAdministrationClient } from "../../../src"; -import { getDistributionPolicyRequest } from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { timeoutMs } from "../utils/constants"; - -describe("JobRouterClient", function () { +import type { DistributionPolicy, JobRouterAdministrationClient } from "../../../src/index.js"; +import { getDistributionPolicyRequest } from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; + +describe("JobRouterClient", () => { let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -18,19 +17,19 @@ describe("JobRouterClient", function () { const { distributionPolicyId, distributionPolicyRequest } = getDistributionPolicyRequest(testRunId); - describe("Distribution Policy Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Distribution Policy Operations", () => { + beforeEach(async (ctx) => { ({ administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); }); - this.afterEach(async function (this: Context) { - if (!this.currentTest?.isPending() && recorder) { + afterEach(async (ctx) => { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create a distribution policy", async function () { + it("should create a distribution policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.createDistributionPolicy( distributionPolicyId, distributionPolicyRequest, @@ -39,9 +38,9 @@ describe("JobRouterClient", function () { assert.isDefined(result); assert.isDefined(result?.id); assert.equal(result.name, distributionPolicyRequest.name); - }).timeout(timeoutMs); + }); - it("should get a distribution policy", async function () { + it("should get a distribution policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.getDistributionPolicy(distributionPolicyId); assert.equal(result.id, distributionPolicyId); @@ -51,9 +50,9 @@ describe("JobRouterClient", function () { distributionPolicyRequest.offerExpiresAfterSeconds, ); assert.deepEqual(result.mode, distributionPolicyRequest.mode); - }).timeout(timeoutMs); + }); - it("should update a distribution policy", async function () { + it("should update a distribution policy", { timeout: timeoutMs }, async () => { const updatePatch = { ...distributionPolicyRequest, name: "new-name" }; const updateResult = await administrationClient.updateDistributionPolicy( distributionPolicyId, @@ -72,9 +71,9 @@ describe("JobRouterClient", function () { assert.isDefined(removeResult.id); assert.equal(updateResult.name, updatePatch.name); assert.isUndefined(removeResult.name); - }).timeout(timeoutMs); + }); - it("should list distribution policies", async function () { + it("should list distribution policies", { timeout: timeoutMs }, async () => { const result: DistributionPolicy[] = []; for await (const policy of administrationClient.listDistributionPolicies({ maxPageSize: 20, @@ -83,12 +82,12 @@ describe("JobRouterClient", function () { } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should delete a distribution policy", async function () { + it("should delete a distribution policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.deleteDistributionPolicy(distributionPolicyId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/methods/exceptionPolicies.spec.ts b/sdk/communication/communication-job-router/test/public/methods/exceptionPolicies.spec.ts index 974c37de2c41..00cdb14f3ba8 100644 --- a/sdk/communication/communication-job-router/test/public/methods/exceptionPolicies.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/exceptionPolicies.spec.ts @@ -2,14 +2,13 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import type { ExceptionPolicy, JobRouterAdministrationClient } from "../../../src"; -import { assert } from "chai"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import type { Context } from "mocha"; -import { getExceptionPolicyRequest } from "../utils/testData"; -import { timeoutMs } from "../utils/constants"; - -describe("JobRouterClient", function () { +import type { ExceptionPolicy, JobRouterAdministrationClient } from "../../../src/index.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { getExceptionPolicyRequest } from "../utils/testData.js"; +import { timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; + +describe("JobRouterClient", () => { let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -17,19 +16,19 @@ describe("JobRouterClient", function () { const { exceptionPolicyId, exceptionPolicyRequest } = getExceptionPolicyRequest(testRunId); - describe("Exception Policy Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Exception Policy Operations", () => { + beforeEach(async (ctx) => { ({ administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); }); - this.afterEach(async function (this: Context) { - if (!this.currentTest?.isPending() && recorder) { + afterEach(async (ctx) => { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create an exception policy", async function () { + it("should create an exception policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.createExceptionPolicy( exceptionPolicyId, exceptionPolicyRequest, @@ -38,17 +37,17 @@ describe("JobRouterClient", function () { assert.isDefined(result); assert.isDefined(result?.id); assert.equal(result.name, exceptionPolicyRequest.name); - }).timeout(timeoutMs); + }); - it("should get an exception policy", async function () { + it("should get an exception policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.getExceptionPolicy(exceptionPolicyId); assert.equal(result.id, exceptionPolicyId); assert.equal(result.name, exceptionPolicyRequest.name); assert.deepEqual(result.exceptionRules, exceptionPolicyRequest.exceptionRules); - }).timeout(timeoutMs); + }); - it("should update an exception policy", async function () { + it("should update an exception policy", { timeout: timeoutMs }, async () => { const updatePatch = { ...exceptionPolicyRequest, name: "new-name" }; const updateResult = await administrationClient.updateExceptionPolicy( exceptionPolicyId, @@ -67,21 +66,21 @@ describe("JobRouterClient", function () { assert.isDefined(removeResult.id); assert.equal(updateResult.name, updatePatch.name); assert.isUndefined(removeResult.name); - }).timeout(timeoutMs); + }); - it("should list exception policies", async function () { + it("should list exception policies", { timeout: timeoutMs }, async () => { const result: ExceptionPolicy[] = []; for await (const policy of administrationClient.listExceptionPolicies({ maxPageSize: 20 })) { result.push(policy.exceptionPolicy!); } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should delete an exception policy", async function () { + it("should delete an exception policy", { timeout: timeoutMs }, async () => { const result = await administrationClient.deleteExceptionPolicy(exceptionPolicyId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/methods/jobs.spec.ts b/sdk/communication/communication-job-router/test/public/methods/jobs.spec.ts index 37dede44f2d3..4e26dcb51bb0 100644 --- a/sdk/communication/communication-job-router/test/public/methods/jobs.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/jobs.spec.ts @@ -2,27 +2,38 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; import type { CreateJobOptions, JobRouterAdministrationClient, JobRouterClient, RouterJob, UpdateJobOptions, -} from "../../../src"; -import type { Context } from "mocha"; +} from "../../../src/index.js"; import { getClassificationPolicyRequest, getDistributionPolicyRequest, getExceptionPolicyRequest, getJobRequest, getQueueRequest, -} from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { sleep, timeoutMs } from "../utils/constants"; -import { pollForJobQueued, retry } from "../utils/polling"; +} from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { sleep, timeoutMs } from "../utils/constants.js"; +import { pollForJobQueued, retry } from "../utils/polling.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; +import type { RunnerTestSuite, TaskContext } from "vitest"; + +function getFullTitle(ctx: TaskContext): string { + function getTitlePath(suite: RunnerTestSuite | undefined): string[] { + if (suite) { + return [...getTitlePath(suite.suite), suite.name]; + } + return []; + } + + return [...getTitlePath(ctx.task.suite), ctx.task.name].join(" "); +} -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let client: JobRouterClient; let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -47,10 +58,10 @@ describe("JobRouterClient", function () { }; } - describe("Job Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Job Operations", () => { + beforeEach(async (ctx) => { ({ client, administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -64,12 +75,10 @@ describe("JobRouterClient", function () { ); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await retry( async () => { - if ( - this.currentTest?.fullTitle() !== "JobRouterClient Job Operations should delete a job" - ) { + if (getFullTitle(ctx) !== "JobRouterClient Job Operations should delete a job") { const job = await client.getJob(jobId); if (job.status !== "cancelled") { await client.cancelJob(jobId); @@ -85,20 +94,20 @@ describe("JobRouterClient", function () { { retries: 5, retryIntervalMs: 1500 }, ); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create a job", async function () { + it("should create a job", { timeout: timeoutMs }, async () => { const result = await client.createJob(jobId, jobRequest); assert.isDefined(result); assert.isDefined(result.id); assert.equal(result.id, jobId); - }).timeout(timeoutMs); + }); - it("should create a scheduled job", async function () { + it("should create a scheduled job", { timeout: timeoutMs }, async () => { const currentTime: Date = new Date(); currentTime.setSeconds(currentTime.getSeconds() + 30); const scheduledTime: string = recorder.variable("scheduledTime", currentTime.toISOString()); @@ -114,18 +123,18 @@ describe("JobRouterClient", function () { result.matchingMode?.scheduleAndSuspendMode?.scheduleAt?.toISOString(), scheduledTime, ); - }).timeout(timeoutMs); + }); - it("should get a job", async function () { + it("should get a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); const result = await client.getJob(jobId); assert.isDefined(result); assert.isDefined(result.id); assert.equal(result.id, jobId); - }).timeout(timeoutMs); + }); - it("should update a job", async function () { + it("should update a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); await sleep(1500); // This test is flaky @@ -144,9 +153,9 @@ describe("JobRouterClient", function () { assert.equal(updateResult.priority, updatePatch.priority); assert.equal(removeResult.priority, 1); assert.isUndefined(removeResult.dispositionCode); - }).timeout(timeoutMs); + }); - it("should get queue position for a job", async function () { + it("should get queue position for a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); await pollForJobQueued(jobId, client); const result = await client.getJobQueuePosition(jobId); @@ -154,9 +163,9 @@ describe("JobRouterClient", function () { assert.isDefined(result); assert.isDefined(result.position); assert.equal(jobId, result.jobId); - }).timeout(timeoutMs); + }); - it("should reclassify a job", async function () { + it("should reclassify a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); let result; await retry( @@ -167,9 +176,9 @@ describe("JobRouterClient", function () { ); assert.isDefined(result); - }).timeout(timeoutMs); + }); - it("should list jobs", async function () { + it("should list jobs", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); const result: RouterJob[] = []; @@ -178,9 +187,9 @@ describe("JobRouterClient", function () { } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should list scheduled jobs", async function () { + it("should list scheduled jobs", { timeout: timeoutMs }, async () => { const currentTime: Date = new Date(); currentTime.setSeconds(currentTime.getSeconds() + 30); const scheduledTime: string = recorder.variable("scheduledTime", currentTime.toISOString()); @@ -197,9 +206,9 @@ describe("JobRouterClient", function () { } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should cancel a job", async function () { + it("should cancel a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); let result; await retry( @@ -210,15 +219,15 @@ describe("JobRouterClient", function () { ); assert.isDefined(result); - }).timeout(timeoutMs); + }); - it("should delete a job", async function () { + it("should delete a job", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); await sleep(500); // This test is flaky await client.cancelJob(jobId, jobRequest); const result = await client.deleteJob(jobId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/methods/queues.spec.ts b/sdk/communication/communication-job-router/test/public/methods/queues.spec.ts index ad2b79042559..4bc081ddca4d 100644 --- a/sdk/communication/communication-job-router/test/public/methods/queues.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/queues.spec.ts @@ -2,18 +2,17 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { RouterQueue, JobRouterAdministrationClient } from "../../../src"; -import type { Context } from "mocha"; +import type { RouterQueue, JobRouterAdministrationClient } from "../../../src/index.js"; import { getDistributionPolicyRequest, getExceptionPolicyRequest, getQueueRequest, -} from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { timeoutMs } from "../utils/constants"; +} from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -24,10 +23,10 @@ describe("JobRouterClient", function () { const { exceptionPolicyId, exceptionPolicyRequest } = getExceptionPolicyRequest(testRunId); const { queueId, queueRequest } = getQueueRequest(testRunId); - describe("Queue Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Queue Operations", () => { + beforeEach(async (ctx) => { ({ administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -37,32 +36,32 @@ describe("JobRouterClient", function () { await administrationClient.createQueue(queueId, queueRequest); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await administrationClient.deleteQueue(queueId); await administrationClient.deleteExceptionPolicy(exceptionPolicyId); await administrationClient.deleteDistributionPolicy(distributionPolicyId); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create a queue", async function () { + it("should create a queue", { timeout: timeoutMs }, async () => { const result = await administrationClient.createQueue(queueId, queueRequest); assert.isDefined(result); assert.isDefined(result?.id); assert.equal(result.name, queueRequest.name); - }).timeout(timeoutMs); + }); - it("should get a queue", async function () { + it("should get a queue", { timeout: timeoutMs }, async () => { const result = await administrationClient.getQueue(queueId); assert.equal(result.id, queueId); assert.equal(result.name, queueRequest.name); - }).timeout(timeoutMs); + }); - it("should update a queue", async function () { + it("should update a queue", { timeout: timeoutMs }, async () => { const updatePatch = { ...queueRequest, name: "new-name" }; const updateResult = await administrationClient.updateQueue(queueId, updatePatch); @@ -75,21 +74,21 @@ describe("JobRouterClient", function () { assert.isDefined(removeResult.id); assert.equal(updateResult.name, updatePatch.name); assert.isUndefined(removeResult.name); - }).timeout(timeoutMs); + }); - it("should list queues", async function () { + it("should list queues", { timeout: timeoutMs }, async () => { const result: RouterQueue[] = []; for await (const queue of administrationClient.listQueues({ maxPageSize: 20 })) { result.push(queue.queue!); } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should delete a queue", async function () { + it("should delete a queue", { timeout: timeoutMs }, async () => { const result = await administrationClient.deleteQueue(queueId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/methods/workers.spec.ts b/sdk/communication/communication-job-router/test/public/methods/workers.spec.ts index c02825679eaa..ae5870035970 100644 --- a/sdk/communication/communication-job-router/test/public/methods/workers.spec.ts +++ b/sdk/communication/communication-job-router/test/public/methods/workers.spec.ts @@ -2,19 +2,22 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { JobRouterAdministrationClient, JobRouterClient, RouterWorker } from "../../../src"; +import type { + JobRouterAdministrationClient, + JobRouterClient, + RouterWorker, +} from "../../../src/index.js"; import { getDistributionPolicyRequest, getExceptionPolicyRequest, getQueueRequest, getWorkerRequest, -} from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { sleep, timeoutMs } from "../utils/constants"; +} from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { sleep, timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let client: JobRouterClient; let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -28,10 +31,10 @@ describe("JobRouterClient", function () { const { workerId, workerRequest } = getWorkerRequest(testRunId); // Order matters (registration idempotency) - describe("Worker Operations", function () { - this.beforeEach(async function (this: Context) { + describe("Worker Operations", () => { + beforeEach(async (ctx) => { ({ client, administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -42,34 +45,34 @@ describe("JobRouterClient", function () { await client.createWorker(workerId, workerRequest); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await client.deleteWorker(workerId); await administrationClient.deleteQueue(queueId); await administrationClient.deleteExceptionPolicy(exceptionPolicyId); await administrationClient.deleteDistributionPolicy(distributionPolicyId); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should create a worker", async function () { + it("should create a worker", { timeout: timeoutMs }, async () => { const result = await client.createWorker(workerId, workerRequest); assert.isDefined(result); assert.isDefined(result.id); assert.equal(result.totalCapacity, workerRequest.totalCapacity); - }).timeout(timeoutMs); + }); - it("should get a worker", async function () { + it("should get a worker", { timeout: timeoutMs }, async () => { const result = await client.getWorker(workerId); assert.equal(result.id, workerId); assert.equal(result.totalCapacity, workerRequest.totalCapacity); assert.deepEqual(result.channelConfigurations, workerRequest.channelConfigurations); - }).timeout(timeoutMs); + }); - it("should update a worker", async function () { + it("should update a worker", { timeout: timeoutMs }, async () => { const updatePatch = { ...workerRequest, totalCapacity: 100, @@ -87,9 +90,9 @@ describe("JobRouterClient", function () { assert.isDefined(removeResult?.id); assert.equal(updateResult.totalCapacity, updatePatch.totalCapacity); assert.isEmpty(removeResult.tags); - }).timeout(timeoutMs); + }); - it("should register and deregister a worker", async function () { + it("should register and deregister a worker", { timeout: timeoutMs }, async () => { const registerResult = await client.updateWorker(workerId, { ...workerRequest, availableForOffers: true, @@ -107,21 +110,21 @@ describe("JobRouterClient", function () { assert.isDefined(deregisterResult); assert.isDefined(deregisterResult?.id); assert.equal(deregisterResult.availableForOffers, false); - }).timeout(timeoutMs); + }); - it("should list workers", async function () { + it("should list workers", { timeout: timeoutMs }, async () => { const result: RouterWorker[] = []; for await (const worker of client.listWorkers({ maxPageSize: 20 })) { result.push(worker.worker!); } assert.isNotEmpty(result); - }).timeout(timeoutMs); + }); - it("should delete a worker", async function () { + it("should delete a worker", { timeout: timeoutMs }, async () => { const result = await client.deleteWorker(workerId); assert.isDefined(result); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/scenarios/assignmentScenario.spec.ts b/sdk/communication/communication-job-router/test/public/scenarios/assignmentScenario.spec.ts index 0b4857655156..e2ffde43b6b7 100644 --- a/sdk/communication/communication-job-router/test/public/scenarios/assignmentScenario.spec.ts +++ b/sdk/communication/communication-job-router/test/public/scenarios/assignmentScenario.spec.ts @@ -8,21 +8,20 @@ import { getJobRequest, getQueueRequest, getWorkerRequest, -} from "../utils/testData"; -import { assert } from "chai"; +} from "../utils/testData.js"; import type { RouterJobAssignment, RouterJobOffer, JobRouterAdministrationClient, JobRouterClient, -} from "../../../src"; -import type { Context } from "mocha"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { timeoutMs } from "../utils/constants"; +} from "../../../src/index.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { timeoutMs } from "../utils/constants.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import { pollForJobAssignment, pollForJobOffer } from "../utils/polling"; +import { pollForJobAssignment, pollForJobOffer } from "../utils/polling.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let client: JobRouterClient; let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -38,10 +37,10 @@ describe("JobRouterClient", function () { const { jobId, jobRequest } = getJobRequest(testRunId); const { workerId, workerRequest } = getWorkerRequest(testRunId); - describe("Assignment Scenario", function () { - this.beforeEach(async function (this: Context) { + describe("Assignment Scenario", () => { + beforeEach(async (ctx) => { ({ client, administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createExceptionPolicy(exceptionPolicyId, exceptionPolicyRequest); await administrationClient.createDistributionPolicy( @@ -56,7 +55,7 @@ describe("JobRouterClient", function () { await client.createWorker(workerId, { ...workerRequest, availableForOffers: true }); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await client.deleteWorker(workerId); await client.deleteJob(jobId); await administrationClient.deleteClassificationPolicy(classificationPolicyId); @@ -64,12 +63,12 @@ describe("JobRouterClient", function () { await administrationClient.deleteDistributionPolicy(distributionPolicyId); await administrationClient.deleteExceptionPolicy(exceptionPolicyId); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should complete assignment scenario", async () => { + it("should complete assignment scenario", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); const offer: RouterJobOffer = await pollForJobOffer(workerId, client); @@ -93,6 +92,6 @@ describe("JobRouterClient", function () { const closeJobResponse = await client.closeJob(jobId, acceptOfferResponse.assignmentId); assert.isNotNull(closeJobResponse); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/scenarios/cancellationScenario.spec.ts b/sdk/communication/communication-job-router/test/public/scenarios/cancellationScenario.spec.ts index 37f6f83fa8d5..0c8698f18757 100644 --- a/sdk/communication/communication-job-router/test/public/scenarios/cancellationScenario.spec.ts +++ b/sdk/communication/communication-job-router/test/public/scenarios/cancellationScenario.spec.ts @@ -7,16 +7,15 @@ import { getExceptionPolicyRequest, getJobRequest, getQueueRequest, -} from "../utils/testData"; -import { assert } from "chai"; -import type { Context } from "mocha"; +} from "../utils/testData.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import type { JobRouterAdministrationClient, JobRouterClient } from "../../../src"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { pollForJobCancelled, pollForJobQueued } from "../utils/polling"; -import { timeoutMs } from "../utils/constants"; +import type { JobRouterAdministrationClient, JobRouterClient } from "../../../src/index.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { pollForJobCancelled, pollForJobQueued } from "../utils/polling.js"; +import { timeoutMs } from "../utils/constants.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let client: JobRouterClient; let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -32,10 +31,10 @@ describe("JobRouterClient", function () { const { jobId, jobRequest } = getJobRequest(testRunId); const dispositionCode = `disposition-${testRunId}`; - describe("Cancellation Scenario", function () { - this.beforeEach(async function (this: Context) { + describe("Cancellation Scenario", () => { + beforeEach(async (ctx) => { ({ client, administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -49,19 +48,19 @@ describe("JobRouterClient", function () { ); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await client.deleteJob(jobId); await administrationClient.deleteClassificationPolicy(classificationPolicyId); await administrationClient.deleteQueue(queueId); await administrationClient.deleteExceptionPolicy(exceptionPolicyId); await administrationClient.deleteDistributionPolicy(distributionPolicyId); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should complete cancellation scenario", async () => { + it("should complete cancellation scenario", { timeout: timeoutMs }, async () => { await client.createJob(jobId, jobRequest); await pollForJobQueued(jobId, client); @@ -70,6 +69,6 @@ describe("JobRouterClient", function () { assert.equal(result.status, "cancelled"); assert.equal(result.dispositionCode, dispositionCode); - }).timeout(timeoutMs); + }); }); }); diff --git a/sdk/communication/communication-job-router/test/public/scenarios/queueingScenario.spec.ts b/sdk/communication/communication-job-router/test/public/scenarios/queueingScenario.spec.ts index 49bfb5a77c90..971ac6fb966f 100644 --- a/sdk/communication/communication-job-router/test/public/scenarios/queueingScenario.spec.ts +++ b/sdk/communication/communication-job-router/test/public/scenarios/queueingScenario.spec.ts @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import type { JobRouterAdministrationClient, JobRouterClient } from "../../../src"; -import type { Context } from "mocha"; +import type { JobRouterAdministrationClient, JobRouterClient } from "../../../src/index.js"; import { getClassificationPolicyCombined, getClassificationPolicyConditional, @@ -19,13 +16,14 @@ import { getQueueEnglish, getQueueFrench, getQueueRequest, -} from "../utils/testData"; -import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient"; -import { timeoutMs } from "../utils/constants"; +} from "../utils/testData.js"; +import { createRecordedRouterClientWithConnectionString } from "../../internal/utils/mockClient.js"; +import { timeoutMs } from "../utils/constants.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import { pollForJobQueued, retry } from "../utils/polling"; +import { pollForJobQueued, retry } from "../utils/polling.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe("JobRouterClient", function () { +describe("JobRouterClient", () => { let client: JobRouterClient; let administrationClient: JobRouterAdministrationClient; let recorder: Recorder; @@ -46,10 +44,10 @@ describe("JobRouterClient", function () { return id; } - describe("Queueing Scenario", function () { - this.beforeEach(async function (this: Context) { + describe("Queueing Scenario", () => { + beforeEach(async (ctx) => { ({ client, administrationClient, recorder } = - await createRecordedRouterClientWithConnectionString(this)); + await createRecordedRouterClientWithConnectionString(ctx)); await administrationClient.createDistributionPolicy( distributionPolicyId, @@ -59,7 +57,7 @@ describe("JobRouterClient", function () { await administrationClient.createQueue(queueId, queueRequest); }); - this.afterEach(async function (this: Context) { + afterEach(async (ctx) => { await retry( async () => { await administrationClient.deleteQueue(queueId); @@ -69,86 +67,102 @@ describe("JobRouterClient", function () { { retries: 1, retryIntervalMs: 500 }, ); - if (!this.currentTest?.isPending() && recorder) { + if (!ctx.task.pending && recorder) { await recorder.stop(); } }); - it("should complete queueing scenario with fallback queue", async () => { - const policy = getClassificationPolicyFallback(testRunId); - const { id, options } = getJobFallback(testRunId); - - await administrationClient.createClassificationPolicy(policy.id!, policy); - await client.createJob(id, options); - const queuedJob = await pollForJobQueued(id, client); - - assert.equal(queuedJob.status, "queued"); - assert.equal(queuedJob.queueId, queueRequest.id); - - await client.cancelJob(id); - await client.deleteJob(id); - await administrationClient.deleteClassificationPolicy(policy.id!); - }).timeout(timeoutMs); - - it("should complete queueing scenario with conditional selector", async () => { - const policy = getClassificationPolicyConditional(testRunId); - const { id, options } = getJobConditional(testRunId); - - await administrationClient.createClassificationPolicy(policy.id!, policy); - await client.createJob(id, options); - const queuedJob = await pollForJobQueued(id, client); - - assert.equal(queuedJob.status, "queued"); - assert.equal(queuedJob.queueId, queueId); - - await client.cancelJob(id); - await client.deleteJob(id); - await administrationClient.deleteClassificationPolicy(policy.id!); - }).timeout(timeoutMs); - - it("should complete queueing scenario with passthrough selectors", async () => { - const policy = getClassificationPolicyPassthrough(testRunId); - const { id, options } = getJobPassthrough(testRunId); - - await administrationClient.createClassificationPolicy(policy.id!, policy); - await client.createJob(id, options); - const queuedJob = await pollForJobQueued(id, client); - - assert.equal(queuedJob.status, "queued"); - assert.equal(queuedJob.queueId, queueId); - - await client.cancelJob(id); - await client.deleteJob(id); - await administrationClient.deleteClassificationPolicy(policy.id!); - }).timeout(timeoutMs); - - it("should complete queueing scenario with combined selectors", async () => { - const policy = getClassificationPolicyCombined(testRunId); - const jobEnglish = getJobEnglish(testRunId); - const jobFrench = getJobFrench(testRunId); - const queueEnglish = getQueueEnglish(testRunId); - const queueFrench = getQueueFrench(testRunId); - - await administrationClient.createClassificationPolicy(policy.id!, policy); - await administrationClient.createQueue(queueEnglish.id!, queueEnglish); - await administrationClient.createQueue(queueFrench.id!, queueFrench); - await client.createJob(jobEnglish.id!, jobEnglish.options); - await client.createJob(jobFrench.id!, jobFrench.options); - const queuedJobEnglish = await pollForJobQueued(jobEnglish.id!, client); - const queuedJobFrench = await pollForJobQueued(jobFrench.id!, client); - - assert.equal(queuedJobEnglish.status, "queued"); - assert.equal(queuedJobFrench.status, "queued"); - assert.equal(queueIdFixup(queuedJobEnglish.queueId), queueEnglish.id!); - assert.equal(queueIdFixup(queuedJobFrench.queueId), queueFrench.id!); - - await client.cancelJob(jobEnglish.id!); - await client.cancelJob(jobFrench.id!); - await client.deleteJob(jobEnglish.id!); - await client.deleteJob(jobFrench.id!); - await administrationClient.deleteClassificationPolicy(policy.id!); - await administrationClient.deleteQueue(queueEnglish.id!); - await administrationClient.deleteQueue(queueFrench.id!); - }).timeout(timeoutMs); + it( + "should complete queueing scenario with fallback queue", + { timeout: timeoutMs }, + async () => { + const policy = getClassificationPolicyFallback(testRunId); + const { id, options } = getJobFallback(testRunId); + + await administrationClient.createClassificationPolicy(policy.id!, policy); + await client.createJob(id, options); + const queuedJob = await pollForJobQueued(id, client); + + assert.equal(queuedJob.status, "queued"); + assert.equal(queuedJob.queueId, queueRequest.id); + + await client.cancelJob(id); + await client.deleteJob(id); + await administrationClient.deleteClassificationPolicy(policy.id!); + }, + ); + + it( + "should complete queueing scenario with conditional selector", + { timeout: timeoutMs }, + async () => { + const policy = getClassificationPolicyConditional(testRunId); + const { id, options } = getJobConditional(testRunId); + + await administrationClient.createClassificationPolicy(policy.id!, policy); + await client.createJob(id, options); + const queuedJob = await pollForJobQueued(id, client); + + assert.equal(queuedJob.status, "queued"); + assert.equal(queuedJob.queueId, queueId); + + await client.cancelJob(id); + await client.deleteJob(id); + await administrationClient.deleteClassificationPolicy(policy.id!); + }, + ); + + it( + "should complete queueing scenario with passthrough selectors", + { timeout: timeoutMs }, + async () => { + const policy = getClassificationPolicyPassthrough(testRunId); + const { id, options } = getJobPassthrough(testRunId); + + await administrationClient.createClassificationPolicy(policy.id!, policy); + await client.createJob(id, options); + const queuedJob = await pollForJobQueued(id, client); + + assert.equal(queuedJob.status, "queued"); + assert.equal(queuedJob.queueId, queueId); + + await client.cancelJob(id); + await client.deleteJob(id); + await administrationClient.deleteClassificationPolicy(policy.id!); + }, + ); + + it( + "should complete queueing scenario with combined selectors", + { timeout: timeoutMs }, + async () => { + const policy = getClassificationPolicyCombined(testRunId); + const jobEnglish = getJobEnglish(testRunId); + const jobFrench = getJobFrench(testRunId); + const queueEnglish = getQueueEnglish(testRunId); + const queueFrench = getQueueFrench(testRunId); + + await administrationClient.createClassificationPolicy(policy.id!, policy); + await administrationClient.createQueue(queueEnglish.id!, queueEnglish); + await administrationClient.createQueue(queueFrench.id!, queueFrench); + await client.createJob(jobEnglish.id!, jobEnglish.options); + await client.createJob(jobFrench.id!, jobFrench.options); + const queuedJobEnglish = await pollForJobQueued(jobEnglish.id!, client); + const queuedJobFrench = await pollForJobQueued(jobFrench.id!, client); + + assert.equal(queuedJobEnglish.status, "queued"); + assert.equal(queuedJobFrench.status, "queued"); + assert.equal(queueIdFixup(queuedJobEnglish.queueId), queueEnglish.id!); + assert.equal(queueIdFixup(queuedJobFrench.queueId), queueFrench.id!); + + await client.cancelJob(jobEnglish.id!); + await client.cancelJob(jobFrench.id!); + await client.deleteJob(jobEnglish.id!); + await client.deleteJob(jobFrench.id!); + await administrationClient.deleteClassificationPolicy(policy.id!); + await administrationClient.deleteQueue(queueEnglish.id!); + await administrationClient.deleteQueue(queueFrench.id!); + }, + ); }); }); diff --git a/sdk/communication/communication-job-router/test/public/utils/connection.ts b/sdk/communication/communication-job-router/test/public/utils/connection.ts index 50c6b8245229..339bb57667cf 100644 --- a/sdk/communication/communication-job-router/test/public/utils/connection.ts +++ b/sdk/communication/communication-job-router/test/public/utils/connection.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { isNode } from "@azure/core-util"; +import { isNodeLike } from "@azure/core-util"; export const baseUri = "https://contoso.api.fake"; @@ -11,6 +11,6 @@ export const generateToken = (): string => { const validForMinutes = 60; 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`; }; diff --git a/sdk/communication/communication-job-router/test/public/utils/constants.ts b/sdk/communication/communication-job-router/test/public/utils/constants.ts index 40cef1b6a4a5..2bdc6149047d 100644 --- a/sdk/communication/communication-job-router/test/public/utils/constants.ts +++ b/sdk/communication/communication-job-router/test/public/utils/constants.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { v4 as uuid } from "uuid"; + +import { randomUUID } from "@azure/core-util"; import { env } from "@azure-tools/test-recorder"; // HACK: Intentionally block to: @@ -12,5 +13,5 @@ export function sleep(ms: number): Promise { export const timeoutMs: number = 15000; export const getTestRunId = (staticId: string): string => { - return ["record", "playback", "undefined"].includes(env.TEST_MODE!) ? staticId : uuid(); + return ["record", "playback", "undefined"].includes(env.TEST_MODE!) ? staticId : randomUUID(); }; diff --git a/sdk/communication/communication-job-router/test/public/utils/polling.ts b/sdk/communication/communication-job-router/test/public/utils/polling.ts index d76aa980dde3..b3c965f8c1ca 100644 --- a/sdk/communication/communication-job-router/test/public/utils/polling.ts +++ b/sdk/communication/communication-job-router/test/public/utils/polling.ts @@ -1,8 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { JobRouterClient } from "../../../src/jobRouterClient"; -import type { RouterJob, RouterWorker, RouterJobAssignment, RouterJobOffer } from "../../../src"; +import type { JobRouterClient } from "../../../src/jobRouterClient.js"; +import type { + RouterJob, + RouterWorker, + RouterJobAssignment, + RouterJobOffer, +} from "../../../src/index.js"; export async function pollForJobOffer( workerId: string, @@ -62,7 +67,7 @@ export const retry = async ( fn: () => Promise | T, { retries, retryIntervalMs }: { retries: number; retryIntervalMs: number }, ): Promise => { - const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)); + const sleep = (ms = 0): Promise => new Promise((resolve) => setTimeout(resolve, ms)); try { return await fn(); } catch (error) { diff --git a/sdk/communication/communication-job-router/test/public/utils/testData.ts b/sdk/communication/communication-job-router/test/public/utils/testData.ts index ea5c0adead8d..1e617cfc925c 100644 --- a/sdk/communication/communication-job-router/test/public/utils/testData.ts +++ b/sdk/communication/communication-job-router/test/public/utils/testData.ts @@ -15,7 +15,7 @@ import type { StaticQueueSelectorAttachment, CreateJobOptions, CreateClassificationPolicyOptions, -} from "../../../src"; +} from "../../../src/index.js"; const queueId = "test-queue"; const exceptionPolicyId = "test-e-policy"; diff --git a/sdk/communication/communication-job-router/tsconfig.browser.config.json b/sdk/communication/communication-job-router/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-job-router/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-job-router/tsconfig.json b/sdk/communication/communication-job-router/tsconfig.json index a984a56991bd..a72edad84e96 100644 --- a/sdk/communication/communication-job-router/tsconfig.json +++ b/sdk/communication/communication-job-router/tsconfig.json @@ -1,12 +1,13 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure/communication-job-router": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, "exclude": ["node_modules", "types", "temp", "browser", "dist", "dist-esm", "./samples/**/*.ts"], - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-job-router/vitest.browser.config.ts b/sdk/communication/communication-job-router/vitest.browser.config.ts new file mode 100644 index 000000000000..50ec2d5489b0 --- /dev/null +++ b/sdk/communication/communication-job-router/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-job-router/vitest.config.ts b/sdk/communication/communication-job-router/vitest.config.ts new file mode 100644 index 000000000000..1d8394b6b104 --- /dev/null +++ b/sdk/communication/communication-job-router/vitest.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.shared.config.js"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["test/**/*.spec.ts"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-phone-numbers/.nycrc b/sdk/communication/communication-phone-numbers/.nycrc deleted file mode 100644 index 29174b423579..000000000000 --- a/sdk/communication/communication-phone-numbers/.nycrc +++ /dev/null @@ -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 -} diff --git a/sdk/communication/communication-phone-numbers/api-extractor.json b/sdk/communication/communication-phone-numbers/api-extractor.json index ee5c77bf833e..d0374cb92128 100644 --- a/sdk/communication/communication-phone-numbers/api-extractor.json +++ b/sdk/communication/communication-phone-numbers/api-extractor.json @@ -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-phone-numbers.d.ts" + "publicTrimmedFilePath": "dist/communication-phone-numbers.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-phone-numbers/karma.conf.js b/sdk/communication/communication-phone-numbers/karma.conf.js deleted file mode 100644 index 8ca91fd02cfd..000000000000 --- a/sdk/communication/communication-phone-numbers/karma.conf.js +++ /dev/null @@ -1,142 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); - -// Get all variables containing the available phone numbers per test agent. -// E.g. -> AZURE_PHONE_NUMBER_windows_2019_node12 -const getPhoneNumberPoolEnvVars = () => { - return Object.keys(process.env).filter((key) => key.startsWith("AZURE_PHONE_NUMBER_")); -}; - -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": ["sourcemap", "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: [ - "TEST_MODE", - "COMMUNICATION_LIVETEST_STATIC_CONNECTION_STRING", - "COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING", - "INCLUDE_PHONENUMBER_LIVE_TESTS", - "AZURE_PHONE_NUMBER", - "COMMUNICATION_ENDPOINT", - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS", - "SKIP_UPDATE_CAPABILITIES_LIVE_TESTS", - "AZURE_TEST_AGENT", - "AZURE_USERAGENT_OVERRIDE", - "RECORDINGS_RELATIVE_PATH", - "AZURE_TEST_DOMAIN", - ...getPhoneNumberPoolEnvVars(), - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-phone-numbers/package.json b/sdk/communication/communication-phone-numbers/package.json index 223f5659d522..17ba9d54bb04 100644 --- a/sdk/communication/communication-phone-numbers/package.json +++ b/sdk/communication/communication-phone-numbers/package.json @@ -3,24 +3,24 @@ "version": "1.3.0-beta.4", "description": "SDK for Azure Communication service which facilitates phone number management.", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-phone-numbers.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:clean": "rush update --recheck && rush rebuild && dev-tool run build", "build:samples": "echo Obsolete.", - "build:test": "tsc -p . && dev-tool run bundle", + "build:test": "dev-tool run build-package && dev-tool run bundle", "bundle": "dev-tool run bundle", "check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* temp types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "generate:client": "autorest --typescript ./swagger/README.md && rushx format", "integration-test": "npm run integration-test:node && npm run integration-test:browser", - "integration-test:browser": "dev-tool run test:browser", - "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 --browser", + "integration-test:node": "dev-tool run test:vitest", "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", @@ -29,14 +29,12 @@ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node", "test:watch": "npm run test -- --watch --reporter min", "unit-test": "npm run unit-test:node && npm run unit-test:browser", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-phone-numbers.d.ts", "README.md", "LICENSE" ], @@ -59,7 +57,7 @@ "prettier": "@azure/eslint-plugin-azure-sdk/prettier.json", "dependencies": { "@azure/abort-controller": "^2.0.0", - "@azure/communication-common": "^2.2.0", + "@azure/communication-common": "^2.3.1", "@azure/core-auth": "^1.3.0", "@azure/core-client": "^1.5.0", "@azure/core-lro": "^2.2.4", @@ -72,34 +70,20 @@ "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-credential": "^1.0.0", - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-credential": "^2.0.0", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/identity": "^4.0.1", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "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", - "nyc": "^17.0.0", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.4" }, "//metadata": { "constantPaths": [ @@ -143,5 +127,43 @@ "releasePhoneNumber.js", "manageSipRoutingConfiguration.js" ] + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/index.ts index 3b1a46da08d4..97becdbb1bcd 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/index.ts @@ -7,7 +7,7 @@ */ /// -export { getContinuationToken } from "./pagingHelper"; -export * from "./models"; -export { PhoneNumbersClient } from "./phoneNumbersClient"; -export * from "./operationsInterfaces"; +export { getContinuationToken } from "./pagingHelper.js"; +export * from "./models/index.js"; +export { PhoneNumbersClient } from "./phoneNumbersClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/models/parameters.ts b/sdk/communication/communication-phone-numbers/src/generated/src/models/parameters.ts index b97bdd9a9e7e..cd2fbc1b109b 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/models/parameters.ts @@ -16,7 +16,7 @@ import { PhoneNumberPurchaseRequest as PhoneNumberPurchaseRequestMapper, PhoneNumberCapabilitiesRequest as PhoneNumberCapabilitiesRequestMapper, OperatorInformationRequest as OperatorInformationRequestMapper, -} from "../models/mappers"; +} from "../models/mappers.js"; export const accept: OperationParameter = { parameterPath: "accept", diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/operations/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/operations/index.ts index 4800e06075d8..8bb0c86962d1 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./phoneNumbers"; +export * from "./phoneNumbers.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/operations/phoneNumbers.ts b/sdk/communication/communication-phone-numbers/src/generated/src/operations/phoneNumbers.ts index d820bf4838dd..e81a477ccff7 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/operations/phoneNumbers.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/operations/phoneNumbers.ts @@ -6,16 +6,16 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; +import { tracingClient } from "../tracing.js"; import { PagedAsyncIterableIterator, PageSettings } from "@azure/core-paging"; -import { setContinuationToken } from "../pagingHelper"; -import { PhoneNumbers } from "../operationsInterfaces"; +import { setContinuationToken } from "../pagingHelper.js"; +import { PhoneNumbers } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { PhoneNumbersClient } from "../phoneNumbersClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { PhoneNumbersClient } from "../phoneNumbersClient.js"; import { PollerLike, PollOperationState, LroEngine } from "@azure/core-lro"; -import { createLroSpec } from "../lroImpl"; +import { createLroSpec } from "../lroImpl.js"; import { PhoneNumberAreaCode, PhoneNumbersListAreaCodesNextOptionalParams, @@ -62,7 +62,7 @@ import { PhoneNumbersListAvailableLocalitiesNextResponse, PhoneNumbersListOfferingsNextResponse, PhoneNumbersListPhoneNumbersNextResponse, -} from "../models"; +} from "../models/index.js"; /// /** Class containing PhoneNumbers operations. */ diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/index.ts index 4800e06075d8..8bb0c86962d1 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./phoneNumbers"; +export * from "./phoneNumbers.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/phoneNumbers.ts b/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/phoneNumbers.ts index 37375d736b80..6a1178d37982 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/phoneNumbers.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/operationsInterfaces/phoneNumbers.ts @@ -39,7 +39,7 @@ import { PhoneNumbersReleasePhoneNumberResponse, PhoneNumbersOperatorInformationSearchOptionalParams, PhoneNumbersOperatorInformationSearchResponse, -} from "../models"; +} from "../models/index.js"; /// /** Interface representing a PhoneNumbers. */ diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/phoneNumbersClient.ts b/sdk/communication/communication-phone-numbers/src/generated/src/phoneNumbersClient.ts index 313ce282de29..345ae7d4a217 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/phoneNumbersClient.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/phoneNumbersClient.ts @@ -12,9 +12,9 @@ import { PipelineResponse, SendRequest, } from "@azure/core-rest-pipeline"; -import { PhoneNumbersImpl } from "./operations"; -import { PhoneNumbers } from "./operationsInterfaces"; -import { PhoneNumbersClientOptionalParams } from "./models"; +import { PhoneNumbersImpl } from "./operations/index.js"; +import { PhoneNumbers } from "./operationsInterfaces/index.js"; +import { PhoneNumbersClientOptionalParams } from "./models/index.js"; export class PhoneNumbersClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/index.ts index 42dfdc29ee5d..8d38655408ea 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/index.ts @@ -6,7 +6,7 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./models"; -export { SipRoutingClient } from "./sipRoutingClient"; -export { SipRoutingClientContext } from "./sipRoutingClientContext"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { SipRoutingClient } from "./sipRoutingClient.js"; +export { SipRoutingClientContext } from "./sipRoutingClientContext.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/models/parameters.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/models/parameters.ts index 8478d5125c17..cc72b87f188a 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/models/parameters.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/models/parameters.ts @@ -11,7 +11,7 @@ import { OperationURLParameter, OperationQueryParameter } from "@azure/core-client"; -import { SipConfigurationUpdate as SipConfigurationUpdateMapper } from "../models/mappers"; +import { SipConfigurationUpdate as SipConfigurationUpdateMapper } from "../models/mappers.js"; export const accept: OperationParameter = { parameterPath: "accept", diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/index.ts index ebbf5b82c61e..92cbf9d99e2e 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./sipRouting"; +export * from "./sipRouting.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/sipRouting.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/sipRouting.ts index f25fb1e85a38..d366afa6b1b6 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/sipRouting.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operations/sipRouting.ts @@ -6,17 +6,17 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { SipRouting } from "../operationsInterfaces"; +import { SipRouting } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { SipRoutingClientContext } from "../sipRoutingClientContext"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { SipRoutingClientContext } from "../sipRoutingClientContext.js"; import { SipRoutingGetOptionalParams, SipRoutingGetResponse, SipRoutingUpdateOptionalParams, SipRoutingUpdateResponse -} from "../models"; +} from "../models/index.js"; /** Class containing SipRouting operations. */ export class SipRoutingImpl implements SipRouting { diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/index.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/index.ts index ebbf5b82c61e..92cbf9d99e2e 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/index.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./sipRouting"; +export * from "./sipRouting.js"; diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/sipRouting.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/sipRouting.ts index 4839116edfee..af6d1fc1703b 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/sipRouting.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/operationsInterfaces/sipRouting.ts @@ -11,7 +11,7 @@ import { SipRoutingGetResponse, SipRoutingUpdateOptionalParams, SipRoutingUpdateResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a SipRouting. */ export interface SipRouting { diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClient.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClient.ts index 2d50fe11faad..3dc88ef6c143 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClient.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClient.ts @@ -6,10 +6,10 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { SipRoutingImpl } from "./operations"; -import { SipRouting } from "./operationsInterfaces"; -import { SipRoutingClientContext } from "./sipRoutingClientContext"; -import { SipRoutingClientOptionalParams } from "./models"; +import { SipRoutingImpl } from "./operations/index.js"; +import { SipRouting } from "./operationsInterfaces/index.js"; +import { SipRoutingClientContext } from "./sipRoutingClientContext.js"; +import { SipRoutingClientOptionalParams } from "./models/index.js"; export class SipRoutingClient extends SipRoutingClientContext { /** diff --git a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClientContext.ts b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClientContext.ts index 9b0194a3ff17..fa3281dfbc1f 100644 --- a/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClientContext.ts +++ b/sdk/communication/communication-phone-numbers/src/generated/src/siprouting/sipRoutingClientContext.ts @@ -7,7 +7,7 @@ */ import * as coreClient from "@azure/core-client"; -import { SipRoutingClientOptionalParams } from "./models"; +import { SipRoutingClientOptionalParams } from "./models/index.js"; export class SipRoutingClientContext extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-phone-numbers/src/index.ts b/sdk/communication/communication-phone-numbers/src/index.ts index 9f5da4655d92..126dba94c757 100644 --- a/sdk/communication/communication-phone-numbers/src/index.ts +++ b/sdk/communication/communication-phone-numbers/src/index.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./models"; -export * from "./phoneNumbersClient"; -export * from "./lroModels"; -export * from "./sipRoutingClient"; +export * from "./models.js"; +export * from "./phoneNumbersClient.js"; +export * from "./lroModels.js"; +export * from "./sipRoutingClient.js"; diff --git a/sdk/communication/communication-phone-numbers/src/mappers.ts b/sdk/communication/communication-phone-numbers/src/mappers.ts index 05de07579ff0..7a93fcc4ed76 100644 --- a/sdk/communication/communication-phone-numbers/src/mappers.ts +++ b/sdk/communication/communication-phone-numbers/src/mappers.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { SipTrunk } from "./models"; -import type { TrunkUpdate as RestSipTrunk } from "./generated/src/siprouting/models"; +import type { SipTrunk } from "./models.js"; +import type { TrunkUpdate as RestSipTrunk } from "./generated/src/siprouting/models/index.js"; /** * @internal diff --git a/sdk/communication/communication-phone-numbers/src/models.ts b/sdk/communication/communication-phone-numbers/src/models.ts index f8b01c89c986..972f50c5eb6b 100644 --- a/sdk/communication/communication-phone-numbers/src/models.ts +++ b/sdk/communication/communication-phone-numbers/src/models.ts @@ -7,7 +7,7 @@ import type { PhoneNumberSearchRequest, PhoneNumbersListAreaCodesOptionalParams, PhoneNumberType, -} from "./generated/src/models/"; +} from "./generated/src/models/index.js"; /** * The result of the phone numbers purchase operation. @@ -113,9 +113,9 @@ export { OperatorInformationOptions, OperatorInformationResult, OperatorNumberType, -} from "./generated/src/models/"; +} from "./generated/src/models/index.js"; -export { SipRoutingError, SipTrunkRoute } from "./generated/src/siprouting/models"; +export { SipRoutingError, SipTrunkRoute } from "./generated/src/siprouting/models/index.js"; /** * Represents a SIP trunk for routing calls. See RFC 4904. diff --git a/sdk/communication/communication-phone-numbers/src/phoneNumbersClient.ts b/sdk/communication/communication-phone-numbers/src/phoneNumbersClient.ts index 35c2b41cd3b4..acf95fcd9450 100644 --- a/sdk/communication/communication-phone-numbers/src/phoneNumbersClient.ts +++ b/sdk/communication/communication-phone-numbers/src/phoneNumbersClient.ts @@ -13,7 +13,7 @@ import { isTokenCredential } from "@azure/core-auth"; import type { InternalPipelineOptions } from "@azure/core-rest-pipeline"; import type { PollOperationState, PollerLike } from "@azure/core-lro"; import type { PagedAsyncIterableIterator } from "@azure/core-paging"; -import { PhoneNumbersClient as PhoneNumbersGeneratedClient } from "./generated/src"; +import { PhoneNumbersClient as PhoneNumbersGeneratedClient } from "./generated/src/index.js"; import type { OperatorInformationResult, PhoneNumberAreaCode, @@ -23,7 +23,7 @@ import type { PhoneNumberOffering, PhoneNumberSearchResult, PurchasedPhoneNumber, -} from "./generated/src/models/"; +} from "./generated/src/models/index.js"; import type { GetPurchasedPhoneNumberOptions, ListAvailableCountriesOptions, @@ -36,17 +36,17 @@ import type { ReleasePhoneNumberResult, SearchAvailablePhoneNumbersRequest, SearchOperatorInformationOptions, -} from "./models"; +} from "./models.js"; import type { BeginPurchasePhoneNumbersOptions, BeginReleasePhoneNumberOptions, BeginSearchAvailablePhoneNumbersOptions, BeginUpdatePhoneNumberCapabilitiesOptions, -} from "./lroModels"; -import { createPhoneNumbersPagingPolicy } from "./utils/customPipelinePolicies"; +} from "./lroModels.js"; +import { createPhoneNumbersPagingPolicy } from "./utils/customPipelinePolicies.js"; import type { CommonClientOptions } from "@azure/core-client"; -import { logger } from "./utils"; -import { tracingClient } from "./generated/src/tracing"; +import { logger } from "./utils/index.js"; +import { tracingClient } from "./generated/src/tracing.js"; /** * Client options used to configure the PhoneNumbersClient API requests. diff --git a/sdk/communication/communication-phone-numbers/src/sipRoutingClient.ts b/sdk/communication/communication-phone-numbers/src/sipRoutingClient.ts index 7e479861af83..9fd268fffbd9 100644 --- a/sdk/communication/communication-phone-numbers/src/sipRoutingClient.ts +++ b/sdk/communication/communication-phone-numbers/src/sipRoutingClient.ts @@ -10,16 +10,24 @@ import { import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; import type { InternalPipelineOptions } from "@azure/core-rest-pipeline"; -import { logger } from "./utils"; -import { SipRoutingClient as SipRoutingGeneratedClient } from "./generated/src/siprouting/sipRoutingClient"; -import type { SipConfigurationUpdate, SipRoutingError } from "./generated/src/siprouting/models"; -import type { ListSipRoutesOptions, ListSipTrunksOptions, SipTrunk, SipTrunkRoute } from "./models"; -import { transformFromRestModel, transformIntoRestModel } from "./mappers"; +import { logger } from "./utils/index.js"; +import { SipRoutingClient as SipRoutingGeneratedClient } from "./generated/src/siprouting/sipRoutingClient.js"; +import type { + SipConfigurationUpdate, + SipRoutingError, +} from "./generated/src/siprouting/models/index.js"; +import type { + ListSipRoutesOptions, + ListSipTrunksOptions, + SipTrunk, + SipTrunkRoute, +} from "./models.js"; +import { transformFromRestModel, transformIntoRestModel } from "./mappers.js"; import type { CommonClientOptions, OperationOptions } from "@azure/core-client"; -import { tracingClient } from "./generated/src/tracing"; +import { tracingClient } from "./generated/src/tracing.js"; import type { PagedAsyncIterableIterator } from "@azure/core-paging"; -export * from "./models"; +export * from "./models.js"; /** * Client options used to configure the SipRoutingClient API requests. diff --git a/sdk/communication/communication-phone-numbers/src/utils/index.ts b/sdk/communication/communication-phone-numbers/src/utils/index.ts index 7f3f320b01d7..8ab8ca4d7856 100644 --- a/sdk/communication/communication-phone-numbers/src/utils/index.ts +++ b/sdk/communication/communication-phone-numbers/src/utils/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./constants"; -export * from "./logger"; +export * from "./constants.js"; +export * from "./logger.js"; diff --git a/sdk/communication/communication-phone-numbers/test/internal/customPipelinePolicies.spec.ts b/sdk/communication/communication-phone-numbers/test/internal/customPipelinePolicies.spec.ts index e3f6c1c0023e..287218e90501 100644 --- a/sdk/communication/communication-phone-numbers/test/internal/customPipelinePolicies.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/internal/customPipelinePolicies.spec.ts @@ -4,8 +4,8 @@ import type { FullOperationResponse } from "@azure/core-client"; import type { PipelineRequest, PipelineResponse } from "@azure/core-rest-pipeline"; import { createHttpHeaders } from "@azure/core-rest-pipeline"; -import { assert } from "chai"; -import { createPhoneNumbersPagingPolicy } from "../../src/utils/customPipelinePolicies"; +import { createPhoneNumbersPagingPolicy } from "../../src/utils/customPipelinePolicies.js"; +import { describe, it, assert } from "vitest"; describe("phoneNumbersPagingPolicy", function () { const endpoint = "https://contoso.spool.azure.local"; @@ -18,7 +18,7 @@ describe("phoneNumbersPagingPolicy", function () { requestId: "any-id", }; - async function createMockResponse(parsedBody: any) { + async function createMockResponse(parsedBody: any): Promise { return Promise.resolve({ parsedBody }) as unknown as PipelineResponse; } diff --git a/sdk/communication/communication-phone-numbers/test/internal/headers.spec.ts b/sdk/communication/communication-phone-numbers/test/internal/headers.spec.ts index 3908287e058e..1ff87f710699 100644 --- a/sdk/communication/communication-phone-numbers/test/internal/headers.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/internal/headers.spec.ts @@ -2,18 +2,16 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import { isNode } from "@azure/core-util"; +import { isNodeLike } from "@azure/core-util"; import type { TokenCredential } from "@azure/identity"; -import { assert } from "chai"; -import sinon from "sinon"; -import { PhoneNumbersClient } from "../../src/phoneNumbersClient"; -import { getPhoneNumberHttpClient } from "../public/utils/mockHttpClients"; -import { SDK_VERSION } from "../../src/utils/constants"; -import type { Context } from "mocha"; -import { createMockToken } from "../public/utils/recordedClient"; +import { PhoneNumbersClient } from "../../src/phoneNumbersClient.js"; +import { getPhoneNumberHttpClient } from "../public/utils/mockHttpClients.js"; +import { SDK_VERSION } from "../../src/utils/constants.js"; +import { createMockToken } from "../public/utils/recordedClient.js"; import type { PipelineRequest } from "@azure/core-rest-pipeline"; +import { describe, it, assert, expect, vi } from "vitest"; -describe("PhoneNumbersClient - headers", function () { +describe("PhoneNumbersClient - headers", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; let client = new PhoneNumbersClient(endpoint, new AzureKeyCredential(accessKey), { @@ -21,39 +19,32 @@ describe("PhoneNumbersClient - headers", function () { }); let request: PipelineRequest; - afterEach(function () { - sinon.restore(); - }); - - it("calls the spy", async function () { - const spy = sinon.spy(getPhoneNumberHttpClient, "sendRequest"); + it("calls the spy", async () => { + const spy = vi.spyOn(getPhoneNumberHttpClient, "sendRequest"); await client.getPurchasedPhoneNumber("+18005550100"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; }); - it("[node] sets correct host", function (this: Context) { - if (!isNode) { - this.skip(); - } + it.skipIf(!isNodeLike)("[node] sets correct host", () => { assert.equal(request.headers.get("host"), "contoso.spool.azure.local"); }); - it("sets correct default user-agent", function () { - const userAgentHeader = isNode ? "user-agent" : "x-ms-useragent"; + it("sets correct default user-agent", () => { + const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( request.headers.get(userAgentHeader) as string, new RegExp(`azsdk-js-communication-phone-numbers/${SDK_VERSION}`, "g"), ); }); - it("sets date header", function () { + it("sets date header", () => { const dateHeader = "x-ms-date"; assert.typeOf(request.headers.get(dateHeader), "string"); }); - it("sets signed authorization header with KeyCredential", function () { + it("sets signed authorization header with KeyCredential", () => { assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -61,16 +52,16 @@ describe("PhoneNumbersClient - headers", function () { ); }); - it("sets signed authorization header with connection string", async function () { + it("sets signed authorization header with connection string", async () => { client = new PhoneNumbersClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getPhoneNumberHttpClient, }); - const spy = sinon.spy(getPhoneNumberHttpClient, "sendRequest"); + const spy = vi.spyOn(getPhoneNumberHttpClient, "sendRequest"); await client.getPurchasedPhoneNumber("+18005550100"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -78,23 +69,23 @@ describe("PhoneNumbersClient - headers", function () { ); }); - it("sets bearer authorization header with TokenCredential", async function (this: Context) { + it("sets bearer authorization header with TokenCredential", async () => { const credential: TokenCredential = createMockToken(); client = new PhoneNumbersClient(endpoint, credential, { httpClient: getPhoneNumberHttpClient, }); - const spy = sinon.spy(getPhoneNumberHttpClient, "sendRequest"); + const spy = vi.spyOn(getPhoneNumberHttpClient, "sendRequest"); await client.getPurchasedPhoneNumber("+18005550100"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match(request.headers.get("authorization") as string, /Bearer ./); }); - it("can set custom user-agent prefix", async function () { + it("can set custom user-agent prefix", async () => { client = new PhoneNumbersClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getPhoneNumberHttpClient, userAgentOptions: { @@ -102,13 +93,13 @@ describe("PhoneNumbersClient - headers", function () { }, }); - const spy = sinon.spy(getPhoneNumberHttpClient, "sendRequest"); + const spy = vi.spyOn(getPhoneNumberHttpClient, "sendRequest"); await client.getPurchasedPhoneNumber("+18005550100"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; - const userAgentHeader = isNode ? "user-agent" : "x-ms-useragent"; + const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( request.headers.get(userAgentHeader) as string, new RegExp( diff --git a/sdk/communication/communication-phone-numbers/test/internal/phoneNumbersClientPolicies.spec.ts b/sdk/communication/communication-phone-numbers/test/internal/phoneNumbersClientPolicies.spec.ts index bd4bca82d0b3..67f064107941 100644 --- a/sdk/communication/communication-phone-numbers/test/internal/phoneNumbersClientPolicies.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/internal/phoneNumbersClientPolicies.spec.ts @@ -2,16 +2,16 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import { assert } from "chai"; -import { PhoneNumbersClient } from "../../src/phoneNumbersClient"; -import { mockListPhoneNumbersHttpClient } from "../public/utils/mockHttpClients"; +import { PhoneNumbersClient } from "../../src/phoneNumbersClient.js"; +import { mockListPhoneNumbersHttpClient } from "../public/utils/mockHttpClients.js"; +import { describe, it, assert } from "vitest"; -describe("PhoneNumbersClient - custom policies ", function () { +describe("PhoneNumbersClient - custom policies ", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; let client: PhoneNumbersClient; - it("applies the phoneNumbersPagingPolicy", async function () { + it("applies the phoneNumbersPagingPolicy", async () => { client = new PhoneNumbersClient(endpoint, new AzureKeyCredential(accessKey), { httpClient: mockListPhoneNumbersHttpClient, }); diff --git a/sdk/communication/communication-phone-numbers/test/internal/siprouting/headers.spec.ts b/sdk/communication/communication-phone-numbers/test/internal/siprouting/headers.spec.ts index ee9aff2e14ca..04486bba3671 100644 --- a/sdk/communication/communication-phone-numbers/test/internal/siprouting/headers.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/internal/siprouting/headers.spec.ts @@ -2,18 +2,16 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import { isNode } from "@azure/core-util"; +import { isNodeLike } from "@azure/core-util"; import type { TokenCredential } from "@azure/identity"; -import { assert } from "chai"; -import sinon from "sinon"; -import { SipRoutingClient } from "../../../src/sipRoutingClient"; -import { getTrunksHttpClient } from "../../public/siprouting/utils/mockHttpClients"; -import { SDK_VERSION } from "../../../src/utils/constants"; -import type { Context } from "mocha"; -import { createMockToken } from "../../public/utils/recordedClient"; +import { SipRoutingClient } from "../../../src/sipRoutingClient.js"; +import { getTrunksHttpClient } from "../../public/siprouting/utils/mockHttpClients.js"; +import { SDK_VERSION } from "../../../src/utils/constants.js"; +import { createMockToken } from "../../public/utils/recordedClient.js"; import type { PipelineRequest } from "@azure/core-rest-pipeline"; +import { describe, it, assert, expect, vi } from "vitest"; -describe("SipRoutingClient - headers", function () { +describe("SipRoutingClient - headers", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; let client = new SipRoutingClient(endpoint, new AzureKeyCredential(accessKey), { @@ -21,40 +19,33 @@ describe("SipRoutingClient - headers", function () { }); let request: PipelineRequest; - afterEach(function () { - sinon.restore(); - }); - - it("calls the spy", async function () { - const spy = sinon.spy(getTrunksHttpClient, "sendRequest"); - const iter = await client.listTrunks(); + it("calls the spy", async () => { + const spy = vi.spyOn(getTrunksHttpClient, "sendRequest"); + const iter = client.listTrunks(); await iter.next(); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; }); - it("[node] sets correct host", function (this: Context) { - if (!isNode) { - this.skip(); - } + it.skipIf(!isNodeLike)("[node] sets correct host", () => { assert.equal(request.headers.get("host"), "contoso.spool.azure.local"); }); - it("sets correct default user-agent", function () { - const userAgentHeader = isNode ? "user-agent" : "x-ms-useragent"; + it("sets correct default user-agent", () => { + const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( request.headers.get(userAgentHeader) as string, new RegExp(`azsdk-js-communication-phone-numbers/${SDK_VERSION}`, "g"), ); }); - it("sets date header", function () { + it("sets date header", () => { const dateHeader = "x-ms-date"; assert.typeOf(request.headers.get(dateHeader), "string"); }); - it("sets signed authorization header with KeyCredential", function () { + it("sets signed authorization header with KeyCredential", () => { assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -62,17 +53,17 @@ describe("SipRoutingClient - headers", function () { ); }); - it("sets signed authorization header with connection string", async function () { + it("sets signed authorization header with connection string", async () => { client = new SipRoutingClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getTrunksHttpClient, }); - const spy = sinon.spy(getTrunksHttpClient, "sendRequest"); - const iter = await client.listTrunks(); + const spy = vi.spyOn(getTrunksHttpClient, "sendRequest"); + const iter = client.listTrunks(); await iter.next(); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -80,24 +71,24 @@ describe("SipRoutingClient - headers", function () { ); }); - it("sets bearer authorization header with TokenCredential", async function (this: Context) { + it("sets bearer authorization header with TokenCredential", async () => { const credential: TokenCredential = createMockToken(); client = new SipRoutingClient(endpoint, credential, { httpClient: getTrunksHttpClient, }); - const spy = sinon.spy(getTrunksHttpClient, "sendRequest"); - const iter = await client.listTrunks(); + const spy = vi.spyOn(getTrunksHttpClient, "sendRequest"); + const iter = client.listTrunks(); await iter.next(); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match(request.headers.get("authorization") as string, /Bearer ./); }); - it("can set custom user-agent prefix", async function () { + it("can set custom user-agent prefix", async () => { client = new SipRoutingClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getTrunksHttpClient, userAgentOptions: { @@ -105,14 +96,14 @@ describe("SipRoutingClient - headers", function () { }, }); - const spy = sinon.spy(getTrunksHttpClient, "sendRequest"); - const iter = await client.listTrunks(); + const spy = vi.spyOn(getTrunksHttpClient, "sendRequest"); + const iter = client.listTrunks(); await iter.next(); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; - const userAgentHeader = isNode ? "user-agent" : "x-ms-useragent"; + const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( request.headers.get(userAgentHeader) as string, new RegExp( diff --git a/sdk/communication/communication-phone-numbers/test/public/areaCodes.spec.ts b/sdk/communication/communication-phone-numbers/test/public/areaCodes.spec.ts index 35ead99ec905..06faca138baa 100644 --- a/sdk/communication/communication-phone-numbers/test/public/areaCodes.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/areaCodes.spec.ts @@ -1,31 +1,31 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersListAreaCodesOptionalParams, PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; +import type { + PhoneNumbersListAreaCodesOptionalParams, + PhoneNumbersClient, +} from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - area codes lists${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - area codes lists${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can list all geographic area codes", async function () { + it("can list all geographic area codes", { timeout: 60000 }, async () => { const availableLocalities = await client.listAvailableLocalities("US"); const locality = await availableLocalities.next(); const request: PhoneNumbersListAreaCodesOptionalParams = { @@ -36,9 +36,9 @@ matrix([[true, false]], async function (useAad) { for await (const areaCode of areaCodes) { assert.isNotNull(areaCode); } - }).timeout(60000); + }); - it("can list all toll free area codes", async function () { + it("can list all toll free area codes", { timeout: 60000 }, async () => { const tollFreeAreaCodesList = [ { areaCode: "888", @@ -69,6 +69,6 @@ matrix([[true, false]], async function (useAad) { for await (const areaCode of areaCodes) { assert.deepInclude(tollFreeAreaCodesList, areaCode); } - }).timeout(60000); + }); }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/countries.spec.ts b/sdk/communication/communication-phone-numbers/test/public/countries.spec.ts index 76e8a82e6f78..1bc742762011 100644 --- a/sdk/communication/communication-phone-numbers/test/public/countries.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/countries.spec.ts @@ -2,31 +2,28 @@ // Licensed under the MIT License. import { setLogLevel } from "@azure/logger"; -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; +import type { PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - countries lists${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - countries lists${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can list all available countries", async function () { + it("can list all available countries", { timeout: 60000 }, async () => { const countriesList = [ { localizedName: "Canada", @@ -45,6 +42,6 @@ matrix([[true, false]], async function (useAad) { assert.deepInclude(responseCountries, currentCountry); } setLogLevel("error"); - }).timeout(60000); + }); }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/ctor.spec.ts b/sdk/communication/communication-phone-numbers/test/public/ctor.spec.ts index 99e8800ccdeb..edb9bafe60de 100644 --- a/sdk/communication/communication-phone-numbers/test/public/ctor.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/ctor.spec.ts @@ -2,32 +2,31 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import { PhoneNumbersClient } from "../../src"; -import { createMockToken } from "./utils/recordedClient"; +import { PhoneNumbersClient } from "../../src/index.js"; +import { createMockToken } from "./utils/recordedClient.js"; +import { describe, it, assert } from "vitest"; -describe("PhoneNumbersClient - constructor", function () { +describe("PhoneNumbersClient - constructor", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; - it("successfully instantiates with valid connection string", function () { + it("successfully instantiates with valid connection string", () => { const client = new PhoneNumbersClient(`endpoint=${endpoint};accesskey=${accessKey}`); assert.instanceOf(client, PhoneNumbersClient); }); - it("throws with invalid connection string", function () { + it("throws with invalid connection string", () => { assert.throws(() => { new PhoneNumbersClient(`endpoints=${endpoint};accesskey=${accessKey}`); }); }); - it("successfully instantiates with with endpoint and access key", function () { + it("successfully instantiates with with endpoint and access key", () => { const client = new PhoneNumbersClient(endpoint, new AzureKeyCredential(accessKey)); assert.instanceOf(client, PhoneNumbersClient); }); - it("successfully instantiates with with endpoint and managed identity", function (this: Context) { + it("successfully instantiates with with endpoint and managed identity", () => { const client = new PhoneNumbersClient(endpoint, createMockToken()); assert.instanceOf(client, PhoneNumbersClient); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/get.spec.ts b/sdk/communication/communication-phone-numbers/test/public/get.spec.ts index 04f824dad60f..f7e0b5312c28 100644 --- a/sdk/communication/communication-phone-numbers/test/public/get.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/get.spec.ts @@ -1,39 +1,36 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; -import { getPhoneNumber } from "./utils/testPhoneNumber"; +import type { PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { getPhoneNumber } from "./utils/testPhoneNumber.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - get phone number${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - get phone number${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can get a purchased phone number", async function (this: Context) { + it("can get a purchased phone number", { timeout: 60000 }, async () => { const purchasedPhoneNumber = getPhoneNumber(); const { phoneNumber } = await client.getPurchasedPhoneNumber(purchasedPhoneNumber); assert.strictEqual(purchasedPhoneNumber, phoneNumber); - }).timeout(60000); + }); - it("errors if phone number not found", async function () { + it("errors if phone number not found", async () => { const fake = "+14155550100"; try { await client.getPurchasedPhoneNumber(fake); diff --git a/sdk/communication/communication-phone-numbers/test/public/list.spec.ts b/sdk/communication/communication-phone-numbers/test/public/list.spec.ts index 3733953944d8..bb971bcb3af4 100644 --- a/sdk/communication/communication-phone-numbers/test/public/list.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/list.spec.ts @@ -1,31 +1,28 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; +import type { PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - lists${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - lists${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can list all purchased phone numbers", async function () { + it("can list all purchased phone numbers", { timeout: 60000 }, async () => { let all = 0; for await (const purchased of client.listPurchasedPhoneNumbers()) { assert.match(purchased.phoneNumber, /\+\d{1}\d{3}\d{3}\d{4}/g); @@ -33,6 +30,6 @@ matrix([[true, false]], async function (useAad) { } assert.isTrue(all > 0); - }).timeout(60000); + }); }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/localities.spec.ts b/sdk/communication/communication-phone-numbers/test/public/localities.spec.ts index e045034d41d4..490f017983f8 100644 --- a/sdk/communication/communication-phone-numbers/test/public/localities.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/localities.spec.ts @@ -1,51 +1,52 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { ListLocalitiesOptions, PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; +import type { ListLocalitiesOptions, PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - localities lists${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - localities lists${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can list available localities", async function () { + it("can list available localities", { timeout: 60000 }, async () => { const responseLocalities = []; for await (const locality of client.listAvailableLocalities("US")) { responseLocalities.push(locality); } assert.isNotEmpty(responseLocalities); - }).timeout(60000); + }); - it("can list available localities with administrative division", async function () { - const availableLocalities = await client.listAvailableLocalities("US"); - const firstLocality = await availableLocalities.next(); - const request: ListLocalitiesOptions = { - administrativeDivision: firstLocality.value.administrativeDivision.abbreviatedName, - }; + it( + "can list available localities with administrative division", + { timeout: 60000 }, + async () => { + const availableLocalities = await client.listAvailableLocalities("US"); + const firstLocality = await availableLocalities.next(); + const request: ListLocalitiesOptions = { + administrativeDivision: firstLocality.value.administrativeDivision.abbreviatedName, + }; - for await (const locality of client.listAvailableLocalities("US", request)) { - assert.equal( - locality.administrativeDivision?.abbreviatedName, - firstLocality.value.administrativeDivision.abbreviatedName, - ); - } - }).timeout(60000); + for await (const locality of client.listAvailableLocalities("US", request)) { + assert.equal( + locality.administrativeDivision?.abbreviatedName, + firstLocality.value.administrativeDivision.abbreviatedName, + ); + } + }, + ); }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/lro.purchaseAndRelease.spec.ts b/sdk/communication/communication-phone-numbers/test/public/lro.purchaseAndRelease.spec.ts index 680af06bd7fb..56c714edca3e 100644 --- a/sdk/communication/communication-phone-numbers/test/public/lro.purchaseAndRelease.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/lro.purchaseAndRelease.spec.ts @@ -1,83 +1,79 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient, SearchAvailablePhoneNumbersRequest } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; - -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - lro - purchase and release${useAad ? " [AAD]" : ""}`, function () { - let recorder: Recorder; - let client: PhoneNumbersClient; - - before(function (this: Context) { - const includePhoneNumberLiveTests = env.INCLUDE_PHONENUMBER_LIVE_TESTS === "true"; - if (!includePhoneNumberLiveTests && !isPlaybackMode()) { - this.skip(); - } - }); - - beforeEach(async function (this: Context) { - ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); - }); - - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { +import type { PhoneNumbersClient, SearchAvailablePhoneNumbersRequest } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; + +matrix([[true, false]], async (useAad) => { + const includePhoneNumberLiveTests = env.INCLUDE_PHONENUMBER_LIVE_TESTS === "true"; + + describe( + `PhoneNumbersClient - lro - purchase and release${useAad ? " [AAD]" : ""}`, + { skip: !includePhoneNumberLiveTests && !isPlaybackMode() }, + () => { + let recorder: Recorder; + let client: PhoneNumbersClient; + + beforeEach(async (ctx) => { + ({ client, recorder } = useAad + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); + }); + + afterEach(async () => { await recorder.stop(); - } - }); - - it("can purchase and release a phone number", async function (this: Context) { - // search for phone number - const searchRequest: SearchAvailablePhoneNumbersRequest = { - countryCode: "US", - phoneNumberType: "tollFree", - assignmentType: "application", - capabilities: { - sms: "inbound+outbound", - calling: "none", - }, - }; - const searchPoller = await client.beginSearchAvailablePhoneNumbers(searchRequest); - const searchResults = await searchPoller.pollUntilDone(); - - assert.ok(searchPoller.getOperationState().isCompleted); - assert.isNotEmpty(searchResults.searchId); - assert.isNotEmpty(searchResults.phoneNumbers); - assert.equal(searchResults.phoneNumbers.length, 1); - - const purchasedPhoneNumber = searchResults.phoneNumbers[0]; - assert.isNotEmpty(purchasedPhoneNumber); - - // purchase phone number - const purchasePoller = await client.beginPurchasePhoneNumbers(searchResults.searchId); - - await purchasePoller.pollUntilDone(); - assert.ok(purchasePoller.getOperationState().isCompleted); - - console.log(`Purchased ${purchasedPhoneNumber}`); - - // get phone number to ensure it was purchased - const { phoneNumber } = await client.getPurchasedPhoneNumber(purchasedPhoneNumber); - assert.equal(purchasedPhoneNumber, phoneNumber); - - // release phone number - console.log(`Will release ${purchasedPhoneNumber}`); - - const releasePoller = await client.beginReleasePhoneNumber(purchasedPhoneNumber as string); - - await releasePoller.pollUntilDone(); - assert.ok(releasePoller.getOperationState().isCompleted); - const result = releasePoller.getOperationState().result! as any; - assert.equal(result.body.status, "succeeded"); - - console.log(`Released: ${purchasedPhoneNumber}`); - }).timeout(90000); - }); + }); + + it("can purchase and release a phone number", { timeout: 90000 }, async () => { + // search for phone number + const searchRequest: SearchAvailablePhoneNumbersRequest = { + countryCode: "US", + phoneNumberType: "tollFree", + assignmentType: "application", + capabilities: { + sms: "inbound+outbound", + calling: "none", + }, + }; + const searchPoller = await client.beginSearchAvailablePhoneNumbers(searchRequest); + const searchResults = await searchPoller.pollUntilDone(); + + assert.ok(searchPoller.getOperationState().isCompleted); + assert.isNotEmpty(searchResults.searchId); + assert.isNotEmpty(searchResults.phoneNumbers); + assert.equal(searchResults.phoneNumbers.length, 1); + + const purchasedPhoneNumber = searchResults.phoneNumbers[0]; + assert.isNotEmpty(purchasedPhoneNumber); + + // purchase phone number + const purchasePoller = await client.beginPurchasePhoneNumbers(searchResults.searchId); + + await purchasePoller.pollUntilDone(); + assert.ok(purchasePoller.getOperationState().isCompleted); + + console.log(`Purchased ${purchasedPhoneNumber}`); + + // get phone number to ensure it was purchased + const { phoneNumber } = await client.getPurchasedPhoneNumber(purchasedPhoneNumber); + assert.equal(purchasedPhoneNumber, phoneNumber); + + // release phone number + console.log(`Will release ${purchasedPhoneNumber}`); + + const releasePoller = await client.beginReleasePhoneNumber(purchasedPhoneNumber as string); + + await releasePoller.pollUntilDone(); + assert.ok(releasePoller.getOperationState().isCompleted); + const result = releasePoller.getOperationState().result! as any; + assert.equal(result.body.status, "succeeded"); + + console.log(`Released: ${purchasedPhoneNumber}`); + }); + }, + ); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/lro.search.spec.ts b/sdk/communication/communication-phone-numbers/test/public/lro.search.spec.ts index b9bb5816e61f..83c27ce4160d 100644 --- a/sdk/communication/communication-phone-numbers/test/public/lro.search.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/lro.search.spec.ts @@ -1,80 +1,76 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient, SearchAvailablePhoneNumbersRequest } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; -import { isClientErrorStatusCode } from "./utils/statusCodeHelpers"; +import type { PhoneNumbersClient, SearchAvailablePhoneNumbersRequest } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { isClientErrorStatusCode } from "./utils/statusCodeHelpers.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - lro - search${useAad ? " [AAD]" : ""}`, function () { - let recorder: Recorder; - let client: PhoneNumbersClient; - const searchRequest: SearchAvailablePhoneNumbersRequest = { - countryCode: "US", - phoneNumberType: "tollFree", - assignmentType: "application", - capabilities: { - sms: "none", - calling: "outbound", - }, - }; +matrix([[true, false]], async (useAad) => { + const skipPhoneNumbersTests = env.COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS === "true"; - before(function (this: Context) { - const skipPhoneNumbersTests = env.COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS === "true"; - if (skipPhoneNumbersTests && !isPlaybackMode()) { - this.skip(); - } - }); + describe( + `PhoneNumbersClient - lro - search${useAad ? " [AAD]" : ""}`, + { skip: skipPhoneNumbersTests && !isPlaybackMode() }, + () => { + let recorder: Recorder; + let client: PhoneNumbersClient; + const searchRequest: SearchAvailablePhoneNumbersRequest = { + countryCode: "US", + phoneNumberType: "tollFree", + assignmentType: "application", + capabilities: { + sms: "none", + calling: "outbound", + }, + }; - beforeEach(async function (this: Context) { - ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); - }); + beforeEach(async (ctx) => { + ({ client, recorder } = useAad + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); + }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async () => { await recorder.stop(); - } - }); + }); - it("can search for 1 available phone number by default", async function () { - const searchPoller = await client.beginSearchAvailablePhoneNumbers(searchRequest); + it("can search for 1 available phone number by default", { timeout: 60000 }, async () => { + const searchPoller = await client.beginSearchAvailablePhoneNumbers(searchRequest); - const results = await searchPoller.pollUntilDone(); - assert.ok(searchPoller.getOperationState().isCompleted); - assert.equal(results.phoneNumbers.length, 1); - }).timeout(60000); + const results = await searchPoller.pollUntilDone(); + assert.ok(searchPoller.getOperationState().isCompleted); + assert.equal(results.phoneNumbers.length, 1); + }); - it("throws on invalid search request", async function () { - // person and toll free is an invalid combination - const invalidSearchRequest: SearchAvailablePhoneNumbersRequest = { - countryCode: "US", - phoneNumberType: "tollFree", - assignmentType: "person", - capabilities: { - sms: "inbound+outbound", - calling: "none", - }, - }; + it("throws on invalid search request", { timeout: 60000 }, async () => { + // person and toll free is an invalid combination + const invalidSearchRequest: SearchAvailablePhoneNumbersRequest = { + countryCode: "US", + phoneNumberType: "tollFree", + assignmentType: "person", + capabilities: { + sms: "inbound+outbound", + calling: "none", + }, + }; - try { - const searchPoller = await client.beginSearchAvailablePhoneNumbers(invalidSearchRequest); - await searchPoller.pollUntilDone(); - } catch (error: any) { - assert.isTrue( - isClientErrorStatusCode(error.statusCode), - `Status code ${error.statusCode} does not indicate client error.`, - ); - return; - } + try { + const searchPoller = await client.beginSearchAvailablePhoneNumbers(invalidSearchRequest); + await searchPoller.pollUntilDone(); + } catch (error: any) { + assert.isTrue( + isClientErrorStatusCode(error.statusCode), + `Status code ${error.statusCode} does not indicate client error.`, + ); + return; + } - assert.fail("beginSearchAvailablePhoneNumbers should have thrown an exception."); - }).timeout(60000); - }); + assert.fail("beginSearchAvailablePhoneNumbers should have thrown an exception."); + }); + }, + ); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/lro.update.spec.ts b/sdk/communication/communication-phone-numbers/test/public/lro.update.spec.ts index afd16ba8d45b..aae7da0d1afc 100644 --- a/sdk/communication/communication-phone-numbers/test/public/lro.update.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/lro.update.spec.ts @@ -1,101 +1,96 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumberCapabilitiesRequest, PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; -import { getPhoneNumber } from "./utils/testPhoneNumber"; -import { isClientErrorStatusCode } from "./utils/statusCodeHelpers"; +import type { PhoneNumberCapabilitiesRequest, PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { getPhoneNumber } from "./utils/testPhoneNumber.js"; +import { isClientErrorStatusCode } from "./utils/statusCodeHelpers.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - lro - update${useAad ? " [AAD]" : ""}`, function () { - const purchasedPhoneNumber = getPhoneNumber(); - const update: PhoneNumberCapabilitiesRequest = { calling: "none", sms: "outbound" }; - let recorder: Recorder; - let client: PhoneNumbersClient; +matrix([[true, false]], async (useAad) => { + const skipPhoneNumbersTests = + !isPlaybackMode() && env.COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS === "true"; + const skipUpdateCapabilitiesLiveTests = + !isPlaybackMode() && env.SKIP_UPDATE_CAPABILITIES_LIVE_TESTS === "true"; - before(function (this: Context) { - const skipPhoneNumbersTests = - !isPlaybackMode() && env.COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS === "true"; - const skipUpdateCapabilitiesLiveTests = - !isPlaybackMode() && env.SKIP_UPDATE_CAPABILITIES_LIVE_TESTS === "true"; + describe( + `PhoneNumbersClient - lro - update${useAad ? " [AAD]" : ""}`, + { skip: skipPhoneNumbersTests || skipUpdateCapabilitiesLiveTests }, + () => { + const purchasedPhoneNumber = getPhoneNumber(); + const update: PhoneNumberCapabilitiesRequest = { calling: "none", sms: "outbound" }; + let recorder: Recorder; + let client: PhoneNumbersClient; - if (skipPhoneNumbersTests || skipUpdateCapabilitiesLiveTests) { - this.skip(); - } - }); + beforeEach(async (ctx) => { + ({ client, recorder } = useAad + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); + }); - beforeEach(async function (this: Context) { - ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); - }); - - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async () => { await recorder.stop(); - } - }); + }); - it("can update a phone number's capabilities", async function () { - const updatePoller = await client.beginUpdatePhoneNumberCapabilities( - purchasedPhoneNumber, - update, - ); + it("can update a phone number's capabilities", { timeout: 120000 }, async () => { + const updatePoller = await client.beginUpdatePhoneNumberCapabilities( + purchasedPhoneNumber, + update, + ); - const phoneNumber = await updatePoller.pollUntilDone(); - await updatePoller.pollUntilDone(); - assert.ok(updatePoller.getOperationState().isCompleted); - assert.deepEqual(phoneNumber.capabilities, update); - }).timeout(120000); + const phoneNumber = await updatePoller.pollUntilDone(); + await updatePoller.pollUntilDone(); + assert.ok(updatePoller.getOperationState().isCompleted); + assert.deepEqual(phoneNumber.capabilities, update); + }); - it("update throws when phone number is unauthorized", async function () { - const fakeNumber = "+14155550100"; - try { - const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); - await searchPoller.pollUntilDone(); - } catch (error: any) { - assert.isTrue( - isClientErrorStatusCode(error.statusCode), - `Status code ${error.statusCode} does not indicate client error.`, - ); - return; - } + it("update throws when phone number is unauthorized", async () => { + const fakeNumber = "+14155550100"; + try { + const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); + await searchPoller.pollUntilDone(); + } catch (error: any) { + assert.isTrue( + isClientErrorStatusCode(error.statusCode), + `Status code ${error.statusCode} does not indicate client error.`, + ); + return; + } - assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); - }); + assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); + }); - it("update throws when phone number is invalid", async function () { - const fakeNumber = "invalid_phone_number"; - try { - const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); - await searchPoller.pollUntilDone(); - } catch (error: any) { - assert.isTrue( - isClientErrorStatusCode(error.statusCode), - `Status code ${error.statusCode} does not indicate client error.`, - ); - return; - } + it("update throws when phone number is invalid", async () => { + const fakeNumber = "invalid_phone_number"; + try { + const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); + await searchPoller.pollUntilDone(); + } catch (error: any) { + assert.isTrue( + isClientErrorStatusCode(error.statusCode), + `Status code ${error.statusCode} does not indicate client error.`, + ); + return; + } - assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); - }); + assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); + }); - it("update throws when phone number is empty", async function () { - const fakeNumber = ""; - try { - const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); - await searchPoller.pollUntilDone(); - } catch (error: any) { - assert.equal(error.message, "phone number can't be empty"); - return; - } + it("update throws when phone number is empty", async () => { + const fakeNumber = ""; + try { + const searchPoller = await client.beginUpdatePhoneNumberCapabilities(fakeNumber, update); + await searchPoller.pollUntilDone(); + } catch (error: any) { + assert.equal(error.message, "phone number can't be empty"); + return; + } - assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); - }); - }); + assert.fail("beginUpdatePhoneNumberCapabilities should have thrown an exception."); + }); + }, + ); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/numberLookup.spec.ts b/sdk/communication/communication-phone-numbers/test/public/numberLookup.spec.ts index d68f82c6a181..fc74ca8e4933 100644 --- a/sdk/communication/communication-phone-numbers/test/public/numberLookup.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/numberLookup.spec.ts @@ -2,27 +2,24 @@ // Licensed under the MIT License. import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient } from "../../src"; -import { createRecordedClient } from "./utils/recordedClient"; -import { getPhoneNumber } from "./utils/testPhoneNumber"; +import type { PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { getPhoneNumber } from "./utils/testPhoneNumber.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`PhoneNumbersClient - look up phone number`, function () { +describe(`PhoneNumbersClient - look up phone number`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can look up a phone number", async function (this: Context) { + it("can look up a phone number", { timeout: 60000 }, async () => { const phoneNumbers = [getPhoneNumber()]; const operatorInformation = await client.searchOperatorInformation(phoneNumbers); @@ -30,9 +27,9 @@ describe(`PhoneNumbersClient - look up phone number`, function () { ? operatorInformation.values[0].phoneNumber : ""; assert.strictEqual(resultPhoneNumber, phoneNumbers[0]); - }).timeout(60000); + }); - it("errors if multiple phone numbers are requested", async function () { + it("errors if multiple phone numbers are requested", { timeout: 60000 }, async () => { const phoneNumbers = [getPhoneNumber(), getPhoneNumber()]; try { await client.searchOperatorInformation(phoneNumbers); @@ -40,9 +37,9 @@ describe(`PhoneNumbersClient - look up phone number`, function () { assert.strictEqual(error.code, "BadRequest"); assert.strictEqual(error.message, "Can only accept one phoneNumber"); } - }).timeout(60000); + }); - it("respects includeAdditionalOperatorDetails option", async function (this: Context) { + it("respects includeAdditionalOperatorDetails option", { timeout: 60000 }, async () => { const phoneNumbers = [getPhoneNumber()]; let operatorInformation = await client.searchOperatorInformation(phoneNumbers, { @@ -82,5 +79,5 @@ describe(`PhoneNumbersClient - look up phone number`, function () { assert.isNotNull( operatorInformation.values ? operatorInformation.values[0].operatorDetails : null, ); - }).timeout(60000); + }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/offerings.spec.ts b/sdk/communication/communication-phone-numbers/test/public/offerings.spec.ts index 75f934df6154..0d504a5b115a 100644 --- a/sdk/communication/communication-phone-numbers/test/public/offerings.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/offerings.spec.ts @@ -1,36 +1,33 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import type { PhoneNumbersClient } from "../../src"; -import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient"; +import type { PhoneNumbersClient } from "../../src/index.js"; +import { createRecordedClient, createRecordedClientWithToken } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`PhoneNumbersClient - offerings lists${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`PhoneNumbersClient - offerings lists${useAad ? " [AAD]" : ""}`, () => { let recorder: Recorder; let client: PhoneNumbersClient; - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this)! - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx)! + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); - it("can list available offerings", async function () { + it("can list available offerings", { timeout: 60000 }, async () => { const responseOfferings = []; for await (const offering of client.listAvailableOfferings("US")) { responseOfferings.push(offering); } assert.isNotEmpty(responseOfferings); - }).timeout(60000); + }); }); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/ctor.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/ctor.spec.ts index 401926cb8831..2c7f90e20e9c 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/ctor.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/ctor.spec.ts @@ -2,32 +2,31 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import { assert } from "chai"; -import type { Context } from "mocha"; -import { SipRoutingClient } from "../../../src"; -import { createMockToken } from "./utils/recordedClient"; +import { SipRoutingClient } from "../../../src/index.js"; +import { createMockToken } from "./utils/recordedClient.js"; +import { describe, it, assert } from "vitest"; -describe("SipRoutingClient - constructor", function () { +describe("SipRoutingClient - constructor", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "accessKey"; - it("successfully instantiates with valid connection string", function () { + it("successfully instantiates with valid connection string", () => { const client = new SipRoutingClient(`endpoint=${endpoint};accesskey=${accessKey}`); assert.instanceOf(client, SipRoutingClient); }); - it("throws with invalid connection string", function () { + it("throws with invalid connection string", () => { assert.throws(() => { new SipRoutingClient(`endpoints=${endpoint};accesskey=${accessKey}`); }); }); - it("successfully instantiates with with endpoint and access key", function () { + it("successfully instantiates with with endpoint and access key", () => { const client = new SipRoutingClient(endpoint, new AzureKeyCredential(accessKey)); assert.instanceOf(client, SipRoutingClient); }); - it("successfully instantiates with with endpoint and managed identity", function (this: Context) { + it("successfully instantiates with with endpoint and managed identity", () => { const client = new SipRoutingClient(endpoint, createMockToken()); assert.instanceOf(client, SipRoutingClient); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/deleteTrunk.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/deleteTrunk.spec.ts index d8730c06fc3b..94bf8e5568bf 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/deleteTrunk.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/deleteTrunk.spec.ts @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { assert } from "chai"; -import type { Context } from "mocha"; - -import type { SipRoutingClient } from "../../../src"; - +import type { SipRoutingClient } from "../../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; -import type { SipTrunk } from "../../../src/models"; +import type { SipTrunk } from "../../../src/models.js"; import { clearSipConfiguration, createRecordedClient, @@ -16,32 +12,31 @@ import { getUniqueFqdn, listAllTrunks, resetUniqueFqdns, -} from "./utils/recordedClient"; -import { matrix } from "@azure-tools/test-utils"; +} from "./utils/recordedClient.js"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`SipRoutingClient - delete trunk${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`SipRoutingClient - delete trunk${useAad ? " [AAD]" : ""}`, () => { let client: SipRoutingClient; let recorder: Recorder; let testFqdn = ""; - before(async function (this: Context) { + beforeAll(async () => { if (!isPlaybackMode()) { await clearSipConfiguration(); } }); - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this) - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx) + : await createRecordedClient(ctx)); testFqdn = getUniqueFqdn(recorder); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); resetUniqueFqdns(); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/getRoutes.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/getRoutes.spec.ts index f06b6087c209..84fb57744e49 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/getRoutes.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/getRoutes.spec.ts @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import type { SipRoutingClient } from "../../../src/index.js"; -import { assert } from "chai"; -import type { Context } from "mocha"; - -import type { SipRoutingClient } from "../../../src"; - -import { matrix } from "@azure-tools/test-utils"; +import { matrix } from "@azure-tools/test-utils-vitest"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; import { @@ -14,29 +10,28 @@ import { createRecordedClient, createRecordedClientWithToken, listAllRoutes, -} from "./utils/recordedClient"; +} from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`SipRoutingClient - get routes${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`SipRoutingClient - get routes${useAad ? " [AAD]" : ""}`, () => { let client: SipRoutingClient; let recorder: Recorder; - before(async function (this: Context) { + beforeAll(async () => { if (!isPlaybackMode()) { await clearSipConfiguration(); } }); - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this) - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx) + : await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); }); it("can retrieve routes", async () => { diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/getTrunks.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/getTrunks.spec.ts index 51d5ee963dec..36c25c7b6916 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/getTrunks.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/getTrunks.spec.ts @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import type { Context } from "mocha"; - -import type { SipRoutingClient } from "../../../src"; +import type { SipRoutingClient } from "../../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; -import type { SipTrunk } from "../../../src/models"; +import type { SipTrunk } from "../../../src/models.js"; import { clearSipConfiguration, createRecordedClient, @@ -16,11 +12,12 @@ import { getUniqueFqdn, listAllTrunks, resetUniqueFqdns, -} from "./utils/recordedClient"; -import { matrix } from "@azure-tools/test-utils"; +} from "./utils/recordedClient.js"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`SipRoutingClient - get trunks${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`SipRoutingClient - get trunks${useAad ? " [AAD]" : ""}`, () => { let client: SipRoutingClient; let recorder: Recorder; let firstFqdn = ""; @@ -28,26 +25,24 @@ matrix([[true, false]], async function (useAad) { let thirdFqdn = ""; let fourthFqdn = ""; - before(async function (this: Context) { + beforeAll(async () => { if (!isPlaybackMode()) { await clearSipConfiguration(); } }); - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this) - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx) + : await createRecordedClient(ctx)); firstFqdn = getUniqueFqdn(recorder); secondFqdn = getUniqueFqdn(recorder); thirdFqdn = getUniqueFqdn(recorder); fourthFqdn = getUniqueFqdn(recorder); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); resetUniqueFqdns(); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/setRoutes.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/setRoutes.spec.ts index 2db2b5e58053..e0fa00552414 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/setRoutes.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/setRoutes.spec.ts @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import type { Context } from "mocha"; - -import type { SipRoutingClient } from "../../../src"; +import type { SipRoutingClient } from "../../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; -import type { SipTrunk, SipTrunkRoute } from "../../../src/models"; +import type { SipTrunk, SipTrunkRoute } from "../../../src/models.js"; import { clearSipConfiguration, createRecordedClient, @@ -17,34 +13,33 @@ import { listAllRoutes, listAllTrunks, resetUniqueFqdns, -} from "./utils/recordedClient"; -import { matrix } from "@azure-tools/test-utils"; +} from "./utils/recordedClient.js"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`SipRoutingClient - set routes${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`SipRoutingClient - set routes${useAad ? " [AAD]" : ""}`, () => { let client: SipRoutingClient; let recorder: Recorder; let firstFqdn = ""; let secondFqdn = ""; - before(async function (this: Context) { + beforeAll(async () => { if (!isPlaybackMode()) { await clearSipConfiguration(); } }); - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this) - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx) + : await createRecordedClient(ctx)); firstFqdn = getUniqueFqdn(recorder); secondFqdn = getUniqueFqdn(recorder); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); resetUniqueFqdns(); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/setTrunks.spec.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/setTrunks.spec.ts index 794819c2a97a..3056cd7d540e 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/setTrunks.spec.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/setTrunks.spec.ts @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import type { Context } from "mocha"; - -import type { SipRoutingClient } from "../../../src"; +import type { SipRoutingClient } from "../../../src/index.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; -import type { SipTrunk, SipTrunkRoute } from "../../../src/models"; +import type { SipTrunk, SipTrunkRoute } from "../../../src/models.js"; import { clearSipConfiguration, createRecordedClient, @@ -17,34 +13,33 @@ import { listAllRoutes, listAllTrunks, resetUniqueFqdns, -} from "./utils/recordedClient"; -import { matrix } from "@azure-tools/test-utils"; +} from "./utils/recordedClient.js"; +import { matrix } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach, beforeAll } from "vitest"; -matrix([[true, false]], async function (useAad) { - describe(`SipRoutingClient - set trunks${useAad ? " [AAD]" : ""}`, function () { +matrix([[true, false]], async (useAad) => { + describe(`SipRoutingClient - set trunks${useAad ? " [AAD]" : ""}`, () => { let client: SipRoutingClient; let recorder: Recorder; let firstFqdn = ""; let secondFqdn = ""; - before(async function (this: Context) { + beforeAll(async () => { if (!isPlaybackMode()) { await clearSipConfiguration(); } }); - beforeEach(async function (this: Context) { + beforeEach(async (ctx) => { ({ client, recorder } = useAad - ? await createRecordedClientWithToken(this) - : await createRecordedClient(this)); + ? await createRecordedClientWithToken(ctx) + : await createRecordedClient(ctx)); firstFqdn = getUniqueFqdn(recorder); secondFqdn = getUniqueFqdn(recorder); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { - await recorder.stop(); - } + afterEach(async () => { + await recorder.stop(); resetUniqueFqdns(); }); diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/mockHttpClients.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/mockHttpClients.ts index 672f48a891b7..c70d8707b6f3 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/mockHttpClients.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/mockHttpClients.ts @@ -7,7 +7,7 @@ import type { PipelineRequest, PipelineResponse, } from "@azure/core-rest-pipeline"; -import type { SipTrunk } from "../../../../src"; +import type { SipTrunk } from "../../../../src/index.js"; export const createMockHttpClient = >( status: number = 200, diff --git a/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/recordedClient.ts b/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/recordedClient.ts index 9e43bb0a16fe..73eaefa77a0d 100644 --- a/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/recordedClient.ts +++ b/sdk/communication/communication-phone-numbers/test/public/siprouting/utils/recordedClient.ts @@ -1,24 +1,22 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { Context, Test } from "mocha"; import * as dotenv from "dotenv"; - -import type { RecorderStartOptions, SanitizerOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, SanitizerOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, assertEnvironmentVariable, env, isPlaybackMode, } from "@azure-tools/test-recorder"; -import type { SipTrunk, SipTrunkRoute } from "../../../../src"; -import { SipRoutingClient } from "../../../../src"; +import type { SipTrunk, SipTrunkRoute } from "../../../../src/index.js"; +import { SipRoutingClient } from "../../../../src/index.js"; import { parseConnectionString } from "@azure/communication-common"; import type { TokenCredential } from "@azure/identity"; import { isNodeLike } from "@azure/core-util"; import { createTestCredential } from "@azure-tools/test-credential"; import { randomUUID } from "@azure/core-util"; -import { createMSUserAgentPolicy } from "./msUserAgentPolicy"; +import { createMSUserAgentPolicy } from "./msUserAgentPolicy.js"; if (isNodeLike) { dotenv.config(); @@ -70,7 +68,7 @@ const recorderOptions: RecorderStartOptions = { ], }; -export async function createRecorder(context: Test | undefined): Promise { +export async function createRecorder(context: TestInfo | undefined): Promise { const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { @@ -83,9 +81,9 @@ export async function createRecorder(context: Test | undefined): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); const client = new SipRoutingClient( assertEnvironmentVariable("COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING"), @@ -111,9 +109,9 @@ export function createMockToken(): TokenCredential { } export async function createRecordedClientWithToken( - context: Context, + context: TestInfo, ): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); let credential: TokenCredential; const endpoint = parseConnectionString( diff --git a/sdk/communication/communication-phone-numbers/test/public/utils/mockHttpClients.ts b/sdk/communication/communication-phone-numbers/test/public/utils/mockHttpClients.ts index 7463fa409cdb..65b5797a8d99 100644 --- a/sdk/communication/communication-phone-numbers/test/public/utils/mockHttpClients.ts +++ b/sdk/communication/communication-phone-numbers/test/public/utils/mockHttpClients.ts @@ -7,8 +7,8 @@ import type { PipelineRequest, PipelineResponse, } from "@azure/core-rest-pipeline"; -import type { PurchasedPhoneNumber } from "../../../src"; -import type { PurchasedPhoneNumbers } from "../../../src/generated/src/models"; +import type { PurchasedPhoneNumber } from "../../../src/index.js"; +import type { PurchasedPhoneNumbers } from "../../../src/generated/src/models/index.js"; export const createMockHttpClient = >( status: number = 200, diff --git a/sdk/communication/communication-phone-numbers/test/public/utils/recordedClient.ts b/sdk/communication/communication-phone-numbers/test/public/utils/recordedClient.ts index 7549df2d33b2..193b5b938677 100644 --- a/sdk/communication/communication-phone-numbers/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-phone-numbers/test/public/utils/recordedClient.ts @@ -1,19 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type { Context, Test } from "mocha"; import * as dotenv from "dotenv"; -import type { RecorderStartOptions, SanitizerOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, SanitizerOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { PhoneNumbersClient } from "../../../src"; +import { PhoneNumbersClient } from "../../../src/index.js"; import { parseConnectionString } from "@azure/communication-common"; import type { TokenCredential } from "@azure/identity"; -import { isNode } from "@azure-tools/test-utils"; +import { isNodeLike } from "@azure/core-util"; import { createTestCredential } from "@azure-tools/test-credential"; -import { createMSUserAgentPolicy } from "./msUserAgentPolicy"; +import { createMSUserAgentPolicy } from "./msUserAgentPolicy.js"; -if (isNode) { +if (isNodeLike) { dotenv.config(); } @@ -68,7 +66,7 @@ const recorderOptions: RecorderStartOptions = { ], }; -export async function createRecorder(context: Test | undefined): Promise { +export async function createRecorder(context: TestInfo | undefined): Promise { const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { @@ -81,9 +79,9 @@ export async function createRecorder(context: Test | undefined): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); const client = new PhoneNumbersClient( env.COMMUNICATION_LIVETEST_STATIC_CONNECTION_STRING ?? "", @@ -110,9 +108,9 @@ export function createMockToken(): TokenCredential { } export async function createRecordedClientWithToken( - context: Context, + context: TestInfo, ): Promise> { - const recorder = await createRecorder(context.currentTest); + const recorder = await createRecorder(context); let credential: TokenCredential; const endpoint = parseConnectionString( diff --git a/sdk/communication/communication-phone-numbers/test/public/utils/testPhoneNumber.ts b/sdk/communication/communication-phone-numbers/test/public/utils/testPhoneNumber.ts index acaa3b03c5ce..088e98d443d3 100644 --- a/sdk/communication/communication-phone-numbers/test/public/utils/testPhoneNumber.ts +++ b/sdk/communication/communication-phone-numbers/test/public/utils/testPhoneNumber.ts @@ -4,8 +4,8 @@ import { env, isPlaybackMode } from "@azure-tools/test-recorder"; const DEFAULT_PHONE_NUMBER = "+14155550100"; -const testAgentPhoneNumber = () => env[`AZURE_PHONE_NUMBER_${env.AZURE_TEST_AGENT}`] ?? ""; -const defaultTestPhoneNumber = () => env.AZURE_PHONE_NUMBER ?? ""; +const testAgentPhoneNumber = (): string => env[`AZURE_PHONE_NUMBER_${env.AZURE_TEST_AGENT}`] ?? ""; +const defaultTestPhoneNumber = (): string => env.AZURE_PHONE_NUMBER ?? ""; export function getPhoneNumber(): string { return isPlaybackMode() ? DEFAULT_PHONE_NUMBER : getPhoneNumberFromEnvironment(); diff --git a/sdk/communication/communication-phone-numbers/tsconfig.browser.config.json b/sdk/communication/communication-phone-numbers/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-phone-numbers/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-phone-numbers/tsconfig.json b/sdk/communication/communication-phone-numbers/tsconfig.json index 7dca9af699eb..1b39d62122f9 100644 --- a/sdk/communication/communication-phone-numbers/tsconfig.json +++ b/sdk/communication/communication-phone-numbers/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure/communication-phone-numbers": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-phone-numbers/vitest.browser.config.ts b/sdk/communication/communication-phone-numbers/vitest.browser.config.ts new file mode 100644 index 000000000000..50ec2d5489b0 --- /dev/null +++ b/sdk/communication/communication-phone-numbers/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-phone-numbers/vitest.config.ts b/sdk/communication/communication-phone-numbers/vitest.config.ts new file mode 100644 index 000000000000..d01fdec8ac69 --- /dev/null +++ b/sdk/communication/communication-phone-numbers/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 5000000, + testTimeout: 5000000, + }, + }), +); diff --git a/sdk/communication/communication-recipient-verification/.nycrc b/sdk/communication/communication-recipient-verification/.nycrc deleted file mode 100644 index 29174b423579..000000000000 --- a/sdk/communication/communication-recipient-verification/.nycrc +++ /dev/null @@ -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 -} diff --git a/sdk/communication/communication-recipient-verification/api-extractor.json b/sdk/communication/communication-recipient-verification/api-extractor.json index adda95354d78..7615d889a58a 100644 --- a/sdk/communication/communication-recipient-verification/api-extractor.json +++ b/sdk/communication/communication-recipient-verification/api-extractor.json @@ -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-recipient-verification.d.ts" + "publicTrimmedFilePath": "dist/communication-recipient-verification.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-recipient-verification/karma.conf.js b/sdk/communication/communication-recipient-verification/karma.conf.js deleted file mode 100644 index b7223a7f2b76..000000000000 --- a/sdk/communication/communication-recipient-verification/karma.conf.js +++ /dev/null @@ -1,129 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); -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": ["sourcemap", "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: [ - "TEST_MODE", - "COMMUNICATION_LIVETEST_STATIC_CONNECTION_STRING", - "INCLUDE_PHONENUMBER_LIVE_TESTS", - "AZURE_PHONE_NUMBER", - "COMMUNICATION_ENDPOINT", - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS", - "RECORDINGS_RELATIVE_PATH", - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-recipient-verification/package.json b/sdk/communication/communication-recipient-verification/package.json index 1370fb3fda46..44e100d6344c 100644 --- a/sdk/communication/communication-recipient-verification/package.json +++ b/sdk/communication/communication-recipient-verification/package.json @@ -3,21 +3,21 @@ "version": "1.0.0-beta.1", "description": "Test", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-recipient-verification.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:autorest": "autorest --typescript ./swagger/README.md && rushx format", - "build:browser": "tsc -p . && dev-tool run bundle", + "build:browser": "dev-tool run build-package && dev-tool run bundle", "build:clean": "rush update --recheck && rush rebuild && npm run build", - "build:node": "tsc -p . && dev-tool run bundle", + "build:node": "dev-tool run build-package && dev-tool run bundle", "build:samples": "dev-tool samples publish --force", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test": "npm run integration-test:node && npm run integration-test:browser", "integration-test:browser": "dev-tool run test:browser", @@ -30,14 +30,12 @@ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node", "test:watch": "npm run test -- --watch --reporter min", "unit-test": "npm run unit-test:node && npm run unit-test:browser", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-recipient-verification.d.ts", "README.md", "LICENSE" ], @@ -69,39 +67,23 @@ "@azure/core-tracing": "^1.0.0", "@azure/logger": "^1.0.0", "events": "^3.0.0", - "tslib": "^2.2.0", - "uuid": "^8.3.2" + "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/core-util": "^1.9.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/identity": "^4.0.1", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", - "@types/uuid": "^8.3.2", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "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", - "nyc": "^17.0.0", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.4" }, "//metadata": { "constantPaths": [ @@ -132,5 +114,43 @@ "requiredResources": { "Azure Communication Services account": "https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource" } + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/index.ts b/sdk/communication/communication-recipient-verification/src/generated/src/index.ts index 2901f8b7b697..d9dffd43460e 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/index.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/index.ts @@ -6,6 +6,6 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./models"; -export { RecipientVerificationClient } from "./recipientVerificationClient"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { RecipientVerificationClient } from "./recipientVerificationClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/models/parameters.ts b/sdk/communication/communication-recipient-verification/src/generated/src/models/parameters.ts index 568ac3090e44..56e3ab1d7264 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/models/parameters.ts @@ -14,7 +14,7 @@ import { import { VerificationRequest as VerificationRequestMapper, VerificationCodeRequest as VerificationCodeRequestMapper -} from "../models/mappers"; +} from "../models/mappers.js"; export const accept: OperationParameter = { parameterPath: "accept", diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/operations/acsVerificationOperations.ts b/sdk/communication/communication-recipient-verification/src/generated/src/operations/acsVerificationOperations.ts index 44ddfdccaaa0..3a3255f45355 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/operations/acsVerificationOperations.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/operations/acsVerificationOperations.ts @@ -6,12 +6,12 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; -import { AcsVerificationOperations } from "../operationsInterfaces"; +import { tracingClient } from "../tracing.js"; +import { AcsVerificationOperations } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { RecipientVerificationClient } from "../recipientVerificationClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { RecipientVerificationClient } from "../recipientVerificationClient.js"; import { AcsVerificationGetVerificationsOptionalParams, AcsVerificationGetVerificationsResponse, @@ -22,7 +22,7 @@ import { AcsVerificationDeleteVerificationOptionalParams, AcsVerificationGetVerificationConstantsOptionalParams, AcsVerificationGetVerificationConstantsResponse -} from "../models"; +} from "../models/index.js"; /** Class containing AcsVerificationOperations operations. */ export class AcsVerificationOperationsImpl diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/operations/index.ts b/sdk/communication/communication-recipient-verification/src/generated/src/operations/index.ts index 0ab635719a40..cd99410d3d7d 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./acsVerificationOperations"; +export * from "./acsVerificationOperations.js"; diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/acsVerificationOperations.ts b/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/acsVerificationOperations.ts index 4279f2fd11bd..77f52aa0a33e 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/acsVerificationOperations.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/acsVerificationOperations.ts @@ -16,7 +16,7 @@ import { AcsVerificationDeleteVerificationOptionalParams, AcsVerificationGetVerificationConstantsOptionalParams, AcsVerificationGetVerificationConstantsResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a AcsVerificationOperations. */ export interface AcsVerificationOperations { diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/index.ts index 0ab635719a40..cd99410d3d7d 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./acsVerificationOperations"; +export * from "./acsVerificationOperations.js"; diff --git a/sdk/communication/communication-recipient-verification/src/generated/src/recipientVerificationClient.ts b/sdk/communication/communication-recipient-verification/src/generated/src/recipientVerificationClient.ts index 9c5090c801ad..13323d5bacab 100644 --- a/sdk/communication/communication-recipient-verification/src/generated/src/recipientVerificationClient.ts +++ b/sdk/communication/communication-recipient-verification/src/generated/src/recipientVerificationClient.ts @@ -13,9 +13,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { AcsVerificationOperationsImpl } from "./operations"; -import { AcsVerificationOperations } from "./operationsInterfaces"; -import { RecipientVerificationClientOptionalParams } from "./models"; +import { AcsVerificationOperationsImpl } from "./operations/index.js"; +import { AcsVerificationOperations } from "./operationsInterfaces/index.js"; +import { RecipientVerificationClientOptionalParams } from "./models/index.js"; export class RecipientVerificationClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-recipient-verification/src/index.ts b/sdk/communication/communication-recipient-verification/src/index.ts index 21657e4d08d9..d0a09eee1d8b 100644 --- a/sdk/communication/communication-recipient-verification/src/index.ts +++ b/sdk/communication/communication-recipient-verification/src/index.ts @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./models"; -export * from "./mappers"; -export * from "./recipientVerificationClient"; +export * from "./models.js"; +export * from "./mappers.js"; +export * from "./recipientVerificationClient.js"; diff --git a/sdk/communication/communication-recipient-verification/src/mappers.ts b/sdk/communication/communication-recipient-verification/src/mappers.ts index fb31428fc66d..9bbed8d3de4a 100644 --- a/sdk/communication/communication-recipient-verification/src/mappers.ts +++ b/sdk/communication/communication-recipient-verification/src/mappers.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export { AcsVerification as AcsVerificationMapper } from "./generated/src/models/mappers"; -export { VerificationConstantsResponse as ConstantsMapper } from "./generated/src/models/mappers"; -export { VerificationCodeRequest as VerificationCodeRequestMapper } from "./generated/src/models/mappers"; -export { VerificationResponse as VerificationResponseMapper } from "./generated/src/models/mappers"; -export { VerificationRequest as VerificationRequestMapper } from "./generated/src/models/mappers"; +export { AcsVerification as AcsVerificationMapper } from "./generated/src/models/mappers.js"; +export { VerificationConstantsResponse as ConstantsMapper } from "./generated/src/models/mappers.js"; +export { VerificationCodeRequest as VerificationCodeRequestMapper } from "./generated/src/models/mappers.js"; +export { VerificationResponse as VerificationResponseMapper } from "./generated/src/models/mappers.js"; +export { VerificationRequest as VerificationRequestMapper } from "./generated/src/models/mappers.js"; diff --git a/sdk/communication/communication-recipient-verification/src/models.ts b/sdk/communication/communication-recipient-verification/src/models.ts index 0a254734b380..202c5be56459 100644 --- a/sdk/communication/communication-recipient-verification/src/models.ts +++ b/sdk/communication/communication-recipient-verification/src/models.ts @@ -14,4 +14,4 @@ export { AcsVerification, VerificationConstantsResponse, VerificationResponse, -} from "./generated/src/models"; +} from "./generated/src/models/index.js"; diff --git a/sdk/communication/communication-recipient-verification/src/recipientVerificationClient.ts b/sdk/communication/communication-recipient-verification/src/recipientVerificationClient.ts index e0e9af15663e..59e4ae10fe58 100644 --- a/sdk/communication/communication-recipient-verification/src/recipientVerificationClient.ts +++ b/sdk/communication/communication-recipient-verification/src/recipientVerificationClient.ts @@ -10,16 +10,19 @@ import type { AcsVerificationVerifyIdentityResponse, AcsVerificationDeleteVerificationOptionalParams, AcsVerificationGetVerificationConstantsOptionalParams, -} from "./models"; +} from "./models.js"; import type { CommonClientOptions, InternalClientPipelineOptions } from "@azure/core-client"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; -import type { AcsVerification, VerificationConstantsResponse } from "./generated/src/models"; +import type { + AcsVerification, + VerificationConstantsResponse, +} from "./generated/src/models/index.js"; import { createCommunicationAuthPolicy } from "@azure/communication-common"; import { isKeyCredential, parseClientArguments } from "@azure/communication-common"; -import { RecipientVerificationClient as RecipientVerificationGeneratedClient } from "./generated/src"; -import { logger } from "./utils"; -import { tracingClient } from "./generated/src/tracing"; +import { RecipientVerificationClient as RecipientVerificationGeneratedClient } from "./generated/src/index.js"; +import { logger } from "./utils/index.js"; +import { tracingClient } from "./generated/src/tracing.js"; /** * Client options used to configure the RecipientVerificationGeneratedClient API requests. diff --git a/sdk/communication/communication-recipient-verification/src/utils/index.ts b/sdk/communication/communication-recipient-verification/src/utils/index.ts index 10e04457131b..7708dfaa00db 100644 --- a/sdk/communication/communication-recipient-verification/src/utils/index.ts +++ b/sdk/communication/communication-recipient-verification/src/utils/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./logger"; -export * from "./constants"; +export * from "./logger.js"; +export * from "./constants.js"; diff --git a/sdk/communication/communication-recipient-verification/test/public/ctor.spec.ts b/sdk/communication/communication-recipient-verification/test/public/ctor.spec.ts index f7fe64f5c7ac..e8b848e457ff 100644 --- a/sdk/communication/communication-recipient-verification/test/public/ctor.spec.ts +++ b/sdk/communication/communication-recipient-verification/test/public/ctor.spec.ts @@ -2,32 +2,31 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import type { Context } from "mocha"; -import { RecipientVerificationClient } from "../../src"; -import { assert } from "chai"; -import { createMockToken } from "./utils/recordedClient"; +import { RecipientVerificationClient } from "../../src/index.js"; +import { createMockToken } from "./utils/recordedClient.js"; +import { describe, it, assert } from "vitest"; -describe("RecipientVerificationClient - constructor", function () { +describe("RecipientVerificationClient - constructor", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; - it("successfully instantiates with valid connection string", function () { + it("successfully instantiates with valid connection string", () => { const client = new RecipientVerificationClient(`endpoint=${endpoint};accesskey=${accessKey}`); assert.instanceOf(client, RecipientVerificationClient); }); - it("throws with invalid connection string", function () { + it("throws with invalid connection string", () => { assert.throws(() => { new RecipientVerificationClient(`endpoints=${endpoint};accesskey=${accessKey}`); }); }); - it("successfully instantiates with with endpoint and access key", function () { + it("successfully instantiates with with endpoint and access key", () => { const client = new RecipientVerificationClient(endpoint, new AzureKeyCredential(accessKey)); assert.instanceOf(client, RecipientVerificationClient); }); - it("successfully instantiates with with endpoint and managed identity", function (this: Context) { + it("successfully instantiates with with endpoint and managed identity", () => { const client = new RecipientVerificationClient(endpoint, createMockToken()); assert.instanceOf(client, RecipientVerificationClient); }); diff --git a/sdk/communication/communication-recipient-verification/test/public/getVerificationConstants.spec.ts b/sdk/communication/communication-recipient-verification/test/public/getVerificationConstants.spec.ts index a82d3779f737..1f930f94fa30 100644 --- a/sdk/communication/communication-recipient-verification/test/public/getVerificationConstants.spec.ts +++ b/sdk/communication/communication-recipient-verification/test/public/getVerificationConstants.spec.ts @@ -1,30 +1,29 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; -import type { RecipientVerificationClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { RecipientVerificationClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`RecipientVerificationClient - Get verification constants`, function () { +describe(`RecipientVerificationClient - Get verification constants`, () => { let recorder: Recorder; let client: RecipientVerificationClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("get verification constants", async function () { + it("get verification constants", { timeout: 30000 }, async () => { const verificationConstants = await client.getVerificationConstants(); assert.isNotNull(verificationConstants.currentNumberOfVerifications); assert.isNotNull(verificationConstants.maxRetriesAllowed); assert.isNotNull(verificationConstants.maxVerificationsAllowed); - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-recipient-verification/test/public/listVerifications.spec.ts b/sdk/communication/communication-recipient-verification/test/public/listVerifications.spec.ts index 497b36a7e341..da4d9daf4853 100644 --- a/sdk/communication/communication-recipient-verification/test/public/listVerifications.spec.ts +++ b/sdk/communication/communication-recipient-verification/test/public/listVerifications.spec.ts @@ -1,30 +1,29 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; -import type { RecipientVerificationClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { RecipientVerificationClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`RecipientVerificationClient - List all verifications`, function () { +describe(`RecipientVerificationClient - List all verifications`, () => { let recorder: Recorder; let client: RecipientVerificationClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("get list of all verifications", async function () { + it("get list of all verifications", { timeout: 30000 }, async () => { // print all verifications for (const verification of await client.getVerifications()) { assert.isNotNull(verification.immutableId); } - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-recipient-verification/test/public/utils/recordedClient.ts b/sdk/communication/communication-recipient-verification/test/public/utils/recordedClient.ts index 6a76cd28560d..f76644b67932 100644 --- a/sdk/communication/communication-recipient-verification/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-recipient-verification/test/public/utils/recordedClient.ts @@ -1,18 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as dotenv from "dotenv"; +import * as dotenv from "dotenv"; import type { TokenCredential } from "@azure/identity"; import { ClientSecretCredential, DefaultAzureCredential } from "@azure/identity"; -import type { RecorderStartOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, assertEnvironmentVariable, env, isPlaybackMode, } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { RecipientVerificationClient } from "../../../src"; +import { RecipientVerificationClient } from "../../../src/index.js"; import { isNodeLike } from "@azure/core-util"; import { parseConnectionString } from "@azure/communication-common"; @@ -52,9 +51,9 @@ export const recorderOptions: RecorderStartOptions = { }; export async function createRecordedClient( - context: Context, + context: TestInfo, ): Promise> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { excludedHeaders: [ @@ -84,9 +83,9 @@ export function createMockToken(): { } export async function createRecordedClientWithToken( - context: Context, + context: TestInfo, ): Promise | undefined> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); let credential: TokenCredential; diff --git a/sdk/communication/communication-recipient-verification/tsconfig.browser.config.json b/sdk/communication/communication-recipient-verification/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-recipient-verification/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-recipient-verification/tsconfig.json b/sdk/communication/communication-recipient-verification/tsconfig.json index 11902823e705..2e03edc86362 100644 --- a/sdk/communication/communication-recipient-verification/tsconfig.json +++ b/sdk/communication/communication-recipient-verification/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure-tools/communication-recipient-verification": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-recipient-verification/vitest.browser.config.ts b/sdk/communication/communication-recipient-verification/vitest.browser.config.ts new file mode 100644 index 000000000000..0f0bef33e382 --- /dev/null +++ b/sdk/communication/communication-recipient-verification/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 300000, + testTimeout: 300000, + }, + }), +); diff --git a/sdk/communication/communication-recipient-verification/vitest.config.ts b/sdk/communication/communication-recipient-verification/vitest.config.ts new file mode 100644 index 000000000000..154f62eeffe9 --- /dev/null +++ b/sdk/communication/communication-recipient-verification/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 300000, + testTimeout: 300000, + }, + }), +); diff --git a/sdk/communication/communication-short-codes/.nycrc b/sdk/communication/communication-short-codes/.nycrc deleted file mode 100644 index 67064d0c1c56..000000000000 --- a/sdk/communication/communication-short-codes/.nycrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "include": [ - "dist-esm/src/**/*.js" - ], - "exclude": [ - "**/*.d.ts" - ], - "reporter": [ - "text-summary", - "html", - "cobertura" - ], - "exclude-after-remap": false, - "sourceMap": true, - "produce-source-map": true, - "instrument": true, - "all": true -} diff --git a/sdk/communication/communication-short-codes/api-extractor.json b/sdk/communication/communication-short-codes/api-extractor.json index fa72a58122a8..3abba0244e31 100644 --- a/sdk/communication/communication-short-codes/api-extractor.json +++ b/sdk/communication/communication-short-codes/api-extractor.json @@ -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-short-codes.d.ts" + "publicTrimmedFilePath": "dist/communication-short-codes.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-short-codes/karma.conf.js b/sdk/communication/communication-short-codes/karma.conf.js deleted file mode 100644 index d903b38b7c9f..000000000000 --- a/sdk/communication/communication-short-codes/karma.conf.js +++ /dev/null @@ -1,130 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); -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": ["sourcemap", "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: [ - "TEST_MODE", - "COMMUNICATION_LIVETEST_STATIC_CONNECTION_STRING", - "INCLUDE_PHONENUMBER_LIVE_TESTS", - "AZURE_PHONE_NUMBER", - "COMMUNICATION_ENDPOINT", - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS", - "RECORDINGS_RELATIVE_PATH", - "AZURE_USERAGENT_OVERRIDE", - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-short-codes/package.json b/sdk/communication/communication-short-codes/package.json index ce385aaa1cd3..0bb731c2fa94 100644 --- a/sdk/communication/communication-short-codes/package.json +++ b/sdk/communication/communication-short-codes/package.json @@ -3,25 +3,25 @@ "version": "1.0.0-beta.5", "description": "SDK for Azure Communication Services which facilitates short code management.", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-short-codes.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:autorest": "autorest --typescript ./swagger/README.md && rushx format", - "build:browser": "tsc -p . && dev-tool run bundle", + "build:browser": "dev-tool run build-package && dev-tool run bundle", "build:clean": "rush update --recheck && rush rebuild && npm run build", - "build:node": "tsc -p . && dev-tool run bundle", + "build:node": "dev-tool run build-package && dev-tool run bundle", "build:samples": "dev-tool samples publish --force", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test": "npm run integration-test:node && npm run integration-test:browser", - "integration-test:browser": "dev-tool run test:browser", - "integration-test:node": "dev-tool run test:node-js-input -- --timeout 300000 '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 --browser", + "integration-test:node": "dev-tool run test:vitest", "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", @@ -30,14 +30,12 @@ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node", "test:watch": "npm run test -- --watch --reporter min", "unit-test": "npm run unit-test:node && npm run unit-test:browser", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-short-codes.d.ts", "README.md", "LICENSE" ], @@ -59,49 +57,33 @@ "sideEffects": false, "prettier": "@azure/eslint-plugin-azure-sdk/prettier.json", "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/communication-common": "^2.2.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.3.2", + "@azure/abort-controller": "^2.1.2", + "@azure/communication-common": "^2.3.1", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.1.1", - "@azure/core-rest-pipeline": "^1.3.2", - "@azure/core-tracing": "^1.0.0", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.2.0", "@azure/logger": "^1.0.0", "events": "^3.0.0", - "tslib": "^2.2.0", - "uuid": "^8.3.2" + "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", - "@azure/core-util": "^1.9.0", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", + "@azure/core-util": "^1.11.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/identity": "^4.0.1", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", - "@types/uuid": "^8.3.2", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "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", - "nyc": "^17.0.0", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.4" }, "//metadata": { "constantPaths": [ @@ -132,5 +114,43 @@ "requiredResources": { "Azure Communication Services account": "https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource" } + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-short-codes/src/generated/src/index.ts b/sdk/communication/communication-short-codes/src/generated/src/index.ts index a37b548b3af6..b23878635e20 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/index.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/index.ts @@ -7,6 +7,6 @@ */ /// -export * from "./models"; -export { ShortCodesClient } from "./shortCodesClient"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { ShortCodesClient } from "./shortCodesClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-short-codes/src/generated/src/models/parameters.ts b/sdk/communication/communication-short-codes/src/generated/src/models/parameters.ts index 8def98cf1944..f0441150ff49 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/models/parameters.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/models/parameters.ts @@ -14,7 +14,7 @@ import { import { USProgramBrief as USProgramBriefMapper, ProgramBriefAttachment as ProgramBriefAttachmentMapper -} from "../models/mappers"; +} from "../models/mappers.js"; export const accept: OperationParameter = { parameterPath: "accept", diff --git a/sdk/communication/communication-short-codes/src/generated/src/operations/index.ts b/sdk/communication/communication-short-codes/src/generated/src/operations/index.ts index 093f97caf8e4..9bef59d39fbf 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/operations/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./shortCodes"; +export * from "./shortCodes.js"; diff --git a/sdk/communication/communication-short-codes/src/generated/src/operations/shortCodes.ts b/sdk/communication/communication-short-codes/src/generated/src/operations/shortCodes.ts index a34a7960a5c3..88d6923d5e4c 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/operations/shortCodes.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/operations/shortCodes.ts @@ -6,13 +6,13 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; +import { tracingClient } from "../tracing.js"; import { PagedAsyncIterableIterator } from "@azure/core-paging"; -import { ShortCodes } from "../operationsInterfaces"; +import { ShortCodes } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { ShortCodesClient } from "../shortCodesClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { ShortCodesClient } from "../shortCodesClient.js"; import { ShortCode, ShortCodesGetShortCodesNextOptionalParams, @@ -48,7 +48,7 @@ import { ShortCodesGetCostsNextResponse, ShortCodesGetUSProgramBriefsNextResponse, ShortCodesGetUSProgramBriefAttachmentsNextResponse -} from "../models"; +} from "../models/index.js"; /// /** Class containing ShortCodes operations. */ diff --git a/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/index.ts index 093f97caf8e4..9bef59d39fbf 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/index.ts @@ -6,4 +6,4 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./shortCodes"; +export * from "./shortCodes.js"; diff --git a/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/shortCodes.ts b/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/shortCodes.ts index d0fa353d002b..c09d6c24c224 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/shortCodes.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/operationsInterfaces/shortCodes.ts @@ -30,7 +30,7 @@ import { ShortCodesGetUSProgramBriefAttachmentOptionalParams, ShortCodesGetUSProgramBriefAttachmentResponse, ShortCodesDeleteUSProgramBriefAttachmentOptionalParams -} from "../models"; +} from "../models/index.js"; /// /** Interface representing a ShortCodes. */ diff --git a/sdk/communication/communication-short-codes/src/generated/src/shortCodesClient.ts b/sdk/communication/communication-short-codes/src/generated/src/shortCodesClient.ts index 50b6f44b058b..6d03cffc0211 100644 --- a/sdk/communication/communication-short-codes/src/generated/src/shortCodesClient.ts +++ b/sdk/communication/communication-short-codes/src/generated/src/shortCodesClient.ts @@ -13,9 +13,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { ShortCodesImpl } from "./operations"; -import { ShortCodes } from "./operationsInterfaces"; -import { ShortCodesClientOptionalParams } from "./models"; +import { ShortCodesImpl } from "./operations/index.js"; +import { ShortCodes } from "./operationsInterfaces/index.js"; +import { ShortCodesClientOptionalParams } from "./models/index.js"; export class ShortCodesClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-short-codes/src/index.ts b/sdk/communication/communication-short-codes/src/index.ts index 2baa50c0e2da..59363c92f0e8 100644 --- a/sdk/communication/communication-short-codes/src/index.ts +++ b/sdk/communication/communication-short-codes/src/index.ts @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./models"; -export * from "./shortCodesClient"; -export * from "./mappers"; +export * from "./models.js"; +export * from "./shortCodesClient.js"; +export * from "./mappers.js"; diff --git a/sdk/communication/communication-short-codes/src/mappers.ts b/sdk/communication/communication-short-codes/src/mappers.ts index 8988708432c3..38c8b6c1cb32 100644 --- a/sdk/communication/communication-short-codes/src/mappers.ts +++ b/sdk/communication/communication-short-codes/src/mappers.ts @@ -6,4 +6,4 @@ export { MessageDetails as MessageDetailsMapper, ProgramDetails as ProgramDetailsMapper, TrafficDetails as TrafficDetailsMapper, -} from "./generated/src/models/mappers"; +} from "./generated/src/models/mappers.js"; diff --git a/sdk/communication/communication-short-codes/src/models.ts b/sdk/communication/communication-short-codes/src/models.ts index e7bd2bf43191..aeafe01ef908 100644 --- a/sdk/communication/communication-short-codes/src/models.ts +++ b/sdk/communication/communication-short-codes/src/models.ts @@ -6,7 +6,7 @@ import type { ShortCodesGetShortCodesOptionalParams, ShortCodesGetUSProgramBriefsOptionalParams, ShortCodesGetCostsOptionalParams, -} from "."; +} from "./index.js"; /** * Additional options for the delete US Program Brief request. @@ -73,4 +73,4 @@ export { AttachmentType, FileType, ProgramBriefAttachmentSummary, -} from "./generated/src/models/"; +} from "./generated/src/models/index.js"; diff --git a/sdk/communication/communication-short-codes/src/shortCodesClient.ts b/sdk/communication/communication-short-codes/src/shortCodesClient.ts index f26441bca20b..4c3d585b1db9 100644 --- a/sdk/communication/communication-short-codes/src/shortCodesClient.ts +++ b/sdk/communication/communication-short-codes/src/shortCodesClient.ts @@ -15,7 +15,7 @@ import type { ShortCodesGetUSProgramBriefAttachmentOptionalParams, ShortCodesGetUSProgramBriefAttachmentsOptionalParams, SubmitUSProgramBriefOptions, -} from "./models"; +} from "./models.js"; import type { CommonClientOptions, InternalClientPipelineOptions } from "@azure/core-client"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; @@ -25,14 +25,14 @@ import type { ShortCodeCost, ShortCodesUpsertUSProgramBriefOptionalParams, USProgramBrief, -} from "./generated/src/models/"; +} from "./generated/src/models/index.js"; import { isKeyCredential, parseClientArguments } from "@azure/communication-common"; import type { PagedAsyncIterableIterator } from "@azure/core-paging"; -import { ShortCodesClient as ShortCodesGeneratedClient } from "./generated/src"; +import { ShortCodesClient as ShortCodesGeneratedClient } from "./generated/src/index.js"; import { createCommunicationAuthPolicy } from "@azure/communication-common"; -import { logger } from "./utils"; -import { tracingClient } from "./generated/src/tracing"; -import { createShortCodesPagingPolicy } from "./utils/customPipelinePolicies"; +import { logger } from "./utils/index.js"; +import { tracingClient } from "./generated/src/tracing.js"; +import { createShortCodesPagingPolicy } from "./utils/customPipelinePolicies.js"; /** * Client options used to configure the ShortCodesClient API requests. diff --git a/sdk/communication/communication-short-codes/src/utils/index.ts b/sdk/communication/communication-short-codes/src/utils/index.ts index 7f3f320b01d7..8ab8ca4d7856 100644 --- a/sdk/communication/communication-short-codes/src/utils/index.ts +++ b/sdk/communication/communication-short-codes/src/utils/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./constants"; -export * from "./logger"; +export * from "./constants.js"; +export * from "./logger.js"; diff --git a/sdk/communication/communication-short-codes/test/internal/generated_client.spec.ts b/sdk/communication/communication-short-codes/test/internal/generated_client.spec.ts index 7aadfe256ca2..f8303add3efc 100644 --- a/sdk/communication/communication-short-codes/test/internal/generated_client.spec.ts +++ b/sdk/communication/communication-short-codes/test/internal/generated_client.spec.ts @@ -7,14 +7,13 @@ import { createEmptyPipeline, bearerTokenAuthenticationPolicyName, } from "@azure/core-rest-pipeline"; -import { ShortCodesClient as ShortCodesGeneratedClient } from "../../src/generated/src"; +import { ShortCodesClient as ShortCodesGeneratedClient } from "../../src/generated/src/index.js"; import type { TokenCredential } from "@azure/identity"; -import { assert } from "chai"; -import { createMockToken } from "../public/utils/recordedClient"; +import { createMockToken } from "../public/utils/recordedClient.js"; import { isNodeLike } from "@azure/core-util"; import { parseClientArguments } from "@azure/communication-common"; -import sinon from "sinon"; import type { HttpClient, PipelineRequest, PipelineResponse } from "@azure/core-rest-pipeline"; +import { describe, it, assert, expect, vi } from "vitest"; export const createMockHttpClient = >( status: number = 200, @@ -110,9 +109,9 @@ describe("ShortCodesGeneratedClient - constructor", function () { "pipeline should have CustomApiVersionPolicy", ); - const spy = sinon.spy(mockHttpClient, "sendRequest"); + const spy = vi.spyOn(mockHttpClient, "sendRequest"); await client.shortCodes.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); }); it("verify bearer policy exists without explicitly adding it", async function () { @@ -146,8 +145,8 @@ describe("ShortCodesGeneratedClient - constructor", function () { "pipeline should have CustomApiVersionPolicy", ); - const spy = sinon.spy(mockHttpClient, "sendRequest"); + const spy = vi.spyOn(mockHttpClient, "sendRequest"); await client.shortCodes.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); }); }); diff --git a/sdk/communication/communication-short-codes/test/internal/headers.spec.ts b/sdk/communication/communication-short-codes/test/internal/headers.spec.ts index 4e3b2e4202d3..2225fc841ee5 100644 --- a/sdk/communication/communication-short-codes/test/internal/headers.spec.ts +++ b/sdk/communication/communication-short-codes/test/internal/headers.spec.ts @@ -2,18 +2,16 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import type { Context } from "mocha"; import type { PipelineRequest } from "@azure/core-rest-pipeline"; -import { SDK_VERSION } from "../../src/utils/constants"; -import { ShortCodesClient } from "../../src/shortCodesClient"; +import { SDK_VERSION } from "../../src/utils/constants.js"; +import { ShortCodesClient } from "../../src/shortCodesClient.js"; import type { TokenCredential } from "@azure/identity"; -import { assert } from "chai"; -import { createMockToken } from "../public/utils/recordedClient"; -import { getUSProgramBriefHttpClient } from "../public/utils/mockHttpClients"; +import { createMockToken } from "../public/utils/recordedClient.js"; +import { getUSProgramBriefHttpClient } from "../public/utils/mockHttpClients.js"; import { isNodeLike } from "@azure/core-util"; -import sinon from "sinon"; +import { describe, it, assert, expect, vi, afterEach } from "vitest"; -describe("ShortCodesClient - headers", function () { +describe("ShortCodesClient - headers", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; let client = new ShortCodesClient(endpoint, new AzureKeyCredential(accessKey), { @@ -21,26 +19,26 @@ describe("ShortCodesClient - headers", function () { }); let request: PipelineRequest; - afterEach(function () { - sinon.restore(); + afterEach(() => { + vi.restoreAllMocks(); }); - it("calls the spy", async function () { - const spy = sinon.spy(getUSProgramBriefHttpClient, "sendRequest"); + it("calls the spy", async () => { + const spy = vi.spyOn(getUSProgramBriefHttpClient, "sendRequest"); await client.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; }); - it("[node] sets correct host", function (this: Context) { + it("[node] sets correct host", (ctx) => { if (!isNodeLike) { - this.skip(); + ctx.skip(); } assert.equal(request.headers.get("host"), "contoso.spool.azure.local"); }); - it("sets correct default user-agent", function () { + it("sets correct default user-agent", () => { const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( request.headers.get(userAgentHeader) as string, @@ -48,12 +46,12 @@ describe("ShortCodesClient - headers", function () { ); }); - it("sets date header", function () { + it("sets date header", () => { const dateHeader = "x-ms-date"; assert.typeOf(request.headers.get(dateHeader), "string"); }); - it("sets signed authorization header with KeyCredential", function () { + it("sets signed authorization header with KeyCredential", () => { assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -61,16 +59,16 @@ describe("ShortCodesClient - headers", function () { ); }); - it("sets signed authorization header with connection string", async function () { + it("sets signed authorization header with connection string", async () => { client = new ShortCodesClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getUSProgramBriefHttpClient, }); - const spy = sinon.spy(getUSProgramBriefHttpClient, "sendRequest"); + const spy = vi.spyOn(getUSProgramBriefHttpClient, "sendRequest"); await client.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match( request.headers.get("authorization") as string, @@ -78,23 +76,23 @@ describe("ShortCodesClient - headers", function () { ); }); - it("sets bearer authorization header with TokenCredential", async function (this: Context) { + it("sets bearer authorization header with TokenCredential", async () => { const credential: TokenCredential = createMockToken(); client = new ShortCodesClient(endpoint, credential, { httpClient: getUSProgramBriefHttpClient, }); - const spy = sinon.spy(getUSProgramBriefHttpClient, "sendRequest"); + const spy = vi.spyOn(getUSProgramBriefHttpClient, "sendRequest"); await client.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; assert.isDefined(request.headers.get("authorization")); assert.match(request.headers.get("authorization") as string, /Bearer ./); }); - it("can set custom user-agent prefix", async function () { + it("can set custom user-agent prefix", async () => { client = new ShortCodesClient(`endpoint=${endpoint};accessKey=${accessKey}`, { httpClient: getUSProgramBriefHttpClient, userAgentOptions: { @@ -102,11 +100,11 @@ describe("ShortCodesClient - headers", function () { }, }); - const spy = sinon.spy(getUSProgramBriefHttpClient, "sendRequest"); + const spy = vi.spyOn(getUSProgramBriefHttpClient, "sendRequest"); await client.getUSProgramBrief("9fb78ef0-5704-4866-bca2-6a040ec83c0b"); - sinon.assert.calledOnce(spy); + expect(spy).toHaveBeenCalledOnce(); - request = spy.getCall(0).args[0]; + request = spy.mock.calls[0][0]; const userAgentHeader = isNodeLike ? "user-agent" : "x-ms-useragent"; assert.match( diff --git a/sdk/communication/communication-short-codes/test/public/ctor.spec.ts b/sdk/communication/communication-short-codes/test/public/ctor.spec.ts index 87b5d7fcd70e..c2da00592e0f 100644 --- a/sdk/communication/communication-short-codes/test/public/ctor.spec.ts +++ b/sdk/communication/communication-short-codes/test/public/ctor.spec.ts @@ -2,32 +2,31 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import type { Context } from "mocha"; -import { ShortCodesClient } from "../../src"; -import { assert } from "chai"; -import { createMockToken } from "./utils/recordedClient"; +import { ShortCodesClient } from "../../src/index.js"; +import { createMockToken } from "./utils/recordedClient.js"; +import { describe, it, assert } from "vitest"; -describe("ShortCodesClient - constructor", function () { +describe("ShortCodesClient - constructor", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; - it("successfully instantiates with valid connection string", function () { + it("successfully instantiates with valid connection string", () => { const client = new ShortCodesClient(`endpoint=${endpoint};accesskey=${accessKey}`); assert.instanceOf(client, ShortCodesClient); }); - it("throws with invalid connection string", function () { + it("throws with invalid connection string", () => { assert.throws(() => { new ShortCodesClient(`endpoints=${endpoint};accesskey=${accessKey}`); }); }); - it("successfully instantiates with with endpoint and access key", function () { + it("successfully instantiates with with endpoint and access key", () => { const client = new ShortCodesClient(endpoint, new AzureKeyCredential(accessKey)); assert.instanceOf(client, ShortCodesClient); }); - it("successfully instantiates with with endpoint and managed identity", function (this: Context) { + it("successfully instantiates with with endpoint and managed identity", () => { const client = new ShortCodesClient(endpoint, createMockToken()); assert.instanceOf(client, ShortCodesClient); }); diff --git a/sdk/communication/communication-short-codes/test/public/listShortCodeCosts.spec.ts b/sdk/communication/communication-short-codes/test/public/listShortCodeCosts.spec.ts index 61ad9d6ed2c8..961325e8e4cf 100644 --- a/sdk/communication/communication-short-codes/test/public/listShortCodeCosts.spec.ts +++ b/sdk/communication/communication-short-codes/test/public/listShortCodeCosts.spec.ts @@ -1,36 +1,34 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; -import type { ShortCodesClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { ShortCodesClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; describe(`ShortCodeCostsClient - lists Short Code Costs`, function () { let recorder: Recorder; let client: ShortCodesClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("can list all short code costs", async function () { + it("can list all short code costs", { timeout: 30000 }, async () => { let count = 0; for await (const shortCodeCost of client.listShortCodeCosts()) { count++; assert.isNotNull(shortCodeCost); } assert.isAtLeast(count, 3); - }).timeout(30000); + }); - it("can list all short code costs, by Page", async function () { + it("can list all short code costs, by Page", { timeout: 30000 }, async () => { const pages = client.listShortCodeCosts({ top: 1 }).byPage(); for await (const page of pages) { if (page.length === 0) { @@ -42,5 +40,5 @@ describe(`ShortCodeCostsClient - lists Short Code Costs`, function () { assert.isNotNull(shortCodeCost); } } - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-short-codes/test/public/listShortCodes.spec.ts b/sdk/communication/communication-short-codes/test/public/listShortCodes.spec.ts index 758e026e7e12..f4b50108d726 100644 --- a/sdk/communication/communication-short-codes/test/public/listShortCodes.spec.ts +++ b/sdk/communication/communication-short-codes/test/public/listShortCodes.spec.ts @@ -1,33 +1,31 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; -import type { ShortCodesClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { ShortCodesClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`ShortCodesClient - lists Short Codes`, function () { +describe(`ShortCodesClient - lists Short Codes`, () => { let recorder: Recorder; let client: ShortCodesClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("can list all acquired short codes", async function () { + it("can list all acquired short codes", { timeout: 30000 }, async () => { for await (const shortCode of client.listShortCodes()) { assert.isNotNull(shortCode.value); } - }).timeout(30000); + }); - it("can list all acquired short codes, by Page", async function () { + it("can list all acquired short codes, by Page", { timeout: 30000 }, async () => { const pages = client.listShortCodes().byPage(); for await (const page of pages) { // loop over each item in the page @@ -35,5 +33,5 @@ describe(`ShortCodesClient - lists Short Codes`, function () { assert.isNotNull(shortCode.value); } } - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-short-codes/test/public/manageProgramBriefAttachment.spec.ts b/sdk/communication/communication-short-codes/test/public/manageProgramBriefAttachment.spec.ts index ac152427a4d7..793655057090 100644 --- a/sdk/communication/communication-short-codes/test/public/manageProgramBriefAttachment.spec.ts +++ b/sdk/communication/communication-short-codes/test/public/manageProgramBriefAttachment.spec.ts @@ -6,33 +6,32 @@ import type { ShortCodesClient, ShortCodesUpsertUSProgramBriefOptionalParams, USProgramBrief, -} from "../../src"; +} from "../../src/index.js"; import { doesProgramBriefContainAnyAttachment, getProgramBriefAttachmentsWithId, getProgramBriefAttachmentsWithIdByPage, getTestProgramBriefAttachment, -} from "./utils/testProgramBriefAttachment"; +} from "./utils/testProgramBriefAttachment.js"; import { doesProgramBriefExist, getTestUSProgramBrief, runTestCleaningLeftovers, -} from "./utils/testUSProgramBrief"; -import type { Context } from "mocha"; +} from "./utils/testUSProgramBrief.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`ShortCodesClient - manage Attachments`, function () { +describe(`ShortCodesClient - manage Attachments`, () => { let recorder: Recorder; let client: ShortCodesClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); @@ -131,7 +130,7 @@ describe(`ShortCodesClient - manage Attachments`, function () { return true; }; - it("can manage Attachments", async function () { + it("can manage Attachments", { timeout: 80000 }, async () => { const uspb = getTestUSProgramBrief(); const pbTestId = recorder.variable(`pb-var`, uspb.id); uspb.id = pbTestId; @@ -202,5 +201,5 @@ describe(`ShortCodesClient - manage Attachments`, function () { "Delete program brief was unsuccessful, program brief is still returned", ); }); - }).timeout(80000); + }); }); diff --git a/sdk/communication/communication-short-codes/test/public/manageUSProgramBriefs.spec.ts b/sdk/communication/communication-short-codes/test/public/manageUSProgramBriefs.spec.ts index e70d797cc468..1e3ee691e6cf 100644 --- a/sdk/communication/communication-short-codes/test/public/manageUSProgramBriefs.spec.ts +++ b/sdk/communication/communication-short-codes/test/public/manageUSProgramBriefs.spec.ts @@ -5,28 +5,27 @@ import type { ShortCodesClient, ShortCodesUpsertUSProgramBriefOptionalParams, USProgramBrief, -} from "../../src"; +} from "../../src/index.js"; import { assertEditableFieldsAreEqual, doesProgramBriefExist, getTestUSProgramBrief, runTestCleaningLeftovers, -} from "./utils/testUSProgramBrief"; -import type { Context } from "mocha"; +} from "./utils/testUSProgramBrief.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`ShortCodesClient - creates, gets, updates, lists, and deletes US Program Brief`, function () { +describe(`ShortCodesClient - creates, gets, updates, lists, and deletes US Program Brief`, () => { let recorder: Recorder; let client: ShortCodesClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async (ctx) => { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async (ctx) => { + if (!ctx.task.pending) { await recorder.stop(); } }); @@ -137,7 +136,7 @@ describe(`ShortCodesClient - creates, gets, updates, lists, and deletes US Progr assertEditableFieldsAreEqual(uspb, actualProgramBrief, "get after initial create"); }; - it("can create and delete a US Program Brief", async function () { + it("can create and delete a US Program Brief", { timeout: 60000 }, async () => { const testProgramBrief = getTestUSProgramBrief(); // override test brief id with variable id const pbTestId = recorder.variable(`pb-var-${0}`, testProgramBrief.id); @@ -152,9 +151,9 @@ describe(`ShortCodesClient - creates, gets, updates, lists, and deletes US Progr // delete program briefs, ensure it was removed await _deleteUSProgramBriefs([testProgramBrief]); }); - }).timeout(60000); + }); - it("can create, and list a US Program Brief", async function () { + it("can create, and list a US Program Brief", { timeout: 60000 }, async () => { const testProgramBriefs = [getTestUSProgramBrief(), getTestUSProgramBrief()]; // override test brief id with variable id const testProgramBriefIds = testProgramBriefs.map((pb, index) => { @@ -176,5 +175,5 @@ describe(`ShortCodesClient - creates, gets, updates, lists, and deletes US Progr // delete program briefs, ensure it was removed await _deleteUSProgramBriefs(testProgramBriefs); }); - }).timeout(60000); + }); }); diff --git a/sdk/communication/communication-short-codes/test/public/utils/recordedClient.ts b/sdk/communication/communication-short-codes/test/public/utils/recordedClient.ts index f32f142ba3b6..8f1ca8c683d4 100644 --- a/sdk/communication/communication-short-codes/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-short-codes/test/public/utils/recordedClient.ts @@ -4,18 +4,17 @@ import * as dotenv from "dotenv"; import type { TokenCredential } from "@azure/identity"; import { ClientSecretCredential, DefaultAzureCredential } from "@azure/identity"; -import type { RecorderStartOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, assertEnvironmentVariable, env, isPlaybackMode, } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { ShortCodesClient } from "../../../src"; +import { ShortCodesClient } from "../../../src/index.js"; import { isNodeLike } from "@azure/core-util"; import { parseConnectionString } from "@azure/communication-common"; -import { createMSUserAgentPolicy } from "./msUserAgentPolicy"; +import { createMSUserAgentPolicy } from "./msUserAgentPolicy.js"; if (isNodeLike) { dotenv.config(); @@ -55,9 +54,9 @@ export const recorderOptions: RecorderStartOptions = { }; export async function createRecordedClient( - context: Context, + context: TestInfo, ): Promise> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { excludedHeaders: [ @@ -94,9 +93,9 @@ export function createMockToken(): { } export async function createRecordedClientWithToken( - context: Context, + context: TestInfo, ): Promise | undefined> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); let credential: TokenCredential; diff --git a/sdk/communication/communication-short-codes/test/public/utils/testProgramBriefAttachment.ts b/sdk/communication/communication-short-codes/test/public/utils/testProgramBriefAttachment.ts index aaad9c90d216..ddcb6eb5044b 100644 --- a/sdk/communication/communication-short-codes/test/public/utils/testProgramBriefAttachment.ts +++ b/sdk/communication/communication-short-codes/test/public/utils/testProgramBriefAttachment.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { ProgramBriefAttachment, ShortCodesClient } from "../../../src"; -import { v4 as uuid } from "uuid"; +import type { ProgramBriefAttachment, ShortCodesClient } from "../../../src/index.js"; +import { randomUUID } from "@azure/core-util"; export function getTestProgramBriefAttachment(): ProgramBriefAttachment { - const attachmentId = uuid(); + const attachmentId = randomUUID(); const testProgramBriefAttachment: ProgramBriefAttachment = { id: attachmentId, diff --git a/sdk/communication/communication-short-codes/test/public/utils/testUSProgramBrief.ts b/sdk/communication/communication-short-codes/test/public/utils/testUSProgramBrief.ts index c98720bffd94..09c8143e1dde 100644 --- a/sdk/communication/communication-short-codes/test/public/utils/testUSProgramBrief.ts +++ b/sdk/communication/communication-short-codes/test/public/utils/testUSProgramBrief.ts @@ -2,23 +2,23 @@ // Licensed under the MIT License. import type { RestError } from "@azure/core-rest-pipeline"; -import type { ShortCodesClient, USProgramBrief } from "../../../src"; +import type { ShortCodesClient, USProgramBrief } from "../../../src/index.js"; import { CompanyInformationMapper, MessageDetailsMapper, ProgramDetailsMapper, TrafficDetailsMapper, -} from "../../../src"; -import { assert } from "chai"; +} from "../../../src/index.js"; import type { CompositeMapper } from "@azure/core-client"; import { isPlaybackMode } from "@azure-tools/test-recorder"; -import { v4 as uuid } from "uuid"; +import { randomUUID } from "@azure/core-util"; +import { assert } from "vitest"; const TestCompanyName: string = "Contoso"; const TestProgramBriefName: string = "Contoso Loyalty Program"; export function getTestUSProgramBrief(): USProgramBrief { - const programBriefId = uuid(); + const programBriefId = randomUUID(); const testUSProgramBrief: USProgramBrief = { id: programBriefId, diff --git a/sdk/communication/communication-short-codes/tsconfig.browser.config.json b/sdk/communication/communication-short-codes/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-short-codes/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-short-codes/tsconfig.json b/sdk/communication/communication-short-codes/tsconfig.json index 84607bdcc149..58b4ca25bcc4 100644 --- a/sdk/communication/communication-short-codes/tsconfig.json +++ b/sdk/communication/communication-short-codes/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure-tools/communication-short-codes": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-short-codes/vitest.browser.config.ts b/sdk/communication/communication-short-codes/vitest.browser.config.ts new file mode 100644 index 000000000000..0f0bef33e382 --- /dev/null +++ b/sdk/communication/communication-short-codes/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 300000, + testTimeout: 300000, + }, + }), +); diff --git a/sdk/communication/communication-short-codes/vitest.config.ts b/sdk/communication/communication-short-codes/vitest.config.ts new file mode 100644 index 000000000000..154f62eeffe9 --- /dev/null +++ b/sdk/communication/communication-short-codes/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 300000, + testTimeout: 300000, + }, + }), +); diff --git a/sdk/communication/communication-tiering/.nycrc b/sdk/communication/communication-tiering/.nycrc deleted file mode 100644 index 29174b423579..000000000000 --- a/sdk/communication/communication-tiering/.nycrc +++ /dev/null @@ -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 -} diff --git a/sdk/communication/communication-tiering/api-extractor.json b/sdk/communication/communication-tiering/api-extractor.json index f326ea93930c..df715d1386da 100644 --- a/sdk/communication/communication-tiering/api-extractor.json +++ b/sdk/communication/communication-tiering/api-extractor.json @@ -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-tiering.d.ts" + "publicTrimmedFilePath": "dist/communication-tiering.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/communication/communication-tiering/karma.conf.js b/sdk/communication/communication-tiering/karma.conf.js deleted file mode 100644 index b7223a7f2b76..000000000000 --- a/sdk/communication/communication-tiering/karma.conf.js +++ /dev/null @@ -1,129 +0,0 @@ -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); - -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); -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": ["sourcemap", "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: [ - "TEST_MODE", - "COMMUNICATION_LIVETEST_STATIC_CONNECTION_STRING", - "INCLUDE_PHONENUMBER_LIVE_TESTS", - "AZURE_PHONE_NUMBER", - "COMMUNICATION_ENDPOINT", - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "COMMUNICATION_SKIP_INT_PHONENUMBERS_TESTS", - "RECORDINGS_RELATIVE_PATH", - ], - - // 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 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", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/communication/communication-tiering/package.json b/sdk/communication/communication-tiering/package.json index 89a150304fd7..d66f5477eacd 100644 --- a/sdk/communication/communication-tiering/package.json +++ b/sdk/communication/communication-tiering/package.json @@ -3,25 +3,25 @@ "version": "1.0.0-beta.1", "description": "Test", "sdk-type": "client", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "types/communication-tiering.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run clean && tsc -p . && dev-tool run bundle && dev-tool run extract-api", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:autorest": "autorest --typescript ./swagger/README.md && rushx format", - "build:browser": "tsc -p . && dev-tool run bundle", + "build:browser": "dev-tool run build-package && dev-tool run bundle", "build:clean": "rush update --recheck && rush rebuild && npm run build", - "build:node": "tsc -p . && dev-tool run bundle", + "build:node": "dev-tool run build-package && dev-tool run bundle", "build:samples": "dev-tool samples publish --force", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test": "npm run integration-test:node && npm run integration-test:browser", "integration-test:browser": "dev-tool run test:browser", - "integration-test:node": "dev-tool run test:node-js-input -- --timeout 300000 'dist-esm/test/public/*.spec.js'", + "integration-test:node": "dev-tool run test:vitest", "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", @@ -30,14 +30,12 @@ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node", "test:watch": "npm run test -- --watch --reporter min", "unit-test": "npm run unit-test:node && npm run unit-test:browser", - "unit-test:browser": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "update-snippets": "echo skipped" }, "files": [ "dist/", - "dist-esm/src/", - "types/communication-tiering.d.ts", "README.md", "LICENSE" ], @@ -73,35 +71,22 @@ "uuid": "^8.3.2" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/core-util": "^1.9.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/identity": "^4.0.1", - "@types/chai": "^4.1.6", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", "@types/uuid": "^8.3.2", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "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", - "nyc": "^17.0.0", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.4" }, "//metadata": { "constantPaths": [ @@ -132,5 +117,43 @@ "requiredResources": { "Azure Communication Services account": "https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource" } + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "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" + } + } } } diff --git a/sdk/communication/communication-tiering/src/generated/src/index.ts b/sdk/communication/communication-tiering/src/generated/src/index.ts index 8302fcac886c..4a82df4b0682 100644 --- a/sdk/communication/communication-tiering/src/generated/src/index.ts +++ b/sdk/communication/communication-tiering/src/generated/src/index.ts @@ -6,6 +6,6 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./models"; -export { TieringClient } from "./tieringClient"; -export * from "./operationsInterfaces"; +export * from "./models/index.js"; +export { TieringClient } from "./tieringClient.js"; +export * from "./operationsInterfaces/index.js"; diff --git a/sdk/communication/communication-tiering/src/generated/src/operations/index.ts b/sdk/communication/communication-tiering/src/generated/src/operations/index.ts index 6e187b6a22c2..ef88a97cc610 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operations/index.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operations/index.ts @@ -6,5 +6,5 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./numberAllotment"; -export * from "./tiering"; +export * from "./numberAllotment.js"; +export * from "./tiering.js"; diff --git a/sdk/communication/communication-tiering/src/generated/src/operations/numberAllotment.ts b/sdk/communication/communication-tiering/src/generated/src/operations/numberAllotment.ts index 026ca61ab667..fcdf476820b7 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operations/numberAllotment.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operations/numberAllotment.ts @@ -6,16 +6,16 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; -import { NumberAllotment } from "../operationsInterfaces"; +import { tracingClient } from "../tracing.js"; +import { NumberAllotment } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { TieringClient } from "../tieringClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { TieringClient } from "../tieringClient.js"; import { NumberAllotmentGetAcquiredNumberLimitsOptionalParams, NumberAllotmentGetAcquiredNumberLimitsResponse -} from "../models"; +} from "../models/index.js"; /** Class containing NumberAllotment operations. */ export class NumberAllotmentImpl implements NumberAllotment { diff --git a/sdk/communication/communication-tiering/src/generated/src/operations/tiering.ts b/sdk/communication/communication-tiering/src/generated/src/operations/tiering.ts index e5b5702162be..f05cfdd7e996 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operations/tiering.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operations/tiering.ts @@ -6,16 +6,16 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -import { tracingClient } from "../tracing"; -import { Tiering } from "../operationsInterfaces"; +import { tracingClient } from "../tracing.js"; +import { Tiering } from "../operationsInterfaces/index.js"; import * as coreClient from "@azure/core-client"; -import * as Mappers from "../models/mappers"; -import * as Parameters from "../models/parameters"; -import { TieringClient } from "../tieringClient"; +import * as Mappers from "../models/mappers.js"; +import * as Parameters from "../models/parameters.js"; +import { TieringClient } from "../tieringClient.js"; import { TieringGetByResourceIdOptionalParams, TieringGetByResourceIdResponse -} from "../models"; +} from "../models/index.js"; /** Class containing Tiering operations. */ export class TieringImpl implements Tiering { diff --git a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/index.ts b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/index.ts index 6e187b6a22c2..ef88a97cc610 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/index.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/index.ts @@ -6,5 +6,5 @@ * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ -export * from "./numberAllotment"; -export * from "./tiering"; +export * from "./numberAllotment.js"; +export * from "./tiering.js"; diff --git a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/numberAllotment.ts b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/numberAllotment.ts index a4928b1575e2..f3ceecc2d6f6 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/numberAllotment.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/numberAllotment.ts @@ -9,7 +9,7 @@ import { NumberAllotmentGetAcquiredNumberLimitsOptionalParams, NumberAllotmentGetAcquiredNumberLimitsResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a NumberAllotment. */ export interface NumberAllotment { diff --git a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/tiering.ts b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/tiering.ts index 24f017e78404..ff52f284e336 100644 --- a/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/tiering.ts +++ b/sdk/communication/communication-tiering/src/generated/src/operationsInterfaces/tiering.ts @@ -9,7 +9,7 @@ import { TieringGetByResourceIdOptionalParams, TieringGetByResourceIdResponse -} from "../models"; +} from "../models/index.js"; /** Interface representing a Tiering. */ export interface Tiering { diff --git a/sdk/communication/communication-tiering/src/generated/src/tieringClient.ts b/sdk/communication/communication-tiering/src/generated/src/tieringClient.ts index 98c89d356085..b0908363adf1 100644 --- a/sdk/communication/communication-tiering/src/generated/src/tieringClient.ts +++ b/sdk/communication/communication-tiering/src/generated/src/tieringClient.ts @@ -12,9 +12,9 @@ import { PipelineResponse, SendRequest } from "@azure/core-rest-pipeline"; -import { NumberAllotmentImpl, TieringImpl } from "./operations"; -import { NumberAllotment, Tiering } from "./operationsInterfaces"; -import { TieringClientOptionalParams } from "./models"; +import { NumberAllotmentImpl, TieringImpl } from "./operations/index.js"; +import { NumberAllotment, Tiering } from "./operationsInterfaces/index.js"; +import { TieringClientOptionalParams } from "./models/index.js"; export class TieringClient extends coreClient.ServiceClient { endpoint: string; diff --git a/sdk/communication/communication-tiering/src/index.ts b/sdk/communication/communication-tiering/src/index.ts index 6eeb1a2e1656..17f2df95b552 100644 --- a/sdk/communication/communication-tiering/src/index.ts +++ b/sdk/communication/communication-tiering/src/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./models"; -export * from "./tieringClient"; +export * from "./models.js"; +export * from "./tieringClient.js"; diff --git a/sdk/communication/communication-tiering/src/models.ts b/sdk/communication/communication-tiering/src/models.ts index 2e12580802ce..ad8b28379d7b 100644 --- a/sdk/communication/communication-tiering/src/models.ts +++ b/sdk/communication/communication-tiering/src/models.ts @@ -25,4 +25,4 @@ export { TrialPhoneNumberUsageSmsBounds, TrialPhoneNumberUsageCallingBounds, Paths190FnhrAdministrationResourcesResourceidTelephoneNumberSummaryGetResponses200ContentApplicationJsonSchema as AssetDetailsModel, -} from "./generated/src/models"; +} from "./generated/src/models/index.js"; diff --git a/sdk/communication/communication-tiering/src/tieringClient.ts b/sdk/communication/communication-tiering/src/tieringClient.ts index feb5b8bc8770..1b9345285e9a 100644 --- a/sdk/communication/communication-tiering/src/tieringClient.ts +++ b/sdk/communication/communication-tiering/src/tieringClient.ts @@ -7,15 +7,15 @@ import type { TieringGetByResourceIdOptionalParams, AcsTier, AssetDetailsModel, -} from "./models"; +} from "./models.js"; import type { CommonClientOptions, InternalClientPipelineOptions } from "@azure/core-client"; import type { KeyCredential, TokenCredential } from "@azure/core-auth"; import { isTokenCredential } from "@azure/core-auth"; import { createCommunicationAuthPolicy } from "@azure/communication-common"; import { isKeyCredential, parseClientArguments } from "@azure/communication-common"; -import { TieringClient as TieringGeneratedClient } from "./generated/src"; -import { logger } from "./utils"; -import { tracingClient } from "./generated/src/tracing"; +import { TieringClient as TieringGeneratedClient } from "./generated/src/index.js"; +import { logger } from "./utils/index.js"; +import { tracingClient } from "./generated/src/tracing.js"; /** * Client options used to configure the TieringGeneratedClient API requests. diff --git a/sdk/communication/communication-tiering/src/utils/index.ts b/sdk/communication/communication-tiering/src/utils/index.ts index 10e04457131b..7708dfaa00db 100644 --- a/sdk/communication/communication-tiering/src/utils/index.ts +++ b/sdk/communication/communication-tiering/src/utils/index.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./logger"; -export * from "./constants"; +export * from "./logger.js"; +export * from "./constants.js"; diff --git a/sdk/communication/communication-tiering/test/public/ctor.spec.ts b/sdk/communication/communication-tiering/test/public/ctor.spec.ts index f4db8797210b..5eda0a6f3c18 100644 --- a/sdk/communication/communication-tiering/test/public/ctor.spec.ts +++ b/sdk/communication/communication-tiering/test/public/ctor.spec.ts @@ -2,32 +2,31 @@ // Licensed under the MIT License. import { AzureKeyCredential } from "@azure/core-auth"; -import type { Context } from "mocha"; -import { TieringClient } from "../../src"; -import { assert } from "chai"; -import { createMockToken } from "./utils/recordedClient"; +import { TieringClient } from "../../src/index.js"; +import { createMockToken } from "./utils/recordedClient.js"; +import { describe, it, assert } from "vitest"; -describe("RecipientVerificationClient - constructor", function () { +describe("RecipientVerificationClient - constructor", () => { const endpoint = "https://contoso.spool.azure.local"; const accessKey = "banana"; - it("successfully instantiates with valid connection string", function () { + it("successfully instantiates with valid connection string", () => { const client = new TieringClient(`endpoint=${endpoint};accesskey=${accessKey}`); assert.instanceOf(client, TieringClient); }); - it("throws with invalid connection string", function () { + it("throws with invalid connection string", () => { assert.throws(() => { new TieringClient(`endpoints=${endpoint};accesskey=${accessKey}`); }); }); - it("successfully instantiates with with endpoint and access key", function () { + it("successfully instantiates with with endpoint and access key", () => { const client = new TieringClient(endpoint, new AzureKeyCredential(accessKey)); assert.instanceOf(client, TieringClient); }); - it("successfully instantiates with with endpoint and managed identity", function (this: Context) { + it("successfully instantiates with with endpoint and managed identity", () => { const client = new TieringClient(endpoint, createMockToken()); assert.instanceOf(client, TieringClient); }); diff --git a/sdk/communication/communication-tiering/test/public/getAcquiredNumberLimit.spec.ts b/sdk/communication/communication-tiering/test/public/getAcquiredNumberLimit.spec.ts index 3f8db786ebe2..24af4a062a5b 100644 --- a/sdk/communication/communication-tiering/test/public/getAcquiredNumberLimit.spec.ts +++ b/sdk/communication/communication-tiering/test/public/getAcquiredNumberLimit.spec.ts @@ -1,31 +1,30 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import type { TieringClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { TieringClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`TieringClient - Get Acquired Number Limits`, function () { +describe(`TieringClient - Get Acquired Number Limits`, () => { let recorder: Recorder; let client: TieringClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async function (ctx) { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async function (ctx) { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("get acquired number limits", async function () { + it("get acquired number limits", { timeout: 30000 }, async () => { // print all acquire number limits const resourceId = env.RESOURCE_ID!; const acquiredNumberLimits = await client.getAcquiredNumberLimits(resourceId); assert.isNotNull(acquiredNumberLimits); - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-tiering/test/public/getTierInfo.spec.ts b/sdk/communication/communication-tiering/test/public/getTierInfo.spec.ts index 74febfcb8aeb..a91b4734bbff 100644 --- a/sdk/communication/communication-tiering/test/public/getTierInfo.spec.ts +++ b/sdk/communication/communication-tiering/test/public/getTierInfo.spec.ts @@ -1,31 +1,30 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { Context } from "mocha"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import type { TieringClient } from "../../src"; -import { assert } from "chai"; -import { createRecordedClient } from "./utils/recordedClient"; +import type { TieringClient } from "../../src/index.js"; +import { createRecordedClient } from "./utils/recordedClient.js"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; -describe(`TieringClient - Get Tier Info`, function () { +describe(`TieringClient - Get Tier Info`, () => { let recorder: Recorder; let client: TieringClient; - beforeEach(async function (this: Context) { - ({ client, recorder } = await createRecordedClient(this)); + beforeEach(async function (ctx) { + ({ client, recorder } = await createRecordedClient(ctx)); }); - afterEach(async function (this: Context) { - if (!this.currentTest?.isPending()) { + afterEach(async function (ctx) { + if (!ctx.task.pending) { await recorder.stop(); } }); - it("get tier info", async function () { + it("get tier info", { timeout: 30000 }, async () => { // print all tier info const resourceId = env.RESOURCE_ID!; const tierInfo = await client.getTierByResourceId(resourceId); assert.isNotNull(tierInfo); - }).timeout(30000); + }); }); diff --git a/sdk/communication/communication-tiering/test/public/utils/recordedClient.ts b/sdk/communication/communication-tiering/test/public/utils/recordedClient.ts index 87f403bb0eda..19af3daa1ecf 100644 --- a/sdk/communication/communication-tiering/test/public/utils/recordedClient.ts +++ b/sdk/communication/communication-tiering/test/public/utils/recordedClient.ts @@ -4,15 +4,14 @@ import * as dotenv from "dotenv"; import type { TokenCredential } from "@azure/identity"; import { ClientSecretCredential, DefaultAzureCredential } from "@azure/identity"; -import type { RecorderStartOptions } from "@azure-tools/test-recorder"; +import type { RecorderStartOptions, TestInfo } from "@azure-tools/test-recorder"; import { Recorder, assertEnvironmentVariable, env, isPlaybackMode, } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { TieringClient } from "../../../src"; +import { TieringClient } from "../../../src/index.js"; import { isNodeLike } from "@azure/core-util"; import { parseConnectionString } from "@azure/communication-common"; @@ -53,9 +52,9 @@ export const recorderOptions: RecorderStartOptions = { }; export async function createRecordedClient( - context: Context, + context: TestInfo, ): Promise> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); await recorder.setMatcher("CustomDefaultMatcher", { excludedHeaders: [ @@ -85,9 +84,9 @@ export function createMockToken(): { } export async function createRecordedClientWithToken( - context: Context, + context: TestInfo, ): Promise | undefined> { - const recorder = new Recorder(context.currentTest); + const recorder = new Recorder(context); await recorder.start(recorderOptions); let credential: TokenCredential; diff --git a/sdk/communication/communication-tiering/tsconfig.browser.config.json b/sdk/communication/communication-tiering/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/communication/communication-tiering/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/communication/communication-tiering/tsconfig.json b/sdk/communication/communication-tiering/tsconfig.json index 762501393d2b..36596c17f3ab 100644 --- a/sdk/communication/communication-tiering/tsconfig.json +++ b/sdk/communication/communication-tiering/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../../tsconfig", "compilerOptions": { - "outDir": "./dist-esm", - "declarationDir": "./types", "paths": { "@azure-tools/communication-tiering": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/communication/communication-tiering/vitest.browser.config.ts b/sdk/communication/communication-tiering/vitest.browser.config.ts new file mode 100644 index 000000000000..3241862f6dcc --- /dev/null +++ b/sdk/communication/communication-tiering/vitest.browser.config.ts @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + hookTimeout: 30000, + testTimeout: 30000, + }, + }), +); diff --git a/sdk/communication/communication-tiering/vitest.config.ts b/sdk/communication/communication-tiering/vitest.config.ts new file mode 100644 index 000000000000..d22586e6a7c1 --- /dev/null +++ b/sdk/communication/communication-tiering/vitest.config.ts @@ -0,0 +1,16 @@ +// 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"], + hookTimeout: 30000, + testTimeout: 30000, + }, + }), +); diff --git a/sdk/core/core-client-rest/CHANGELOG.md b/sdk/core/core-client-rest/CHANGELOG.md index 353fabe79c9b..4509498b8af0 100644 --- a/sdk/core/core-client-rest/CHANGELOG.md +++ b/sdk/core/core-client-rest/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Allow dashes (`-`) in path parameter identifiers. PR [#31731](https://github.com/Azure/azure-sdk-for-js/pull/31731) + ### Other Changes ## 2.3.1 (2024-10-10) diff --git a/sdk/core/core-client-rest/src/urlHelpers.ts b/sdk/core/core-client-rest/src/urlHelpers.ts index 69c6b4f744c9..f30583bbcaa9 100644 --- a/sdk/core/core-client-rest/src/urlHelpers.ts +++ b/sdk/core/core-client-rest/src/urlHelpers.ts @@ -198,7 +198,7 @@ function buildRoutePath( value = encodeURIComponent(value); } - routePath = routePath.replace(/\{\w+\}/, String(value)); + routePath = routePath.replace(/\{[\w-]+\}/, String(value)); } return routePath; } diff --git a/sdk/core/core-client-rest/test/urlHelpers.spec.ts b/sdk/core/core-client-rest/test/urlHelpers.spec.ts index 1337542a2271..0de028aff1db 100644 --- a/sdk/core/core-client-rest/test/urlHelpers.spec.ts +++ b/sdk/core/core-client-rest/test/urlHelpers.spec.ts @@ -123,6 +123,12 @@ describe("urlHelpers", () => { assert.equal(result, `https://example.org/foo?existing=hey&arrayQuery=`); }); + it("should build url with dashes in path parameters", () => { + const result = buildRequestUrl(mockBaseUrl, "/foo/{settings-name}", ["example"]); + + assert.equal(result, `https://example.org/foo/example`); + }); + it("should handle full urls as path", () => { const result = buildRequestUrl(mockBaseUrl, "https://example2.org", []); assert.equal(result, `https://example2.org`); diff --git a/sdk/core/core-rest-pipeline/CHANGELOG.md b/sdk/core/core-rest-pipeline/CHANGELOG.md index 036a21053202..7a2b16b088e4 100644 --- a/sdk/core/core-rest-pipeline/CHANGELOG.md +++ b/sdk/core/core-rest-pipeline/CHANGELOG.md @@ -10,8 +10,6 @@ - Fix an issue in `isStreamComplete` where the method never resolves if the stream is not readable. -### Other Changes - ## 1.17.0 (2024-09-12) ### Features Added diff --git a/sdk/core/ts-http-runtime/src/client/urlHelpers.ts b/sdk/core/ts-http-runtime/src/client/urlHelpers.ts index 69c6b4f744c9..f30583bbcaa9 100644 --- a/sdk/core/ts-http-runtime/src/client/urlHelpers.ts +++ b/sdk/core/ts-http-runtime/src/client/urlHelpers.ts @@ -198,7 +198,7 @@ function buildRoutePath( value = encodeURIComponent(value); } - routePath = routePath.replace(/\{\w+\}/, String(value)); + routePath = routePath.replace(/\{[\w-]+\}/, String(value)); } return routePath; } diff --git a/sdk/core/ts-http-runtime/test/client/urlHelpers.spec.ts b/sdk/core/ts-http-runtime/test/client/urlHelpers.spec.ts index b3b57e36b470..ebdc5d2b2e6e 100644 --- a/sdk/core/ts-http-runtime/test/client/urlHelpers.spec.ts +++ b/sdk/core/ts-http-runtime/test/client/urlHelpers.spec.ts @@ -117,6 +117,12 @@ describe("urlHelpers", () => { assert.equal(result, `https://example.org/foo?existing=hey&arrayQuery=`); }); + it("should build url with dashes in path parameters", () => { + const result = buildRequestUrl(mockBaseUrl, "/foo/{settings-name}", ["example"]); + + assert.equal(result, `https://example.org/foo/example`); + }); + it("should handle full urls as path", () => { const result = buildRequestUrl(mockBaseUrl, "https://example2.org", []); assert.equal(result, `https://example2.org`); diff --git a/sdk/identity/identity-broker/CHANGELOG.md b/sdk/identity/identity-broker/CHANGELOG.md index 28ab8ae20e6e..525680eef02e 100644 --- a/sdk/identity/identity-broker/CHANGELOG.md +++ b/sdk/identity/identity-broker/CHANGELOG.md @@ -10,6 +10,8 @@ ### Other Changes +- Native ESM support has been added, and this package will now emit both CommonJS and ESM. [#31647](https://github.com/Azure/azure-sdk-for-js/pull/31647) + ## 1.1.0 (2024-10-15) ### Features Added @@ -25,9 +27,11 @@ ## 1.0.0 (2023-11-07) ### Features Added + - First GA release of the plugin package `@azure/identity-broker` to [support authentication through broker such as WAM](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-acquire-token-wam). This plugin works with the [`brokerOptions` on `InteractiveBrowserCredential` added in the `@azure/identity` package](https://github.com/Azure/azure-sdk-for-js/pull/26091/). ## 1.0.0-beta.1 (2023-10-23) ### Features Added + - Created a plugin package to [support authentication through broker such as WAM](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-acquire-token-wam). This plugin works with the [`brokerOptions` on `InteractiveBrowserCredential` added in the `@azure/identity` package](https://github.com/Azure/azure-sdk-for-js/pull/26091). diff --git a/sdk/identity/identity-broker/api-extractor.json b/sdk/identity/identity-broker/api-extractor.json index b509f8c8782a..eb522e372d2c 100644 --- a/sdk/identity/identity-broker/api-extractor.json +++ b/sdk/identity/identity-broker/api-extractor.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "mainEntryPointFilePath": "./types/identity-broker/src/index.d.ts", + "mainEntryPointFilePath": "dist/esm/index.d.ts", "docModel": { "enabled": true }, @@ -11,7 +11,7 @@ "dtsRollup": { "enabled": true, "untrimmedFilePath": "", - "publicTrimmedFilePath": "./types/identity-broker.d.ts" + "publicTrimmedFilePath": "dist/identity-broker.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/identity/identity-broker/package.json b/sdk/identity/identity-broker/package.json index cb4b50f13362..a9f2571bd5b5 100644 --- a/sdk/identity/identity-broker/package.json +++ b/sdk/identity/identity-broker/package.json @@ -3,17 +3,17 @@ "version": "1.1.1", "sdk-type": "client", "description": "A native plugin for Azure Identity credentials to enable broker authentication such as WAM", - "main": "dist/index.js", - "module": "dist-esm/identity-broker/src/index.js", - "types": "./types/identity-broker.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", "scripts": { - "build": "npm run extract-api && tsc -p . && dev-tool run bundle", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "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": "dev-tool run vendored rimraf --glob dist dist-esm 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": "echo skipped", @@ -22,19 +22,16 @@ "lint:fix": "eslint package.json api-extractor.json README.md src test --fix --fix-type [problem,suggestion]", "pack": "npm pack 2>&1", "test": "npm run clean && npm run build:test && npm run unit-test && npm run integration-test", - "test:browser": "npm run clean && npm run build:test && npm run unit-test:browser && npm run integration-test:browser", + "test:browser": "echo skipped", "test:node": "npm run clean && 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": "echo skipped", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 300000 --exclude 'test/**/browser/**/*.spec.ts' --exclude 'test/snippets.spec.ts' 'test/**/**/*.spec.ts'", + "unit-test:node": "dev-tool run test:vitest -- --test-timeout 300000", "update-snippets": "dev-tool run update-snippets", "unit-test:manual": "dev-tool run test:node-ts-input -- --timeout 300000 'test/manual/node/popTokenSupport.spec.ts'" }, "files": [ "dist/", - "dist-esm/identity/src", - "dist-esm/identity-broker/src", - "types/identity-broker.d.ts", "README.md", "LICENSE" ], @@ -65,8 +62,8 @@ "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/abort-controller": "^1.1.0", "@azure/core-client": "^1.7.0", "@azure/core-rest-pipeline": "^1.17.0", @@ -74,14 +71,13 @@ "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/logger": "^1.0.4", - "@types/mocha": "^10.0.0", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "eslint": "^9.9.0", - "mocha": "^10.0.0", - "puppeteer": "^23.0.2", - "sinon": "^17.0.0", - "typescript": "~5.6.2" + "playwright": "^1.48.2", + "typescript": "~5.6.2", + "vitest": "^2.1.4" }, "//sampleConfiguration": { "productName": "Azure Identity Brokered Auth Plugin", @@ -92,5 +88,38 @@ "requiredResources": { "Microsoft Entra App Registration": "https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app" } + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser" + ], + "selfLink": false + }, + "browser": "./dist/browser/index.js", + "exports": { + "./package.json": "./package.json", + ".": { + "browser": { + "types": "./dist/browser/index.d.ts", + "default": "./dist/browser/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" + } + } } } diff --git a/sdk/identity/identity-broker/src/index.ts b/sdk/identity/identity-broker/src/index.ts index bbfd0cbcbc13..9d322360ca01 100644 --- a/sdk/identity/identity-broker/src/index.ts +++ b/sdk/identity/identity-broker/src/index.ts @@ -1,10 +1,23 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AzurePluginContext } from "../../identity/src/plugins/provider"; import type { IdentityPlugin } from "@azure/identity"; import { NativeBrokerPlugin } from "@azure/msal-node-extensions"; +/** + * A subset of the AzurePluginContext provided by \@azure/identity + * + * @internal + */ +interface AzurePluginContext { + nativeBrokerPluginControl: NativeBrokerPluginControl; +} + +interface NativeBrokerPluginControl { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + setNativeBroker(nativeBroker: import("@azure/msal-node").INativeBrokerPlugin): void; +} + /** * A plugin that provides WAM Integration for `@azure/identity` * credentials. The plugin API is compatible with `@azure/identity` versions @@ -26,7 +39,6 @@ import { NativeBrokerPlugin } from "@azure/msal-node-extensions"; * }); * ``` */ - export const nativeBrokerPlugin: IdentityPlugin = (context: unknown) => { const { nativeBrokerPluginControl } = context as AzurePluginContext; const brokerPlugin = new NativeBrokerPlugin(); diff --git a/sdk/identity/identity-broker/test/internal/node/interactiveBrowserCredential.spec.ts b/sdk/identity/identity-broker/test/internal/node/interactiveBrowserCredential.spec.ts index 84ddcb142a65..8c1ec3cfc7c8 100644 --- a/sdk/identity/identity-broker/test/internal/node/interactiveBrowserCredential.spec.ts +++ b/sdk/identity/identity-broker/test/internal/node/interactiveBrowserCredential.spec.ts @@ -2,49 +2,42 @@ // Licensed under the MIT License. import type { InteractiveBrowserCredentialNodeOptions } from "@azure/identity"; import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity"; -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; import { PublicClientApplication } from "@azure/msal-node"; -import type Sinon from "sinon"; import type { Recorder } from "@azure-tools/test-recorder"; import { isLiveMode, env, isPlaybackMode } from "@azure-tools/test-recorder"; -import { nativeBrokerPlugin } from "../../../src"; +import { nativeBrokerPlugin } from "../../../src/index.js"; import { isNodeLike } from "@azure/core-util"; -import { assert } from "@azure-tools/test-utils"; -import type http from "http"; +import type http from "node:http"; +import type { MockInstance } from "vitest"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; -describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite) { - let cleanup: MsalTestCleanup; +describe("InteractiveBrowserCredential (internal)", function () { let listen: http.Server | undefined; - let doGetTokenSpy: Sinon.SinonSpy; + let doGetTokenSpy: MockInstance; let recorder: Recorder; - beforeEach(async function (this: Mocha.Context) { - const setup = await msalNodeTestSetup(this.currentTest); - cleanup = setup.cleanup; - recorder = setup.recorder; - - // getTokenSilentSpy = setup.sandbox.spy(MsalNode.prototype, "getTokenSilent"); - - doGetTokenSpy = setup.sandbox.spy(PublicClientApplication.prototype, "acquireTokenInteractive"); + beforeEach(async function (ctx) { + doGetTokenSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenInteractive"); }); + afterEach(async function () { if (listen) { listen.close(); } - await cleanup(); + vi.restoreAllMocks(); }); - it("Throws error when no plugin is imported", async function (this: Mocha.Context) { + + it("Throws error when no plugin is imported", async function (ctx) { if (isNodeLike) { // OSX asks for passwords on CI, so we need to skip these tests from our automation if (process.platform !== "win32") { - this.skip(); + ctx.skip(); } // These tests should not run live because this credential requires user interaction. // currently test with broker is hanging, so skipping in playback mode for the ci if (isLiveMode() || isPlaybackMode()) { - this.skip(); + ctx.skip(); } const winHandle = Buffer.from("srefleqr93285329lskadjffa"); const interactiveBrowserCredentialOptions: InteractiveBrowserCredentialNodeOptions = { @@ -61,19 +54,19 @@ describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite) ); }, "Broker for WAM was requested to be enabled, but no native broker was configured."); } else { - this.skip(); + ctx.skip(); } }); - it("Accepts interactiveBrowserCredentialOptions", async function (this: Mocha.Context) { + it("Accepts interactiveBrowserCredentialOptions", async function (ctx) { if (isNodeLike) { // OSX asks for passwords on CI, so we need to skip these tests from our automation if (process.platform !== "win32") { - this.skip(); + ctx.skip(); } // These tests should not run live because this credential requires user interaction. // currently test with broker is hanging, so skipping in playback mode for the ci if (isLiveMode() || isPlaybackMode()) { - this.skip(); + ctx.skip(); } useIdentityPlugin(nativeBrokerPlugin); const winHandle = Buffer.from("srefleqr93285329lskadjffa"); @@ -94,15 +87,16 @@ describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite) try { const accessToken = await credential.getToken(scope); assert.exists(accessToken.token); - assert.equal(doGetTokenSpy.callCount, 1); - const result = await doGetTokenSpy.lastCall.returnValue; - assert.equal(result.fromNativeBroker, true); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); + expect(doGetTokenSpy.mock.results[0].value).toEqual( + expect.objectContaining({ fromNativeBroker: true }), + ); } catch (e) { console.log(e); - assert.equal(doGetTokenSpy.callCount, 1); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); } } else { - this.skip(); + ctx.skip(); } }); }); diff --git a/sdk/identity/identity-broker/test/manual/node/popTokenAuthenticationPolicy.ts b/sdk/identity/identity-broker/test/manual/node/popTokenAuthenticationPolicy.ts index 53417eb1ca43..c044344f6fd7 100644 --- a/sdk/identity/identity-broker/test/manual/node/popTokenAuthenticationPolicy.ts +++ b/sdk/identity/identity-broker/test/manual/node/popTokenAuthenticationPolicy.ts @@ -9,7 +9,7 @@ import type { SendRequest, PipelinePolicy, } from "@azure/core-rest-pipeline"; -import { createTokenCycler } from "./popTokenCycler"; +import { createTokenCycler } from "./popTokenCycler.js"; /** * The programmatic identifier of the popTokenAuthenticationPolicy. diff --git a/sdk/identity/identity-broker/test/manual/node/popTokenClient.ts b/sdk/identity/identity-broker/test/manual/node/popTokenClient.ts index 99dc26615d05..03557bf76b6a 100644 --- a/sdk/identity/identity-broker/test/manual/node/popTokenClient.ts +++ b/sdk/identity/identity-broker/test/manual/node/popTokenClient.ts @@ -14,9 +14,9 @@ import { createPipelineRequest, createDefaultHttpClient, } from "@azure/core-rest-pipeline"; -import { popTokenAuthenticationPolicy } from "./popTokenAuthenticationPolicy"; +import { popTokenAuthenticationPolicy } from "./popTokenAuthenticationPolicy.js"; import type { TokenCredential } from "@azure/core-auth"; -import { authorizeRequestOnPopTokenChallenge } from "./authRequestPopTokenChallenge"; +import { authorizeRequestOnPopTokenChallenge } from "./authRequestPopTokenChallenge.js"; export async function sendGraphRequest(credential: TokenCredential): Promise { const pipeline = createEmptyPipeline(); diff --git a/sdk/identity/identity-broker/test/manual/node/popTokenSupport.spec.ts b/sdk/identity/identity-broker/test/manual/node/popTokenSupport.spec.ts index b6e6577aa985..20e111370a58 100644 --- a/sdk/identity/identity-broker/test/manual/node/popTokenSupport.spec.ts +++ b/sdk/identity/identity-broker/test/manual/node/popTokenSupport.spec.ts @@ -4,20 +4,20 @@ import type { InteractiveBrowserCredentialNodeOptions } from "@azure/identity"; import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity"; import { env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder"; -import { nativeBrokerPlugin } from "../../../src"; +import { nativeBrokerPlugin } from "../../../src/index.js"; import { isNodeLike } from "@azure/core-util"; -import { sendGraphRequest } from "./popTokenClient"; -import { assert } from "@azure-tools/test-utils"; +import { sendGraphRequest } from "./popTokenClient.js"; +import { describe, it, assert } from "vitest"; -describe("InteractiveBrowserCredential", function (this: Mocha.Suite) { - it("supports pop token authentication", async function (this: Mocha.Context) { +describe("InteractiveBrowserCredential", function () { + it("supports pop token authentication", async function (ctx) { if (isNodeLike) { // OSX asks for passwords on CI, so we need to skip these tests from our automation if (process.platform !== "win32") { - this.skip(); + ctx.skip(); } if (isLiveMode() || isPlaybackMode()) { - this.skip(); + ctx.skip(); } useIdentityPlugin(nativeBrokerPlugin); const winHandle = Buffer.from("srefleqr93285329lskadjffa"); @@ -35,7 +35,7 @@ describe("InteractiveBrowserCredential", function (this: Mocha.Suite) { assert.equal(response.status, 200); assert.exists(response.bodyAsText); } else { - this.skip(); + ctx.skip(); } }); }); diff --git a/sdk/identity/identity-broker/test/snippets.spec.ts b/sdk/identity/identity-broker/test/snippets.spec.ts index d5c3fe6cd8a2..bfe39d768cce 100644 --- a/sdk/identity/identity-broker/test/snippets.spec.ts +++ b/sdk/identity/identity-broker/test/snippets.spec.ts @@ -4,6 +4,7 @@ import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity"; import { nativeBrokerPlugin } from "@azure/identity-broker"; import { setLogLevel } from "@azure/logger"; +import { describe, it } from "vitest"; describe("snippets", function () { it("getting_started", function () { diff --git a/sdk/identity/identity-broker/tsconfig.browser.config.json b/sdk/identity/identity-broker/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/identity/identity-broker/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/identity/identity-broker/tsconfig.json b/sdk/identity/identity-broker/tsconfig.json index 0ebdd89e0edc..5527a9274e35 100644 --- a/sdk/identity/identity-broker/tsconfig.json +++ b/sdk/identity/identity-broker/tsconfig.json @@ -3,12 +3,13 @@ "compilerOptions": { "target": "es2020", "lib": ["DOM"], - "declarationDir": "./types", - "outDir": "./dist-esm", "resolveJsonModule": true, "paths": { "@azure/identity-broker": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*", "test/**/*"] + "include": ["src/**/*.ts", "src/**/*.mts", "src/**/*.cts", "samples-dev/**/*.ts", "test/**/*.ts"] } diff --git a/sdk/identity/identity-broker/vitest.browser.config.ts b/sdk/identity/identity-broker/vitest.browser.config.ts new file mode 100644 index 000000000000..b48c61b2ef46 --- /dev/null +++ b/sdk/identity/identity-broker/vitest.browser.config.ts @@ -0,0 +1,17 @@ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: [ + "dist-test/browser/test/**/*.spec.js", + ], + }, + }), +); diff --git a/sdk/identity/identity-broker/vitest.config.ts b/sdk/identity/identity-broker/vitest.config.ts new file mode 100644 index 000000000000..49798d657fbf --- /dev/null +++ b/sdk/identity/identity-broker/vitest.config.ts @@ -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"], + exclude: ["test/snippets.spec.ts"], + }, + }), +); diff --git a/sdk/identity/identity-cache-persistence/api-extractor.json b/sdk/identity/identity-cache-persistence/api-extractor.json index f7b471ed2265..9d69b233b0ed 100644 --- a/sdk/identity/identity-cache-persistence/api-extractor.json +++ b/sdk/identity/identity-cache-persistence/api-extractor.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "mainEntryPointFilePath": "./types/identity-cache-persistence/src/index.d.ts", + "mainEntryPointFilePath": "./types/src/index.d.ts", "docModel": { "enabled": true }, diff --git a/sdk/identity/identity-cache-persistence/package.json b/sdk/identity/identity-cache-persistence/package.json index 7db12793f96b..3bf3a2962435 100644 --- a/sdk/identity/identity-cache-persistence/package.json +++ b/sdk/identity/identity-cache-persistence/package.json @@ -4,7 +4,7 @@ "sdk-type": "client", "description": "A secure, persistent token cache for Azure Identity credentials that uses the OS secret-management API", "main": "dist/index.js", - "module": "dist-esm/identity-cache-persistence/src/index.js", + "module": "dist-esm/src/index.js", "types": "./types/identity-cache-persistence.d.ts", "scripts": { "build": "npm run clean && npm run extract-api && tsc -p . && dev-tool run bundle", @@ -31,8 +31,7 @@ }, "files": [ "dist/", - "dist-esm/identity/src", - "dist-esm/identity-cache-persistence/src", + "dist-esm/src", "types/identity-cache-persistence.d.ts", "README.md", "LICENSE" diff --git a/sdk/identity/identity-cache-persistence/src/index.ts b/sdk/identity/identity-cache-persistence/src/index.ts index cc924cda695f..3994a733b992 100644 --- a/sdk/identity/identity-cache-persistence/src/index.ts +++ b/sdk/identity/identity-cache-persistence/src/index.ts @@ -1,10 +1,29 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AzurePluginContext } from "../../identity/src/plugins/provider"; -import type { IdentityPlugin } from "@azure/identity"; +import type { IdentityPlugin, TokenCachePersistenceOptions } from "@azure/identity"; import { createPersistenceCachePlugin } from "./provider"; +/** + * Plugin context entries for controlling cache plugins. + */ +interface CachePluginControl { + setPersistence( + persistenceFactory: ( + options?: TokenCachePersistenceOptions, + ) => Promise, + ): void; +} +/** + * Context options passed to a plugin during initialization. + * + * Represents a subset of the context defined in `@azure/identity` + * + */ +interface AzurePluginContext { + cachePluginControl: CachePluginControl; +} + /** * A plugin that provides persistent token caching for `@azure/identity` * credentials. The plugin API is compatible with `@azure/identity` versions diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/clientCertificateCredential.spec.ts b/sdk/identity/identity-cache-persistence/test/internal/node/clientCertificateCredential.spec.ts index e14863ed7f67..1ba48486561d 100644 --- a/sdk/identity/identity-cache-persistence/test/internal/node/clientCertificateCredential.spec.ts +++ b/sdk/identity/identity-cache-persistence/test/internal/node/clientCertificateCredential.spec.ts @@ -6,10 +6,10 @@ import * as path from "path"; -import type { TokenCachePersistenceOptions } from "../../../../identity/src"; -import { ClientCertificateCredential } from "../../../../identity/src"; -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; +import type { TokenCachePersistenceOptions } from "@azure/identity"; +import { ClientCertificateCredential } from "@azure/identity"; +import type { MsalTestCleanup } from "./msalNodeTestSetup"; +import { msalNodeTestSetup } from "./msalNodeTestSetup"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isPlaybackMode } from "@azure-tools/test-recorder"; diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/clientSecretCredential.spec.ts b/sdk/identity/identity-cache-persistence/test/internal/node/clientSecretCredential.spec.ts index 17f3bd8a3b7c..8dff4b9402e5 100644 --- a/sdk/identity/identity-cache-persistence/test/internal/node/clientSecretCredential.spec.ts +++ b/sdk/identity/identity-cache-persistence/test/internal/node/clientSecretCredential.spec.ts @@ -4,10 +4,9 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ /* eslint-disable sort-imports */ -import type { TokenCachePersistenceOptions } from "../../../../identity/src"; -import { ClientSecretCredential } from "../../../../identity/src"; -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; +import type { TokenCachePersistenceOptions } from "@azure/identity"; +import { ClientSecretCredential } from "@azure/identity"; +import { msalNodeTestSetup, type MsalTestCleanup } from "./msalNodeTestSetup"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/deviceCodeCredential.spec.ts b/sdk/identity/identity-cache-persistence/test/internal/node/deviceCodeCredential.spec.ts index 5f4437ae2b80..b5f8651f945d 100644 --- a/sdk/identity/identity-cache-persistence/test/internal/node/deviceCodeCredential.spec.ts +++ b/sdk/identity/identity-cache-persistence/test/internal/node/deviceCodeCredential.spec.ts @@ -4,10 +4,8 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ /* eslint-disable sort-imports */ -import type { TokenCachePersistenceOptions } from "../../../../identity/src"; -import { DeviceCodeCredential } from "../../../../identity/src"; -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; +import { DeviceCodeCredential, type TokenCachePersistenceOptions } from "@azure/identity"; +import { msalNodeTestSetup, type MsalTestCleanup } from "./msalNodeTestSetup"; import type { Recorder } from "@azure-tools/test-recorder"; import { isLiveMode } from "@azure-tools/test-recorder"; diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/msalNodeTestSetup.ts b/sdk/identity/identity-cache-persistence/test/internal/node/msalNodeTestSetup.ts new file mode 100644 index 000000000000..b790125689e5 --- /dev/null +++ b/sdk/identity/identity-cache-persistence/test/internal/node/msalNodeTestSetup.ts @@ -0,0 +1,233 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import type { AuthenticationResult } from "@azure/msal-node"; +import { ConfidentialClientApplication, PublicClientApplication } from "@azure/msal-node"; +import type Sinon from "sinon"; +import { createSandbox } from "sinon"; + +import { Recorder } from "@azure-tools/test-recorder"; +import { Test } from "mocha"; + +const PlaybackTenantId = "12345678-1234-1234-1234-123456789012"; + +export type MsalTestCleanup = () => Promise; + +export interface MsalTestSetupResponse { + cleanup: MsalTestCleanup; + recorder?: Recorder; + sandbox: Sinon.SinonSandbox; +} + +export async function msalNodeTestSetup( + testContext?: Test, + playbackClientId?: string, +): Promise<{ + cleanup: MsalTestCleanup; + recorder: Recorder; + sandbox: Sinon.SinonSandbox; +}>; + +export async function msalNodeTestSetup(stubbedToken: AuthenticationResult): Promise<{ + cleanup: MsalTestCleanup; + sandbox: Sinon.SinonSandbox; +}>; + +export async function msalNodeTestSetup( + testContextOrStubbedToken?: Test | AuthenticationResult, + playbackClientId = "azure_client_id", +): Promise { + const playbackValues = { + correlationId: "client-request-id", + }; + + const sandbox = createSandbox(); + + if (testContextOrStubbedToken instanceof Test || testContextOrStubbedToken === undefined) { + const testContext = testContextOrStubbedToken; + + const recorder = new Recorder(testContext); + recorder.setMatcher("CustomDefaultMatcher", { + excludedHeaders: ["X-AnchorMailbox", "Content-Length", "User-Agent"], + }); + + await recorder.start({ + envSetupForPlayback: { + AZURE_TENANT_ID: PlaybackTenantId, + AZURE_CLIENT_ID: playbackClientId, + AZURE_CLIENT_SECRET: "azure_client_secret", + AZURE_IDENTITY_TEST_TENANTID: PlaybackTenantId, + AZURE_IDENTITY_TEST_USERNAME: "azure_username", + AZURE_IDENTITY_TEST_PASSWORD: "azure_password", + IDENTITY_SP_CLIENT_ID: "", + IDENTITY_SP_TENANT_ID: "", + IDENTITY_SP_CLIENT_SECRET: "", + IDENTITY_SP_CERT_PEM: "", + AZURE_CAE_MANAGEMENT_ENDPOINT: "https://management.azure.com/", + AZURE_CLIENT_CERTIFICATE_PATH: "assets/fake-cert.pem", + AZURE_IDENTITY_MULTI_TENANT_TENANT_ID: "99999999-9999-9999-9999-999999999999", + AZURE_IDENTITY_MULTI_TENANT_CLIENT_ID: "azure_multi_tenant_client_id", + AZURE_IDENTITY_MULTI_TENANT_CLIENT_SECRET: "azure_multi_tenant_client_secret", + }, + sanitizerOptions: { + headerSanitizers: [ + { + key: "User-Agent", + value: "User-Agent", + }, + { + key: "Set-Cookie", + regex: true, + target: `(fpc|esctx)=(?[^;]+)`, + value: "secret_cookie", + groupForReplace: "secret_cookie", + }, + ], + generalSanitizers: [ + { + regex: true, + target: `enter the code [A-Z0-9]* to authenticate`, + value: `enter the code USER_CODE to authenticate`, + }, + ], + }, + }); + + // Playback sanitizers + await recorder.addSanitizers( + { + bodySanitizers: [ + { + regex: true, + target: 'username=[^&"]+', // env sanitizers do not handle matching urlencoded params well (@ character is urlencoded) + value: "username=azure_username", + }, + { + regex: true, + target: 'client_secret=[^&"]+', + value: "client_secret=azure_client_secret", + }, + { + regex: true, + target: `client_assertion=[a-zA-Z0-9-._]*`, + value: "client_assertion=client_assertion", + }, + { + regex: true, + target: 'device_code=[^&"]+', + value: "device_code=DEVICE_CODE", + }, + { + regex: true, + target: `x-client-OS=[a-zA-Z0-9]+`, + value: `x-client-OS=Sanitized`, + }, + { + regex: true, + target: `x-client-CPU=[a-zA-Z0-9]+`, + value: `x-client-CPU=Sanitized`, + }, + { + regex: true, + target: `x-client-VER=[a-zA-Z0-9.-]+`, + value: `x-client-VER=identity-client-version`, + }, + { + regex: true, + target: `client-request-id=[a-zA-Z0-9-]+`, + value: `client-request-id=${playbackValues.correlationId}`, + }, + ], + bodyKeySanitizers: [ + { + jsonPath: "$.device_code", + value: "DEVICE_CODE", + }, + { + jsonPath: "$.bodyProvided.device_code", + value: "DEVICE_CODE", + }, + { + jsonPath: "$.interval", + value: "0", + }, + { + jsonPath: "$.client-request-id", + value: playbackValues.correlationId, + }, + { + jsonPath: "$.access_token", + value: "access_token", + }, + { + jsonPath: "$.bodyProvided.access_token", + value: "access_token", + }, + { + jsonPath: "$.refresh_token", + value: "refresh_token", + }, + { + jsonPath: "$.bodyProvided.refresh_token", + value: "refresh_token", + }, + { + jsonPath: "$.id_token", + value: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtpZCJ9.eyJhdWQiOiJhdWQiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyL3YyLjAiLCJpYXQiOjE2MTUzMzcxNjMsIm5iZiI6MTYxNTMzNzE2MywiZXhwIjoxNjE1MzQxMDYzLCJhaW8iOiJhaW8iLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9pZHAvIiwibmFtZSI6IkRhbmllbCBSb2Ryw61ndWV6Iiwib2lkIjoib2lkIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZGFucm9kcmlAbWljcm9zb2Z0LmNvbSIsInJoIjoicmguIiwic3ViIjoic3ViIiwidGlkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIiwidXRpIjoidXRpIiwidmVyIjoiMi4wIn0=.bm9faWRlYV93aGF0c190aGlz", + }, + { + jsonPath: "$.client_info", + value: + "eyJ1aWQiOiIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwMTIiLCJ1dGlkIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyIn0K", + }, + ], + }, + ["record", "playback"], + ); + + return { + sandbox, + recorder, + async cleanup() { + await recorder.stop(); + sandbox.restore(); + }, + }; + } else { + const stubbedToken = testContextOrStubbedToken; + + const publicClientMethods: Array = [ + "acquireTokenByCode", + "acquireTokenByDeviceCode", + "acquireTokenByRefreshToken", + "acquireTokenByUsernamePassword", + "acquireTokenInteractive", + "acquireTokenSilent", + ]; + const confidentialClientMethods: Array = [ + "acquireTokenByClientCredential", + "acquireTokenByCode", + "acquireTokenByRefreshToken", + "acquireTokenByUsernamePassword", + "acquireTokenOnBehalfOf", + "acquireTokenSilent", + ]; + + publicClientMethods.forEach((method) => + sandbox.stub(PublicClientApplication.prototype, method).callsFake(async () => stubbedToken), + ); + confidentialClientMethods.forEach((method) => + sandbox + .stub(ConfidentialClientApplication.prototype, method) + .callsFake(async () => stubbedToken), + ); + + return { + sandbox, + async cleanup() { + sandbox.restore(); + }, + }; + } +} diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/setup.spec.ts b/sdk/identity/identity-cache-persistence/test/internal/node/setup.spec.ts index 0605dd54566d..3dd43933187c 100644 --- a/sdk/identity/identity-cache-persistence/test/internal/node/setup.spec.ts +++ b/sdk/identity/identity-cache-persistence/test/internal/node/setup.spec.ts @@ -5,7 +5,7 @@ // We need to set up the plugin for the tests! -import { useIdentityPlugin } from "../../../../identity/src"; +import { useIdentityPlugin } from "@azure/identity"; // The persistence tests have to run on the same version of Node that's used to // install dependencies, currently 16. diff --git a/sdk/identity/identity-cache-persistence/test/internal/node/usernamePasswordCredential.spec.ts b/sdk/identity/identity-cache-persistence/test/internal/node/usernamePasswordCredential.spec.ts index 725f5f892734..e6aa48f8dab1 100644 --- a/sdk/identity/identity-cache-persistence/test/internal/node/usernamePasswordCredential.spec.ts +++ b/sdk/identity/identity-cache-persistence/test/internal/node/usernamePasswordCredential.spec.ts @@ -4,17 +4,17 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ /* eslint-disable sort-imports */ -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import type { TokenCachePersistenceOptions } from "../../../../identity/src"; -import { UsernamePasswordCredential } from "../../../../identity/src"; +import type { TokenCachePersistenceOptions } from "@azure/identity"; +import { UsernamePasswordCredential } from "@azure/identity"; import { PublicClientApplication } from "@azure/msal-node"; import type Sinon from "sinon"; import assert from "assert"; import { createPersistence } from "./setup.spec"; +import type { MsalTestCleanup } from "./msalNodeTestSetup"; +import { msalNodeTestSetup } from "./msalNodeTestSetup"; describe("UsernamePasswordCredential (internal)", function (this: Mocha.Suite) { let cleanup: MsalTestCleanup; diff --git a/sdk/identity/identity-vscode/api-extractor.json b/sdk/identity/identity-vscode/api-extractor.json index 52d0268dd182..9ce43119c136 100644 --- a/sdk/identity/identity-vscode/api-extractor.json +++ b/sdk/identity/identity-vscode/api-extractor.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "mainEntryPointFilePath": "./types/identity-vscode/src/index.d.ts", + "mainEntryPointFilePath": "./types/src/index.d.ts", "docModel": { "enabled": true }, diff --git a/sdk/identity/identity-vscode/package.json b/sdk/identity/identity-vscode/package.json index 808132c27869..f493ac4c0783 100644 --- a/sdk/identity/identity-vscode/package.json +++ b/sdk/identity/identity-vscode/package.json @@ -4,7 +4,7 @@ "sdk-type": "client", "description": "Use the Azure Account extension for Visual Studio Code to authenticate with Azure Identity", "main": "dist/index.js", - "module": "dist-esm/identity-vscode/src/index.js", + "module": "dist-esm/src/index.js", "types": "./types/identity-vscode.d.ts", "scripts": { "build": "npm run clean && npm run extract-api && tsc -p . && dev-tool run bundle", @@ -31,8 +31,7 @@ }, "files": [ "dist/", - "dist-esm/identity/src", - "dist-esm/identity-vscode/src", + "dist-esm/src", "types/identity-vscode.d.ts", "README.md", "LICENSE" diff --git a/sdk/identity/identity-vscode/src/index.ts b/sdk/identity/identity-vscode/src/index.ts index 2715f9877a6e..e12da3a65620 100644 --- a/sdk/identity/identity-vscode/src/index.ts +++ b/sdk/identity/identity-vscode/src/index.ts @@ -1,12 +1,37 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AzurePluginContext } from "../../identity/src/plugins/provider"; import type { IdentityPlugin } from "@azure/identity"; import keytar from "keytar"; const VSCodeServiceName = "VS Code Azure"; +/** + * A function that searches for credentials in the Visual Studio Code credential store. + * + * @returns an array of credentials (username and password) + */ +type VSCodeCredentialFinder = () => Promise>; + +/** + * Plugin context entries for controlling VisualStudioCodeCredential. + */ +interface VisualStudioCodeCredentialControl { + setVsCodeCredentialFinder(finder: VSCodeCredentialFinder): void; +} + +/** + * Context options passed to a plugin during initialization. + * + * Plugin authors are responsible for casting their plugin context values + * to this type. + * + * @internal + */ +interface AzurePluginContext { + vsCodeCredentialControl: VisualStudioCodeCredentialControl; +} + /** * A plugin that provides the dependencies of `VisualStudioCodeCredential` * and enables it within `@azure/identity`. The plugin API is compatible with diff --git a/sdk/identity/identity-vscode/test/public/node/visualStudioCodeCredential.spec.ts b/sdk/identity/identity-vscode/test/public/node/visualStudioCodeCredential.spec.ts index ae303c57b374..5c5b29b3b845 100644 --- a/sdk/identity/identity-vscode/test/public/node/visualStudioCodeCredential.spec.ts +++ b/sdk/identity/identity-vscode/test/public/node/visualStudioCodeCredential.spec.ts @@ -5,8 +5,6 @@ /* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable sort-imports */ -import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup"; import type { Recorder } from "@azure-tools/test-recorder"; import { isRecordMode } from "@azure-tools/test-recorder"; import { VisualStudioCodeCredential } from "@azure/identity"; @@ -22,18 +20,11 @@ const mockedResponse = [ // TODO: Enable again once the VisualStudio cache bug is fixed. describe.skip("VisualStudioCodeCredential", function (this: Mocha.Suite) { - let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Mocha.Context) { - const setup = await msalNodeTestSetup(this.currentTest); - cleanup = setup.cleanup; - recorder = setup.recorder; - }); + beforeEach(async function (this: Mocha.Context) {}); - afterEach(async function () { - await cleanup(); - }); + afterEach(async function () {}); const scope = "https://graph.microsoft.com/.default"; diff --git a/sdk/identity/identity/.nycrc b/sdk/identity/identity/.nycrc deleted file mode 100644 index 320eddfeffb9..000000000000 --- a/sdk/identity/identity/.nycrc +++ /dev/null @@ -1,19 +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 - } diff --git a/sdk/identity/identity/CHANGELOG.md b/sdk/identity/identity/CHANGELOG.md index f5361623356b..abb83cc9ebfc 100644 --- a/sdk/identity/identity/CHANGELOG.md +++ b/sdk/identity/identity/CHANGELOG.md @@ -14,6 +14,8 @@ - Mark `AzureAuthorityHosts.AZURE_GERMANY` deprecated as the Germany cloud closed in 2021. [#31519](https://github.com/Azure/azure-sdk-for-js/pull/31519) +- Native ESM support has been added, and this package will now emit both CommonJS and ESM. [#31647](https://github.com/Azure/azure-sdk-for-js/pull/31647) + ## 4.5.0 (2024-10-15) ### Features Added diff --git a/sdk/identity/identity/api-extractor.json b/sdk/identity/identity/api-extractor.json index 713d80c9364b..cac285687f43 100644 --- a/sdk/identity/identity/api-extractor.json +++ b/sdk/identity/identity/api-extractor.json @@ -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/identity.d.ts" + "publicTrimmedFilePath": "dist/identity.d.ts" }, "messages": { "tsdocMessageReporting": { diff --git a/sdk/identity/identity/karma.conf.js b/sdk/identity/identity/karma.conf.js deleted file mode 100644 index 5c7b340b107e..000000000000 --- a/sdk/identity/identity/karma.conf.js +++ /dev/null @@ -1,123 +0,0 @@ -const { relativeRecordingsPath } = require("@azure-tools/test-recorder"); -process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); - -// https://github.com/karma-runner/karma-chrome-launcher -process.env.CHROME_BIN = require("puppeteer").executablePath(); -require("dotenv").config(); - -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", - { pattern: "dist-test/index.browser.js.map", type: "html", included: false, served: true }, - ], - - // 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": ["sourcemap", "env"], - }, - - // 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: [ - "AZURE_CLIENT_ID", - "AZURE_CLIENT_SECRET", - "AZURE_TENANT_ID", - "TEST_MODE", - "RECORDINGS_RELATIVE_PATH", - ], - - // 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 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, - - // --no-sandbox allows our tests to run in Linux without having to change the system. - // --disable-web-security allows us to authenticate from the browser without having to write tests using interactive auth, which would be far more complex. - browsers: ["ChromeHeadlessNoSandbox"], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: "ChromeHeadless", - flags: ["--no-sandbox", "--disable-web-security"], - }, - }, - - // 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", - }, - }, - }); -}; diff --git a/sdk/identity/identity/package.json b/sdk/identity/identity/package.json index 59b809f37b49..1e65c63921bd 100644 --- a/sdk/identity/identity/package.json +++ b/sdk/identity/identity/package.json @@ -3,37 +3,10 @@ "sdk-type": "client", "version": "4.5.1", "description": "Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID", - "main": "dist/index.js", - "module": "dist-esm/src/index.js", - "types": "./types/identity.d.ts", - "browser": { - "os": false, - "process": false, - "./dist-esm/src/credentials/azureCliCredential.js": "./dist-esm/src/credentials/azureCliCredential.browser.js", - "./dist-esm/src/credentials/azureDeveloperCliCredential.js": "./dist-esm/src/credentials/azureDeveloperCliCredential.browser.js", - "./dist-esm/src/credentials/environmentCredential.js": "./dist-esm/src/credentials/environmentCredential.browser.js", - "./dist-esm/src/credentials/managedIdentityCredential/index.js": "./dist-esm/src/credentials/managedIdentityCredential/index.browser.js", - "./dist-esm/src/credentials/clientCertificateCredential.js": "./dist-esm/src/credentials/clientCertificateCredential.browser.js", - "./dist-esm/src/credentials/clientSecretCredential.js": "./dist-esm/src/credentials/clientSecretCredential.browser.js", - "./dist-esm/src/credentials/clientAssertionCredential.js": "./dist-esm/src/credentials/clientAssertionCredential.browser.js", - "./dist-esm/src/credentials/deviceCodeCredential.js": "./dist-esm/src/credentials/deviceCodeCredential.browser.js", - "./dist-esm/src/credentials/defaultAzureCredential.js": "./dist-esm/src/credentials/defaultAzureCredential.browser.js", - "./dist-esm/src/credentials/authorizationCodeCredential.js": "./dist-esm/src/credentials/authorizationCodeCredential.browser.js", - "./dist-esm/src/credentials/interactiveBrowserCredential.js": "./dist-esm/src/credentials/interactiveBrowserCredential.browser.js", - "./dist-esm/src/credentials/visualStudioCodeCredential.js": "./dist-esm/src/credentials/visualStudioCodeCredential.browser.js", - "./dist-esm/src/credentials/usernamePasswordCredential.js": "./dist-esm/src/credentials/usernamePasswordCredential.browser.js", - "./dist-esm/src/credentials/azurePowerShellCredential.js": "./dist-esm/src/credentials/azurePowerShellCredential.browser.js", - "./dist-esm/src/credentials/azureApplicationCredential.js": "./dist-esm/src/credentials/azureApplicationCredential.browser.js", - "./dist-esm/src/credentials/azurePipelinesCredential.js": "./dist-esm/src/credentials/azurePipelinesCredential.browser.js", - "./dist-esm/src/credentials/onBehalfOfCredential.js": "./dist-esm/src/credentials/onBehalfOfCredential.browser.js", - "./dist-esm/src/credentials/workloadIdentityCredential.js": "./dist-esm/src/credentials/workloadIdentityCredential.browser.js", - "./dist-esm/src/msal/msal.js": "./dist-esm/src/msal/msal.browser.js", - "./dist-esm/src/util/authHostEnv.js": "./dist-esm/src/util/authHostEnv.browser.js", - "./dist-esm/src/util/processMultiTenantRequest.js": "./dist-esm/src/util/processMultiTenantRequest.browser.js", - "./dist-esm/src/tokenCache/TokenCachePersistence.js": "./dist-esm/src/tokenCache/TokenCachePersistence.browser.js", - "./dist-esm/src/plugins/consumer.js": "./dist-esm/src/plugins/consumer.browser.js", - "./dist-esm/test/httpRequests.js": "./dist-esm/test/httpRequests.browser.js" - }, + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/commonjs/index.d.ts", + "browser": "./dist/browser/index.js", "//sampleConfiguration": { "productName": "Azure Identity", "productSlugs": [ @@ -46,34 +19,32 @@ } }, "scripts": { - "build": "npm run clean && npm run extract-api && tsc -p . && dev-tool run bundle", + "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api", "build:samples": "echo Obsolete.", "build:test": "echo skipped. actual commands inlined in browser test scripts", "check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "clean": "dev-tool run vendored rimraf --glob dist dist-* types *.tgz *.log", "execute:samples": "dev-tool samples run samples-dev", - "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\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", "integration-test": "npm run integration-test:node && npm run integration-test:browser", "integration-test:browser": "echo skipped", - "integration-test:managed-identity": "dev-tool run test:node-ts-input -- --timeout 180000 'test/integration/**/*.spec.ts'", - "integration-test:node": "dev-tool run test:node-ts-input -- --timeout 180000 'test/public/node/*.spec.ts' 'test/internal/node/*.spec.ts'", + "integration-test:managed-identity": "dev-tool run test:vitest -- --test-timeout 180000 'test/integration/**/*.spec.ts'", + "integration-test:node": "dev-tool run test:vitest -- --test-timeout 180000 'test/public/node/*.spec.ts' 'test/internal/node/*.spec.ts'", "lint": "eslint package.json api-extractor.json src test", "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]", "pack": "npm pack 2>&1", "test": "npm run clean && npm run build:test && npm run unit-test && npm run integration-test", - "test:browser": "npm run clean && tsc -p . && dev-tool run bundle && npm run unit-test:browser && npm run integration-test:browser", + "test:browser": "npm run unit-test:browser && npm run integration-test:browser", "test:node": "npm run clean && 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": "dev-tool run test:browser", - "unit-test:node": "dev-tool run test:node-ts-input -- --timeout 300000 --exclude 'test/**/browser/**/*.spec.ts' --exclude 'test/snippets.spec.ts' --exclude 'test/integration/**/*.spec.ts' 'test/**/**/*.spec.ts'", + "unit-test:browser": "npm run clean && dev-tool run build-package && dev-tool run build-test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", "unit-test:node:no-timeouts": "dev-tool run test:node-ts-input -- --timeout Infinite --exclude 'test/snippets.spec.ts' --exclude 'test/**/browser/**/*.spec.ts' 'test/**/**/*.spec.ts'", "update-snippets": "dev-tool run update-snippets" }, "files": [ "dist/", - "dist-esm/src/", - "types/identity.d.ts", "README.md", "LICENSE" ], @@ -119,45 +90,63 @@ "@azure/msal-browser": "^3.26.1", "events": "^3.0.0", "jws": "^4.0.0", - "open": "^8.0.0", + "open": "^10.1.0", "stoppable": "^1.1.0", "tslib": "^2.2.0" }, "devDependencies": { - "@azure-tools/test-recorder": "^3.0.0", - "@azure-tools/test-utils": "^1.0.1", + "@azure-tools/test-recorder": "^4.1.0", + "@azure-tools/test-utils-vitest": "^1.0.0", "@azure/dev-tool": "^1.0.0", "@azure/eslint-plugin-azure-sdk": "^3.0.0", "@azure/keyvault-keys": "^4.2.0", - "@types/chai": "^4.1.6", "@types/jsonwebtoken": "^9.0.0", "@types/jws": "^3.2.2", - "@types/mocha": "^10.0.0", "@types/ms": "^0.7.31", "@types/node": "^18.0.0", - "@types/sinon": "^17.0.0", "@types/stoppable": "^1.1.0", - "@types/uuid": "^8.0.0", - "chai": "^4.2.0", + "@vitest/browser": "^2.1.4", + "@vitest/coverage-istanbul": "^2.1.4", "dotenv": "^16.0.0", "eslint": "^9.9.0", "inherits": "^2.0.3", "jsonwebtoken": "^9.0.0", - "karma": "^6.2.0", - "karma-chrome-launcher": "^3.0.0", - "karma-coverage": "^2.0.0", - "karma-env-preprocessor": "^0.1.1", - "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", "ms": "^2.1.3", - "nyc": "^17.0.0", - "puppeteer": "^23.0.2", - "sinon": "^17.0.0", - "ts-node": "^10.0.0", + "playwright": "^1.48.2", "typescript": "~5.6.2", - "util": "^0.12.1" + "util": "^0.12.1", + "vitest": "^2.1.4" + }, + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser" + ], + "selfLink": false + }, + "exports": { + "./package.json": "./package.json", + ".": { + "browser": { + "types": "./dist/browser/index.d.ts", + "default": "./dist/browser/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" + } + } } } diff --git a/sdk/identity/identity/src/client/identityClient.ts b/sdk/identity/identity/src/client/identityClient.ts index 9dc6520f07bc..2181170ef2f1 100644 --- a/sdk/identity/identity/src/client/identityClient.ts +++ b/sdk/identity/identity/src/client/identityClient.ts @@ -8,17 +8,17 @@ import { isNode } from "@azure/core-util"; import type { PipelineRequest, PipelineResponse } from "@azure/core-rest-pipeline"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; import type { AbortSignalLike } from "@azure/abort-controller"; -import { AuthenticationError, AuthenticationErrorName } from "../errors"; -import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint"; -import { DefaultAuthorityHost, SDK_VERSION } from "../constants"; -import { tracingClient } from "../util/tracing"; -import { logger } from "../util/logging"; -import type { TokenCredentialOptions } from "../tokenCredentialOptions"; -import type { TokenResponseParsedBody } from "../credentials/managedIdentityCredential/utils"; +import { AuthenticationError, AuthenticationErrorName } from "../errors.js"; +import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint.js"; +import { DefaultAuthorityHost, SDK_VERSION } from "../constants.js"; +import { tracingClient } from "../util/tracing.js"; +import { logger } from "../util/logging.js"; +import type { TokenCredentialOptions } from "../tokenCredentialOptions.js"; +import type { TokenResponseParsedBody } from "../credentials/managedIdentityCredential/utils.js"; import { parseExpirationTimestamp, parseRefreshTimestamp, -} from "../credentials/managedIdentityCredential/utils"; +} from "../credentials/managedIdentityCredential/utils.js"; const noCorrelationId = "noCorrelationId"; diff --git a/sdk/identity/identity/src/credentials/authorizationCodeCredential.browser.ts b/sdk/identity/identity/src/credentials/authorizationCodeCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/authorizationCodeCredential.browser.ts rename to sdk/identity/identity/src/credentials/authorizationCodeCredential-browser.mts index a60af240b740..d1dd877d4692 100644 --- a/sdk/identity/identity/src/credentials/authorizationCodeCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/authorizationCodeCredential-browser.mts @@ -2,8 +2,8 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; -import type { AuthorizationCodeCredentialOptions } from "./authorizationCodeCredentialOptions"; +import { credentialLogger, formatError } from "../util/logging.js"; +import type { AuthorizationCodeCredentialOptions } from "./authorizationCodeCredentialOptions.js"; const BrowserNotSupportedError = new Error( "AuthorizationCodeCredential is not supported in the browser. InteractiveBrowserCredential is more appropriate for this use case.", diff --git a/sdk/identity/identity/src/credentials/authorizationCodeCredential.ts b/sdk/identity/identity/src/credentials/authorizationCodeCredential.ts index 44476bc934c8..44dc18ed4e99 100644 --- a/sdk/identity/identity/src/credentials/authorizationCodeCredential.ts +++ b/sdk/identity/identity/src/credentials/authorizationCodeCredential.ts @@ -5,14 +5,14 @@ import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core- import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import type { AuthorizationCodeCredentialOptions } from "./authorizationCodeCredentialOptions"; -import { checkTenantId } from "../util/tenantIdUtils"; -import { credentialLogger } from "../util/logging"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; +} from "../util/tenantIdUtils.js"; +import type { AuthorizationCodeCredentialOptions } from "./authorizationCodeCredentialOptions.js"; +import { checkTenantId } from "../util/tenantIdUtils.js"; +import { credentialLogger } from "../util/logging.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; const logger = credentialLogger("AuthorizationCodeCredential"); diff --git a/sdk/identity/identity/src/credentials/authorizationCodeCredentialOptions.ts b/sdk/identity/identity/src/credentials/authorizationCodeCredentialOptions.ts index 479ac66e4ccc..7ffab4cc45f4 100644 --- a/sdk/identity/identity/src/credentials/authorizationCodeCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/authorizationCodeCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link AuthorizationCodeCredential} diff --git a/sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts b/sdk/identity/identity/src/credentials/azureApplicationCredential-browser.mts similarity index 94% rename from sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts rename to sdk/identity/identity/src/credentials/azureApplicationCredential-browser.mts index 377f9cc029d9..7e5a91d4fec0 100644 --- a/sdk/identity/identity/src/credentials/azureApplicationCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azureApplicationCredential-browser.mts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; import type { AccessToken } from "@azure/core-auth"; -import { ChainedTokenCredential } from "./chainedTokenCredential"; -import type { TokenCredentialOptions } from "../tokenCredentialOptions"; +import { ChainedTokenCredential } from "./chainedTokenCredential.js"; +import type { TokenCredentialOptions } from "../tokenCredentialOptions.js"; const BrowserNotSupportedError = new Error( "ApplicationCredential is not supported in the browser. Use InteractiveBrowserCredential instead.", diff --git a/sdk/identity/identity/src/credentials/azureApplicationCredential.ts b/sdk/identity/identity/src/credentials/azureApplicationCredential.ts index 0ede7dd69f2e..48f4f2500d87 100644 --- a/sdk/identity/identity/src/credentials/azureApplicationCredential.ts +++ b/sdk/identity/identity/src/credentials/azureApplicationCredential.ts @@ -4,10 +4,10 @@ import { createDefaultManagedIdentityCredential, createEnvironmentCredential, -} from "./defaultAzureCredential"; +} from "./defaultAzureCredential.js"; -import type { AzureApplicationCredentialOptions } from "./azureApplicationCredentialOptions"; -import { ChainedTokenCredential } from "./chainedTokenCredential"; +import type { AzureApplicationCredentialOptions } from "./azureApplicationCredentialOptions.js"; +import { ChainedTokenCredential } from "./chainedTokenCredential.js"; /** * Provides a default {@link ChainedTokenCredential} configuration that should diff --git a/sdk/identity/identity/src/credentials/azureApplicationCredentialOptions.ts b/sdk/identity/identity/src/credentials/azureApplicationCredentialOptions.ts index a4e1a35c5e76..8fa45a76c60b 100644 --- a/sdk/identity/identity/src/credentials/azureApplicationCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/azureApplicationCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Provides options to configure the {@link AzureApplicationCredential} class. diff --git a/sdk/identity/identity/src/credentials/azureCliCredential.browser.ts b/sdk/identity/identity/src/credentials/azureCliCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/azureCliCredential.browser.ts rename to sdk/identity/identity/src/credentials/azureCliCredential-browser.mts index ae00807f4ad4..b8b5dcd9f1f7 100644 --- a/sdk/identity/identity/src/credentials/azureCliCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azureCliCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error("AzureCliCredential is not supported in the browser."); const logger = credentialLogger("AzureCliCredential"); diff --git a/sdk/identity/identity/src/credentials/azureCliCredential.ts b/sdk/identity/identity/src/credentials/azureCliCredential.ts index 6e03a39819eb..b63242382e61 100644 --- a/sdk/identity/identity/src/credentials/azureCliCredential.ts +++ b/sdk/identity/identity/src/credentials/azureCliCredential.ts @@ -6,15 +6,15 @@ import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; -import { ensureValidScopeForDevTimeCreds, getScopeResource } from "../util/scopeUtils"; +} from "../util/tenantIdUtils.js"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; +import { ensureValidScopeForDevTimeCreds, getScopeResource } from "../util/scopeUtils.js"; -import type { AzureCliCredentialOptions } from "./azureCliCredentialOptions"; -import { CredentialUnavailableError } from "../errors"; +import type { AzureCliCredentialOptions } from "./azureCliCredentialOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; import child_process from "child_process"; -import { tracingClient } from "../util/tracing"; -import { checkSubscription } from "../util/subscriptionUtils"; +import { tracingClient } from "../util/tracing.js"; +import { checkSubscription } from "../util/subscriptionUtils.js"; /** * Mockable reference to the CLI credential cliCredentialFunctions diff --git a/sdk/identity/identity/src/credentials/azureCliCredentialOptions.ts b/sdk/identity/identity/src/credentials/azureCliCredentialOptions.ts index 7e71f47a4940..a54e6e9300ac 100644 --- a/sdk/identity/identity/src/credentials/azureCliCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/azureCliCredentialOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link AzureCliCredential} diff --git a/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.browser.ts b/sdk/identity/identity/src/credentials/azureDeveloperCliCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/azureDeveloperCliCredential.browser.ts rename to sdk/identity/identity/src/credentials/azureDeveloperCliCredential-browser.mts index 3aa21eafc64e..d5c5138e1874 100644 --- a/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azureDeveloperCliCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "AzureDeveloperCliCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.ts b/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.ts index a713281cfc5c..0b50686d6067 100644 --- a/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.ts +++ b/sdk/identity/identity/src/credentials/azureDeveloperCliCredential.ts @@ -2,17 +2,17 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; -import type { AzureDeveloperCliCredentialOptions } from "./azureDeveloperCliCredentialOptions"; -import { CredentialUnavailableError } from "../errors"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; +import type { AzureDeveloperCliCredentialOptions } from "./azureDeveloperCliCredentialOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; import child_process from "child_process"; import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import { tracingClient } from "../util/tracing"; -import { ensureValidScopeForDevTimeCreds } from "../util/scopeUtils"; +} from "../util/tenantIdUtils.js"; +import { tracingClient } from "../util/tracing.js"; +import { ensureValidScopeForDevTimeCreds } from "../util/scopeUtils.js"; /** * Mockable reference to the Developer CLI credential cliCredentialFunctions diff --git a/sdk/identity/identity/src/credentials/azureDeveloperCliCredentialOptions.ts b/sdk/identity/identity/src/credentials/azureDeveloperCliCredentialOptions.ts index 27ed72d40cb2..6b31a085d5a7 100644 --- a/sdk/identity/identity/src/credentials/azureDeveloperCliCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/azureDeveloperCliCredentialOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link AzureDeveloperCliCredential} diff --git a/sdk/identity/identity/src/credentials/azurePipelinesCredential.browser.ts b/sdk/identity/identity/src/credentials/azurePipelinesCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/azurePipelinesCredential.browser.ts rename to sdk/identity/identity/src/credentials/azurePipelinesCredential-browser.mts index c34011644a10..de07ee555504 100644 --- a/sdk/identity/identity/src/credentials/azurePipelinesCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azurePipelinesCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "AzurePipelinesCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/azurePipelinesCredential.ts b/sdk/identity/identity/src/credentials/azurePipelinesCredential.ts index fe4038fe6ce2..b9e5527c1226 100644 --- a/sdk/identity/identity/src/credentials/azurePipelinesCredential.ts +++ b/sdk/identity/identity/src/credentials/azurePipelinesCredential.ts @@ -2,15 +2,15 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { AuthenticationError, CredentialUnavailableError } from "../errors"; +import { AuthenticationError, CredentialUnavailableError } from "../errors.js"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; -import type { AzurePipelinesCredentialOptions } from "./azurePipelinesCredentialOptions"; -import { ClientAssertionCredential } from "./clientAssertionCredential"; -import { IdentityClient } from "../client/identityClient"; +import type { AzurePipelinesCredentialOptions } from "./azurePipelinesCredentialOptions.js"; +import { ClientAssertionCredential } from "./clientAssertionCredential.js"; +import { IdentityClient } from "../client/identityClient.js"; import type { PipelineResponse } from "@azure/core-rest-pipeline"; -import { checkTenantId } from "../util/tenantIdUtils"; -import { credentialLogger } from "../util/logging"; +import { checkTenantId } from "../util/tenantIdUtils.js"; +import { credentialLogger } from "../util/logging.js"; const credentialName = "AzurePipelinesCredential"; const logger = credentialLogger(credentialName); diff --git a/sdk/identity/identity/src/credentials/azurePipelinesCredentialOptions.ts b/sdk/identity/identity/src/credentials/azurePipelinesCredentialOptions.ts index e5ddc67c0c79..50a9b6027975 100644 --- a/sdk/identity/identity/src/credentials/azurePipelinesCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/azurePipelinesCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Optional parameters for the {@link AzurePipelinesCredential} class. diff --git a/sdk/identity/identity/src/credentials/azurePowerShellCredential.browser.ts b/sdk/identity/identity/src/credentials/azurePowerShellCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/azurePowerShellCredential.browser.ts rename to sdk/identity/identity/src/credentials/azurePowerShellCredential-browser.mts index a9ad0d68cd36..5cc29649edf8 100644 --- a/sdk/identity/identity/src/credentials/azurePowerShellCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/azurePowerShellCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "AzurePowerShellCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts b/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts index 1581f3555c3e..5847a63a7d10 100644 --- a/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts +++ b/sdk/identity/identity/src/credentials/azurePowerShellCredential.ts @@ -6,14 +6,14 @@ import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; -import { ensureValidScopeForDevTimeCreds, getScopeResource } from "../util/scopeUtils"; +} from "../util/tenantIdUtils.js"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; +import { ensureValidScopeForDevTimeCreds, getScopeResource } from "../util/scopeUtils.js"; -import type { AzurePowerShellCredentialOptions } from "./azurePowerShellCredentialOptions"; -import { CredentialUnavailableError } from "../errors"; -import { processUtils } from "../util/processUtils"; -import { tracingClient } from "../util/tracing"; +import type { AzurePowerShellCredentialOptions } from "./azurePowerShellCredentialOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; +import { processUtils } from "../util/processUtils.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("AzurePowerShellCredential"); diff --git a/sdk/identity/identity/src/credentials/azurePowerShellCredentialOptions.ts b/sdk/identity/identity/src/credentials/azurePowerShellCredentialOptions.ts index 15cd9ac8101d..9e0e588589ab 100644 --- a/sdk/identity/identity/src/credentials/azurePowerShellCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/azurePowerShellCredentialOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link AzurePowerShellCredential} diff --git a/sdk/identity/identity/src/credentials/brokerAuthOptions.ts b/sdk/identity/identity/src/credentials/brokerAuthOptions.ts index 9a79fde0f45a..ccccb7b14ccf 100644 --- a/sdk/identity/identity/src/credentials/brokerAuthOptions.ts +++ b/sdk/identity/identity/src/credentials/brokerAuthOptions.ts @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { BrokerOptions } from "../msal/nodeFlows/brokerOptions"; +import type { BrokerOptions } from "../msal/nodeFlows/brokerOptions.js"; /** * Configuration options for InteractiveBrowserCredential diff --git a/sdk/identity/identity/src/credentials/chainedTokenCredential.ts b/sdk/identity/identity/src/credentials/chainedTokenCredential.ts index 1f2d60fd8c1f..97412932568d 100644 --- a/sdk/identity/identity/src/credentials/chainedTokenCredential.ts +++ b/sdk/identity/identity/src/credentials/chainedTokenCredential.ts @@ -2,9 +2,9 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { AggregateAuthenticationError, CredentialUnavailableError } from "../errors"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; -import { tracingClient } from "../util/tracing"; +import { AggregateAuthenticationError, CredentialUnavailableError } from "../errors.js"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; +import { tracingClient } from "../util/tracing.js"; /** * @internal diff --git a/sdk/identity/identity/src/credentials/clientAssertionCredential.browser.ts b/sdk/identity/identity/src/credentials/clientAssertionCredential-browser.mts similarity index 91% rename from sdk/identity/identity/src/credentials/clientAssertionCredential.browser.ts rename to sdk/identity/identity/src/credentials/clientAssertionCredential-browser.mts index baf7a3967908..80a52dce3497 100644 --- a/sdk/identity/identity/src/credentials/clientAssertionCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/clientAssertionCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "ClientAssertionCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/clientAssertionCredential.ts b/sdk/identity/identity/src/credentials/clientAssertionCredential.ts index 761751f9782e..e3b0bc21defc 100644 --- a/sdk/identity/identity/src/credentials/clientAssertionCredential.ts +++ b/sdk/identity/identity/src/credentials/clientAssertionCredential.ts @@ -2,17 +2,17 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { ClientAssertionCredentialOptions } from "./clientAssertionCredentialOptions"; -import { CredentialUnavailableError } from "../errors"; -import { credentialLogger } from "../util/logging"; -import { tracingClient } from "../util/tracing"; +import type { ClientAssertionCredentialOptions } from "./clientAssertionCredentialOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; +import { credentialLogger } from "../util/logging.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("ClientAssertionCredential"); diff --git a/sdk/identity/identity/src/credentials/clientAssertionCredentialOptions.ts b/sdk/identity/identity/src/credentials/clientAssertionCredentialOptions.ts index 1f04b0df87ab..49d506cfa51e 100644 --- a/sdk/identity/identity/src/credentials/clientAssertionCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/clientAssertionCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link ClientAssertionCredential} diff --git a/sdk/identity/identity/src/credentials/clientCertificateCredential.browser.ts b/sdk/identity/identity/src/credentials/clientCertificateCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/clientCertificateCredential.browser.ts rename to sdk/identity/identity/src/credentials/clientCertificateCredential-browser.mts index 16d0ecf023a9..87d0a370775c 100644 --- a/sdk/identity/identity/src/credentials/clientCertificateCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/clientCertificateCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "ClientCertificateCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/clientCertificateCredential.ts b/sdk/identity/identity/src/credentials/clientCertificateCredential.ts index e7ea916c438d..ccdd29b9afc2 100644 --- a/sdk/identity/identity/src/credentials/clientCertificateCredential.ts +++ b/sdk/identity/identity/src/credentials/clientCertificateCredential.ts @@ -2,19 +2,19 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; -import { createHash, createPrivateKey } from "crypto"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createHash, createPrivateKey } from "node:crypto"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { CertificateParts } from "../msal/types"; -import type { ClientCertificateCredentialOptions } from "./clientCertificateCredentialOptions"; -import { credentialLogger } from "../util/logging"; -import { readFile } from "fs/promises"; -import { tracingClient } from "../util/tracing"; +import type { CertificateParts } from "../msal/types.js"; +import type { ClientCertificateCredentialOptions } from "./clientCertificateCredentialOptions.js"; +import { credentialLogger } from "../util/logging.js"; +import { readFile } from "node:fs/promises"; +import { tracingClient } from "../util/tracing.js"; const credentialName = "ClientCertificateCredential"; const logger = credentialLogger(credentialName); diff --git a/sdk/identity/identity/src/credentials/clientCertificateCredentialOptions.ts b/sdk/identity/identity/src/credentials/clientCertificateCredentialOptions.ts index 009042d5d797..88fb8bc0497b 100644 --- a/sdk/identity/identity/src/credentials/clientCertificateCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/clientCertificateCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Optional parameters for the {@link ClientCertificateCredential} class. diff --git a/sdk/identity/identity/src/credentials/clientSecretCredential.browser.ts b/sdk/identity/identity/src/credentials/clientSecretCredential-browser.mts similarity index 95% rename from sdk/identity/identity/src/credentials/clientSecretCredential.browser.ts rename to sdk/identity/identity/src/credentials/clientSecretCredential-browser.mts index 0813354d7c01..a72db16d4709 100644 --- a/sdk/identity/identity/src/credentials/clientSecretCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/clientSecretCredential-browser.mts @@ -3,15 +3,15 @@ import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import type { ClientSecretCredentialOptions } from "./clientSecretCredentialOptions"; -import { IdentityClient } from "../client/identityClient"; -import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint"; -import { tracingClient } from "../util/tracing"; +} from "../util/tenantIdUtils.js"; +import type { ClientSecretCredentialOptions } from "./clientSecretCredentialOptions.js"; +import { IdentityClient } from "../client/identityClient.js"; +import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("ClientSecretCredential"); diff --git a/sdk/identity/identity/src/credentials/clientSecretCredential.ts b/sdk/identity/identity/src/credentials/clientSecretCredential.ts index 9a26f6fc8abc..6e118f5dbc8e 100644 --- a/sdk/identity/identity/src/credentials/clientSecretCredential.ts +++ b/sdk/identity/identity/src/credentials/clientSecretCredential.ts @@ -2,18 +2,18 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { ClientSecretCredentialOptions } from "./clientSecretCredentialOptions"; -import { CredentialUnavailableError } from "../errors"; -import { credentialLogger } from "../util/logging"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; +import type { ClientSecretCredentialOptions } from "./clientSecretCredentialOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; +import { credentialLogger } from "../util/logging.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("ClientSecretCredential"); diff --git a/sdk/identity/identity/src/credentials/clientSecretCredentialOptions.ts b/sdk/identity/identity/src/credentials/clientSecretCredentialOptions.ts index ea768cc31da7..2c7d6ed6c2a5 100644 --- a/sdk/identity/identity/src/credentials/clientSecretCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/clientSecretCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Optional parameters for the {@link ClientSecretCredential} class. diff --git a/sdk/identity/identity/src/credentials/credentialPersistenceOptions.ts b/sdk/identity/identity/src/credentials/credentialPersistenceOptions.ts index 9706b7342c55..0b650e8b7f3b 100644 --- a/sdk/identity/identity/src/credentials/credentialPersistenceOptions.ts +++ b/sdk/identity/identity/src/credentials/credentialPersistenceOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { TokenCachePersistenceOptions } from "../msal/nodeFlows/tokenCachePersistenceOptions"; +import type { TokenCachePersistenceOptions } from "../msal/nodeFlows/tokenCachePersistenceOptions.js"; /** * Shared configuration options for credentials that support persistent token diff --git a/sdk/identity/identity/src/credentials/defaultAzureCredential.browser.ts b/sdk/identity/identity/src/credentials/defaultAzureCredential-browser.mts similarity index 93% rename from sdk/identity/identity/src/credentials/defaultAzureCredential.browser.ts rename to sdk/identity/identity/src/credentials/defaultAzureCredential-browser.mts index 852c1ba29f9f..624953d71db4 100644 --- a/sdk/identity/identity/src/credentials/defaultAzureCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/defaultAzureCredential-browser.mts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; import type { AccessToken } from "@azure/core-auth"; -import { ChainedTokenCredential } from "./chainedTokenCredential"; -import type { TokenCredentialOptions } from "../tokenCredentialOptions"; +import { ChainedTokenCredential } from "./chainedTokenCredential.js"; +import type { TokenCredentialOptions } from "../tokenCredentialOptions.js"; const BrowserNotSupportedError = new Error( "DefaultAzureCredential is not supported in the browser. Use InteractiveBrowserCredential instead.", diff --git a/sdk/identity/identity/src/credentials/defaultAzureCredential.ts b/sdk/identity/identity/src/credentials/defaultAzureCredential.ts index 23d1e6ec852e..30ebfbd5da7d 100644 --- a/sdk/identity/identity/src/credentials/defaultAzureCredential.ts +++ b/sdk/identity/identity/src/credentials/defaultAzureCredential.ts @@ -5,22 +5,22 @@ import type { DefaultAzureCredentialClientIdOptions, DefaultAzureCredentialOptions, DefaultAzureCredentialResourceIdOptions, -} from "./defaultAzureCredentialOptions"; +} from "./defaultAzureCredentialOptions.js"; import type { ManagedIdentityCredentialClientIdOptions, ManagedIdentityCredentialResourceIdOptions, -} from "./managedIdentityCredential"; -import { ManagedIdentityCredential } from "./managedIdentityCredential"; +} from "./managedIdentityCredential/index.js"; +import { ManagedIdentityCredential } from "./managedIdentityCredential/index.js"; -import { AzureCliCredential } from "./azureCliCredential"; -import { AzureDeveloperCliCredential } from "./azureDeveloperCliCredential"; -import { AzurePowerShellCredential } from "./azurePowerShellCredential"; -import { ChainedTokenCredential } from "./chainedTokenCredential"; -import { EnvironmentCredential } from "./environmentCredential"; +import { AzureCliCredential } from "./azureCliCredential.js"; +import { AzureDeveloperCliCredential } from "./azureDeveloperCliCredential.js"; +import { AzurePowerShellCredential } from "./azurePowerShellCredential.js"; +import { ChainedTokenCredential } from "./chainedTokenCredential.js"; +import { EnvironmentCredential } from "./environmentCredential.js"; import type { TokenCredential } from "@azure/core-auth"; -import { WorkloadIdentityCredential } from "./workloadIdentityCredential"; -import type { WorkloadIdentityCredentialOptions } from "./workloadIdentityCredentialOptions"; -import { credentialLogger } from "../util/logging"; +import { WorkloadIdentityCredential } from "./workloadIdentityCredential.js"; +import type { WorkloadIdentityCredentialOptions } from "./workloadIdentityCredentialOptions.js"; +import { credentialLogger } from "../util/logging.js"; const logger = credentialLogger("DefaultAzureCredential"); diff --git a/sdk/identity/identity/src/credentials/defaultAzureCredentialOptions.ts b/sdk/identity/identity/src/credentials/defaultAzureCredentialOptions.ts index 73266ef4e925..3c07d89120f8 100644 --- a/sdk/identity/identity/src/credentials/defaultAzureCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/defaultAzureCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Provides options to configure the {@link DefaultAzureCredential} class. diff --git a/sdk/identity/identity/src/credentials/deviceCodeCredential.browser.ts b/sdk/identity/identity/src/credentials/deviceCodeCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/deviceCodeCredential.browser.ts rename to sdk/identity/identity/src/credentials/deviceCodeCredential-browser.mts index 49ca1e3076e8..9f4e7a345d1e 100644 --- a/sdk/identity/identity/src/credentials/deviceCodeCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/deviceCodeCredential-browser.mts @@ -3,7 +3,7 @@ import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error("DeviceCodeCredential is not supported in the browser."); const logger = credentialLogger("DeviceCodeCredential"); diff --git a/sdk/identity/identity/src/credentials/deviceCodeCredential.ts b/sdk/identity/identity/src/credentials/deviceCodeCredential.ts index 02e0027afb8c..85abf5f3ee4c 100644 --- a/sdk/identity/identity/src/credentials/deviceCodeCredential.ts +++ b/sdk/identity/identity/src/credentials/deviceCodeCredential.ts @@ -6,19 +6,19 @@ import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, resolveTenantId, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; import type { DeviceCodeCredentialOptions, DeviceCodeInfo, DeviceCodePromptCallback, -} from "./deviceCodeCredentialOptions"; -import type { AuthenticationRecord } from "../msal/types"; -import { credentialLogger } from "../util/logging"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; -import { DeveloperSignOnClientId } from "../constants"; +} from "./deviceCodeCredentialOptions.js"; +import type { AuthenticationRecord } from "../msal/types.js"; +import { credentialLogger } from "../util/logging.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; +import { DeveloperSignOnClientId } from "../constants.js"; const logger = credentialLogger("DeviceCodeCredential"); diff --git a/sdk/identity/identity/src/credentials/deviceCodeCredentialOptions.ts b/sdk/identity/identity/src/credentials/deviceCodeCredentialOptions.ts index 46440da225e4..2aff6d31e864 100644 --- a/sdk/identity/identity/src/credentials/deviceCodeCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/deviceCodeCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { InteractiveCredentialOptions } from "./interactiveCredentialOptions"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { InteractiveCredentialOptions } from "./interactiveCredentialOptions.js"; /** * Provides the user code and verification URI where the code must be diff --git a/sdk/identity/identity/src/credentials/environmentCredential.browser.ts b/sdk/identity/identity/src/credentials/environmentCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/environmentCredential.browser.ts rename to sdk/identity/identity/src/credentials/environmentCredential-browser.mts index 3a3f7d620501..b1b95fe830a2 100644 --- a/sdk/identity/identity/src/credentials/environmentCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/environmentCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "EnvironmentCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/environmentCredential.ts b/sdk/identity/identity/src/credentials/environmentCredential.ts index 55160007459e..cbfdd840b67b 100644 --- a/sdk/identity/identity/src/credentials/environmentCredential.ts +++ b/sdk/identity/identity/src/credentials/environmentCredential.ts @@ -2,15 +2,15 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { AuthenticationError, CredentialUnavailableError } from "../errors"; -import { credentialLogger, formatError, formatSuccess, processEnvVars } from "../util/logging"; +import { AuthenticationError, CredentialUnavailableError } from "../errors.js"; +import { credentialLogger, formatError, formatSuccess, processEnvVars } from "../util/logging.js"; -import { ClientCertificateCredential } from "./clientCertificateCredential"; -import { ClientSecretCredential } from "./clientSecretCredential"; -import type { EnvironmentCredentialOptions } from "./environmentCredentialOptions"; -import { UsernamePasswordCredential } from "./usernamePasswordCredential"; -import { checkTenantId } from "../util/tenantIdUtils"; -import { tracingClient } from "../util/tracing"; +import { ClientCertificateCredential } from "./clientCertificateCredential.js"; +import { ClientSecretCredential } from "./clientSecretCredential.js"; +import type { EnvironmentCredentialOptions } from "./environmentCredentialOptions.js"; +import { UsernamePasswordCredential } from "./usernamePasswordCredential.js"; +import { checkTenantId } from "../util/tenantIdUtils.js"; +import { tracingClient } from "../util/tracing.js"; /** * Contains the list of all supported environment variable names so that an diff --git a/sdk/identity/identity/src/credentials/environmentCredentialOptions.ts b/sdk/identity/identity/src/credentials/environmentCredentialOptions.ts index 3cab9668f733..cfda966fb83c 100644 --- a/sdk/identity/identity/src/credentials/environmentCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/environmentCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Enables authentication to Microsoft Entra ID depending on the available environment variables. diff --git a/sdk/identity/identity/src/credentials/interactiveBrowserCredential.browser.ts b/sdk/identity/identity/src/credentials/interactiveBrowserCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/interactiveBrowserCredential.browser.ts rename to sdk/identity/identity/src/credentials/interactiveBrowserCredential-browser.mts index cc9d8de99a65..8f0abcaf7822 100644 --- a/sdk/identity/identity/src/credentials/interactiveBrowserCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/interactiveBrowserCredential-browser.mts @@ -5,19 +5,19 @@ import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core- import type { InteractiveBrowserCredentialInBrowserOptions, InteractiveBrowserCredentialNodeOptions, -} from "./interactiveBrowserCredentialOptions"; -import { credentialLogger, formatError } from "../util/logging"; +} from "./interactiveBrowserCredentialOptions.js"; +import { credentialLogger, formatError } from "../util/logging.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { AuthenticationRecord } from "../msal/types"; -import { MSALAuthCode } from "../msal/browserFlows/msalAuthCode"; -import type { MsalBrowserFlowOptions } from "../msal/browserFlows/msalBrowserCommon"; -import type { MsalFlow } from "../msal/browserFlows/flows"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; +import type { AuthenticationRecord } from "../msal/types.js"; +import { MSALAuthCode } from "../msal/browserFlows/msalAuthCode.js"; +import type { MsalBrowserFlowOptions } from "../msal/browserFlows/msalBrowserCommon.js"; +import type { MsalFlow } from "../msal/browserFlows/flows.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("InteractiveBrowserCredential"); diff --git a/sdk/identity/identity/src/credentials/interactiveBrowserCredential.ts b/sdk/identity/identity/src/credentials/interactiveBrowserCredential.ts index 0804d1c43652..a582de85f52d 100644 --- a/sdk/identity/identity/src/credentials/interactiveBrowserCredential.ts +++ b/sdk/identity/identity/src/credentials/interactiveBrowserCredential.ts @@ -5,20 +5,20 @@ import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core- import type { InteractiveBrowserCredentialInBrowserOptions, InteractiveBrowserCredentialNodeOptions, -} from "./interactiveBrowserCredentialOptions"; +} from "./interactiveBrowserCredentialOptions.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, resolveTenantId, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { AuthenticationRecord } from "../msal/types"; -import { credentialLogger } from "../util/logging"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; -import type { MsalClient, MsalClientOptions } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; -import { DeveloperSignOnClientId } from "../constants"; +import type { AuthenticationRecord } from "../msal/types.js"; +import { credentialLogger } from "../util/logging.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; +import type { MsalClient, MsalClientOptions } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; +import { DeveloperSignOnClientId } from "../constants.js"; const logger = credentialLogger("InteractiveBrowserCredential"); diff --git a/sdk/identity/identity/src/credentials/interactiveBrowserCredentialOptions.ts b/sdk/identity/identity/src/credentials/interactiveBrowserCredentialOptions.ts index 7c807a7eb7a4..08f78cc5b826 100644 --- a/sdk/identity/identity/src/credentials/interactiveBrowserCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/interactiveBrowserCredentialOptions.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { BrowserCustomizationOptions } from "./browserCustomizationOptions"; -import type { BrokerAuthOptions } from "./brokerAuthOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { InteractiveCredentialOptions } from "./interactiveCredentialOptions"; +import type { BrowserCustomizationOptions } from "./browserCustomizationOptions.js"; +import type { BrokerAuthOptions } from "./brokerAuthOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { InteractiveCredentialOptions } from "./interactiveCredentialOptions.js"; /** * (Browser-only feature) diff --git a/sdk/identity/identity/src/credentials/interactiveCredentialOptions.ts b/sdk/identity/identity/src/credentials/interactiveCredentialOptions.ts index 449e56e665c0..5a3e046de428 100644 --- a/sdk/identity/identity/src/credentials/interactiveCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/interactiveCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthenticationRecord } from "../msal/types"; -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthenticationRecord } from "../msal/types.js"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Common constructor options for the Identity credentials that requires user interaction. diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts index 600d6efe8c1e..020432ece877 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts @@ -6,10 +6,10 @@ import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipel import { isError } from "@azure/core-util"; import type { GetTokenOptions } from "@azure/core-auth"; -import { credentialLogger } from "../../util/logging"; -import { mapScopesToResource } from "./utils"; -import { tracingClient } from "../../util/tracing"; -import { IdentityClient } from "../../client/identityClient"; +import { credentialLogger } from "../../util/logging.js"; +import { mapScopesToResource } from "./utils.js"; +import { tracingClient } from "../../util/tracing.js"; +import { IdentityClient } from "../../client/identityClient.js"; const msiName = "ManagedIdentityCredential - IMDS"; const logger = credentialLogger(msiName); diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.ts index 503dd2cbda2f..d0448d3c7be2 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.ts @@ -4,7 +4,7 @@ import type { PipelinePolicy } from "@azure/core-rest-pipeline"; import { retryPolicy } from "@azure/core-rest-pipeline"; -import type { MSIConfiguration } from "./models"; +import type { MSIConfiguration } from "./models.js"; import { calculateRetryDelay } from "@azure/core-util"; // Matches the default retry configuration in expontentialRetryStrategy.ts diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.browser.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/index-browser.mts similarity index 99% rename from sdk/identity/identity/src/credentials/managedIdentityCredential/index.browser.ts rename to sdk/identity/identity/src/credentials/managedIdentityCredential/index-browser.mts index a0fed57619fd..f5ad1304696f 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.browser.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/index-browser.mts @@ -3,7 +3,7 @@ import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../../util/logging"; +import { credentialLogger, formatError } from "../../util/logging.js"; const BrowserNotSupportedError = new Error( "ManagedIdentityCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts index a065ec741674..742d17209eca 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/index.ts @@ -3,20 +3,20 @@ import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { TokenCredentialOptions } from "../../tokenCredentialOptions"; +import type { TokenCredentialOptions } from "../../tokenCredentialOptions.js"; import { getLogLevel } from "@azure/logger"; import { ManagedIdentityApplication } from "@azure/msal-node"; -import { IdentityClient } from "../../client/identityClient"; -import { AuthenticationRequiredError, CredentialUnavailableError } from "../../errors"; -import { getMSALLogLevel, defaultLoggerCallback } from "../../msal/utils"; -import { imdsRetryPolicy } from "./imdsRetryPolicy"; -import { MSIConfiguration } from "./models"; -import { formatSuccess, formatError, credentialLogger } from "../../util/logging"; -import { tracingClient } from "../../util/tracing"; -import { imdsMsi } from "./imdsMsi"; -import { tokenExchangeMsi } from "./tokenExchangeMsi"; -import { mapScopesToResource } from "./utils"; -import { MsalToken, ValidMsalToken } from "../../msal/types"; +import { IdentityClient } from "../../client/identityClient.js"; +import { AuthenticationRequiredError, CredentialUnavailableError } from "../../errors.js"; +import { getMSALLogLevel, defaultLoggerCallback } from "../../msal/utils.js"; +import { imdsRetryPolicy } from "./imdsRetryPolicy.js"; +import { MSIConfiguration } from "./models.js"; +import { formatSuccess, formatError, credentialLogger } from "../../util/logging.js"; +import { tracingClient } from "../../util/tracing.js"; +import { imdsMsi } from "./imdsMsi.js"; +import { tokenExchangeMsi } from "./tokenExchangeMsi.js"; +import { mapScopesToResource } from "./utils.js"; +import { MsalToken, ValidMsalToken } from "../../msal/types.js"; const logger = credentialLogger("ManagedIdentityCredential"); diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/models.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/models.ts index 453e60ee0e93..ae87223f55f2 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/models.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/models.ts @@ -3,7 +3,7 @@ import type { AccessToken } from "@azure/core-auth"; -import type { IdentityClient } from "../../client/identityClient"; +import type { IdentityClient } from "../../client/identityClient.js"; /** * @internal diff --git a/sdk/identity/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.ts b/sdk/identity/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.ts index 997c0bb5fcde..62e8285d0a9b 100644 --- a/sdk/identity/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.ts +++ b/sdk/identity/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.ts @@ -2,10 +2,10 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions } from "@azure/core-auth"; -import type { MSIConfiguration } from "./models"; -import { WorkloadIdentityCredential } from "../workloadIdentityCredential"; -import { credentialLogger } from "../../util/logging"; -import type { WorkloadIdentityCredentialOptions } from "../workloadIdentityCredentialOptions"; +import type { MSIConfiguration } from "./models.js"; +import { WorkloadIdentityCredential } from "../workloadIdentityCredential.js"; +import { credentialLogger } from "../../util/logging.js"; +import type { WorkloadIdentityCredentialOptions } from "../workloadIdentityCredentialOptions.js"; const msiName = "ManagedIdentityCredential - Token Exchange"; const logger = credentialLogger(msiName); diff --git a/sdk/identity/identity/src/credentials/multiTenantTokenCredentialOptions.ts b/sdk/identity/identity/src/credentials/multiTenantTokenCredentialOptions.ts index 9017baf814a8..c160a9e1c17f 100644 --- a/sdk/identity/identity/src/credentials/multiTenantTokenCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/multiTenantTokenCredentialOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { TokenCredentialOptions } from "../tokenCredentialOptions"; +import type { TokenCredentialOptions } from "../tokenCredentialOptions.js"; /** * Options for multi-tenant applications which allows for additionally allowed tenants. diff --git a/sdk/identity/identity/src/credentials/onBehalfOfCredential.browser.ts b/sdk/identity/identity/src/credentials/onBehalfOfCredential-browser.mts similarity index 92% rename from sdk/identity/identity/src/credentials/onBehalfOfCredential.browser.ts rename to sdk/identity/identity/src/credentials/onBehalfOfCredential-browser.mts index 48c45e4ce165..c8fa0bf56662 100644 --- a/sdk/identity/identity/src/credentials/onBehalfOfCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/onBehalfOfCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const credentialName = "OnBehalfOfCredential"; const BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`); diff --git a/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts b/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts index 8b3c25c8cdc0..b05a757dc0bc 100644 --- a/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts +++ b/sdk/identity/identity/src/credentials/onBehalfOfCredential.ts @@ -2,29 +2,29 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; import type { OnBehalfOfCredentialAssertionOptions, OnBehalfOfCredentialCertificateOptions, OnBehalfOfCredentialOptions, OnBehalfOfCredentialSecretOptions, -} from "./onBehalfOfCredentialOptions"; -import { credentialLogger, formatError } from "../util/logging"; +} from "./onBehalfOfCredentialOptions.js"; +import { credentialLogger, formatError } from "../util/logging.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import type { CertificateParts } from "../msal/types"; -import type { ClientCertificatePEMCertificatePath } from "./clientCertificateCredential"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import { CredentialUnavailableError } from "../errors"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { CertificateParts } from "../msal/types.js"; +import type { ClientCertificatePEMCertificatePath } from "./clientCertificateCredential.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import { CredentialUnavailableError } from "../errors.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; import { createHash } from "node:crypto"; -import { ensureScopes } from "../util/scopeUtils"; +import { ensureScopes } from "../util/scopeUtils.js"; import { readFile } from "node:fs/promises"; -import { tracingClient } from "../util/tracing"; +import { tracingClient } from "../util/tracing.js"; const credentialName = "OnBehalfOfCredential"; const logger = credentialLogger(credentialName); diff --git a/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts b/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts index a5cefdac355f..f19d7a30e506 100644 --- a/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/onBehalfOfCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Defines the parameters to authenticate the {@link OnBehalfOfCredential} with a secret. diff --git a/sdk/identity/identity/src/credentials/usernamePasswordCredential.browser.ts b/sdk/identity/identity/src/credentials/usernamePasswordCredential-browser.mts similarity index 95% rename from sdk/identity/identity/src/credentials/usernamePasswordCredential.browser.ts rename to sdk/identity/identity/src/credentials/usernamePasswordCredential-browser.mts index a03b64006240..8c8c27988a84 100644 --- a/sdk/identity/identity/src/credentials/usernamePasswordCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/usernamePasswordCredential-browser.mts @@ -6,13 +6,13 @@ import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; -import { credentialLogger, formatSuccess } from "../util/logging"; -import { IdentityClient } from "../client/identityClient"; -import type { UsernamePasswordCredentialOptions } from "./usernamePasswordCredentialOptions"; -import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint"; -import { tracingClient } from "../util/tracing"; +import { credentialLogger, formatSuccess } from "../util/logging.js"; +import { IdentityClient } from "../client/identityClient.js"; +import type { UsernamePasswordCredentialOptions } from "./usernamePasswordCredentialOptions.js"; +import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("UsernamePasswordCredential"); diff --git a/sdk/identity/identity/src/credentials/usernamePasswordCredential.ts b/sdk/identity/identity/src/credentials/usernamePasswordCredential.ts index a9b11a8a75c1..3785b9058772 100644 --- a/sdk/identity/identity/src/credentials/usernamePasswordCredential.ts +++ b/sdk/identity/identity/src/credentials/usernamePasswordCredential.ts @@ -2,18 +2,18 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalClient } from "../msal/nodeFlows/msalClient"; -import { createMsalClient } from "../msal/nodeFlows/msalClient"; +import type { MsalClient } from "../msal/nodeFlows/msalClient.js"; +import { createMsalClient } from "../msal/nodeFlows/msalClient.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; +} from "../util/tenantIdUtils.js"; -import { CredentialUnavailableError } from "../errors"; -import type { UsernamePasswordCredentialOptions } from "./usernamePasswordCredentialOptions"; -import { credentialLogger } from "../util/logging"; -import { ensureScopes } from "../util/scopeUtils"; -import { tracingClient } from "../util/tracing"; +import { CredentialUnavailableError } from "../errors.js"; +import type { UsernamePasswordCredentialOptions } from "./usernamePasswordCredentialOptions.js"; +import { credentialLogger } from "../util/logging.js"; +import { ensureScopes } from "../util/scopeUtils.js"; +import { tracingClient } from "../util/tracing.js"; const logger = credentialLogger("UsernamePasswordCredential"); diff --git a/sdk/identity/identity/src/credentials/usernamePasswordCredentialOptions.ts b/sdk/identity/identity/src/credentials/usernamePasswordCredentialOptions.ts index 5a2ff7047558..aee79c15d6be 100644 --- a/sdk/identity/identity/src/credentials/usernamePasswordCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/usernamePasswordCredentialOptions.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { CredentialPersistenceOptions } from "./credentialPersistenceOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Defines options for the {@link UsernamePasswordCredential} class. diff --git a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.browser.ts b/sdk/identity/identity/src/credentials/visualStudioCodeCredential-browser.mts similarity index 94% rename from sdk/identity/identity/src/credentials/visualStudioCodeCredential.browser.ts rename to sdk/identity/identity/src/credentials/visualStudioCodeCredential-browser.mts index 81e0cde7075a..9e11e1adbcb6 100644 --- a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/visualStudioCodeCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "VisualStudioCodeCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts b/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts index 99c7501c540c..c3f0aa95bd30 100644 --- a/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts +++ b/sdk/identity/identity/src/credentials/visualStudioCodeCredential.ts @@ -2,20 +2,20 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError, formatSuccess } from "../util/logging"; +import { credentialLogger, formatError, formatSuccess } from "../util/logging.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, -} from "../util/tenantIdUtils"; -import { AzureAuthorityHosts } from "../constants"; -import { CredentialUnavailableError } from "../errors"; -import { IdentityClient } from "../client/identityClient"; -import type { VisualStudioCodeCredentialOptions } from "./visualStudioCodeCredentialOptions"; -import type { VSCodeCredentialFinder } from "./visualStudioCodeCredentialPlugin"; -import { checkTenantId } from "../util/tenantIdUtils"; -import fs from "fs"; -import os from "os"; -import path from "path"; +} from "../util/tenantIdUtils.js"; +import { AzureAuthorityHosts } from "../constants.js"; +import { CredentialUnavailableError } from "../errors.js"; +import { IdentityClient } from "../client/identityClient.js"; +import type { VisualStudioCodeCredentialOptions } from "./visualStudioCodeCredentialOptions.js"; +import type { VSCodeCredentialFinder } from "./visualStudioCodeCredentialPlugin.js"; +import { checkTenantId } from "../util/tenantIdUtils.js"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; const CommonTenantId = "common"; const AzureAccountClientId = "aebc6443-996d-45c2-90f0-388ff96faa56"; // VSC: 'aebc6443-996d-45c2-90f0-388ff96faa56' diff --git a/sdk/identity/identity/src/credentials/visualStudioCodeCredentialOptions.ts b/sdk/identity/identity/src/credentials/visualStudioCodeCredentialOptions.ts index d2270457212d..0ecd2d2e60b3 100644 --- a/sdk/identity/identity/src/credentials/visualStudioCodeCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/visualStudioCodeCredentialOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Provides options to configure the Visual Studio Code credential. diff --git a/sdk/identity/identity/src/credentials/workloadIdentityCredential.browser.ts b/sdk/identity/identity/src/credentials/workloadIdentityCredential-browser.mts similarity index 93% rename from sdk/identity/identity/src/credentials/workloadIdentityCredential.browser.ts rename to sdk/identity/identity/src/credentials/workloadIdentityCredential-browser.mts index 44c363779035..3b0bc1c21078 100644 --- a/sdk/identity/identity/src/credentials/workloadIdentityCredential.browser.ts +++ b/sdk/identity/identity/src/credentials/workloadIdentityCredential-browser.mts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, formatError } from "../util/logging"; +import { credentialLogger, formatError } from "../util/logging.js"; const BrowserNotSupportedError = new Error( "WorkloadIdentityCredential is not supported in the browser.", diff --git a/sdk/identity/identity/src/credentials/workloadIdentityCredential.ts b/sdk/identity/identity/src/credentials/workloadIdentityCredential.ts index 979b0bdc565a..77d3ecec70f2 100644 --- a/sdk/identity/identity/src/credentials/workloadIdentityCredential.ts +++ b/sdk/identity/identity/src/credentials/workloadIdentityCredential.ts @@ -2,13 +2,13 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import { credentialLogger, processEnvVars } from "../util/logging"; +import { credentialLogger, processEnvVars } from "../util/logging.js"; -import { ClientAssertionCredential } from "./clientAssertionCredential"; -import { CredentialUnavailableError } from "../errors"; -import type { WorkloadIdentityCredentialOptions } from "./workloadIdentityCredentialOptions"; -import { checkTenantId } from "../util/tenantIdUtils"; -import { readFile } from "fs/promises"; +import { ClientAssertionCredential } from "./clientAssertionCredential.js"; +import { CredentialUnavailableError } from "../errors.js"; +import type { WorkloadIdentityCredentialOptions } from "./workloadIdentityCredentialOptions.js"; +import { checkTenantId } from "../util/tenantIdUtils.js"; +import { readFile } from "node:fs/promises"; const credentialName = "WorkloadIdentityCredential"; /** diff --git a/sdk/identity/identity/src/credentials/workloadIdentityCredentialOptions.ts b/sdk/identity/identity/src/credentials/workloadIdentityCredentialOptions.ts index 8e26e7aca22e..f2a9d8fcd1bd 100644 --- a/sdk/identity/identity/src/credentials/workloadIdentityCredentialOptions.ts +++ b/sdk/identity/identity/src/credentials/workloadIdentityCredentialOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthorityValidationOptions } from "./authorityValidationOptions"; -import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions"; +import type { AuthorityValidationOptions } from "./authorityValidationOptions.js"; +import type { MultiTenantTokenCredentialOptions } from "./multiTenantTokenCredentialOptions.js"; /** * Options for the {@link WorkloadIdentityCredential} diff --git a/sdk/identity/identity/src/index.ts b/sdk/identity/identity/src/index.ts index 0758577ab5e6..ee34eb5bd76a 100644 --- a/sdk/identity/identity/src/index.ts +++ b/sdk/identity/identity/src/index.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export * from "./plugins/consumer"; +export * from "./plugins/consumer.js"; -export { IdentityPlugin } from "./plugins/provider"; +export { IdentityPlugin } from "./plugins/provider.js"; import type { TokenCredential } from "@azure/core-auth"; -import { DefaultAzureCredential } from "./credentials/defaultAzureCredential"; +import { DefaultAzureCredential } from "./credentials/defaultAzureCredential.js"; export { AuthenticationError, @@ -18,97 +18,97 @@ export { CredentialUnavailableErrorName, AuthenticationRequiredError, AuthenticationRequiredErrorOptions, -} from "./errors"; +} from "./errors.js"; -export { AuthenticationRecord } from "./msal/types"; -export { serializeAuthenticationRecord, deserializeAuthenticationRecord } from "./msal/utils"; -export { TokenCredentialOptions } from "./tokenCredentialOptions"; -export { MultiTenantTokenCredentialOptions } from "./credentials/multiTenantTokenCredentialOptions"; -export { AuthorityValidationOptions } from "./credentials/authorityValidationOptions"; +export { AuthenticationRecord } from "./msal/types.js"; +export { serializeAuthenticationRecord, deserializeAuthenticationRecord } from "./msal/utils.js"; +export { TokenCredentialOptions } from "./tokenCredentialOptions.js"; +export { MultiTenantTokenCredentialOptions } from "./credentials/multiTenantTokenCredentialOptions.js"; +export { AuthorityValidationOptions } from "./credentials/authorityValidationOptions.js"; // TODO: Export again once we're ready to release this feature. // export { RegionalAuthority } from "./regionalAuthority"; -export { BrokerAuthOptions } from "./credentials/brokerAuthOptions"; +export { BrokerAuthOptions } from "./credentials/brokerAuthOptions.js"; export { BrokerOptions, BrokerEnabledOptions, BrokerDisabledOptions, -} from "./msal/nodeFlows/brokerOptions"; -export { InteractiveCredentialOptions } from "./credentials/interactiveCredentialOptions"; +} from "./msal/nodeFlows/brokerOptions.js"; +export { InteractiveCredentialOptions } from "./credentials/interactiveCredentialOptions.js"; -export { ChainedTokenCredential } from "./credentials/chainedTokenCredential"; +export { ChainedTokenCredential } from "./credentials/chainedTokenCredential.js"; -export { ClientSecretCredential } from "./credentials/clientSecretCredential"; -export { ClientSecretCredentialOptions } from "./credentials/clientSecretCredentialOptions"; +export { ClientSecretCredential } from "./credentials/clientSecretCredential.js"; +export { ClientSecretCredentialOptions } from "./credentials/clientSecretCredentialOptions.js"; -export { DefaultAzureCredential } from "./credentials/defaultAzureCredential"; +export { DefaultAzureCredential } from "./credentials/defaultAzureCredential.js"; export { DefaultAzureCredentialOptions, DefaultAzureCredentialClientIdOptions, DefaultAzureCredentialResourceIdOptions, -} from "./credentials/defaultAzureCredentialOptions"; +} from "./credentials/defaultAzureCredentialOptions.js"; -export { EnvironmentCredential } from "./credentials/environmentCredential"; -export { EnvironmentCredentialOptions } from "./credentials/environmentCredentialOptions"; +export { EnvironmentCredential } from "./credentials/environmentCredential.js"; +export { EnvironmentCredentialOptions } from "./credentials/environmentCredentialOptions.js"; export { ClientCertificateCredential, ClientCertificateCredentialPEMConfiguration, ClientCertificatePEMCertificatePath, ClientCertificatePEMCertificate, -} from "./credentials/clientCertificateCredential"; -export { ClientCertificateCredentialOptions } from "./credentials/clientCertificateCredentialOptions"; -export { ClientAssertionCredential } from "./credentials/clientAssertionCredential"; -export { ClientAssertionCredentialOptions } from "./credentials/clientAssertionCredentialOptions"; -export { CredentialPersistenceOptions } from "./credentials/credentialPersistenceOptions"; -export { AzureCliCredential } from "./credentials/azureCliCredential"; -export { AzureCliCredentialOptions } from "./credentials/azureCliCredentialOptions"; -export { AzureDeveloperCliCredential } from "./credentials/azureDeveloperCliCredential"; -export { AzureDeveloperCliCredentialOptions } from "./credentials/azureDeveloperCliCredentialOptions"; -export { InteractiveBrowserCredential } from "./credentials/interactiveBrowserCredential"; +} from "./credentials/clientCertificateCredential.js"; +export { ClientCertificateCredentialOptions } from "./credentials/clientCertificateCredentialOptions.js"; +export { ClientAssertionCredential } from "./credentials/clientAssertionCredential.js"; +export { ClientAssertionCredentialOptions } from "./credentials/clientAssertionCredentialOptions.js"; +export { CredentialPersistenceOptions } from "./credentials/credentialPersistenceOptions.js"; +export { AzureCliCredential } from "./credentials/azureCliCredential.js"; +export { AzureCliCredentialOptions } from "./credentials/azureCliCredentialOptions.js"; +export { AzureDeveloperCliCredential } from "./credentials/azureDeveloperCliCredential.js"; +export { AzureDeveloperCliCredentialOptions } from "./credentials/azureDeveloperCliCredentialOptions.js"; +export { InteractiveBrowserCredential } from "./credentials/interactiveBrowserCredential.js"; export { InteractiveBrowserCredentialNodeOptions, InteractiveBrowserCredentialInBrowserOptions, BrowserLoginStyle, -} from "./credentials/interactiveBrowserCredentialOptions"; +} from "./credentials/interactiveBrowserCredentialOptions.js"; export { ManagedIdentityCredential, ManagedIdentityCredentialClientIdOptions, ManagedIdentityCredentialResourceIdOptions, ManagedIdentityCredentialObjectIdOptions, -} from "./credentials/managedIdentityCredential"; -export { DeviceCodeCredential } from "./credentials/deviceCodeCredential"; +} from "./credentials/managedIdentityCredential/index.js"; +export { DeviceCodeCredential } from "./credentials/deviceCodeCredential.js"; export { DeviceCodePromptCallback, DeviceCodeInfo, -} from "./credentials/deviceCodeCredentialOptions"; -export { DeviceCodeCredentialOptions } from "./credentials/deviceCodeCredentialOptions"; -export { AzurePipelinesCredential as AzurePipelinesCredential } from "./credentials/azurePipelinesCredential"; -export { AzurePipelinesCredentialOptions as AzurePipelinesCredentialOptions } from "./credentials/azurePipelinesCredentialOptions"; -export { AuthorizationCodeCredential } from "./credentials/authorizationCodeCredential"; -export { AuthorizationCodeCredentialOptions } from "./credentials/authorizationCodeCredentialOptions"; -export { AzurePowerShellCredential } from "./credentials/azurePowerShellCredential"; -export { AzurePowerShellCredentialOptions } from "./credentials/azurePowerShellCredentialOptions"; +} from "./credentials/deviceCodeCredentialOptions.js"; +export { DeviceCodeCredentialOptions } from "./credentials/deviceCodeCredentialOptions.js"; +export { AzurePipelinesCredential as AzurePipelinesCredential } from "./credentials/azurePipelinesCredential.js"; +export { AzurePipelinesCredentialOptions as AzurePipelinesCredentialOptions } from "./credentials/azurePipelinesCredentialOptions.js"; +export { AuthorizationCodeCredential } from "./credentials/authorizationCodeCredential.js"; +export { AuthorizationCodeCredentialOptions } from "./credentials/authorizationCodeCredentialOptions.js"; +export { AzurePowerShellCredential } from "./credentials/azurePowerShellCredential.js"; +export { AzurePowerShellCredentialOptions } from "./credentials/azurePowerShellCredentialOptions.js"; export { OnBehalfOfCredentialOptions, OnBehalfOfCredentialSecretOptions, OnBehalfOfCredentialCertificateOptions, OnBehalfOfCredentialAssertionOptions, -} from "./credentials/onBehalfOfCredentialOptions"; -export { UsernamePasswordCredential } from "./credentials/usernamePasswordCredential"; -export { UsernamePasswordCredentialOptions } from "./credentials/usernamePasswordCredentialOptions"; -export { VisualStudioCodeCredential } from "./credentials/visualStudioCodeCredential"; -export { VisualStudioCodeCredentialOptions } from "./credentials/visualStudioCodeCredentialOptions"; -export { OnBehalfOfCredential } from "./credentials/onBehalfOfCredential"; -export { WorkloadIdentityCredential } from "./credentials/workloadIdentityCredential"; -export { WorkloadIdentityCredentialOptions } from "./credentials/workloadIdentityCredentialOptions"; -export { BrowserCustomizationOptions } from "./credentials/browserCustomizationOptions"; -export { TokenCachePersistenceOptions } from "./msal/nodeFlows/tokenCachePersistenceOptions"; +} from "./credentials/onBehalfOfCredentialOptions.js"; +export { UsernamePasswordCredential } from "./credentials/usernamePasswordCredential.js"; +export { UsernamePasswordCredentialOptions } from "./credentials/usernamePasswordCredentialOptions.js"; +export { VisualStudioCodeCredential } from "./credentials/visualStudioCodeCredential.js"; +export { VisualStudioCodeCredentialOptions } from "./credentials/visualStudioCodeCredentialOptions.js"; +export { OnBehalfOfCredential } from "./credentials/onBehalfOfCredential.js"; +export { WorkloadIdentityCredential } from "./credentials/workloadIdentityCredential.js"; +export { WorkloadIdentityCredentialOptions } from "./credentials/workloadIdentityCredentialOptions.js"; +export { BrowserCustomizationOptions } from "./credentials/browserCustomizationOptions.js"; +export { TokenCachePersistenceOptions } from "./msal/nodeFlows/tokenCachePersistenceOptions.js"; export { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; -export { logger } from "./util/logging"; +export { logger } from "./util/logging.js"; -export { AzureAuthorityHosts } from "./constants"; +export { AzureAuthorityHosts } from "./constants.js"; /** * Returns a new instance of the {@link DefaultAzureCredential}. @@ -117,4 +117,4 @@ export function getDefaultAzureCredential(): TokenCredential { return new DefaultAzureCredential(); } -export { getBearerTokenProvider, GetBearerTokenProviderOptions } from "./tokenProvider"; +export { getBearerTokenProvider, GetBearerTokenProviderOptions } from "./tokenProvider.js"; diff --git a/sdk/identity/identity/src/msal/browserFlows/flows.ts b/sdk/identity/identity/src/msal/browserFlows/flows.ts index fbce9411bb60..a4126711595a 100644 --- a/sdk/identity/identity/src/msal/browserFlows/flows.ts +++ b/sdk/identity/identity/src/msal/browserFlows/flows.ts @@ -2,9 +2,9 @@ // Licensed under the MIT License. import type { AccessToken } from "@azure/core-auth"; -import type { AuthenticationRecord } from "../types"; -import type { CredentialFlowGetTokenOptions } from "../credentials"; -import type { CredentialLogger } from "../../util/logging"; +import type { AuthenticationRecord } from "../types.js"; +import type { CredentialFlowGetTokenOptions } from "../credentials.js"; +import type { CredentialLogger } from "../../util/logging.js"; /** * Union of the constructor parameters that all MSAL flow types take. diff --git a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts index 545a27cbc2e0..dadec04e8f2d 100644 --- a/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts +++ b/sdk/identity/identity/src/msal/browserFlows/msalAuthCode.ts @@ -3,20 +3,20 @@ import * as msalBrowser from "@azure/msal-browser"; -import type { MsalBrowserFlowOptions } from "./msalBrowserCommon"; -import { MsalBrowser } from "./msalBrowserCommon"; +import type { MsalBrowserFlowOptions } from "./msalBrowserCommon.js"; +import { MsalBrowser } from "./msalBrowserCommon.js"; import { defaultLoggerCallback, getMSALLogLevel, handleMsalError, msalToPublic, publicToMsal, -} from "../utils"; +} from "../utils.js"; import type { AccessToken } from "@azure/core-auth"; -import type { AuthenticationRecord } from "../types"; -import { AuthenticationRequiredError } from "../../errors"; -import type { CredentialFlowGetTokenOptions } from "../credentials"; +import type { AuthenticationRecord } from "../types.js"; +import { AuthenticationRequiredError } from "../../errors.js"; +import type { CredentialFlowGetTokenOptions } from "../credentials.js"; import { getLogLevel } from "@azure/logger"; // We keep a copy of the redirect hash. diff --git a/sdk/identity/identity/src/msal/browserFlows/msalBrowserCommon.ts b/sdk/identity/identity/src/msal/browserFlows/msalBrowserCommon.ts index 7df357e1319d..c7916b2a7787 100644 --- a/sdk/identity/identity/src/msal/browserFlows/msalBrowserCommon.ts +++ b/sdk/identity/identity/src/msal/browserFlows/msalBrowserCommon.ts @@ -4,23 +4,23 @@ import type * as msalBrowser from "@azure/msal-browser"; import type { AccessToken, GetTokenOptions } from "@azure/core-auth"; -import type { AuthenticationRecord, MsalResult } from "../types"; -import { AuthenticationRequiredError, CredentialUnavailableError } from "../../errors"; -import type { CredentialLogger } from "../../util/logging"; -import { formatSuccess } from "../../util/logging"; -import type { MsalFlow, MsalFlowOptions } from "./flows"; -import { ensureValidMsalToken, getAuthority, getKnownAuthorities, msalToPublic } from "../utils"; +import type { AuthenticationRecord, MsalResult } from "../types.js"; +import { AuthenticationRequiredError, CredentialUnavailableError } from "../../errors.js"; +import type { CredentialLogger } from "../../util/logging.js"; +import { formatSuccess } from "../../util/logging.js"; +import type { MsalFlow, MsalFlowOptions } from "./flows.js"; +import { ensureValidMsalToken, getAuthority, getKnownAuthorities, msalToPublic } from "../utils.js"; import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, resolveTenantId, -} from "../../util/tenantIdUtils"; +} from "../../util/tenantIdUtils.js"; -import type { BrowserLoginStyle } from "../../credentials/interactiveBrowserCredentialOptions"; -import type { CredentialFlowGetTokenOptions } from "../credentials"; -import { DefaultTenantId } from "../../constants"; +import type { BrowserLoginStyle } from "../../credentials/interactiveBrowserCredentialOptions.js"; +import type { CredentialFlowGetTokenOptions } from "../credentials.js"; +import { DefaultTenantId } from "../../constants.js"; import type { LogPolicyOptions } from "@azure/core-rest-pipeline"; -import type { MultiTenantTokenCredentialOptions } from "../../credentials/multiTenantTokenCredentialOptions"; +import type { MultiTenantTokenCredentialOptions } from "../../credentials/multiTenantTokenCredentialOptions.js"; /** * Union of the constructor parameters that all MSAL flow types take. diff --git a/sdk/identity/identity/src/msal/credentials.ts b/sdk/identity/identity/src/msal/credentials.ts index 7b3eb912d4e9..2922ae54a737 100644 --- a/sdk/identity/identity/src/msal/credentials.ts +++ b/sdk/identity/identity/src/msal/credentials.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions } from "@azure/core-auth"; -import type { AuthenticationRecord } from "./types"; +import type { AuthenticationRecord } from "./types.js"; /** * The MSAL clients `getToken` requests can receive a `correlationId` and `disableAutomaticAuthentication`. diff --git a/sdk/identity/identity/src/msal/msal.browser.ts b/sdk/identity/identity/src/msal/msal-browser.mts similarity index 100% rename from sdk/identity/identity/src/msal/msal.browser.ts rename to sdk/identity/identity/src/msal/msal-browser.mts diff --git a/sdk/identity/identity/src/msal/nodeFlows/msalClient.ts b/sdk/identity/identity/src/msal/nodeFlows/msalClient.ts index 12dc6e3799f7..834019f59ab0 100644 --- a/sdk/identity/identity/src/msal/nodeFlows/msalClient.ts +++ b/sdk/identity/identity/src/msal/nodeFlows/msalClient.ts @@ -4,11 +4,11 @@ import * as msal from "@azure/msal-node"; import type { AccessToken, GetTokenOptions } from "@azure/core-auth"; -import type { AuthenticationRecord, CertificateParts } from "../types"; -import type { CredentialLogger } from "../../util/logging"; -import { credentialLogger, formatSuccess } from "../../util/logging"; -import type { PluginConfiguration } from "./msalPlugins"; -import { msalPlugins } from "./msalPlugins"; +import type { AuthenticationRecord, CertificateParts } from "../types.js"; +import type { CredentialLogger } from "../../util/logging.js"; +import { credentialLogger, formatSuccess } from "../../util/logging.js"; +import type { PluginConfiguration } from "./msalPlugins.js"; +import { msalPlugins } from "./msalPlugins.js"; import { defaultLoggerCallback, ensureValidMsalToken, @@ -19,18 +19,17 @@ import { handleMsalError, msalToPublic, publicToMsal, -} from "../utils"; - -import { AuthenticationRequiredError } from "../../errors"; -import type { BrokerOptions } from "./brokerOptions"; -import type { DeviceCodePromptCallback } from "../../credentials/deviceCodeCredentialOptions"; -import { IdentityClient } from "../../client/identityClient"; -import type { InteractiveBrowserCredentialNodeOptions } from "../../credentials/interactiveBrowserCredentialOptions"; -import type { TokenCachePersistenceOptions } from "./tokenCachePersistenceOptions"; -import { calculateRegionalAuthority } from "../../regionalAuthority"; +} from "../utils.js"; + +import { AuthenticationRequiredError } from "../../errors.js"; +import type { BrokerOptions } from "./brokerOptions.js"; +import type { DeviceCodePromptCallback } from "../../credentials/deviceCodeCredentialOptions.js"; +import { IdentityClient } from "../../client/identityClient.js"; +import type { InteractiveBrowserCredentialNodeOptions } from "../../credentials/interactiveBrowserCredentialOptions.js"; +import type { TokenCachePersistenceOptions } from "./tokenCachePersistenceOptions.js"; +import { calculateRegionalAuthority } from "../../regionalAuthority.js"; import { getLogLevel } from "@azure/logger"; -import open from "open"; -import { resolveTenantId } from "../../util/tenantIdUtils"; +import { resolveTenantId } from "../../util/tenantIdUtils.js"; /** * The default logger used if no logger was passed in by the credential. @@ -244,14 +243,6 @@ export interface MsalClientOptions { authenticationRecord?: AuthenticationRecord; } -/** - * A call to open(), but mockable - * @internal - */ -export const interactiveBrowserMockable = { - open, -}; - /** * Generates the configuration for MSAL (Microsoft Authentication Library). * @@ -835,7 +826,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov function createBaseInteractiveRequest(): msal.InteractiveRequest { return { openBrowser: async (url) => { - await interactiveBrowserMockable.open(url, { wait: true, newInstance: true }); + const open = await import("open"); + await open.default(url, { wait: true, newInstance: true }); }, scopes, authority: calculateRequestAuthority(options), diff --git a/sdk/identity/identity/src/msal/nodeFlows/msalPlugins.ts b/sdk/identity/identity/src/msal/nodeFlows/msalPlugins.ts index 8b989200d8ac..bb1e2821b6e2 100644 --- a/sdk/identity/identity/src/msal/nodeFlows/msalPlugins.ts +++ b/sdk/identity/identity/src/msal/nodeFlows/msalPlugins.ts @@ -3,11 +3,15 @@ import type * as msalNode from "@azure/msal-node"; -import { CACHE_CAE_SUFFIX, CACHE_NON_CAE_SUFFIX, DEFAULT_TOKEN_CACHE_NAME } from "../../constants"; +import { + CACHE_CAE_SUFFIX, + CACHE_NON_CAE_SUFFIX, + DEFAULT_TOKEN_CACHE_NAME, +} from "../../constants.js"; -import type { MsalClientOptions } from "./msalClient"; -import type { NativeBrokerPluginControl } from "../../plugins/provider"; -import type { TokenCachePersistenceOptions } from "./tokenCachePersistenceOptions"; +import type { MsalClientOptions } from "./msalClient.js"; +import type { NativeBrokerPluginControl } from "../../plugins/provider.js"; +import type { TokenCachePersistenceOptions } from "./tokenCachePersistenceOptions.js"; /** * Configuration for the plugins used by the MSAL node client. diff --git a/sdk/identity/identity/src/msal/utils.ts b/sdk/identity/identity/src/msal/utils.ts index bf0b632626cd..b599a4e65905 100644 --- a/sdk/identity/identity/src/msal/utils.ts +++ b/sdk/identity/identity/src/msal/utils.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthenticationRecord, MsalAccountInfo, MsalToken, ValidMsalToken } from "./types"; -import { AuthenticationRequiredError, CredentialUnavailableError } from "../errors"; -import type { CredentialLogger } from "../util/logging"; -import { credentialLogger, formatError } from "../util/logging"; -import { DefaultAuthorityHost, DefaultTenantId } from "../constants"; +import type { AuthenticationRecord, MsalAccountInfo, MsalToken, ValidMsalToken } from "./types.js"; +import { AuthenticationRequiredError, CredentialUnavailableError } from "../errors.js"; +import type { CredentialLogger } from "../util/logging.js"; +import { credentialLogger, formatError } from "../util/logging.js"; +import { DefaultAuthorityHost, DefaultTenantId } from "../constants.js"; import { randomUUID as coreRandomUUID, isNode, isNodeLike } from "@azure/core-util"; import { AbortError } from "@azure/abort-controller"; import type { AzureLogLevel } from "@azure/logger"; import type { GetTokenOptions } from "@azure/core-auth"; -import { msalCommon } from "./msal"; +import { msalCommon } from "./msal.js"; export interface ILoggerCallback { (level: msalCommon.LogLevel, message: string, containsPii: boolean): void; diff --git a/sdk/identity/identity/src/plugins/consumer.browser.ts b/sdk/identity/identity/src/plugins/consumer-browser.mts similarity index 100% rename from sdk/identity/identity/src/plugins/consumer.browser.ts rename to sdk/identity/identity/src/plugins/consumer-browser.mts diff --git a/sdk/identity/identity/src/plugins/consumer.ts b/sdk/identity/identity/src/plugins/consumer.ts index 62dbf23a6f2a..a263384445c8 100644 --- a/sdk/identity/identity/src/plugins/consumer.ts +++ b/sdk/identity/identity/src/plugins/consumer.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AzurePluginContext, IdentityPlugin } from "./provider"; +import type { AzurePluginContext, IdentityPlugin } from "./provider.js"; import { msalNodeFlowCacheControl, msalNodeFlowNativeBrokerControl, -} from "../msal/nodeFlows/msalPlugins"; +} from "../msal/nodeFlows/msalPlugins.js"; -import { vsCodeCredentialControl } from "../credentials/visualStudioCodeCredential"; +import { vsCodeCredentialControl } from "../credentials/visualStudioCodeCredential.js"; /** * The context passed to an Identity plugin. This contains objects that diff --git a/sdk/identity/identity/src/plugins/provider.ts b/sdk/identity/identity/src/plugins/provider.ts index 7fed077c19e6..494afe012401 100644 --- a/sdk/identity/identity/src/plugins/provider.ts +++ b/sdk/identity/identity/src/plugins/provider.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { TokenCachePersistenceOptions } from "../msal/nodeFlows/tokenCachePersistenceOptions"; -import type { VSCodeCredentialFinder } from "../credentials/visualStudioCodeCredentialPlugin"; +import type { TokenCachePersistenceOptions } from "../msal/nodeFlows/tokenCachePersistenceOptions.js"; +import type { VSCodeCredentialFinder } from "../credentials/visualStudioCodeCredentialPlugin.js"; /** * The type of an Azure Identity plugin, a function accepting a plugin diff --git a/sdk/identity/identity/src/util/authHostEnv.browser.ts b/sdk/identity/identity/src/util/authHostEnv-browser.mts similarity index 100% rename from sdk/identity/identity/src/util/authHostEnv.browser.ts rename to sdk/identity/identity/src/util/authHostEnv-browser.mts diff --git a/sdk/identity/identity/src/util/processMultiTenantRequest.browser.ts b/sdk/identity/identity/src/util/processMultiTenantRequest-browser.mts similarity index 100% rename from sdk/identity/identity/src/util/processMultiTenantRequest.browser.ts rename to sdk/identity/identity/src/util/processMultiTenantRequest-browser.mts diff --git a/sdk/identity/identity/src/util/processMultiTenantRequest.ts b/sdk/identity/identity/src/util/processMultiTenantRequest.ts index 0121b8132e02..f1cc57dd9dbc 100644 --- a/sdk/identity/identity/src/util/processMultiTenantRequest.ts +++ b/sdk/identity/identity/src/util/processMultiTenantRequest.ts @@ -2,8 +2,8 @@ // Licensed under the MIT License. import type { GetTokenOptions } from "@azure/core-auth"; -import { CredentialUnavailableError } from "../errors"; -import type { CredentialLogger } from "./logging"; +import { CredentialUnavailableError } from "../errors.js"; +import type { CredentialLogger } from "./logging.js"; function createConfigurationErrorMessage(tenantId: string): string { return `The current credential is not configured to acquire tokens for tenant ${tenantId}. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to AdditionallyAllowedTenants to allow acquiring tokens for any tenant.`; diff --git a/sdk/identity/identity/src/util/scopeUtils.ts b/sdk/identity/identity/src/util/scopeUtils.ts index 68b0fb69fa6a..9d158114f660 100644 --- a/sdk/identity/identity/src/util/scopeUtils.ts +++ b/sdk/identity/identity/src/util/scopeUtils.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { CredentialLogger } from "./logging"; -import { formatError } from "./logging"; +import type { CredentialLogger } from "./logging.js"; +import { formatError } from "./logging.js"; /** * Ensures the scopes value is an array. diff --git a/sdk/identity/identity/src/util/subscriptionUtils.ts b/sdk/identity/identity/src/util/subscriptionUtils.ts index 1e4bbcaf63ba..5ef0822589ce 100644 --- a/sdk/identity/identity/src/util/subscriptionUtils.ts +++ b/sdk/identity/identity/src/util/subscriptionUtils.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { CredentialLogger } from "./logging"; -import { formatError } from "./logging"; +import type { CredentialLogger } from "./logging.js"; +import { formatError } from "./logging.js"; /** * @internal diff --git a/sdk/identity/identity/src/util/tenantIdUtils.ts b/sdk/identity/identity/src/util/tenantIdUtils.ts index 9c5fe9b4fd8f..e88f8668a35b 100644 --- a/sdk/identity/identity/src/util/tenantIdUtils.ts +++ b/sdk/identity/identity/src/util/tenantIdUtils.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { ALL_TENANTS, DeveloperSignOnClientId } from "../constants"; -import type { CredentialLogger } from "./logging"; -import { formatError } from "./logging"; -export { processMultiTenantRequest } from "./processMultiTenantRequest"; +import { ALL_TENANTS, DeveloperSignOnClientId } from "../constants.js"; +import type { CredentialLogger } from "./logging.js"; +import { formatError } from "./logging.js"; +export { processMultiTenantRequest } from "./processMultiTenantRequest.js"; /** * @internal diff --git a/sdk/identity/identity/src/util/tracing.ts b/sdk/identity/identity/src/util/tracing.ts index 8456bcf9c26c..d25ac092d921 100644 --- a/sdk/identity/identity/src/util/tracing.ts +++ b/sdk/identity/identity/src/util/tracing.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { SDK_VERSION } from "../constants"; +import { SDK_VERSION } from "../constants.js"; import { createTracingClient } from "@azure/core-tracing"; /** diff --git a/sdk/identity/identity/test/authTestUtils.ts b/sdk/identity/identity/test/authTestUtils.ts index e299951e17c5..13e9c5965162 100644 --- a/sdk/identity/identity/test/authTestUtils.ts +++ b/sdk/identity/identity/test/authTestUtils.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AuthenticationError } from "../src"; -import { AzureAuthorityHosts } from "../src"; -import { assert } from "chai"; +import type { AuthenticationError } from "../src/index.js"; +import { AzureAuthorityHosts } from "../src/index.js"; +import { assert } from "vitest"; /** * @internal diff --git a/sdk/identity/identity/test/httpRequests.browser.ts b/sdk/identity/identity/test/httpRequests-browser.mts similarity index 91% rename from sdk/identity/identity/test/httpRequests.browser.ts rename to sdk/identity/identity/test/httpRequests-browser.mts index a62929679447..1eb050314dc1 100644 --- a/sdk/identity/identity/test/httpRequests.browser.ts +++ b/sdk/identity/identity/test/httpRequests-browser.mts @@ -1,7 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import * as sinon from "sinon"; import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; import type { AzureLogLevel } from "@azure/logger"; import { AzureLogger, getLogLevel, setLogLevel } from "@azure/logger"; @@ -9,9 +7,10 @@ import type { IdentityTestContextInterface, RawTestResponse, TestResponse, -} from "./httpRequestsCommon"; +} from "./httpRequestsCommon.js"; import type { RestError } from "@azure/core-rest-pipeline"; -import { getError } from "./authTestUtils"; +import { getError } from "./authTestUtils.js"; +import { type MockInstance, vi } from "vitest"; /** * Helps specify a different number of responses for Node and for the browser. @@ -52,18 +51,15 @@ export type TrackedRequest = { * @internal */ export class IdentityTestContext implements IdentityTestContextInterface { - public sandbox: sinon.SinonSandbox; - public clock: sinon.SinonFakeTimers; public oldLogLevel: AzureLogLevel | undefined; public oldLogger: any; public logMessages: string[]; - public fetch: sinon.SinonStub; + public fetch: MockInstance; public requests: TrackedRequest[]; public responses: RawTestResponse[]; constructor({ replaceLogger, logLevel }: { replaceLogger?: boolean; logLevel?: AzureLogLevel }) { - this.sandbox = sinon.createSandbox(); - this.clock = this.sandbox.useFakeTimers(); + vi.useFakeTimers(); this.oldLogLevel = getLogLevel(); this.oldLogger = AzureLogger.log; this.logMessages = []; @@ -72,7 +68,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { * Browser specific code. * Sets up a fake fetch implementation that will be used to answer any outgoing request. */ - this.fetch = this.sandbox.stub(self, "fetch"); + this.fetch = vi.spyOn(self, "fetch"); this.requests = []; this.responses = []; @@ -104,7 +100,8 @@ export class IdentityTestContext implements IdentityTestContextInterface { } async restore(): Promise { - this.sandbox.restore(); + vi.useRealTimers(); + vi.restoreAllMocks(); AzureLogger.log = this.oldLogger; setLogLevel(this.oldLogLevel); } @@ -121,7 +118,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { * Both keeps track of the outgoing requests, * and ensures each request answers with each received response, in order. */ - this.fetch.callsFake(async (url, request) => { + this.fetch.mockImplementation(async (url, request) => { this._trackRequest(url, request); return new Response(response.body, { @@ -130,7 +127,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { }); }); const promise = sendPromise(); - await this.clock.runAllAsync(); + await vi.runAllTimersAsync(); return promise; } @@ -170,7 +167,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { }[]; }> { this.responses.push(...[...insecureResponses, ...secureResponses]); - this.fetch.callsFake(async (url, request) => { + this.fetch.mockImplementation(async (url, request) => { this._trackRequest(url, request); if (!this.responses.length) { throw new Error("No responses to send"); @@ -199,7 +196,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { // We need the promises to begin triggering, so the server has something to respond to, // and only then we can wait for all of the async processes to finish. const promise = credential.getToken(scopes, getTokenOptions); - await this.clock.runAllAsync(); + await vi.runAllTimersAsync(); result = await promise; } catch (e: any) { error = e; diff --git a/sdk/identity/identity/test/httpRequests.ts b/sdk/identity/identity/test/httpRequests.ts index 852c53a6cf02..e9b1f78324de 100644 --- a/sdk/identity/identity/test/httpRequests.ts +++ b/sdk/identity/identity/test/httpRequests.ts @@ -1,24 +1,40 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import http from "http"; -import https from "https"; -import type { AccessToken, GetTokenOptions, TokenCredential } from "../src"; +import * as https from "node:https"; +import * as http from "node:http"; +import type { AccessToken, GetTokenOptions, TokenCredential } from "../src/index.js"; import type { AzureLogLevel } from "@azure/logger"; import { AzureLogger, getLogLevel, setLogLevel } from "@azure/logger"; -import type { ClientRequest, IncomingHttpHeaders, IncomingMessage } from "http"; +import type { ClientRequest, IncomingHttpHeaders, IncomingMessage } from "node:http"; import type { IdentityTestContextInterface, RawTestResponse, TestResponse, -} from "./httpRequestsCommon"; -import { createResponse } from "./httpRequestsCommon"; -import type Sinon from "sinon"; -import * as sinon from "sinon"; -import { PassThrough } from "stream"; +} from "./httpRequestsCommon.js"; +import { createResponse } from "./httpRequestsCommon.js"; +import { PassThrough } from "node:stream"; import type { RestError } from "@azure/core-rest-pipeline"; -import { getError } from "./authTestUtils"; -import { openIdConfigurationResponse } from "./msalTestUtils"; +import { getError } from "./authTestUtils.js"; +import { openIdConfigurationResponse } from "./msalTestUtils.js"; + +import type { MockInstance } from "vitest"; +import { vi } from "vitest"; + +vi.mock("node:https", async () => { + const actual = await vi.importActual("node:https"); + return { + ...actual, + request: vi.fn(), + }; +}); +vi.mock("node:http", async () => { + const actual = await vi.importActual("node:http"); + return { + ...actual, + request: vi.fn(), + }; +}); /** * Helps write responses that extend the PassThrough class. @@ -98,15 +114,12 @@ export function prepareMSALResponses(): RawTestResponse[] { * @internal */ export class IdentityTestContext implements IdentityTestContextInterface { - public sandbox: Sinon.SinonSandbox; - public clock: Sinon.SinonFakeTimers; public oldLogLevel: AzureLogLevel | undefined; public oldLogger: any; public logMessages: string[]; constructor({ replaceLogger, logLevel }: { replaceLogger?: boolean; logLevel?: AzureLogLevel }) { - this.sandbox = sinon.createSandbox(); - this.clock = this.sandbox.useFakeTimers(); + vi.useFakeTimers(); this.oldLogLevel = getLogLevel(); this.oldLogger = AzureLogger.log; this.logMessages = []; @@ -123,7 +136,9 @@ export class IdentityTestContext implements IdentityTestContextInterface { } async restore(): Promise { - this.sandbox.restore(); + vi.useRealTimers(); + vi.restoreAllMocks(); + vi.unstubAllEnvs(); AzureLogger.log = this.oldLogger; setLogLevel(this.oldLogLevel); } @@ -136,15 +151,13 @@ export class IdentityTestContext implements IdentityTestContextInterface { { response }: { response: TestResponse }, ): Promise { const request = createRequest(); - this.sandbox.replace( - https, - "request", + vi.mocked(https.request).mockImplementation( (_options: string | URL | http.RequestOptions, resolve: any) => { resolve(responseToIncomingMessage(response)); return request; }, ); - this.clock.runAllAsync(); + await vi.runAllTimersAsync(); return sendPromise(); } @@ -164,7 +177,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { public registerResponses( provider: "http" | "https", responses: { response?: TestResponse; error?: RestError }[], - spies: sinon.SinonSpy[], + spies: MockInstance[], ): http.RequestOptions[] { const providerObject = provider === "http" ? http : https; const totalOptions: http.RequestOptions[] = []; @@ -187,11 +200,11 @@ export class IdentityTestContext implements IdentityTestContextInterface { resolve(responseToIncomingMessage(response!)); } const request = createRequest(); - spies.push(this.sandbox.spy(request, "end")); + spies.push(vi.spyOn(request, "end")); return request; }; - this.sandbox.replace(providerObject, "request", fakeRequest); - this.sandbox.replace(providerObject.Agent.prototype as any, "request", fakeRequest); + + vi.mocked(providerObject.request).mockImplementation(fakeRequest); } catch (e: any) { console.debug( "Failed to replace the request. This might be expected if you're running multiple sendCredentialRequests() calls.", @@ -210,7 +223,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { */ extractRequests( options: http.RequestOptions[], - spies: sinon.SinonSpy[], + spies: MockInstance[], protocol: "http" | "https", ): { url: string; @@ -218,7 +231,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { method: string; headers: Record; }[] { - return spies.reduce((accumulator: any, spy: sinon.SinonSpy, index: number) => { + return spies.reduce((accumulator: any, spy: MockInstance, index: number) => { if (!options[index]) { return accumulator; } @@ -227,7 +240,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { ...accumulator, { url: `${protocol}://${requestOptions.hostname}${requestOptions.path}`, - body: (spy.args[0] && spy.args[0][0]) || "", + body: (spy.mock.calls[0] && spy.mock.calls[0][0]) || "", method: requestOptions.method, headers: requestOptions.headers, }, @@ -268,10 +281,10 @@ export class IdentityTestContext implements IdentityTestContextInterface { // Generally, there should be no insecure requests, but in practice, some authentication methods require // requests to go out to insecure endpoints, specially at the beginning of the authentication flow. // An example would be the IMDS endpoint. - const insecureSpies: sinon.SinonSpy[] = []; + const insecureSpies: MockInstance[] = []; const insecureOptions = this.registerResponses("http", insecureResponses, insecureSpies); - const secureSpies: sinon.SinonSpy[] = []; + const secureSpies: MockInstance[] = []; const secureOptions = this.registerResponses("https", secureResponses, secureSpies); let result: AccessToken | null = null; @@ -282,7 +295,7 @@ export class IdentityTestContext implements IdentityTestContextInterface { // So loosely tell Sinon's clock to advance the time, // and then we trigger our main getToken request, and wait for it. // All the errors will be safely be caught by the try surrounding the getToken request. - this.clock.runAllAsync(); + await vi.runAllTimersAsync(); result = await credential.getToken(scopes, getTokenOptions); } catch (e: any) { error = e; diff --git a/sdk/identity/identity/test/httpRequestsCommon.ts b/sdk/identity/identity/test/httpRequestsCommon.ts index b4c37df1ed36..fe3c8855722a 100644 --- a/sdk/identity/identity/test/httpRequestsCommon.ts +++ b/sdk/identity/identity/test/httpRequestsCommon.ts @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type * as sinon from "sinon"; -import type { AccessToken, GetTokenOptions, TokenCredential } from "../src"; +import type { AccessToken, GetTokenOptions, TokenCredential } from "../src/index.js"; import type { AzureLogLevel, AzureLogger } from "@azure/logger"; import type { RawHttpHeaders, RestError } from "@azure/core-rest-pipeline"; @@ -73,8 +71,6 @@ export type SendCredentialRequests = (options: { * @internal */ export interface IdentityTestContextInterface { - sandbox: sinon.SinonSandbox; - clock: sinon.SinonFakeTimers; logMessages: string[]; oldLogger: typeof AzureLogger.log; oldLogLevel: AzureLogLevel | undefined; diff --git a/sdk/identity/identity/test/integration/azureFunctionsTest.spec.ts b/sdk/identity/identity/test/integration/azureFunctionsTest.spec.ts index aee773464bfa..62ca582e408e 100644 --- a/sdk/identity/identity/test/integration/azureFunctionsTest.spec.ts +++ b/sdk/identity/identity/test/integration/azureFunctionsTest.spec.ts @@ -3,30 +3,29 @@ import { ServiceClient } from "@azure/core-client"; import { createPipelineRequest } from "@azure/core-rest-pipeline"; -import { assert } from "chai"; -import type { Context } from "mocha"; import { isLiveMode } from "@azure-tools/test-recorder"; +import { describe, it, assert } from "vitest"; describe("AzureFunctions Integration test", function () { - it("test the Azure Functions endpoint where the sync MI credential is used.", async function (this: Context) { - if (!isLiveMode()) { - this.skip(); - } - const baseUri = baseUrl(); - const client = new ServiceClient({ baseUri: baseUri }); - const pipelineRequest = createPipelineRequest({ - url: baseUri, - method: "GET", - }); - const response = await client.sendRequest(pipelineRequest); - console.log(response.bodyAsText); - assert.equal(response.status, 200, `Expected status 200. Received ${response.status}`); - assert.equal( - response.bodyAsText, - "Successfully authenticated with storage", - `Expected message: "Successfully authenticated with storage". Received message: ${response.bodyAsText}`, - ); - }); + it.skipIf(!isLiveMode())( + "test the Azure Functions endpoint where the sync MI credential is used.", + async function () { + const baseUri = baseUrl(); + const client = new ServiceClient({ baseUri: baseUri }); + const pipelineRequest = createPipelineRequest({ + url: baseUri, + method: "GET", + }); + const response = await client.sendRequest(pipelineRequest); + console.log(response.bodyAsText); + assert.equal(response.status, 200, `Expected status 200. Received ${response.status}`); + assert.equal( + response.bodyAsText, + "Successfully authenticated with storage", + `Expected message: "Successfully authenticated with storage". Received message: ${response.bodyAsText}`, + ); + }, + ); }); function baseUrl(): string { diff --git a/sdk/identity/identity/test/integration/azureVMUserAssignedTest.spec.ts b/sdk/identity/identity/test/integration/azureVMUserAssignedTest.spec.ts index 4edd4b22377c..a6600d2a65ce 100644 --- a/sdk/identity/identity/test/integration/azureVMUserAssignedTest.spec.ts +++ b/sdk/identity/identity/test/integration/azureVMUserAssignedTest.spec.ts @@ -1,17 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import type { Context } from "mocha"; import { isLiveMode } from "@azure-tools/test-recorder"; -import { ManagedIdentityCredential } from "../../src"; +import { ManagedIdentityCredential } from "../../src/index.js"; +import { describe, it, assert } from "vitest"; describe("AzureVM UserAssigned Integration test", function () { - it("works with a user assigned clientId", async function (this: Context) { - if (!isLiveMode()) { - this.skip(); - } - + it.skipIf(!isLiveMode())("works with a user assigned clientId", async function () { const userAssignedClientId = process.env.IDENTITY_VM_USER_ASSIGNED_MI_CLIENT_ID; if (!userAssignedClientId) { console.log("IDENTITY_VM_USER_ASSIGNED_MI_CLIENT_ID is not set"); @@ -22,9 +16,9 @@ describe("AzureVM UserAssigned Integration test", function () { assert.exists(accessToken.token); }); - it("works with a user assigned objectId", async function (this: Context) { + it("works with a user assigned objectId", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } const userAssignedObjectId = process.env.IDENTITY_VM_USER_ASSIGNED_MI_OBJECT_ID; diff --git a/sdk/identity/identity/test/integration/azureWebAppsTest.spec.ts b/sdk/identity/identity/test/integration/azureWebAppsTest.spec.ts index 0a96096d3fcd..92ef1a548379 100644 --- a/sdk/identity/identity/test/integration/azureWebAppsTest.spec.ts +++ b/sdk/identity/identity/test/integration/azureWebAppsTest.spec.ts @@ -3,25 +3,24 @@ import { ServiceClient } from "@azure/core-client"; import { createPipelineRequest } from "@azure/core-rest-pipeline"; -import { assert } from "chai"; -import type { Context } from "mocha"; import { isLiveMode } from "@azure-tools/test-recorder"; +import { describe, it, assert } from "vitest"; describe("AzureWebApps Integration test", function () { - it("test the Azure Web Apps endpoint where the MI credential is used.", async function (this: Context) { - if (!isLiveMode()) { - this.skip(); - } - const baseUri = baseUrl(); - const client = new ServiceClient({ baseUri: baseUri }); - const pipelineRequest = createPipelineRequest({ - url: baseUri, - method: "GET", - }); - const response = await client.sendRequest(pipelineRequest); - console.log(response.bodyAsText); - assert.equal(response.status, 200, `Expected status 200. Received ${response.status}`); - }); + it.skipIf(!isLiveMode())( + "test the Azure Web Apps endpoint where the MI credential is used.", + async function () { + const baseUri = baseUrl(); + const client = new ServiceClient({ baseUri: baseUri }); + const pipelineRequest = createPipelineRequest({ + url: baseUri, + method: "GET", + }); + const response = await client.sendRequest(pipelineRequest); + console.log(response.bodyAsText); + assert.equal(response.status, 200, `Expected status 200. Received ${response.status}`); + }, + ); }); function baseUrl(): string { diff --git a/sdk/identity/identity/test/integration/node/azureKubernetesTest.spec.ts b/sdk/identity/identity/test/integration/node/azureKubernetesTest.spec.ts index 34f42c74a770..2f4a241b0f86 100644 --- a/sdk/identity/identity/test/integration/node/azureKubernetesTest.spec.ts +++ b/sdk/identity/identity/test/integration/node/azureKubernetesTest.spec.ts @@ -1,15 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; import { execSync } from "child_process"; import { isLiveMode } from "@azure-tools/test-recorder"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, beforeAll } from "vitest"; describe("Azure Kubernetes Integration test", function () { let podOutput: string; - before(async function () { + beforeEach(async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } const resourceGroup = requireEnvVar("IDENTITY_RESOURCE_GROUP"); const aksClusterName = requireEnvVar("IDENTITY_AKS_CLUSTER_NAME"); @@ -38,9 +37,9 @@ describe("Azure Kubernetes Integration test", function () { podOutput = runCommand("kubectl", `exec ${podName} -- node /app/index.js`); }); - it("can authenticate using managed identity", async function () { + it("can authenticate using managed identity", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } assert.include( @@ -50,9 +49,9 @@ describe("Azure Kubernetes Integration test", function () { ); }); - it("can authenticate using workload identity", async function () { + it("can authenticate using workload identity", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } assert.include( diff --git a/sdk/identity/identity/test/internal/logger.spec.ts b/sdk/identity/identity/test/internal/logger.spec.ts index a4a2bee835e4..a1855aea46f0 100644 --- a/sdk/identity/identity/test/internal/logger.spec.ts +++ b/sdk/identity/identity/test/internal/logger.spec.ts @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AccessToken, GetTokenOptions, TokenCredential } from "../../src"; -import type { CredentialLogger } from "../../src/util/logging"; +import type { AccessToken, GetTokenOptions, TokenCredential } from "../../src/index.js"; +import type { CredentialLogger } from "../../src/util/logging.js"; import { credentialLogger, credentialLoggerInstance, formatError, formatSuccess, -} from "../../src/util/logging"; -import { assert } from "chai"; +} from "../../src/util/logging.js"; +import { describe, it, assert } from "vitest"; describe("Identity logging utilities", function () { describe("credentialLoggerInstance", function () { diff --git a/sdk/identity/identity/test/internal/node/azureApplicationCredential.spec.ts b/sdk/identity/identity/test/internal/node/azureApplicationCredential.spec.ts index 2a0281e2cd30..8d7d9dd53fa1 100644 --- a/sdk/identity/identity/test/internal/node/azureApplicationCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/azureApplicationCredential.spec.ts @@ -1,73 +1,59 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { IdentityTestContextInterface } from "../../httpRequestsCommon"; -import { createResponse } from "../../httpRequestsCommon"; - -import { AzureApplicationCredential } from "../../../src/credentials/azureApplicationCredential"; -import { IdentityTestContext } from "../../httpRequests"; -import { RestError } from "@azure/core-rest-pipeline"; -import { assert } from "chai"; -import * as dac from "../../../src/credentials/defaultAzureCredential"; -import { ManagedIdentityCredential } from "../../../src/credentials/managedIdentityCredential/index"; +import { AzureApplicationCredential } from "../../../src/credentials/azureApplicationCredential.js"; +import { + createDefaultHttpClient, + createHttpHeaders, + HttpClient, + RestError, +} from "@azure/core-rest-pipeline"; import { ManagedIdentityApplication } from "@azure/msal-node"; +import { describe, it, afterEach, beforeEach, vi, expect } from "vitest"; describe("AzureApplicationCredential testing Managed Identity (internal)", function () { - let testContext: IdentityTestContextInterface; + let httpClient: HttpClient; beforeEach(async () => { - testContext = new IdentityTestContext({}); - testContext.sandbox - .stub(dac, "createDefaultManagedIdentityCredential") - .callsFake( - (...args) => - new ManagedIdentityCredential({ ...args, clientId: process.env.AZURE_CLIENT_ID }), - ); + // Let the IMDS ping request succeed, but fail the token acquisition + httpClient = createDefaultHttpClient(); + vi.spyOn(httpClient, "sendRequest").mockImplementation((request) => { + return Promise.resolve({ + headers: createHttpHeaders(), + request, + status: 200, + }); + }); }); afterEach(async () => { - await testContext.restore(); + vi.restoreAllMocks(); + vi.unstubAllEnvs(); }); it("an unexpected error bubbles all the way up", async function () { - process.env.AZURE_CLIENT_ID = "errclient"; - const errorMessage = "ManagedIdentityCredential authentication failed."; - testContext.sandbox - .stub(ManagedIdentityApplication.prototype, "acquireToken") - .rejects(new Error(errorMessage)); - const { error } = await testContext.sendCredentialRequests({ - scopes: ["scopes"], - credential: new AzureApplicationCredential(), - insecureResponses: [ - createResponse(200), // IMDS Endpoint ping - ], - }); - console.log(error); - assert.ok(error?.message.includes(errorMessage)); + // The IMDS ping request will succeed + // An unexpected error comes from MSAL + vi.spyOn(ManagedIdentityApplication.prototype, "acquireToken").mockRejectedValue( + new Error(errorMessage), + ); + + await expect(new AzureApplicationCredential({ httpClient }).getToken("scopes")).rejects.toThrow( + new RegExp(errorMessage), + ); }); it("returns expected error when the network was unreachable", async function () { - process.env.AZURE_CLIENT_ID = "errclient"; - - const netError: RestError = new RestError("Request Timeout", { + const netError: RestError = new RestError("Request timeout: network unreachable", { code: "ENETUNREACH", statusCode: 408, }); + vi.spyOn(ManagedIdentityApplication.prototype, "acquireToken").mockRejectedValue(netError); - testContext.sandbox - .stub(ManagedIdentityApplication.prototype, "acquireToken") - .rejects(netError); - - const { error } = await testContext.sendCredentialRequests({ - scopes: ["scopes"], - credential: new AzureApplicationCredential(), - insecureResponses: [ - createResponse(200), // IMDS Endpoint ping - { error: netError }, - ], - }); - assert.ok(error!.message!.indexOf("Network unreachable.") > -1); + await expect(new AzureApplicationCredential({ httpClient }).getToken("scopes")).rejects.toThrow( + /Network unreachable/, + ); }); }); diff --git a/sdk/identity/identity/test/internal/node/azureCliCredential.spec.ts b/sdk/identity/identity/test/internal/node/azureCliCredential.spec.ts index 11f800215769..96c9f6cd9806 100644 --- a/sdk/identity/identity/test/internal/node/azureCliCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/azureCliCredential.spec.ts @@ -1,28 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type Sinon from "sinon"; -import { createSandbox } from "sinon"; - -import { AzureCliCredential } from "../../../src/credentials/azureCliCredential"; +import { AzureCliCredential } from "../../../src/credentials/azureCliCredential.js"; import type { GetTokenOptions } from "@azure/core-auth"; -import { assert } from "@azure-tools/test-utils"; -import child_process from "child_process"; +import child_process from "node:child_process"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("AzureCliCredential (internal)", function () { - let sandbox: Sinon.SinonSandbox | undefined; let stdout: string = ""; let stderr: string = ""; let azArgs: string[][] = []; let azOptions: { cwd: string; shell: boolean }[] = []; beforeEach(async function () { - sandbox = createSandbox(); azArgs = []; azOptions = []; - sandbox - .stub(child_process, "execFile") - .callsFake((_file, args, options, callback): child_process.ChildProcess => { + vi.spyOn(child_process, "execFile").mockImplementation( + (_file, args, options, callback): child_process.ChildProcess => { azArgs.push(args as string[]); azOptions.push(options as { cwd: string; shell: boolean }); if (callback) { @@ -30,11 +23,12 @@ describe("AzureCliCredential (internal)", function () { } // Bypassing the type check. We don't use this return value in our code. return {} as child_process.ChildProcess; - }); + }, + ); }); afterEach(async function () { - sandbox?.restore(); + vi.restoreAllMocks(); }); it("get access token without error", async function () { @@ -323,12 +317,11 @@ az login --scope https://test.windows.net/.default`; tenantId === " " ? "whitespace" : tenantId === "\0" ? "null character" : `"${tenantId}"`; it(`rejects invalid tenant id of ${testCase} in getToken`, async function () { const credential = new AzureCliCredential(); - await assert.isRejected( + await expect( credential.getToken("https://service/.default", { tenantId: tenantId, }), - tenantIdErrorMessage, - ); + ).rejects.toThrow(tenantIdErrorMessage); }); it(`rejects invalid tenant id of ${testCase} in constructor`, function () { @@ -369,8 +362,7 @@ az login --scope https://test.windows.net/.default`; : `"${inputScope}"`; it(`rejects invalid scope of ${testCase}`, async function () { const credential = new AzureCliCredential(); - await assert.isRejected( - credential.getToken(inputScope), + await expect(credential.getToken(inputScope)).rejects.toThrow( "Invalid scope was specified by the user or calling client", ); }); @@ -455,8 +447,7 @@ az login --scope https://test.windows.net/.default`; }`; stderr = ""; const credential = new AzureCliCredential(); - await assert.isRejected( - credential.getToken("https://service/.default"), + await expect(credential.getToken("https://service/.default")).rejects.toThrow( /Expected "expiresOn" to be a RFC3339 date string. Got: "not-a-date"$/, ); }); diff --git a/sdk/identity/identity/test/internal/node/azureDeveloperCliCredential.spec.ts b/sdk/identity/identity/test/internal/node/azureDeveloperCliCredential.spec.ts index 04b1ce0ce00d..fdaa57e36411 100644 --- a/sdk/identity/identity/test/internal/node/azureDeveloperCliCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/azureDeveloperCliCredential.spec.ts @@ -1,39 +1,34 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import type Sinon from "sinon"; -import { createSandbox } from "sinon"; -import { AzureDeveloperCliCredential } from "../../../src/credentials/azureDeveloperCliCredential"; +import { AzureDeveloperCliCredential } from "../../../src/credentials/azureDeveloperCliCredential.js"; import type { GetTokenOptions } from "@azure/core-auth"; -import { assert } from "@azure-tools/test-utils"; -import child_process from "child_process"; +import child_process, { type ChildProcess } from "node:child_process"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("AzureDeveloperCliCredential (internal)", function () { - let sandbox: Sinon.SinonSandbox | undefined; let stdout: string = ""; let stderr: string = ""; let azdArgs: string[][] = []; let azdOptions: { cwd: string }[] = []; beforeEach(async function () { - sandbox = createSandbox(); azdArgs = []; azdOptions = []; - sandbox - .stub(child_process, "execFile") - .callsFake((_file, args, options, callback): child_process.ChildProcess => { + vi.spyOn(child_process, "execFile").mockImplementation( + (_file, args, options, callback): ChildProcess => { azdArgs.push(args as string[]); azdOptions.push(options as { cwd: string }); if (callback) { callback(null, stdout, stderr); } // Bypassing the type check. We don't use this return value in our code. - return {} as child_process.ChildProcess; - }); + return {} as ChildProcess; + }, + ); }); afterEach(async function () { - sandbox?.restore(); + vi.restoreAllMocks(); }); it("get access token without error", async function () { @@ -184,12 +179,11 @@ describe("AzureDeveloperCliCredential (internal)", function () { tenantId === " " ? "whitespace" : tenantId === "\0" ? "null character" : `"${tenantId}"`; it(`rejects invalid tenant id of ${testCase} in getToken`, async function () { const credential = new AzureDeveloperCliCredential(); - await assert.isRejected( + await expect( credential.getToken("https://service/.default", { tenantId: tenantId, }), - tenantIdErrorMessage, - ); + ).rejects.toThrow(tenantIdErrorMessage); }); it(`rejects invalid tenant id of ${testCase} in constructor`, function () { assert.throws(() => { @@ -207,8 +201,7 @@ describe("AzureDeveloperCliCredential (internal)", function () { : `"${inputScope}"`; it(`rejects invalid scope of ${testCase}`, async function () { const credential = new AzureDeveloperCliCredential(); - await assert.isRejected( - credential.getToken(inputScope), + await expect(credential.getToken(inputScope)).rejects.toThrow( "Invalid scope was specified by the user or calling client", ); }); diff --git a/sdk/identity/identity/test/internal/node/azurePipelinesCredential.spec.ts b/sdk/identity/identity/test/internal/node/azurePipelinesCredential.spec.ts index 4399f8315d9e..e67499f559e8 100644 --- a/sdk/identity/identity/test/internal/node/azurePipelinesCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/azurePipelinesCredential.spec.ts @@ -3,8 +3,8 @@ import type { PipelineResponse } from "@azure/core-rest-pipeline"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; -import { handleOidcResponse } from "../../../src/credentials/azurePipelinesCredential"; -import { assert } from "@azure-tools/test-utils"; +import { handleOidcResponse } from "../../../src/credentials/azurePipelinesCredential.js"; +import { describe, it, assert, beforeEach } from "vitest"; describe("AzurePipelinesCredential (internal)", function () { let response: PipelineResponse; diff --git a/sdk/identity/identity/test/internal/node/azurePowerShellCredential.spec.ts b/sdk/identity/identity/test/internal/node/azurePowerShellCredential.spec.ts index c511f9caf95d..c7cdbc7f4fda 100644 --- a/sdk/identity/identity/test/internal/node/azurePowerShellCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/azurePowerShellCredential.spec.ts @@ -8,13 +8,12 @@ import { parseJsonToken, powerShellErrors, powerShellPublicErrorMessages, -} from "../../../src/credentials/azurePowerShellCredential"; -import { AzurePowerShellCredential } from "../../../src"; +} from "../../../src/credentials/azurePowerShellCredential.js"; +import { AzurePowerShellCredential } from "../../../src/index.js"; import type { GetTokenOptions } from "@azure/core-auth"; -import Sinon from "sinon"; -import { assert } from "@azure-tools/test-utils"; -import { commandStack } from "../../../src/credentials/azurePowerShellCredential"; -import { processUtils } from "../../../src/util/processUtils"; +import { commandStack } from "../../../src/credentials/azurePowerShellCredential.js"; +import { processUtils } from "../../../src/util/processUtils.js"; +import { describe, it, assert, expect, vi, afterEach } from "vitest"; function resetCommandStack(): void { commandStack[0] = formatCommand("pwsh"); @@ -29,12 +28,9 @@ describe("AzurePowerShellCredential", function () { const scope = "https://vault.azure.net/.default"; const tenantIdErrorMessage = "Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names."; - let sandbox: Sinon.SinonSandbox; - beforeEach(() => { - sandbox = Sinon.createSandbox(); - }); + afterEach(() => { - sandbox.restore(); + vi.restoreAllMocks(); resetCommandStack(); }); @@ -46,9 +42,11 @@ describe("AzurePowerShellCredential", function () { }); it("throws an expected error if the user hasn't logged in through PowerShell", async function () { - const stub = sandbox.stub(processUtils, "execFile"); - stub.onCall(0).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(1).throws(new Error(`Get-AzAccessToken: ${powerShellErrors.login}`)); + vi.spyOn(processUtils, "execFile") + .mockResolvedValueOnce("") // The first call checks that the command is available. + .mockImplementationOnce(() => { + throw new Error(`Get-AzAccessToken: ${powerShellErrors.login}`); + }); const credential = new AzurePowerShellCredential(); @@ -65,9 +63,11 @@ describe("AzurePowerShellCredential", function () { }); it("throws an expected error if the user hasn't installed the Az.Account module", async function () { - const stub = sandbox.stub(processUtils, "execFile"); - stub.onCall(0).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(1).throws(new Error(powerShellErrors.installed)); + vi.spyOn(processUtils, "execFile") + .mockResolvedValueOnce("") // The first call checks that the command is available. + .mockImplementationOnce(() => { + throw new Error(`Get-AzAccessToken: ${powerShellErrors.installed}`); + }); const credential = new AzurePowerShellCredential(); @@ -84,12 +84,16 @@ describe("AzurePowerShellCredential", function () { }); it("throws an expected error if PowerShell isn't installed", async function () { - const stub = sandbox.stub(processUtils, "execFile"); - stub.onCall(0).throws(new Error()); + const stub = vi.spyOn(processUtils, "execFile"); + stub.mockImplementationOnce(() => { + throw new Error(); + }); // Additionally stub the second call on windows, for the fallback to Windows PowerShell if (process.platform === "win32") { - stub.onCall(1).throws(new Error()); + stub.mockImplementationOnce(() => { + throw new Error(); + }); } const credential = new AzurePowerShellCredential(); @@ -110,10 +114,9 @@ describe("AzurePowerShellCredential", function () { }); it("throws an expected error if PowerShell returns something that isn't valid JSON", async function () { - const stub = sandbox.stub(processUtils, "execFile"); - let idx = 0; - stub.onCall(idx++).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(idx++).returns(Promise.resolve("Not valid JSON")); + vi.spyOn(processUtils, "execFile") + .mockResolvedValueOnce("") + .mockResolvedValueOnce("Not valid JSON"); const credential = new AzurePowerShellCredential(); @@ -134,11 +137,12 @@ describe("AzurePowerShellCredential", function () { if (process.platform === "win32") { it("throws an expected error if PowerShell returns something that isn't valid JSON (Windows PowerShell fallback)", async function () { - const stub = sandbox.stub(processUtils, "execFile"); - let idx = 0; - stub.onCall(idx++).throws(new Error()); - stub.onCall(idx++).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(idx++).returns(Promise.resolve("Not valid JSON")); + vi.spyOn(processUtils, "execFile") + .mockImplementationOnce(() => { + throw new Error(); + }) + .mockResolvedValueOnce("") + .mockResolvedValueOnce("Not valid JSON"); const credential = new AzurePowerShellCredential(); @@ -166,9 +170,9 @@ describe("AzurePowerShellCredential", function () { Type: "Bearer", }; - const stub = sandbox.stub(processUtils, "execFile"); - stub.onCall(0).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(1).returns(Promise.resolve(JSON.stringify(tokenResponse))); + vi.spyOn(processUtils, "execFile") + .mockResolvedValueOnce("") + .mockResolvedValueOnce(JSON.stringify(tokenResponse)); const credential = new AzurePowerShellCredential(); @@ -185,9 +189,10 @@ describe("AzurePowerShellCredential", function () { Type: "Bearer", }; - const stub = sandbox.stub(processUtils, "execFile"); - stub.onCall(0).returns(Promise.resolve("")); // The first call checks that the command is available. - stub.onCall(1).returns(Promise.resolve(JSON.stringify(tokenResponse))); + const stub = vi + .spyOn(processUtils, "execFile") + .mockResolvedValueOnce("") // The first call checks that the command is available. + .mockResolvedValueOnce(JSON.stringify(tokenResponse)); const credential = new AzurePowerShellCredential(); @@ -223,12 +228,11 @@ describe("AzurePowerShellCredential", function () { tenantId === " " ? "whitespace" : tenantId === "\0" ? "null character" : `"${tenantId}"`; it(`rejects invalid tenant id of ${testCase} in getToken`, async function () { const credential = new AzurePowerShellCredential(); - await assert.isRejected( + await expect( credential.getToken("https://service/.default", { tenantId: tenantId, }), - tenantIdErrorMessage, - ); + ).rejects.toThrow(tenantIdErrorMessage); }); it(`rejects invalid tenant id of ${testCase} in constructor`, function () { assert.throws(() => { @@ -246,8 +250,7 @@ describe("AzurePowerShellCredential", function () { : `"${inputScope}"`; it(`rejects invalid scope of ${testCase}`, async function () { const credential = new AzurePowerShellCredential(); - await assert.isRejected( - credential.getToken(inputScope), + await expect(credential.getToken(inputScope)).rejects.toThrow( "Invalid scope was specified by the user or calling client", ); }); diff --git a/sdk/identity/identity/test/internal/node/chainedTokenCredential.spec.ts b/sdk/identity/identity/test/internal/node/chainedTokenCredential.spec.ts index bfa962418402..a822fc203809 100644 --- a/sdk/identity/identity/test/internal/node/chainedTokenCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/chainedTokenCredential.spec.ts @@ -1,11 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AccessToken, TokenCredential } from "../../../src"; -import { ChainedTokenCredential } from "../../../src"; -import Sinon from "sinon"; -import { assert } from "chai"; -import { logger as chainedTokenCredentialLogger } from "../../../src/credentials/chainedTokenCredential"; +import type { AccessToken, TokenCredential } from "../../../src/index.js"; +import { ChainedTokenCredential } from "../../../src/index.js"; +import { logger as chainedTokenCredentialLogger } from "../../../src/credentials/chainedTokenCredential.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; class TestMockCredential implements TokenCredential { constructor(public returnPromise: Promise) {} @@ -16,6 +15,9 @@ class TestMockCredential implements TokenCredential { } describe("ChainedTokenCredential", function () { + afterEach(() => { + vi.restoreAllMocks(); + }); it("Logs the expected successful message", async () => { const chainedTokenCredential = new ChainedTokenCredential( new TestMockCredential( @@ -23,23 +25,22 @@ describe("ChainedTokenCredential", function () { ), ); - const infoSpy = Sinon.spy(chainedTokenCredentialLogger.parent, "info"); - const getTokenInfoSpy = Sinon.spy(chainedTokenCredentialLogger.getToken, "info"); + const infoSpy = vi.spyOn(chainedTokenCredentialLogger.parent, "info"); + const getTokenInfoSpy = vi.spyOn(chainedTokenCredentialLogger.getToken, "info"); const accessToken = await chainedTokenCredential.getToken(""); assert.notStrictEqual(accessToken, null); + expect(infoSpy).toHaveBeenCalled(); assert.equal( - infoSpy.getCalls()[0].args.join(" "), + infoSpy.mock.calls[0].join(" "), "ChainedTokenCredential => getToken() => Result for TestMockCredential: SUCCESS. Scopes: .", ); + expect(getTokenInfoSpy).toHaveBeenCalled(); assert.equal( - getTokenInfoSpy.getCalls()[0].args[0], + getTokenInfoSpy.mock.calls[0][0], "Result for TestMockCredential: SUCCESS. Scopes: .", ); - - infoSpy.restore(); - getTokenInfoSpy.restore(); }); it("Doesn't throw with a clossure credential", async () => { @@ -55,22 +56,18 @@ describe("ChainedTokenCredential", function () { ), ); - const infoSpy = Sinon.spy(chainedTokenCredentialLogger.parent, "info"); - const getTokenInfoSpy = Sinon.spy(chainedTokenCredentialLogger.getToken, "info"); + const infoSpy = vi.spyOn(chainedTokenCredentialLogger.parent, "info"); + const getTokenInfoSpy = vi.spyOn(chainedTokenCredentialLogger.getToken, "info"); const accessToken = await chainedTokenCredential.getToken(""); assert.notStrictEqual(accessToken, null); + expect(infoSpy).toHaveBeenCalled(); assert.equal( - infoSpy.getCalls()[0].args.join(" "), + infoSpy.mock.calls[0].join(" "), "ChainedTokenCredential => getToken() => Result for Object: SUCCESS. Scopes: .", ); - assert.equal( - getTokenInfoSpy.getCalls()[0].args[0], - "Result for Object: SUCCESS. Scopes: .", - ); - - infoSpy.restore(); - getTokenInfoSpy.restore(); + expect(getTokenInfoSpy).toHaveBeenCalled(); + assert.equal(getTokenInfoSpy.mock.calls[0][0], "Result for Object: SUCCESS. Scopes: ."); }); }); diff --git a/sdk/identity/identity/test/internal/node/clientAssertionCredential.spec.ts b/sdk/identity/identity/test/internal/node/clientAssertionCredential.spec.ts index 3025edcc297e..eb75384760bc 100644 --- a/sdk/identity/identity/test/internal/node/clientAssertionCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/clientAssertionCredential.spec.ts @@ -1,28 +1,28 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as path from "path"; +import * as path from "node:path"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; -import { ClientAssertionCredential } from "../../../src"; +import { ClientAssertionCredential } from "../../../src/index.js"; import { ConfidentialClientApplication } from "@azure/msal-node"; -import type { Context } from "mocha"; -import type Sinon from "sinon"; -import { assert } from "chai"; -import { createJWTTokenFromCertificate } from "../../public/node/utils/utils"; +import { createJWTTokenFromCertificate } from "../../public/node/utils/utils.js"; import { env } from "@azure-tools/test-recorder"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, MockInstance } from "vitest"; describe("ClientAssertionCredential (internal)", function () { let cleanup: MsalTestCleanup; - let doGetTokenSpy: Sinon.SinonSpy; + let doGetTokenSpy: MockInstance< + typeof ConfidentialClientApplication.prototype.acquireTokenByClientCredential + >; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; - doGetTokenSpy = setup.sandbox.spy( + doGetTokenSpy = vi.spyOn( ConfidentialClientApplication.prototype, "acquireTokenByClientCredential", ); @@ -76,7 +76,8 @@ describe("ClientAssertionCredential (internal)", function () { // We're ignoring errors since our main goal here is to ensure that we send the correct parameters to MSAL. } - assert.equal(doGetTokenSpy.callCount, 1); - assert.equal(doGetTokenSpy.lastCall.firstArg.clientAssertion, getAssertion); + expect(doGetTokenSpy).toHaveBeenCalledWith( + expect.objectContaining({ clientAssertion: getAssertion }), + ); }); }); diff --git a/sdk/identity/identity/test/internal/node/clientCertificateCredential.spec.ts b/sdk/identity/identity/test/internal/node/clientCertificateCredential.spec.ts index daeb43b65a93..943d94a7d7f4 100644 --- a/sdk/identity/identity/test/internal/node/clientCertificateCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/clientCertificateCredential.spec.ts @@ -1,17 +1,16 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as path from "path"; +import * as path from "node:path"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import { ClientCertificateCredential } from "../../../src"; -import type { Context } from "mocha"; -import { assert } from "chai"; -import { parseCertificate } from "../../../src/credentials/clientCertificateCredential"; +import { ClientCertificateCredential } from "../../../src/index.js"; +import { parseCertificate } from "../../../src/credentials/clientCertificateCredential.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; const ASSET_PATH = "assets"; @@ -19,8 +18,8 @@ describe("ClientCertificateCredential (internal)", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; @@ -101,7 +100,7 @@ describe("ClientCertificateCredential (internal)", function () { ); }); - it("throws when given a file that doesn't contain a PEM-formatted certificate", async function (this: Context) { + it("throws when given a file that doesn't contain a PEM-formatted certificate", async function (ctx) { const fullPath = path.resolve("./clientCertificateCredential.spec.ts"); const credential = new ClientCertificateCredential("tenant", "client", { certificatePath: fullPath, @@ -118,7 +117,7 @@ describe("ClientCertificateCredential (internal)", function () { assert.deepEqual(error?.message, `ENOENT: no such file or directory, open '${fullPath}'`); }); - it("throws when given a certificate that isn't PEM-formatted", async function (this: Context) { + it("throws when given a certificate that isn't PEM-formatted", async function (ctx) { const credential = new ClientCertificateCredential("tenant", "client", { certificate: "not-pem-formatted", }); diff --git a/sdk/identity/identity/test/internal/node/clientSecretCredential.spec.ts b/sdk/identity/identity/test/internal/node/clientSecretCredential.spec.ts index f8dcc1a382c3..583445b6f405 100644 --- a/sdk/identity/identity/test/internal/node/clientSecretCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/clientSecretCredential.spec.ts @@ -4,34 +4,35 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ import { AzureLogger, setLogLevel } from "@azure/logger"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; -import { delay, env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder"; +import { env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder"; -import { ClientSecretCredential } from "../../../src"; +import { ClientSecretCredential } from "../../../src/index.js"; import { ConfidentialClientApplication } from "@azure/msal-node"; -import type { Context } from "mocha"; import type { GetTokenOptions } from "@azure/core-auth"; -import Sinon from "sinon"; -import { assert } from "chai"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, MockInstance } from "vitest"; describe("ClientSecretCredential (internal)", function () { let cleanup: MsalTestCleanup; - let doGetTokenSpy: Sinon.SinonSpy; + let doGetTokenSpy: MockInstance< + typeof ConfidentialClientApplication.prototype.acquireTokenByClientCredential + >; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; // MsalClientSecret calls to this method underneath. - doGetTokenSpy = setup.sandbox.spy( + doGetTokenSpy = vi.spyOn( ConfidentialClientApplication.prototype, "acquireTokenByClientCredential", ); }); + afterEach(async function () { await cleanup(); }); @@ -53,10 +54,10 @@ describe("ClientSecretCredential (internal)", function () { ); }); - it("Authenticates with tenantId on getToken", async function (this: Context) { + it("Authenticates with tenantId on getToken", async function (ctx) { // The live environment isn't ready for this test if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new ClientSecretCredential( env.AZURE_TENANT_ID!, @@ -66,41 +67,13 @@ describe("ClientSecretCredential (internal)", function () { ); await credential.getToken(scope, { tenantId: env.AZURE_TENANT_ID } as GetTokenOptions); - assert.equal(doGetTokenSpy.callCount, 1); - }); - - // TODO: Enable again once we're ready to release this feature. - it.skip("supports specifying the regional authority", async function () { - const credential = new ClientSecretCredential( - env.AZURE_TENANT_ID!, - env.AZURE_CLIENT_ID!, - env.AZURE_CLIENT_SECRET!, - { - // TODO: Uncomment once we're ready to release this feature. - // regionalAuthority: RegionalAuthority.AutoDiscoverRegion - }, - ); - - // We'll abort since we only want to ensure the parameters are sent appropriately. - const controller = new AbortController(); - const getTokenPromise = credential.getToken(scope, { - abortSignal: controller.signal, - }); - await delay(5); - controller.abort(); - try { - await getTokenPromise; - } catch (e: any) { - // Nothing to do here. - } - - assert.equal(doGetTokenSpy.getCall(0).args[0].azureRegion, "AUTO_DISCOVER"); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); }); - it("authenticates (with allowLoggingAccountIdentifiers set to true)", async function (this: Context) { + it("authenticates (with allowLoggingAccountIdentifiers set to true)", async function (ctx) { if (isLiveMode() || isPlaybackMode()) { // The recorder clears the access tokens. - this.skip(); + ctx.skip(); } const credential = new ClientSecretCredential( env.AZURE_TENANT_ID!, @@ -111,18 +84,18 @@ describe("ClientSecretCredential (internal)", function () { }), ); setLogLevel("info"); - const spy = Sinon.spy(process.stderr, "write"); + const spy = vi.spyOn(process.stderr, "write"); const token = await credential.getToken(scope); assert.ok(token?.token); assert.ok(token?.expiresOnTimestamp! > Date.now()); - const expectedCall = spy - .getCalls() - .find((x) => (x.args[0] as any as string).match(/Authenticated account/)); - assert.ok(expectedCall); + const expectedCall = spy.mock.calls.find((x) => + (x[0] as any as string).match(/Authenticated account/), + ); + assert.exists(expectedCall); const expectedMessage = `azure:identity:info [Authenticated account] Client ID: ${env.AZURE_CLIENT_ID}. Tenant ID: ${env.AZURE_TENANT_ID}. User Principal Name: No User Principal Name available. Object ID (user): HIDDEN`; assert.equal( - (expectedCall!.args[0] as any as string) + (expectedCall![0] as any as string) .replace( /Object ID .user.: [a-z0-9]+-[a-z0-9]+-[a-z0-9]+-[a-z0-9]+-[a-z0-9]+/g, "Object ID (user): HIDDEN", @@ -130,7 +103,6 @@ describe("ClientSecretCredential (internal)", function () { .trim(), expectedMessage, ); - spy.restore(); AzureLogger.destroy(); }); }); diff --git a/sdk/identity/identity/test/internal/node/deviceCodeCredential.spec.ts b/sdk/identity/identity/test/internal/node/deviceCodeCredential.spec.ts index 6c3f3d474b29..7614b763c71f 100644 --- a/sdk/identity/identity/test/internal/node/deviceCodeCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/deviceCodeCredential.spec.ts @@ -1,35 +1,32 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isLiveMode } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { DeviceCodeCredential } from "../../../src"; +import { DeviceCodeCredential } from "../../../src/index.js"; import { PublicClientApplication } from "@azure/msal-node"; -import type Sinon from "sinon"; -import { assert } from "chai"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, MockInstance } from "vitest"; describe("DeviceCodeCredential (internal)", function () { let cleanup: MsalTestCleanup; - let getTokenSilentSpy: Sinon.SinonSpy; - let doGetTokenSpy: Sinon.SinonSpy; + let getTokenSilentSpy: MockInstance; + let doGetTokenSpy: MockInstance< + typeof PublicClientApplication.prototype.acquireTokenByDeviceCode + >; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; // MsalClient calls to this method underneath when silent authentication can be attempted. - getTokenSilentSpy = setup.sandbox.spy(PublicClientApplication.prototype, "acquireTokenSilent"); + getTokenSilentSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenSilent"); // MsalClient calls to this method underneath for interactive auth. - doGetTokenSpy = setup.sandbox.spy( - PublicClientApplication.prototype, - "acquireTokenByDeviceCode", - ); + doGetTokenSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenByDeviceCode"); }); afterEach(async function () { await cleanup(); @@ -37,10 +34,10 @@ describe("DeviceCodeCredential (internal)", function () { const scope = "https://vault.azure.net/.default"; - it("Authenticates silently after the initial request", async function (this: Context) { + it("Authenticates silently after the initial request", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( recorder.configureClientOptions({ @@ -50,25 +47,20 @@ describe("DeviceCodeCredential (internal)", function () { ); await credential.getToken(scope); - assert.equal(doGetTokenSpy.callCount, 1, "doGetTokenSpy.callCount should have been 1."); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); await credential.getToken(scope); - assert.equal( - getTokenSilentSpy.callCount, - 1, - "getTokenSilentSpy.callCount should have been 1 (Silent authentication after the initial request).", - ); - assert.equal( - doGetTokenSpy.callCount, - 1, + expect(getTokenSilentSpy).toHaveBeenCalledOnce(); + expect( + doGetTokenSpy, "Expected no additional calls to doGetTokenSpy after the initial request.", - ); + ).toHaveBeenCalledOnce(); }); - it("Authenticates with tenantId on getToken", async function (this: Context) { + it("Authenticates with tenantId on getToken", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( recorder.configureClientOptions({ @@ -78,6 +70,6 @@ describe("DeviceCodeCredential (internal)", function () { ); await credential.getToken(scope, { tenantId: env.AZURE_TENANT_ID }); - assert.equal(doGetTokenSpy.callCount, 1, "doGetTokenSpy.callCount should have been 1"); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); }); }); diff --git a/sdk/identity/identity/test/internal/node/environmentCredential.spec.ts b/sdk/identity/identity/test/internal/node/environmentCredential.spec.ts index a9f3bf878a55..fd825cf20c97 100644 --- a/sdk/identity/identity/test/internal/node/environmentCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/environmentCredential.spec.ts @@ -1,54 +1,45 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import Sinon from "sinon"; -import { assert } from "@azure-tools/test-utils"; -import { getSendCertificateChain } from "../../../src/credentials/environmentCredential"; +import { getSendCertificateChain } from "../../../src/credentials/environmentCredential.js"; +import { describe, it, assert, vi, afterEach } from "vitest"; describe("EnvironmentCredential (internal)", function () { afterEach(function () { - Sinon.restore(); + vi.restoreAllMocks(); + vi.unstubAllEnvs(); }); describe("#getSendCertificateChain", () => { it("should parse 'true' correctly", async () => { - Sinon.stub(process, "env").value({ - AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: "true", - }); + vi.stubEnv("AZURE_CLIENT_SEND_CERTIFICATE_CHAIN", "true"); const sendCertificateChain = getSendCertificateChain(); assert.isTrue(sendCertificateChain); }); it("should parse '1' correctly", async () => { - Sinon.stub(process, "env").value({ - AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: "1", - }); + vi.stubEnv("AZURE_CLIENT_SEND_CERTIFICATE_CHAIN", "1"); const sendCertificateChain = getSendCertificateChain(); assert.isTrue(sendCertificateChain); }); it("is case insensitive", async () => { - Sinon.stub(process, "env").value({ - AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: "TrUe", - }); + vi.stubEnv("AZURE_CLIENT_SEND_CERTIFICATE_CHAIN", "TrUe"); const sendCertificateChain = getSendCertificateChain(); assert.isTrue(sendCertificateChain); }); it("should parse undefined correctly", async () => { - Sinon.stub(process, "env").value({}); + vi.stubEnv("AZURE_CLIENT_SEND_CERTIFICATE_CHAIN", undefined); const sendCertificateChain = getSendCertificateChain(); assert.isFalse(sendCertificateChain); }); it("should default other values to false", async () => { - Sinon.stub(process, "env").value({ - AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: "foobar", - }); + vi.stubEnv("AZURE_CLIENT_SEND_CERTIFICATE_CHAIN", "foobar"); const sendCertificateChain = getSendCertificateChain(); assert.isFalse(sendCertificateChain); diff --git a/sdk/identity/identity/test/internal/identityClient.spec.ts b/sdk/identity/identity/test/internal/node/identityClient.spec.ts similarity index 59% rename from sdk/identity/identity/test/internal/identityClient.spec.ts rename to sdk/identity/identity/test/internal/node/identityClient.spec.ts index abb8b7fb5522..79c4c4195df9 100644 --- a/sdk/identity/identity/test/internal/identityClient.spec.ts +++ b/sdk/identity/identity/test/internal/node/identityClient.spec.ts @@ -1,17 +1,20 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { TokenResponse } from "../../src/client/identityClient"; -import { IdentityClient, getIdentityClientAuthorityHost } from "../../src/client/identityClient"; -import { IdentityTestContext, prepareMSALResponses } from "../httpRequests"; -import type { IdentityTestContextInterface } from "../httpRequestsCommon"; -import { createResponse } from "../httpRequestsCommon"; -import { ClientSecretCredential } from "../../src"; -import type { Context } from "mocha"; -import { PlaybackTenantId } from "../msalTestUtils"; -import { assert } from "chai"; -import { isExpectedError } from "../authTestUtils"; +import { + IdentityClient, + getIdentityClientAuthorityHost, +} from "../../../src/client/identityClient.js"; +import { IdentityTestContext } from "../../httpRequests.js"; +import type { IdentityTestContextInterface } from "../../httpRequestsCommon.js"; +import { createResponse } from "../../httpRequestsCommon.js"; +import { ClientSecretCredential } from "../../../src/index.js"; +import { openIdConfigurationResponse, PlaybackTenantId } from "../../msalTestUtils.js"; +import { isExpectedError } from "../../authTestUtils.js"; import { isNode } from "@azure/core-util"; +import { describe, it, assert, beforeEach, afterEach, vi, expect } from "vitest"; +import type { HttpClient } from "@azure/core-rest-pipeline"; +import { createDefaultHttpClient, createHttpHeaders } from "@azure/core-rest-pipeline"; describe("IdentityClient", function () { let testContext: IdentityTestContextInterface; @@ -51,29 +54,40 @@ describe("IdentityClient", function () { }); it("throws an exception when an authentication request fails", async () => { - const { error } = await testContext.sendCredentialRequests({ - scopes: ["https://test/.default"], - credential: new ClientSecretCredential("adfs", "client", "secret", { - // createResponse below will simulate a 200 when trying to resolve the authority, - // then the 400 error when trying to get the token - authorityHost: "https://fake-authority.com", - }), - secureResponses: [ - ...prepareMSALResponses(), - createResponse(400, { - error: "test_error", - error_description: "This is a test error", - }), - ], + const mockHttpClient: HttpClient = createDefaultHttpClient(); + vi.spyOn(mockHttpClient, "sendRequest") + .mockImplementationOnce(async (request) => { + return { + request, + status: 200, + bodyAsText: JSON.stringify(openIdConfigurationResponse), + headers: createHttpHeaders(), + }; + }) + .mockImplementationOnce(async (request) => { + return { + request, + status: 400, + bodyAsText: JSON.stringify({ + error: "test_error", + error_description: "This is a test error", + }), + headers: createHttpHeaders(), + }; + }); + + const credential = new ClientSecretCredential("adfs", "client", "secret", { + authorityHost: "https://fake-authority.com", + httpClient: mockHttpClient, }); + if (isNode) { - assert.strictEqual(error!.name, "AuthenticationRequiredError"); - assert.ok(error!.message.indexOf("This is a test error") > -1); + await expect(credential.getToken(["scope"])).rejects.toThrow("This is a test error"); } else { // The browser version of this credential uses a legacy approach. // While the Node version uses MSAL, the browser version does the network requests directly. // While that means the browser version is simpler, it also means the browser version will not keep the same behavior. - assert.strictEqual(error!.name, "AuthenticationError"); + await expect(credential.getToken(["scope"])).rejects.toThrow("AuthenticationError"); } }); @@ -94,18 +108,18 @@ describe("IdentityClient", function () { ); }); - it("parses authority host environment variable as expected", function (this: Context) { + it("parses authority host environment variable as expected", function (ctx) { if (!isNode) { - return this.skip(); + return ctx.skip(); } process.env.AZURE_AUTHORITY_HOST = "http://totallyinsecure.lol"; assert.equal(getIdentityClientAuthorityHost({}), process.env.AZURE_AUTHORITY_HOST); return; }); - it("throws an exception when an Env AZURE_AUTHORITY_HOST using 'http' is provided", async function (this: Context) { + it("throws an exception when an Env AZURE_AUTHORITY_HOST using 'http' is provided", async function (ctx) { if (!isNode) { - return this.skip(); + return ctx.skip(); } process.env.AZURE_AUTHORITY_HOST = "http://totallyinsecure.lol"; assert.throws( @@ -130,61 +144,74 @@ describe("IdentityClient", function () { }); it("returns a usable error when the authentication response doesn't contain a body", async () => { - const credential = new ClientSecretCredential("adfs", "client", "secret"); - const { error } = await testContext.sendCredentialRequests({ - scopes: ["scope"], - credential, - secureResponses: [...prepareMSALResponses(), createResponse(300)], + const mockHttpClient: HttpClient = createDefaultHttpClient(); + vi.spyOn(mockHttpClient, "sendRequest") + .mockImplementationOnce(async (request) => { + return { + request, + status: 200, + bodyAsText: JSON.stringify(openIdConfigurationResponse), + headers: createHttpHeaders(), + }; + }) + .mockImplementationOnce(async (request) => { + return { + request, + status: 300, + headers: createHttpHeaders(), + }; + }); + const credential = new ClientSecretCredential("adfs", "client", "secret", { + httpClient: mockHttpClient, }); + if (isNode) { - assert.strictEqual(error?.name, "AuthenticationRequiredError"); - assert.strictEqual(error?.message, `Response had no "expiresOn" property.`); + await expect(credential.getToken(["scope"])).rejects.toThrow( + 'Response had no "expiresOn" property.', + ); } else { // The browser version of this credential uses a legacy approach. // While the Node version uses MSAL, the browser version does the network requests directly. // While that means the browser version is simpler, it also means the browser version will not keep the same behavior. - assert.strictEqual(error!.name, "AuthenticationError"); + await expect(credential.getToken(["scope"])).rejects.toThrow("AuthenticationError"); } }); - it("parses authority host environment variable as expected", function (this: Context) { + it("parses authority host environment variable as expected", function (ctx) { if (!isNode) { - return this.skip(); + return ctx.skip(); } process.env.AZURE_AUTHORITY_HOST = "http://totallyinsecure.lol"; assert.equal(getIdentityClientAuthorityHost({}), process.env.AZURE_AUTHORITY_HOST); return; }); - it("returns null when the token refresh request returns an 'interaction_required' error", async function (this: Context) { - const client = new IdentityClient({ authorityHost: "https://authority" }); - const response = createResponse(401, { - error: "interaction_required", - error_description: "Interaction required", + it("returns null when the token refresh request returns an 'interaction_required' error", async function () { + const mockHttpClient = createDefaultHttpClient(); + vi.spyOn(mockHttpClient, "sendRequest").mockImplementation((request) => + Promise.resolve({ + request, + headers: createHttpHeaders(), + status: 401, + bodyAsText: JSON.stringify({ + error: "interaction_required", + error_description: "Interaction required", + }), + }), + ); + const client = new IdentityClient({ + authorityHost: "https://authority", + httpClient: mockHttpClient, }); - const tokenResponse = await testContext.sendIndividualRequest(async () => { - return client.refreshAccessToken("tenant", "client", "scopes", "token", undefined); - }, response); - - assert.equal(tokenResponse, null); - - const expectedMessages = [ - /.*azure:identity:info.*IdentityClient: refreshing access token with client ID: client, scopes: scopes started.*/, - /.*azure:identity:info.*IdentityClient: sending token request to \[https:\/\/authority\/tenant\/oauth2\/v2.0\/token\].*/, - /.*azure:identity:warning.*IdentityClient: authentication error. HTTP status: 401, Interaction required.*/, - /.*azure:identity:info.*IdentityClient: interaction required for client ID: client.*/, - ]; - - const logMessages = testContext.logMessages.filter( - (msg: string) => msg.indexOf("azure:identity:") >= 0, + const tokenResponse = await client.refreshAccessToken( + "tenant", + "client", + "scopes", + "token", + undefined, ); - assert.equal(logMessages.length, expectedMessages.length); - - for (let i = 0; i < logMessages.length; i++) { - assert.ok(logMessages[i].match(expectedMessages[i]), `Checking[${i}] ${logMessages[i]}`); - } - return; + assert.equal(tokenResponse, null); }); it("rethrows any other error that is thrown while refreshing the access token", async () => { diff --git a/sdk/identity/identity/test/internal/node/interactiveBrowserCredential.spec.ts b/sdk/identity/identity/test/internal/node/interactiveBrowserCredential.spec.ts index 3df94e947b24..727fd77d6fe0 100644 --- a/sdk/identity/identity/test/internal/node/interactiveBrowserCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/interactiveBrowserCredential.spec.ts @@ -3,18 +3,14 @@ /* eslint-disable @typescript-eslint/no-namespace */ -import type { InteractiveBrowserCredentialNodeOptions } from "../../../src"; -import { InteractiveBrowserCredential } from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { InteractiveBrowserCredentialNodeOptions } from "../../../src/index.js"; +import { InteractiveBrowserCredential } from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; - -import type { Context } from "mocha"; -import type Sinon from "sinon"; -import { assert } from "chai"; -import type http from "http"; -import { interactiveBrowserMockable } from "../../../src/msal/nodeFlows/msalClient"; +import type http from "node:http"; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; declare global { namespace NodeJS { @@ -24,18 +20,27 @@ declare global { } } +vi.mock("open", async () => { + const original = await vi.importActual("open"); + return { + ...original, + default: () => { + throw new Error("No browsers available on this test."); + }, + }; +}); + describe("InteractiveBrowserCredential (internal)", function () { let cleanup: MsalTestCleanup; - let sandbox: Sinon.SinonSandbox; let listen: http.Server | undefined; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); - sandbox = setup.sandbox; + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); + afterEach(async function () { if (listen) { listen.close(); @@ -45,14 +50,7 @@ describe("InteractiveBrowserCredential (internal)", function () { const scope = "https://vault.azure.net/.default"; - it("Throws an expected error if no browser is available", async function (this: Context) { - // The SinonStub type does not include this second parameter to throws(). - const testErrorMessage = "No browsers available on this test."; - (sandbox.stub(interactiveBrowserMockable, "open") as any).throws( - "BrowserConfigurationAuthError", - testErrorMessage, - ); - + it("Throws an expected error if no browser is available", async function (ctx) { const credential = new InteractiveBrowserCredential( recorder.configureClientOptions({ redirectUri: "http://localhost:8081", @@ -61,13 +59,6 @@ describe("InteractiveBrowserCredential (internal)", function () { } as InteractiveBrowserCredentialNodeOptions), ); - let error: Error | undefined; - try { - await credential.getToken(scope); - } catch (e: any) { - error = e; - } - assert.equal(error?.name, "BrowserConfigurationAuthError"); - assert.equal(error?.message, "No browsers available on this test."); + await expect(credential.getToken(scope)).rejects.toThrow("No browsers available on this test."); }); }); diff --git a/sdk/identity/identity/test/internal/node/managedIdentityCredential/imdsRetryPolicy.spec.ts b/sdk/identity/identity/test/internal/node/managedIdentityCredential/imdsRetryPolicy.spec.ts index cf76af21c7b3..6f941468bf6d 100644 --- a/sdk/identity/identity/test/internal/node/managedIdentityCredential/imdsRetryPolicy.spec.ts +++ b/sdk/identity/identity/test/internal/node/managedIdentityCredential/imdsRetryPolicy.spec.ts @@ -4,9 +4,9 @@ import type { PipelineRequest, SendRequest } from "@azure/core-rest-pipeline"; import { RestError, createHttpHeaders } from "@azure/core-rest-pipeline"; -import type { MSIConfiguration } from "../../../../src/credentials/managedIdentityCredential/models"; -import { assert } from "@azure-tools/test-utils"; -import { imdsRetryPolicy } from "../../../../src/credentials/managedIdentityCredential/imdsRetryPolicy"; +import type { MSIConfiguration } from "../../../../src/credentials/managedIdentityCredential/models.js"; +import { imdsRetryPolicy } from "../../../../src/credentials/managedIdentityCredential/imdsRetryPolicy.js"; +import { describe, it, assert, expect } from "vitest"; describe("imdsRetryPolicy", () => { const mockRetryConfig: MSIConfiguration["retryConfig"] = { @@ -80,7 +80,7 @@ describe("imdsRetryPolicy", () => { throw new RestError("Not found", { statusCode: 404, request, response }); }; - await assert.isRejected(policy.sendRequest(pipelineRequest, sendRequest), "Not found"); + await expect(policy.sendRequest(pipelineRequest, sendRequest)).rejects.toThrow("Not found"); assert.strictEqual(sendRequestCount, mockRetryConfig.maxRetries + 1); // Should retry the maximum number of times }); }); diff --git a/sdk/identity/identity/test/internal/node/managedIdentityCredential/msalMsiProvider.spec.ts b/sdk/identity/identity/test/internal/node/managedIdentityCredential/msalMsiProvider.spec.ts index 913f8c9135ad..641222ef3329 100644 --- a/sdk/identity/identity/test/internal/node/managedIdentityCredential/msalMsiProvider.spec.ts +++ b/sdk/identity/identity/test/internal/node/managedIdentityCredential/msalMsiProvider.spec.ts @@ -1,20 +1,29 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import Sinon from "sinon"; -import { assert } from "@azure-tools/test-utils"; -import type { AuthenticationResult } from "@azure/msal-node"; +import type { AuthenticationResult, ManagedIdentityRequestParams } from "@azure/msal-node"; import { AuthError, ManagedIdentityApplication } from "@azure/msal-node"; -import { ManagedIdentityCredential } from "../../../../src/credentials/managedIdentityCredential/index"; -import { tokenExchangeMsi } from "../../../../src/credentials/managedIdentityCredential/tokenExchangeMsi"; -import { imdsMsi } from "../../../../src/credentials/managedIdentityCredential/imdsMsi"; +import { ManagedIdentityCredential } from "../../../../src/credentials/managedIdentityCredential/index.js"; +import { tokenExchangeMsi } from "../../../../src/credentials/managedIdentityCredential/tokenExchangeMsi.js"; +import { imdsMsi } from "../../../../src/credentials/managedIdentityCredential/imdsMsi.js"; import { RestError } from "@azure/core-rest-pipeline"; -import { AuthenticationRequiredError, CredentialUnavailableError } from "../../../../src/errors"; -import type { AccessToken } from "@azure/core-auth"; +import { AuthenticationRequiredError, CredentialUnavailableError } from "../../../../src/errors.js"; +import type { AccessToken, GetTokenOptions } from "@azure/core-auth"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, MockInstance } from "vitest"; +import { IdentityClient } from "../../../../src/client/identityClient.js"; describe("ManagedIdentityCredential (MSAL)", function () { - let acquireTokenStub: Sinon.SinonStub; - let imdsIsAvailableStub: Sinon.SinonStub; + let acquireTokenStub: MockInstance< + (managedIdentityRequestParams: ManagedIdentityRequestParams) => Promise + >; + let imdsIsAvailableStub: MockInstance< + (options: { + scopes: string | string[]; + identityClient?: IdentityClient; + clientId?: string; + resourceId?: string; + getTokenOptions?: GetTokenOptions; + }) => Promise + >; const validAuthenticationResult: Partial = { accessToken: "test_token", @@ -22,12 +31,12 @@ describe("ManagedIdentityCredential (MSAL)", function () { }; beforeEach(function () { - acquireTokenStub = Sinon.stub(ManagedIdentityApplication.prototype, "acquireToken"); - imdsIsAvailableStub = Sinon.stub(imdsMsi, "isAvailable").resolves(true); // Skip pinging the IMDS endpoint in tests + acquireTokenStub = vi.spyOn(ManagedIdentityApplication.prototype, "acquireToken"); + imdsIsAvailableStub = vi.spyOn(imdsMsi, "isAvailable").mockResolvedValue(true); // Skip pinging the IMDS endpoint in tests }); afterEach(function () { - Sinon.restore(); + vi.restoreAllMocks(); }); describe("constructor", function () { @@ -67,7 +76,7 @@ describe("ManagedIdentityCredential (MSAL)", function () { describe("when using CloudShell Managed Identity", function () { it("throws when user-assigned IDs are provided", function () { - Sinon.stub(ManagedIdentityApplication.prototype, "getManagedIdentitySource").returns( + vi.spyOn(ManagedIdentityApplication.prototype, "getManagedIdentitySource").mockReturnValue( "CloudShell", ); @@ -90,7 +99,7 @@ describe("ManagedIdentityCredential (MSAL)", function () { describe("#getToken", function () { describe("when getToken is successful", function () { it("returns a token", async function () { - acquireTokenStub.resolves(validAuthenticationResult as AuthenticationResult); + acquireTokenStub.mockResolvedValue(validAuthenticationResult as AuthenticationResult); const credential = new ManagedIdentityCredential(); const token = await credential.getToken("scope"); assert.strictEqual(token.token, validAuthenticationResult.accessToken); @@ -107,8 +116,10 @@ describe("ManagedIdentityCredential (MSAL)", function () { expiresOnTimestamp: new Date().getTime(), tokenType: "Bearer", } as AccessToken; - Sinon.stub(tokenExchangeMsi, "isAvailable").resolves(true); - Sinon.stub(tokenExchangeMsi, "getToken").resolves(validToken); + + vi.spyOn(tokenExchangeMsi, "isAvailable").mockResolvedValue(true); + + vi.spyOn(tokenExchangeMsi, "getToken").mockResolvedValue(validToken); const credential = new ManagedIdentityCredential(); const token = await credential.getToken("scope"); @@ -119,50 +130,51 @@ describe("ManagedIdentityCredential (MSAL)", function () { describe("when using IMDS", function () { it("probes the IMDS endpoint", async function () { - Sinon.stub(ManagedIdentityApplication.prototype, "getManagedIdentitySource").returns( - "DefaultToImds", - ); - acquireTokenStub.resolves(validAuthenticationResult as AuthenticationResult); + vi.spyOn( + ManagedIdentityApplication.prototype, + "getManagedIdentitySource", + ).mockReturnValue("DefaultToImds"); + acquireTokenStub.mockResolvedValue(validAuthenticationResult as AuthenticationResult); const credential = new ManagedIdentityCredential(); await credential.getToken("scope"); - assert.isTrue(imdsIsAvailableStub.calledOnce); + expect(imdsIsAvailableStub).toHaveBeenCalledOnce(); }); }); }); it("validates multiple scopes are not supported", async function () { const credential = new ManagedIdentityCredential(); - await assert.isRejected(credential.getToken(["scope1", "scope2"]), /Multiple scopes/); + await expect(credential.getToken(["scope1", "scope2"])).rejects.toThrow(/Multiple scopes/); }); describe("error handling", function () { it("rethrows AuthenticationRequiredError", async function () { - acquireTokenStub.rejects(new AuthenticationRequiredError({ scopes: ["scope"] })); + acquireTokenStub.mockRejectedValue(new AuthenticationRequiredError({ scopes: ["scope"] })); const credential = new ManagedIdentityCredential(); - await assert.isRejected(credential.getToken("scope"), AuthenticationRequiredError); + await expect(credential.getToken("scope")).rejects.toThrow(AuthenticationRequiredError); }); it("handles an unreachable network error", async function () { - acquireTokenStub.rejects(new AuthError("network_error")); + acquireTokenStub.mockRejectedValue(new AuthError("network_error")); const credential = new ManagedIdentityCredential(); - await assert.isRejected(credential.getToken("scope"), CredentialUnavailableError); + await expect(credential.getToken("scope")).rejects.toThrow(CredentialUnavailableError); }); it("handles a 403 status code", async function () { - acquireTokenStub.rejects( + acquireTokenStub.mockRejectedValue( new RestError("A socket operation was attempted to an unreachable network", { statusCode: 403, }), ); const credential = new ManagedIdentityCredential(); - await assert.isRejected(credential.getToken("scope"), /Network unreachable/); + await expect(credential.getToken("scope")).rejects.toThrow(/Network unreachable/); }); it("handles unexpected errors", async function () { - acquireTokenStub.rejects(new Error("Some unexpected error")); + acquireTokenStub.mockRejectedValue(new Error("Some unexpected error")); const credential = new ManagedIdentityCredential(); - await assert.isRejected(credential.getToken("scope"), /Authentication failed/); + await expect(credential.getToken("scope")).rejects.toThrow(/Authentication failed/); }); }); }); diff --git a/sdk/identity/identity/test/internal/node/msalClient.spec.ts b/sdk/identity/identity/test/internal/node/msalClient.spec.ts index 6856450a0e6f..0ffc7e55f3ad 100644 --- a/sdk/identity/identity/test/internal/node/msalClient.spec.ts +++ b/sdk/identity/identity/test/internal/node/msalClient.spec.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as msalClient from "../../../src/msal/nodeFlows/msalClient"; +import * as msalClient from "../../../src/msal/nodeFlows/msalClient.js"; import type { AuthenticationResult } from "@azure/msal-node"; import { @@ -9,21 +9,19 @@ import { ConfidentialClientApplication, PublicClientApplication, } from "@azure/msal-node"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env, isLiveMode } from "@azure-tools/test-recorder"; import { AbortError } from "@azure/abort-controller"; -import { AuthenticationRequiredError } from "../../../src/errors"; -import type { Context } from "mocha"; -import { DeveloperSignOnClientId } from "../../../src/constants"; -import { IdentityClient } from "../../../src/client/identityClient"; -import { assert } from "@azure-tools/test-utils"; -import { credentialLogger } from "../../../src/util/logging"; -import { getUsernamePasswordStaticResources } from "../../msalTestUtils"; -import { msalPlugins } from "../../../src/msal/nodeFlows/msalPlugins"; -import sinon from "sinon"; +import { AuthenticationRequiredError } from "../../../src/errors.js"; +import { DeveloperSignOnClientId } from "../../../src/constants.js"; +import { IdentityClient } from "../../../src/client/identityClient.js"; +import { credentialLogger } from "../../../src/util/logging.js"; +import { getUsernamePasswordStaticResources } from "../../msalTestUtils.js"; +import { msalPlugins } from "../../../src/msal/nodeFlows/msalPlugins.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("MsalClient", function () { describe("recorded tests", function () { @@ -34,14 +32,14 @@ describe("MsalClient", function () { await cleanup(); }); - beforeEach(async function () { - ({ cleanup, recorder } = await msalNodeTestSetup(this.currentTest)); + beforeEach(async function (ctx) { + ({ cleanup, recorder } = await msalNodeTestSetup(ctx)); }); - it("supports getTokenByClientSecret", async function () { + it("supports getTokenByClientSecret", async function (ctx) { if (isLiveMode()) { // https://github.com/Azure/azure-sdk-for-js/issues/29929 - this.skip(); + ctx.skip(); } const scopes = ["https://vault.azure.net/.default"]; const clientSecret = env.IDENTITY_SP_CLIENT_SECRET || env.AZURE_CLIENT_SECRET!; @@ -58,10 +56,10 @@ describe("MsalClient", function () { assert.isNotNaN(accessToken.expiresOnTimestamp); }); - it("supports getTokenByDeviceCode", async function (this: Context) { + it("supports getTokenByDeviceCode", async function (ctx) { if (isLiveMode()) { // Skip in CI live tests since this credential requires user interaction. - this.skip(); + ctx.skip(); } const scopes = ["https://vault.azure.net/.default"]; const clientId = DeveloperSignOnClientId; @@ -109,7 +107,7 @@ describe("MsalClient", function () { const clientId = "client-id"; const tenantId = "tenant-id"; const logger = credentialLogger("test"); - const logSpy = sinon.spy(logger.getToken, "info"); + const logSpy = vi.spyOn(logger.getToken, "info"); const client = msalClient.createMsalClient(clientId, tenantId, { logger }); try { @@ -118,7 +116,7 @@ describe("MsalClient", function () { // ignore errors } - assert.isAbove(logSpy.callCount, 0); + assert.isAbove(logSpy.mock.calls.length, 0); }); }); @@ -161,7 +159,7 @@ describe("MsalClient", function () { const tenantId = "tenant-id"; afterEach(async function () { - sinon.restore(); + vi.restoreAllMocks(); }); describe("when CAE is enabled", function () { @@ -169,15 +167,15 @@ describe("MsalClient", function () { it("uses the CAE cache", async function () { const cachePluginCae = { - afterCacheAccess: sinon.stub(), - beforeCacheAccess: sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; const cachePlugin = { - afterCacheAccess: sinon.stub(), - beforeCacheAccess: sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; - sinon.stub(msalPlugins, "generatePluginConfiguration").returns({ + vi.spyOn(msalPlugins, "generatePluginConfiguration").mockReturnValue({ broker: { isEnabled: false, enableMsaPassthrough: false, @@ -204,8 +202,8 @@ describe("MsalClient", function () { // ignore errors } - assert.isAbove(cachePluginCae.beforeCacheAccess.callCount, 0); - assert.equal(cachePlugin.beforeCacheAccess.callCount, 0); + assert.isAbove(cachePluginCae.beforeCacheAccess.mock.calls.length, 0); + expect(cachePlugin.beforeCacheAccess).toHaveBeenCalledTimes(0); }); }); @@ -213,15 +211,15 @@ describe("MsalClient", function () { const enableCae = false; it("initializes the default cache", async function () { const cachePluginCae = { - afterCacheAccess: sinon.stub(), - beforeCacheAccess: sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; const cachePlugin = { - afterCacheAccess: sinon.stub(), - beforeCacheAccess: sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; - sinon.stub(msalPlugins, "generatePluginConfiguration").returns({ + vi.spyOn(msalPlugins, "generatePluginConfiguration").mockReturnValue({ broker: { isEnabled: false, enableMsaPassthrough: false, @@ -248,8 +246,8 @@ describe("MsalClient", function () { // ignore errors } - assert.isAbove(cachePlugin.beforeCacheAccess.callCount, 0); - assert.equal(cachePluginCae.beforeCacheAccess.callCount, 0); + assert.isAbove(cachePlugin.beforeCacheAccess.mock.calls.length, 0); + expect(cachePluginCae.beforeCacheAccess).toHaveBeenCalledTimes(0); }); }); }); @@ -271,25 +269,21 @@ describe("MsalClient", function () { const scopes = ["https://vault.azure.net/.default"]; afterEach(async function () { - sinon.restore(); + vi.restoreAllMocks(); }); describe("with clientSecret", function () { it("uses a confidentialClientApplication", async function () { const client = msalClient.createMsalClient(clientId, tenantId); - const publicClientStub = sinon.stub( - PublicClientApplication.prototype, - "acquireTokenByCode", - ); - const confidentialClientStub = sinon - .stub(ConfidentialClientApplication.prototype, "acquireTokenByCode") - .resolves(fakeTokenResponse as AuthenticationResult); - + const publicClientStub = vi.spyOn(PublicClientApplication.prototype, "acquireTokenByCode"); + const confidentialClientStub = vi + .spyOn(ConfidentialClientApplication.prototype, "acquireTokenByCode") + .mockResolvedValue(fakeTokenResponse as AuthenticationResult); await client.getTokenByAuthorizationCode(scopes, "code", "redirectUri", "clientSecret"); - assert.equal(publicClientStub.callCount, 0); - assert.equal(confidentialClientStub.callCount, 1); + expect(publicClientStub).toHaveBeenCalledTimes(0); + expect(confidentialClientStub).toHaveBeenCalledTimes(1); }); }); @@ -297,10 +291,10 @@ describe("MsalClient", function () { it("uses a publicClientApplication", async function () { const client = msalClient.createMsalClient(clientId, tenantId); - const publicClientStub = sinon - .stub(PublicClientApplication.prototype, "acquireTokenByCode") - .resolves(fakeTokenResponse as AuthenticationResult); - const confidentialClientStub = sinon.stub( + const publicClientStub = vi + .spyOn(PublicClientApplication.prototype, "acquireTokenByCode") + .mockResolvedValue(fakeTokenResponse as AuthenticationResult); + const confidentialClientStub = vi.spyOn( ConfidentialClientApplication.prototype, "acquireTokenByCode", ); @@ -312,8 +306,8 @@ describe("MsalClient", function () { undefined /* clientSecret */, ); - assert.equal(publicClientStub.callCount, 1); - assert.equal(confidentialClientStub.callCount, 0); + expect(publicClientStub).toHaveBeenCalledTimes(1); + expect(confidentialClientStub).toHaveBeenCalledTimes(0); }); }); }); @@ -326,7 +320,7 @@ describe("MsalClient", function () { }; afterEach(async function () { - sinon.restore(); + vi.restoreAllMocks(); }); describe("with silent authentication", function () { @@ -343,19 +337,18 @@ describe("MsalClient", function () { authenticationRecord, }); - const silentAuthSpy = sinon - .stub(ClientApplication.prototype, "acquireTokenSilent") - .resolves({ + const silentAuthSpy = vi + .spyOn(ClientApplication.prototype, "acquireTokenSilent") + .mockResolvedValue({ accessToken: "token", expiresOn: new Date(), } as AuthenticationResult); - const scopes = ["https://vault.azure.net/.default"]; await client.getTokenByDeviceCode(scopes, deviceCodeCallback); - assert.equal(silentAuthSpy.callCount, 1); - assert.deepEqual(silentAuthSpy.firstCall.firstArg.account, { + expect(silentAuthSpy).toHaveBeenCalledTimes(1); + assert.deepEqual(silentAuthSpy.mock.calls[0][0].account, { ...authenticationRecord, localAccountId: authenticationRecord.homeAccountId, environment: "login.microsoftonline.com", @@ -363,16 +356,15 @@ describe("MsalClient", function () { }); it("attempts silent authentication without AuthenticationRecord", async function () { - const silentAuthStub = sinon - .stub(ClientApplication.prototype, "acquireTokenSilent") - .resolves({ + const silentAuthStub = vi + .spyOn(ClientApplication.prototype, "acquireTokenSilent") + .mockResolvedValue({ accessToken: "token", expiresOn: new Date(), } as AuthenticationResult); - - const clientCredentialAuthStub = sinon - .stub(PublicClientApplication.prototype, "acquireTokenByDeviceCode") - .resolves({ + const clientCredentialAuthStub = vi + .spyOn(PublicClientApplication.prototype, "acquireTokenByDeviceCode") + .mockResolvedValue({ accessToken: "token", expiresOn: new Date(Date.now() + 3600 * 1000), account: { @@ -383,7 +375,6 @@ describe("MsalClient", function () { username: "username", }, } as AuthenticationResult); - const scopes = ["https://vault.azure.net/.default"]; const client = msalClient.createMsalClient(clientId, tenantId); @@ -392,12 +383,12 @@ describe("MsalClient", function () { await client.getTokenByDeviceCode(scopes, deviceCodeCallback); assert.equal( - clientCredentialAuthStub.callCount, + clientCredentialAuthStub.mock.calls.length, 1, "expected acquireTokenByClientCredential to have been called once", ); assert.equal( - silentAuthStub.callCount, + silentAuthStub.mock.calls.length, 1, "expected acquireTokenSilent to have been called once", ); @@ -415,23 +406,22 @@ describe("MsalClient", function () { }, }); - sinon - .stub(ClientApplication.prototype, "acquireTokenSilent") - .rejects(new AbortError("operation has been aborted")); // AbortErrors should get re-thrown + vi.spyOn(ClientApplication.prototype, "acquireTokenSilent").mockRejectedValue( + new AbortError("operation has been aborted"), + ); // AbortErrors should get re-thrown const scopes = ["https://vault.azure.net/.default"]; - await assert.isRejected( - client.getTokenByDeviceCode(scopes, deviceCodeCallback), + await expect(client.getTokenByDeviceCode(scopes, deviceCodeCallback)).rejects.toThrow( "operation has been aborted", ); }); it("throws when silentAuthentication fails and disableAutomaticAuthentication is true", async function () { const scopes = ["https://vault.azure.net/.default"]; - sinon - .stub(ClientApplication.prototype, "acquireTokenSilent") - .rejects(new AuthenticationRequiredError({ scopes })); + vi.spyOn(ClientApplication.prototype, "acquireTokenSilent").mockRejectedValue( + new AuthenticationRequiredError({ scopes }), + ); const client = msalClient.createMsalClient(clientId, tenantId, { // An authentication record will get us to try the silent flow @@ -444,7 +434,7 @@ describe("MsalClient", function () { }, }); - await assert.isRejected( + await expect( client.getTokenByDeviceCode( scopes, () => { @@ -452,12 +442,11 @@ describe("MsalClient", function () { }, { disableAutomaticAuthentication: true }, ), - /Automatic authentication has been disabled/, - ); + ).rejects.toThrow(/Automatic authentication has been disabled/); }); }); - it("supports cancellation", async function (this: Context) { + it("supports cancellation", async function (ctx) { const client = msalClient.createMsalClient(clientId, tenantId); const scopes = ["https://vault.azure.net/.default"]; @@ -472,24 +461,23 @@ describe("MsalClient", function () { abortSignal, }, ); - await assert.isRejected(request, AbortError); + await expect(request).rejects.toThrow(AbortError); }); describe("cross-tenant federation", function () { - it("allows passing an authority host", async function (this: Context) { + it("allows passing an authority host", async function (ctx) { const tenantIdOne = "tenantOne"; const tenantIdTwo = "tenantTwo"; const authorityHost = "https://custom.authority.com"; const expectedAuthority = `${authorityHost}/${tenantIdTwo}`; - const clientCredentialAuthStub = sinon - .stub(PublicClientApplication.prototype, "acquireTokenByDeviceCode") - .resolves({ + const clientCredentialAuthStub = vi + .spyOn(PublicClientApplication.prototype, "acquireTokenByDeviceCode") + .mockResolvedValue({ accessToken: "token", expiresOn: new Date(Date.now() + 3600 * 1000), } as AuthenticationResult); - const client = msalClient.createMsalClient(clientId, tenantIdOne, { authorityHost, }); @@ -498,33 +486,32 @@ describe("MsalClient", function () { await client.getTokenByDeviceCode(scopes, deviceCodeCallback, { tenantId: tenantIdTwo }); - const { authority: requestAuthority } = clientCredentialAuthStub.firstCall.firstArg; + const { authority: requestAuthority } = clientCredentialAuthStub.mock.calls[0][0]; assert.equal(requestAuthority, expectedAuthority); }); - it("allows using the AZURE_AUTHORITY_HOST environment variable", async function (this: Context) { + it("allows using the AZURE_AUTHORITY_HOST environment variable", async function (ctx) { const tenantIdOne = "tenantOne"; const tenantIdTwo = "tenantTwo"; const authorityHost = "https://custom.authority.com"; const expectedAuthority = `${authorityHost}/${tenantIdTwo}`; - sinon.stub(process, "env").value({ AZURE_AUTHORITY_HOST: authorityHost }); + vi.stubEnv("AZURE_AUTHORITY_HOST", authorityHost); - const clientCredentialAuthStub = sinon - .stub(PublicClientApplication.prototype, "acquireTokenByDeviceCode") - .resolves({ + const clientCredentialAuthStub = vi + .spyOn(PublicClientApplication.prototype, "acquireTokenByDeviceCode") + .mockResolvedValue({ accessToken: "token", expiresOn: new Date(Date.now() + 3600 * 1000), } as AuthenticationResult); - const client = msalClient.createMsalClient(clientId, tenantIdOne); const scopes = ["https://vault.azure.net/.default"]; await client.getTokenByDeviceCode(scopes, deviceCodeCallback, { tenantId: tenantIdTwo }); - const { authority: requestAuthority } = clientCredentialAuthStub.firstCall.firstArg; + const { authority: requestAuthority } = clientCredentialAuthStub.mock.calls[0][0]; assert.equal(requestAuthority, expectedAuthority); }); }); diff --git a/sdk/identity/identity/test/internal/node/msalPlugins.spec.ts b/sdk/identity/identity/test/internal/node/msalPlugins.spec.ts index ad07718056b6..3ef7126080f9 100644 --- a/sdk/identity/identity/test/internal/node/msalPlugins.spec.ts +++ b/sdk/identity/identity/test/internal/node/msalPlugins.spec.ts @@ -2,16 +2,15 @@ // Licensed under the MIT License. import type { ICachePlugin, INativeBrokerPlugin } from "@azure/msal-node"; -import type { PluginConfiguration } from "../../../src/msal/nodeFlows/msalPlugins"; +import type { PluginConfiguration } from "../../../src/msal/nodeFlows/msalPlugins.js"; import { msalNodeFlowCacheControl, msalNodeFlowNativeBrokerControl, msalPlugins, -} from "../../../src/msal/nodeFlows/msalPlugins"; +} from "../../../src/msal/nodeFlows/msalPlugins.js"; -import type { MsalClientOptions } from "../../../src/msal/nodeFlows/msalClient"; -import Sinon from "sinon"; -import { assert } from "@azure-tools/test-utils"; +import type { MsalClientOptions } from "../../../src/msal/nodeFlows/msalClient.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("#generatePluginConfiguration", function () { let options: MsalClientOptions; @@ -50,8 +49,8 @@ describe("#generatePluginConfiguration", function () { options.tokenCachePersistenceOptions = { enabled: true }; const cachePlugin = { - afterCacheAccess: Sinon.stub(), - beforeCacheAccess: Sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; const pluginProvider: () => Promise = () => Promise.resolve(cachePlugin); msalNodeFlowCacheControl.setPersistence(pluginProvider); @@ -65,8 +64,8 @@ describe("#generatePluginConfiguration", function () { options.tokenCachePersistenceOptions = { enabled: true }; const cachePluginCae = { - afterCacheAccess: Sinon.stub(), - beforeCacheAccess: Sinon.stub(), + afterCacheAccess: vi.fn(), + beforeCacheAccess: vi.fn(), }; const pluginProvider: () => Promise = () => Promise.resolve(cachePluginCae); msalNodeFlowCacheControl.setPersistence(pluginProvider); diff --git a/sdk/identity/identity/test/internal/node/onBehalfOfCredential.spec.ts b/sdk/identity/identity/test/internal/node/onBehalfOfCredential.spec.ts index b54cde3752b6..f13cc1ea5a6d 100644 --- a/sdk/identity/identity/test/internal/node/onBehalfOfCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/onBehalfOfCredential.spec.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as path from "path"; -import { IdentityTestContext, prepareMSALResponses } from "../../httpRequests"; -import type { IdentityTestContextInterface } from "../../httpRequestsCommon"; -import { createResponse } from "../../httpRequestsCommon"; -import { OnBehalfOfCredential } from "../../../src"; -import { assert } from "chai"; +import * as path from "node:path"; +import { IdentityTestContext, prepareMSALResponses } from "../../httpRequests.js"; +import type { IdentityTestContextInterface } from "../../httpRequestsCommon.js"; +import { createResponse } from "../../httpRequestsCommon.js"; +import { OnBehalfOfCredential } from "../../../src/index.js"; import { isNode } from "@azure/core-util"; +import { describe, it, assert, afterEach, beforeEach } from "vitest"; describe("OnBehalfOfCredential", function () { let testContext: IdentityTestContextInterface; diff --git a/sdk/identity/identity/test/internal/node/regionalAuthority.spec.ts b/sdk/identity/identity/test/internal/node/regionalAuthority.spec.ts index 99f210c71c66..8d484053d6b0 100644 --- a/sdk/identity/identity/test/internal/node/regionalAuthority.spec.ts +++ b/sdk/identity/identity/test/internal/node/regionalAuthority.spec.ts @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { RegionalAuthority, calculateRegionalAuthority } from "../../../src/regionalAuthority"; - -import { assert } from "chai"; +import { RegionalAuthority, calculateRegionalAuthority } from "../../../src/regionalAuthority.js"; +import { describe, it, assert, afterEach, beforeEach } from "vitest"; describe("#calculateRegionalAuthority", function () { beforeEach(function () { diff --git a/sdk/identity/identity/test/internal/node/usernamePasswordCredential.spec.ts b/sdk/identity/identity/test/internal/node/usernamePasswordCredential.spec.ts index 5ed73fa33a13..5786029df0e6 100644 --- a/sdk/identity/identity/test/internal/node/usernamePasswordCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/usernamePasswordCredential.spec.ts @@ -4,37 +4,33 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ import { AzureLogger, setLogLevel } from "@azure/logger"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isPlaybackMode } from "@azure-tools/test-recorder"; - -import type { Context } from "mocha"; import { PublicClientApplication } from "@azure/msal-node"; -import Sinon from "sinon"; -import { UsernamePasswordCredential } from "../../../src"; -import { assert } from "chai"; -import { getUsernamePasswordStaticResources } from "../../msalTestUtils"; +import { UsernamePasswordCredential } from "../../../src/index.js"; +import { getUsernamePasswordStaticResources } from "../../msalTestUtils.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach, MockInstance } from "vitest"; describe("UsernamePasswordCredential (internal)", function () { let cleanup: MsalTestCleanup; - let getTokenSilentSpy: Sinon.SinonSpy; - let doGetTokenSpy: Sinon.SinonSpy; + let getTokenSilentSpy: MockInstance; + let doGetTokenSpy: MockInstance< + typeof PublicClientApplication.prototype.acquireTokenByUsernamePassword + >; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; // MsalClient calls to this method underneath when silent authentication can be attempted. - getTokenSilentSpy = setup.sandbox.spy(PublicClientApplication.prototype, "acquireTokenSilent"); + getTokenSilentSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenSilent"); // MsalClient calls to this method underneath for interactive auth. - doGetTokenSpy = setup.sandbox.spy( - PublicClientApplication.prototype, - "acquireTokenByUsernamePassword", - ); + doGetTokenSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenByUsernamePassword"); }); afterEach(async function () { @@ -62,7 +58,7 @@ describe("UsernamePasswordCredential (internal)", function () { ); }); - it("Authenticates silently after the initial request", async function (this: Context) { + it("Authenticates silently after the initial request", async function (ctx) { const { clientId, password, tenantId, username } = getUsernamePasswordStaticResources(); const credential = new UsernamePasswordCredential( tenantId, @@ -73,22 +69,20 @@ describe("UsernamePasswordCredential (internal)", function () { ); await credential.getToken(scope); - assert.equal(doGetTokenSpy.callCount, 1); + expect(doGetTokenSpy).toHaveBeenCalledOnce(); await credential.getToken(scope); - assert.equal( - getTokenSilentSpy.callCount, - 1, + expect( + getTokenSilentSpy, "getTokenSilentSpy.callCount should have been 1 (Silent authentication after the initial request).", - ); - assert.equal( - doGetTokenSpy.callCount, - 1, + ).toHaveBeenCalledOnce(); + expect( + doGetTokenSpy, "Expected no additional calls to doGetTokenSpy after the initial request.", - ); + ).toHaveBeenCalledOnce(); }); - it("Authenticates with tenantId on getToken", async function (this: Context) { + it("Authenticates with tenantId on getToken", async function (ctx) { const { clientId, password, tenantId, username } = getUsernamePasswordStaticResources(); const credential = new UsernamePasswordCredential( tenantId, @@ -99,28 +93,30 @@ describe("UsernamePasswordCredential (internal)", function () { ); await credential.getToken(scope); - assert.equal(doGetTokenSpy.callCount, 1); + expect(doGetTokenSpy).toHaveBeenCalledTimes(1); }); - it("authenticates (with allowLoggingAccountIdentifiers set to true)", async function (this: Context) { + it("authenticates (with allowLoggingAccountIdentifiers set to true)", async function (ctx) { const { clientId, password, tenantId, username } = getUsernamePasswordStaticResources(); if (isPlaybackMode()) { // The recorder clears the access tokens. - this.skip(); + ctx.skip(); } const credential = new UsernamePasswordCredential(tenantId, clientId, username, password, { loggingOptions: { allowLoggingAccountIdentifiers: true }, }); setLogLevel("info"); - const spy = Sinon.spy(process.stderr, "write"); + const spy = vi.spyOn(process.stderr, "write"); const token = await credential.getToken(scope); assert.ok(token?.token); assert.ok(token?.expiresOnTimestamp! > Date.now()); - assert.ok(spy.getCall(spy.callCount - 2).args[0]); + const expectedArgument = spy.mock.calls[spy.mock.calls.length - 2][0]; + expect(expectedArgument).toBeDefined(); const expectedMessage = `azure:identity:info [Authenticated account] Client ID: ${clientId}. Tenant ID: ${tenantId}. User Principal Name: HIDDEN. Object ID (user): HIDDEN`; assert.equal( - (spy.getCall(spy.callCount - 2).args[0] as any as string) + expectedArgument + .toString() .replace(/User Principal Name: [^ ]+. /g, "User Principal Name: HIDDEN. ") .replace( /Object ID .user.: [a-z0-9]+-[a-z0-9]+-[a-z0-9]+-[a-z0-9]+-[a-z0-9]+/g, @@ -129,7 +125,6 @@ describe("UsernamePasswordCredential (internal)", function () { .trim(), expectedMessage, ); - spy.restore(); AzureLogger.destroy(); }); }); diff --git a/sdk/identity/identity/test/internal/node/utils.spec.ts b/sdk/identity/identity/test/internal/node/utils.spec.ts index 11f4f16f5dcc..ac1876caa5b6 100644 --- a/sdk/identity/identity/test/internal/node/utils.spec.ts +++ b/sdk/identity/identity/test/internal/node/utils.spec.ts @@ -1,8 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import { processMultiTenantRequest } from "../../../src/util/tenantIdUtils"; +import { processMultiTenantRequest } from "../../../src/util/tenantIdUtils.js"; +import { describe, it, assert, afterEach } from "vitest"; describe("Identity utilities (Node.js only)", function () { describe("validateMultiTenantRequest (Node.js only)", function () { diff --git a/sdk/identity/identity/test/internal/node/workloadIdentityCredential.spec.ts b/sdk/identity/identity/test/internal/node/workloadIdentityCredential.spec.ts index 1349570600ca..dbeb967fc16e 100644 --- a/sdk/identity/identity/test/internal/node/workloadIdentityCredential.spec.ts +++ b/sdk/identity/identity/test/internal/node/workloadIdentityCredential.spec.ts @@ -3,21 +3,19 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import type { AccessToken, WorkloadIdentityCredentialOptions } from "../../../src"; +import type { AccessToken, WorkloadIdentityCredentialOptions } from "../../../src/index.js"; import { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, -} from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +} from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { AuthenticationResult } from "@azure/msal-node"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; import { env } from "@azure-tools/test-recorder"; -import path from "path"; -import sinon from "sinon"; +import path from "node:path"; +import { describe, it, assert, vi, beforeEach, afterEach } from "vitest"; describe("WorkloadIdentityCredential", function () { let cleanup: MsalTestCleanup; @@ -45,7 +43,7 @@ describe("WorkloadIdentityCredential", function () { correlationId: "correlationId", }; - beforeEach(async function (this: Context) { + beforeEach(async function () { const setup = await msalNodeTestSetup(stubbedToken); cleanup = setup.cleanup; }); @@ -54,7 +52,7 @@ describe("WorkloadIdentityCredential", function () { await cleanup(); }); - it("authenticates with WorkloadIdentity Credential", async function (this: Context) { + it("authenticates with WorkloadIdentity Credential", async function (ctx) { const credential = new WorkloadIdentityCredential({ tenantId, clientId, @@ -69,17 +67,18 @@ describe("WorkloadIdentityCredential", function () { }); }); - it("authenticates with ManagedIdentity Credential", async function (this: Context) { - process.env.AZURE_FEDERATED_TOKEN_FILE = tokenFilePath; + it("authenticates with ManagedIdentity Credential", async function (ctx) { + vi.stubEnv("AZURE_FEDERATED_TOKEN_FILE", tokenFilePath); + vi.stubEnv("AZURE_CLIENT_ID", clientId); + vi.stubEnv("AZURE_TENANT_ID", tenantId); const credential = new ManagedIdentityCredential("dummy-clientId"); const token = await credential.getToken(scope); assert.ok(token?.token); assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with DefaultAzure Credential", async function (this: Context) { + it("authenticates with DefaultAzure Credential", async function (ctx) { const credential = new DefaultAzureCredential(); - const sandbox = sinon.createSandbox(); try { const { token, successfulCredential } = await credential["getTokenInternal"](scope); assert.isDefined(successfulCredential); @@ -96,15 +95,14 @@ describe("WorkloadIdentityCredential", function () { } catch (e) { console.log(e); } finally { - sandbox.restore(); + vi.restoreAllMocks(); } }); - it("authenticates with DefaultAzure Credential and client ID", async function (this: Context) { + it("authenticates with DefaultAzure Credential and client ID", async function (ctx) { const credential = new DefaultAzureCredential({ managedIdentityClientId: "managedIdentityClientId", workloadIdentityClientId: "workloadIdentityClientId", }); - const sandbox = sinon.createSandbox(); try { const { token, successfulCredential } = await credential["getTokenInternal"](scope); assert.isDefined(successfulCredential); @@ -121,7 +119,7 @@ describe("WorkloadIdentityCredential", function () { } catch (e) { console.log(e); } finally { - sandbox.restore(); + vi.restoreAllMocks(); } }); }); diff --git a/sdk/identity/identity/test/internal/tenantIdUtils.spec.ts b/sdk/identity/identity/test/internal/tenantIdUtils.spec.ts index 6158b2a46787..32fd26a43d77 100644 --- a/sdk/identity/identity/test/internal/tenantIdUtils.spec.ts +++ b/sdk/identity/identity/test/internal/tenantIdUtils.spec.ts @@ -5,10 +5,10 @@ import { checkTenantId, resolveAdditionallyAllowedTenantIds, resolveTenantId, -} from "../../src/util/tenantIdUtils"; -import { DeveloperSignOnClientId } from "../../src/constants"; -import { assert } from "@azure-tools/test-utils"; -import { credentialLogger } from "../../src/util/logging"; +} from "../../src/util/tenantIdUtils.js"; +import { DeveloperSignOnClientId } from "../../src/constants.js"; +import { credentialLogger } from "../../src/util/logging.js"; +import { describe, it, assert } from "vitest"; describe("tenantIdUtils", () => { describe("resolveAddionallyAllowedTenantIds", () => { diff --git a/sdk/identity/identity/test/internal/utils.spec.ts b/sdk/identity/identity/test/internal/utils.spec.ts index 2b8b99a83319..b391434bde37 100644 --- a/sdk/identity/identity/test/internal/utils.spec.ts +++ b/sdk/identity/identity/test/internal/utils.spec.ts @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { assert } from "chai"; -import { getAuthority } from "../../src/msal/utils"; -import { processMultiTenantRequest } from "../../src/util/tenantIdUtils"; +import { getAuthority } from "../../src/msal/utils.js"; +import { processMultiTenantRequest } from "../../src/util/tenantIdUtils.js"; +import { describe, it, assert } from "vitest"; describe("Identity utilities", function () { describe("validateMultiTenantRequest", function () { diff --git a/sdk/identity/identity/test/msalTestUtils.ts b/sdk/identity/identity/test/msalTestUtils.ts index cd85a296b1ed..50069e1961af 100644 --- a/sdk/identity/identity/test/msalTestUtils.ts +++ b/sdk/identity/identity/test/msalTestUtils.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { env } from "@azure-tools/test-recorder"; -import { DeveloperSignOnClientId } from "../src/constants"; +import { DeveloperSignOnClientId } from "../src/constants.js"; export const PlaybackTenantId = "12345678-1234-1234-1234-123456789012"; diff --git a/sdk/identity/identity/test/node/msalNodeTestSetup.ts b/sdk/identity/identity/test/node/msalNodeTestSetup.ts index 83289c049898..f432507b8983 100644 --- a/sdk/identity/identity/test/node/msalNodeTestSetup.ts +++ b/sdk/identity/identity/test/node/msalNodeTestSetup.ts @@ -3,46 +3,53 @@ import type { AuthenticationResult } from "@azure/msal-node"; import { ConfidentialClientApplication, PublicClientApplication } from "@azure/msal-node"; -import type Sinon from "sinon"; -import { createSandbox } from "sinon"; - -import { PlaybackTenantId } from "../msalTestUtils"; -import { Recorder } from "@azure-tools/test-recorder"; -import { Test } from "mocha"; +import { PlaybackTenantId } from "../msalTestUtils.js"; +import { Recorder, VitestTestContext } from "@azure-tools/test-recorder"; +import { vi } from "vitest"; export type MsalTestCleanup = () => Promise; export interface MsalTestSetupResponse { cleanup: MsalTestCleanup; recorder?: Recorder; - sandbox: Sinon.SinonSandbox; +} + +/** + * Determines whether the given test is a Vitest Test. + * @param test - The test to check. + * @returns true if the given test is a Vitest Test. + */ +function isVitestTestContext(test: unknown): test is VitestTestContext { + return ( + typeof test === "function" && + "task" in test && + typeof test.task === "object" && + test.task != null && + "name" in test.task + ); } export async function msalNodeTestSetup( - testContext?: Test, + testContext?: VitestTestContext, playbackClientId?: string, ): Promise<{ cleanup: MsalTestCleanup; recorder: Recorder; - sandbox: Sinon.SinonSandbox; }>; export async function msalNodeTestSetup(stubbedToken: AuthenticationResult): Promise<{ cleanup: MsalTestCleanup; - sandbox: Sinon.SinonSandbox; }>; export async function msalNodeTestSetup( - testContextOrStubbedToken?: Test | AuthenticationResult, + testContextOrStubbedToken?: VitestTestContext | AuthenticationResult, playbackClientId = "azure_client_id", ): Promise { const playbackValues = { correlationId: "client-request-id", }; - const sandbox = createSandbox(); - - if (testContextOrStubbedToken instanceof Test || testContextOrStubbedToken === undefined) { + if (isVitestTestContext(testContextOrStubbedToken)) { const testContext = testContextOrStubbedToken; const recorder = new Recorder(testContext); @@ -186,11 +193,11 @@ export async function msalNodeTestSetup( ); return { - sandbox, recorder, async cleanup() { await recorder.stop(); - sandbox.restore(); + vi.unstubAllEnvs(); + vi.restoreAllMocks(); }, }; } else { @@ -214,18 +221,19 @@ export async function msalNodeTestSetup( ]; publicClientMethods.forEach((method) => - sandbox.stub(PublicClientApplication.prototype, method).callsFake(async () => stubbedToken), + vi + .spyOn(PublicClientApplication.prototype, method) + .mockImplementation(async () => stubbedToken ?? null), ); confidentialClientMethods.forEach((method) => - sandbox - .stub(ConfidentialClientApplication.prototype, method) - .callsFake(async () => stubbedToken), + vi + .spyOn(ConfidentialClientApplication.prototype, method) + .mockImplementation(async () => stubbedToken ?? null), ); return { - sandbox, async cleanup() { - sandbox.restore(); + vi.restoreAllMocks(); }, }; } diff --git a/sdk/identity/identity/test/public/browser/clientSecretCredential.spec.ts b/sdk/identity/identity/test/public/browser/clientSecretCredential.spec.ts index f2f242eab5d4..11531303e903 100644 --- a/sdk/identity/identity/test/public/browser/clientSecretCredential.spec.ts +++ b/sdk/identity/identity/test/public/browser/clientSecretCredential.spec.ts @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { IdentityTestContextInterface } from "../../httpRequestsCommon"; -import { createResponse } from "../../httpRequestsCommon"; -import { ClientSecretCredential } from "../../../src"; -import { IdentityTestContext } from "../../httpRequests"; -import { assertClientCredentials } from "../../authTestUtils"; +import type { IdentityTestContextInterface } from "../../httpRequestsCommon.js"; +import { createResponse } from "../../httpRequestsCommon.js"; +import { ClientSecretCredential } from "../../../src/index.js"; +import { IdentityTestContext } from "../../httpRequests.js"; +import { assertClientCredentials } from "../../authTestUtils.js"; +import { describe, it, beforeEach, afterEach } from "vitest"; describe("ClientSecretCredential", function () { let testContext: IdentityTestContextInterface; diff --git a/sdk/identity/identity/test/public/browser/usernamePasswordCredential.spec.ts b/sdk/identity/identity/test/public/browser/usernamePasswordCredential.spec.ts index cb18fade2940..8a7a5eae5355 100644 --- a/sdk/identity/identity/test/public/browser/usernamePasswordCredential.spec.ts +++ b/sdk/identity/identity/test/public/browser/usernamePasswordCredential.spec.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { IdentityTestContextInterface } from "../../httpRequestsCommon"; -import { createResponse } from "../../httpRequestsCommon"; -import { IdentityTestContext } from "../../httpRequests"; -import { UsernamePasswordCredential } from "../../../src"; -import { assert } from "chai"; -import { assertClientCredentials } from "../../authTestUtils"; -import { fakeTestPasswordPlaceholder } from "@azure-tools/test-utils"; +import type { IdentityTestContextInterface } from "../../httpRequestsCommon.js"; +import { createResponse } from "../../httpRequestsCommon.js"; +import { IdentityTestContext } from "../../httpRequests.js"; +import { UsernamePasswordCredential } from "../../../src/index.js"; +import { assertClientCredentials } from "../../authTestUtils.js"; +import { fakeTestPasswordPlaceholder } from "@azure-tools/test-utils-vitest"; +import { describe, it, assert, beforeEach, afterEach } from "vitest"; describe("UsernamePasswordCredential", function () { let testContext: IdentityTestContextInterface; diff --git a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts index 2e28eb3c21a1..fbf252e756d3 100644 --- a/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts +++ b/sdk/identity/identity/test/public/chainedTokenCredential.spec.ts @@ -1,14 +1,18 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { AccessToken, AggregateAuthenticationError, TokenCredential } from "../../src"; +import type { + AccessToken, + AggregateAuthenticationError, + TokenCredential, +} from "../../src/index.js"; import { AuthenticationRequiredError, ChainedTokenCredential, CredentialUnavailableError, -} from "../../src"; -import { assert } from "chai"; -import { getError } from "../authTestUtils"; +} from "../../src/index.js"; +import { getError } from "../authTestUtils.js"; +import { describe, it, assert } from "vitest"; function mockCredential(returnPromise: Promise): TokenCredential { return { diff --git a/sdk/identity/identity/test/public/errors.spec.ts b/sdk/identity/identity/test/public/errors.spec.ts index 36f840c78336..5f94385a193d 100644 --- a/sdk/identity/identity/test/public/errors.spec.ts +++ b/sdk/identity/identity/test/public/errors.spec.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { AggregateAuthenticationError } from "../../src"; -import { assert } from "chai"; +import { AggregateAuthenticationError } from "../../src/index.js"; +import { describe, it, assert } from "vitest"; describe("AggregateAuthenticationError", function () { it("produces a message containing details of the errors it contains", async () => { diff --git a/sdk/identity/identity/test/public/node/authorityValidation.spec.ts b/sdk/identity/identity/test/public/node/authorityValidation.spec.ts index 957336eb717c..6e8021f27dc5 100644 --- a/sdk/identity/identity/test/public/node/authorityValidation.spec.ts +++ b/sdk/identity/identity/test/public/node/authorityValidation.spec.ts @@ -1,19 +1,18 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import { ClientSecretCredential } from "../../../src"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; +import { ClientSecretCredential } from "../../../src/index.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("AuthorityValidation", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); diff --git a/sdk/identity/identity/test/public/node/azureApplicationCredential.spec.ts b/sdk/identity/identity/test/public/node/azureApplicationCredential.spec.ts index 8002d2b399f6..7c82ae44a48b 100644 --- a/sdk/identity/identity/test/public/node/azureApplicationCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/azureApplicationCredential.spec.ts @@ -2,11 +2,13 @@ // Licensed under the MIT License. import type { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; -import { getError } from "../../authTestUtils"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; +import { getError } from "../../authTestUtils.js"; +import { describe, it, assert, expect, afterEach, beforeEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; + +expect.extend({ toSupportTracing }); // TODO: Use the real one once we decide to re-enable this on the public API. class AzureApplicationCredential implements TokenCredential { @@ -21,8 +23,8 @@ describe.skip("AzureApplicationCredential", function () { const environmentVariableNames = ["AZURE_TENANT_ID", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET"]; const cachedValues: Record = {}; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; environmentVariableNames.forEach((name) => { cachedValues[name] = process.env[name]; @@ -53,24 +55,19 @@ describe.skip("AzureApplicationCredential", function () { }); it("supports tracing with environment client secret", async () => { - await assert.supportsTracing( - async (tracingOptions) => { - // The following environment variables must be set for this to work. - // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. - process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; - process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; - process.env.AZURE_CLIENT_SECRET = cachedValues.AZURE_CLIENT_SECRET; - - const credential = new AzureApplicationCredential(); - - await credential.getToken(scope, tracingOptions); - }, - [ - "ChainedTokenCredential.getToken", - "EnvironmentCredential.getToken", - "ClientSecretCredential.getToken", - ], - ); + await expect(async (tracingOptions: any) => { + // The following environment variables must be set for this to work. + // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. + process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; + process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; + process.env.AZURE_CLIENT_SECRET = cachedValues.AZURE_CLIENT_SECRET; + const credential = new AzureApplicationCredential(); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing([ + "ChainedTokenCredential.getToken", + "EnvironmentCredential.getToken", + "ClientSecretCredential.getToken", + ]); }); it("throws an AggregateAuthenticationError when getToken is called and no credential was configured", async () => { diff --git a/sdk/identity/identity/test/public/node/azurePipelinesCredential.spec.ts b/sdk/identity/identity/test/public/node/azurePipelinesCredential.spec.ts index 5380b1c5b777..c6e6a8b7160f 100644 --- a/sdk/identity/identity/test/public/node/azurePipelinesCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/azurePipelinesCredential.spec.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { AzurePipelinesCredential } from "../../../src"; +import { AzurePipelinesCredential } from "../../../src/index.js"; import { isLiveMode } from "@azure-tools/test-recorder"; -import { assert } from "@azure-tools/test-utils"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("AzurePipelinesCredential", function () { const scope = "https://vault.azure.net/.default"; const tenantId = process.env.AZURE_SERVICE_CONNECTION_TENANT_ID!; - it("authenticates with a valid service connection", async function () { + it("authenticates with a valid service connection", async function (ctx) { if (!isLiveMode() || !process.env.AZURE_SERVICE_CONNECTION_ID) { - this.skip(); + ctx.skip(); } // this serviceConnection corresponds to the Azure SDK Test Resources - LiveTestSecrets service const existingServiceConnectionId = process.env.AZURE_SERVICE_CONNECTION_ID!; @@ -30,9 +30,9 @@ describe("AzurePipelinesCredential", function () { if (token?.expiresOnTimestamp) assert.ok(token?.expiresOnTimestamp > Date.now()); }); - it("fails with invalid service connection", async function () { + it("fails with invalid service connection", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } // clientId for above service connection const clientId = process.env.AZURE_SERVICE_CONNECTION_CLIENT_ID!; @@ -45,16 +45,12 @@ describe("AzurePipelinesCredential", function () { ); const regExp: RegExp = /invalid_client: Error\(s\): 700213 .* AADSTS700213: No matching federated identity record found for presented assertion subject .* Please note that the matching is done using a case-sensitive comparison. Check your federated identity credential Subject, Audience and Issuer against the presented assertion/; - await assert.isRejected( - credential.getToken(scope), - regExp, - "error thrown doesn't match or promise not rejected", - ); + await expect(credential.getToken(scope)).rejects.toThrow(regExp); }); - it("failure includes the expected response headers", async function () { + it("failure includes the expected response headers", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } // clientId for above service connection const clientId = process.env.AZURE_SERVICE_CONNECTION_CLIENT_ID!; @@ -68,22 +64,14 @@ describe("AzurePipelinesCredential", function () { const regExpHeader1: RegExp = /"x-vss-e2eid"/gm; const regExpHeader2: RegExp = /"x-msedge-ref"/gm; - await assert.isRejected( - credential.getToken(scope), - regExpHeader1, - "error thrown doesn't contain expected header 'x-vss-e2eid'", - ); + await expect(credential.getToken(scope)).rejects.toThrow(regExpHeader1); - await assert.isRejected( - credential.getToken(scope), - regExpHeader2, - "error thrown doesn't contain expected header 'x-msedge-ref'", - ); + await expect(credential.getToken(scope)).rejects.toThrow(regExpHeader2); }); - it("fails with with invalid client id", async function () { + it("fails with with invalid client id", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } const existingServiceConnectionId = process.env.AZURE_SERVICE_CONNECTION_ID!; const systemAccessToken = process.env.SYSTEM_ACCESSTOKEN!; @@ -95,16 +83,12 @@ describe("AzurePipelinesCredential", function () { ); const regExp: RegExp = /AADSTS700016: Application with identifier 'clientId' was not found in the directory 'Microsoft'/; - await assert.isRejected( - credential.getToken(scope), - regExp, - "error thrown doesn't match or promise not rejected", - ); + await expect(credential.getToken(scope)).rejects.toThrow(regExp); }); - it("fails with with invalid system access token", async function () { + it("fails with with invalid system access token", async function (ctx) { if (!isLiveMode()) { - this.skip(); + ctx.skip(); } const clientId = process.env.AZURE_SERVICE_CONNECTION_CLIENT_ID!; const existingServiceConnectionId = process.env.AZURE_SERVICE_CONNECTION_ID!; @@ -114,6 +98,6 @@ describe("AzurePipelinesCredential", function () { existingServiceConnectionId, "invalidSystemAccessToken", ); - await assert.isRejected(credential.getToken(scope), /Status code: 401/); + await expect(credential.getToken(scope)).rejects.toThrow(/Status code: 401/); }); }); diff --git a/sdk/identity/identity/test/public/node/caeARM.spec.ts b/sdk/identity/identity/test/public/node/caeARM.spec.ts index f915b4ee8bb9..462d93aba396 100644 --- a/sdk/identity/identity/test/public/node/caeARM.spec.ts +++ b/sdk/identity/identity/test/public/node/caeARM.spec.ts @@ -3,10 +3,10 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import type { AccessToken, TokenCredential } from "../../../src"; -import { DeviceCodeCredential, UsernamePasswordCredential } from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { AccessToken, TokenCredential } from "../../../src/index.js"; +import { DeviceCodeCredential, UsernamePasswordCredential } from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { delay, env } from "@azure-tools/test-recorder"; import { @@ -15,11 +15,10 @@ import { createEmptyPipeline, createPipelineRequest, } from "@azure/core-rest-pipeline"; -import type { Context } from "mocha"; -import { DeveloperSignOnClientId } from "../../../src/constants"; -import { IdentityClient } from "../../../src/client/identityClient"; -import { assert } from "chai"; +import { DeveloperSignOnClientId } from "../../../src/constants.js"; +import { IdentityClient } from "../../../src/client/identityClient.js"; import { authorizeRequestOnClaimChallenge } from "@azure/core-client"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; /** * Sequence of events needed to test the CAE challenges on the Graph endpoint. @@ -137,8 +136,8 @@ describe.skip("CAE", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); @@ -146,7 +145,7 @@ describe.skip("CAE", function () { await cleanup(); }); - it("DeviceCodeCredential", async function (this: Context) { + it("DeviceCodeCredential", async function (ctx) { const [firstAccessToken, finalAccessToken] = await challengeFlow( new DeviceCodeCredential(recorder.configureClientOptions({ tenantId: env.AZURE_TENANT_ID })), recorder, @@ -155,7 +154,7 @@ describe.skip("CAE", function () { assert.notDeepEqual(firstAccessToken, finalAccessToken); }); - it("UsernamePasswordCredential", async function (this: Context) { + it("UsernamePasswordCredential", async function (ctx) { // Important: Recording this test may only work in certain tenants. const [firstAccessToken, finalAccessToken] = await challengeFlow( diff --git a/sdk/identity/identity/test/public/node/clientCertificateCredential.spec.ts b/sdk/identity/identity/test/public/node/clientCertificateCredential.spec.ts index e143b0bcefdb..7f9506f85a4e 100644 --- a/sdk/identity/identity/test/public/node/clientCertificateCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/clientCertificateCredential.spec.ts @@ -3,18 +3,20 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import * as path from "path"; +import * as path from "node:path"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { delay, env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder"; -import { ClientCertificateCredential } from "../../../src"; -import type { Context } from "mocha"; +import { ClientCertificateCredential } from "../../../src/index.js"; import type { PipelineResponse } from "@azure/core-rest-pipeline"; -import { assert } from "@azure-tools/test-utils"; -import fs from "fs"; +import fs from "node:fs"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; + +expect.extend({ toSupportTracing }); const ASSET_PATH = "assets"; @@ -22,14 +24,14 @@ describe("ClientCertificateCredential", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; await recorder.setMatcher("BodilessMatcher"); if (isLiveMode()) { // https://github.com/Azure/azure-sdk-for-js/issues/29929 - this.skip(); + ctx.skip(); } }); afterEach(async function () { @@ -39,7 +41,7 @@ describe("ClientCertificateCredential", function () { const certificatePath = env.IDENTITY_SP_CERT_PEM || path.join(ASSET_PATH, "fake-cert.pem"); const scope = "https://vault.azure.net/.default"; - it("authenticates", async function (this: Context) { + it("authenticates", async function (ctx) { const credential = new ClientCertificateCredential( env.IDENTITY_SP_TENANT_ID || env.AZURE_TENANT_ID!, env.IDENTITY_SP_CLIENT_ID || env.AZURE_CLIENT_ID!, @@ -52,7 +54,7 @@ describe("ClientCertificateCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with a PEM certificate string directly", async function (this: Context) { + it("authenticates with a PEM certificate string directly", async function (ctx) { const credential = new ClientCertificateCredential( env.IDENTITY_SP_TENANT_ID || env.AZURE_TENANT_ID!, env.IDENTITY_SP_CLIENT_ID || env.AZURE_CLIENT_ID!, @@ -68,11 +70,11 @@ describe("ClientCertificateCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("allows cancelling the authentication", async function (this: Context) { + it("allows cancelling the authentication", async function (ctx) { if (!fs.existsSync(certificatePath)) { // In min-max tests, the certificate file can't be found. console.log("Failed to locate the certificate file. Skipping."); - this.skip(); + ctx.skip(); } const credential = new ClientCertificateCredential( env.IDENTITY_SP_TENANT_ID || env.AZURE_TENANT_ID!, @@ -107,24 +109,20 @@ describe("ClientCertificateCredential", function () { assert.ok(error?.message.includes("endpoints_resolution_error")); }); - it("supports tracing", async function (this: Context) { + it("supports tracing", async function (ctx) { if (isPlaybackMode()) { // MSAL creates a client assertion based on the certificate that I haven't been able to mock. // This assertion could be provided as parameters, but we don't have that in the public API yet, // and I'm trying to avoid having to generate one ourselves. - this.skip(); + ctx.skip(); } - await assert.supportsTracing( - async (tracingOptions) => { - const credential = new ClientCertificateCredential( - env.IDENTITY_SP_TENANT_ID || env.AZURE_TENANT_ID!, - env.IDENTITY_SP_CLIENT_ID || env.AZURE_CLIENT_ID!, - recorder.configureClientOptions({ certificatePath }), - ); - - await credential.getToken(scope, tracingOptions); - }, - ["ClientCertificateCredential.getToken"], - ); + await expect(async (tracingOptions) => { + const credential = new ClientCertificateCredential( + env.IDENTITY_SP_TENANT_ID || env.AZURE_TENANT_ID!, + env.IDENTITY_SP_CLIENT_ID || env.AZURE_CLIENT_ID!, + recorder.configureClientOptions({ certificatePath }), + ); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["ClientCertificateCredential.getToken"]); }); }); diff --git a/sdk/identity/identity/test/public/node/clientSecretCredential.spec.ts b/sdk/identity/identity/test/public/node/clientSecretCredential.spec.ts index 31c642a69d3f..1eee413c93c2 100644 --- a/sdk/identity/identity/test/public/node/clientSecretCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/clientSecretCredential.spec.ts @@ -3,20 +3,22 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { delay, env, isRecordMode } from "@azure-tools/test-recorder"; -import { ClientSecretCredential } from "../../../src"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; +import { ClientSecretCredential } from "../../../src/index.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; + +expect.extend({ toSupportTracing }); describe("ClientSecretCredential", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); @@ -81,42 +83,14 @@ describe("ClientSecretCredential", function () { }); it("supports tracing", async () => { - await assert.supportsTracing( - async (tracingOptions) => { - const credential = new ClientSecretCredential( - env.AZURE_TENANT_ID!, - env.AZURE_CLIENT_ID!, - env.AZURE_CLIENT_SECRET!, - recorder.configureClientOptions({}), - ); - - await credential.getToken(scope, tracingOptions); - }, - ["ClientSecretCredential.getToken"], - ); - }); - - // TODO: Enable again once we're ready to release this feature. - it.skip("supports specifying the regional authority", async function (this: Context) { - // This test is extremely slow. Let's skip it for now. - // I've tried Sinon's clock and it doesn't affect it. - // We have internal tests that check that the parameters are properly sent to MSAL, which should be enough from the perspective of the SDK. - if (!isRecordMode()) { - this.skip(); - } - - const credential = new ClientSecretCredential( - env.AZURE_TENANT_ID!, - env.AZURE_CLIENT_ID!, - env.AZURE_CLIENT_SECRET!, - recorder.configureClientOptions({ - // TODO: Uncomment again once we're ready to release this feature. - // regionalAuthority: RegionalAuthority.AutoDiscoverRegion - }), - ); - - const token = await credential.getToken(scope); - assert.ok(token?.token); - assert.ok(token?.expiresOnTimestamp! > Date.now()); + await expect(async (tracingOptions) => { + const credential = new ClientSecretCredential( + env.AZURE_TENANT_ID!, + env.AZURE_CLIENT_ID!, + env.AZURE_CLIENT_SECRET!, + recorder.configureClientOptions({}), + ); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["ClientSecretCredential.getToken"]); }); }); diff --git a/sdk/identity/identity/test/public/node/deviceCodeCredential.spec.ts b/sdk/identity/identity/test/public/node/deviceCodeCredential.spec.ts index 6f822da29f0c..acae7f747733 100644 --- a/sdk/identity/identity/test/public/node/deviceCodeCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/deviceCodeCredential.spec.ts @@ -4,14 +4,16 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ import type { AbortError } from "@azure/abort-controller"; -import type { DeviceCodePromptCallback } from "../../../src"; -import { DeviceCodeCredential } from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { DeviceCodePromptCallback } from "../../../src/index.js"; +import { DeviceCodeCredential } from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { delay, env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; + +expect.extend({ toSupportTracing }); // https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9 const DeveloperSignOnClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; @@ -20,8 +22,8 @@ describe("DeviceCodeCredential", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest, DeveloperSignOnClientId); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx, DeveloperSignOnClientId); cleanup = setup.cleanup; recorder = setup.recorder; }); @@ -31,10 +33,10 @@ describe("DeviceCodeCredential", function () { const scope = "https://vault.azure.net/.default"; - it("authenticates with default values", async function (this: Context) { + it("authenticates with default values", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential(recorder.configureClientOptions({})); @@ -43,10 +45,10 @@ describe("DeviceCodeCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with provided values", async function (this: Context) { + it("authenticates with provided values", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( recorder.configureClientOptions({ @@ -60,10 +62,10 @@ describe("DeviceCodeCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with specific permissions", async function (this: Context) { + it("authenticates with specific permissions", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( recorder.configureClientOptions({ @@ -78,10 +80,10 @@ describe("DeviceCodeCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates and allows the customization of the prompt callback", async function (this: Context) { + it("authenticates and allows the customization of the prompt callback", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const callback: DeviceCodePromptCallback = (info) => { console.log("CUSTOMIZED PROMPT CALLBACK", info.message); @@ -99,15 +101,15 @@ describe("DeviceCodeCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("allows cancelling the authentication", async function (this: Context) { + it("allows cancelling the authentication", async function (ctx) { // Because of the user interaction, this test works inconsistently in our live test pipelines. if (isLiveMode()) { - this.skip(); + ctx.skip(); } // On playback we can't quite control the time needed to trigger this error. if (isPlaybackMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( @@ -136,10 +138,10 @@ describe("DeviceCodeCredential", function () { assert.ok(error?.message.match("The authentication has been aborted by the caller.")); }); - it("allows setting disableAutomaticAuthentication", async function (this: Context) { + it("allows setting disableAutomaticAuthentication", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } const credential = new DeviceCodeCredential( recorder.configureClientOptions({ @@ -162,23 +164,19 @@ describe("DeviceCodeCredential", function () { assert.ok(account); }); - it("supports tracing", async function (this: Context) { + it("supports tracing", async function (ctx) { // These tests should not run live because this credential requires user interaction. if (isLiveMode()) { - this.skip(); + ctx.skip(); } - await assert.supportsTracing( - async (tracingOptions) => { - const credential = new DeviceCodeCredential( - recorder.configureClientOptions({ - tenantId: env.AZURE_TENANT_ID, - clientId: env.AZURE_CLIENT_ID, - }), - ); - - await credential.getToken(scope, tracingOptions); - }, - ["DeviceCodeCredential.getToken"], - ); + await expect(async (tracingOptions: any) => { + const credential = new DeviceCodeCredential( + recorder.configureClientOptions({ + tenantId: env.AZURE_TENANT_ID, + clientId: env.AZURE_CLIENT_ID, + }), + ); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["DeviceCodeCredential.getToken"]); }); }); diff --git a/sdk/identity/identity/test/public/node/environmentCredential.spec.ts b/sdk/identity/identity/test/public/node/environmentCredential.spec.ts index cab35b0efb90..b7ab29af602b 100644 --- a/sdk/identity/identity/test/public/node/environmentCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/environmentCredential.spec.ts @@ -3,15 +3,16 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import { EnvironmentCredential, UsernamePasswordCredential } from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import { EnvironmentCredential, UsernamePasswordCredential } from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { isLiveMode } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; -import { getError } from "../../authTestUtils"; -import sinon from "sinon"; +import { getError } from "../../authTestUtils.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; + +expect.extend({ toSupportTracing }); describe("EnvironmentCredential", function () { let cleanup: MsalTestCleanup; @@ -27,8 +28,8 @@ describe("EnvironmentCredential", function () { ]; const cachedValues: Record = {}; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); recorder = setup.recorder; cleanup = setup.cleanup; environmentVariableNames.forEach((name) => { @@ -59,10 +60,10 @@ describe("EnvironmentCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with a client certificate on the environment variables", async function (this: Context) { + it("authenticates with a client certificate on the environment variables", async function (ctx) { if (isLiveMode()) { // Live test run not supported on CI at the moment. Locally should work though. - this.skip(); + ctx.skip(); } // The following environment variables must be set for this to work. // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. @@ -77,10 +78,10 @@ describe("EnvironmentCredential", function () { assert.ok(token?.expiresOnTimestamp! > Date.now()); }); - it("authenticates with a client certificate and password on the environment variables", async function (this: Context) { + it("authenticates with a client certificate and password on the environment variables", async function (ctx) { if (isLiveMode()) { // Live test run not supported on CI at the moment. Locally should work though. - this.skip(); + ctx.skip(); } // The following environment variables must be set for this to work. // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. @@ -105,7 +106,7 @@ describe("EnvironmentCredential", function () { process.env.AZURE_USERNAME = "user"; process.env.AZURE_PASSWORD = "password"; - const getTokenSpy = sinon.spy(UsernamePasswordCredential.prototype, "getToken"); + const getTokenSpy = vi.spyOn(UsernamePasswordCredential.prototype, "getToken"); try { const credential = new EnvironmentCredential(recorder.configureClientOptions({})); @@ -115,73 +116,54 @@ describe("EnvironmentCredential", function () { // We will focus our test on making sure the underlying getToken was called. } - assert.equal( - getTokenSpy.callCount, - 1, - "UsernamePasswordCredential getToken should have been called", - ); + expect(getTokenSpy).toHaveBeenCalledOnce(); }); it("supports tracing with environment client secret", async () => { - await assert.supportsTracing( - async (tracingOptions) => { - // The following environment variables must be set for this to work. - // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. - process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; - process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; - process.env.AZURE_CLIENT_SECRET = cachedValues.AZURE_CLIENT_SECRET; - - const credential = new EnvironmentCredential(recorder.configureClientOptions({})); - - await credential.getToken(scope, tracingOptions); - }, - ["EnvironmentCredential.getToken"], - ); + await expect(async (tracingOptions: any) => { + // The following environment variables must be set for this to work. + // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. + process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; + process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; + process.env.AZURE_CLIENT_SECRET = cachedValues.AZURE_CLIENT_SECRET; + const credential = new EnvironmentCredential(recorder.configureClientOptions({})); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["EnvironmentCredential.getToken"]); }); - it("supports tracing with environment client certificate", async function (this: Context) { + it("supports tracing with environment client certificate", async function (ctx) { if (isLiveMode()) { // Live test run not supported on CI at the moment. Locally should work though. - this.skip(); + ctx.skip(); } - await assert.supportsTracing( - async (tracingOptions) => { - // The following environment variables must be set for this to work. - // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. - process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; - process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; - process.env.AZURE_CLIENT_CERTIFICATE_PATH = - cachedValues.AZURE_CLIENT_CERTIFICATE_PATH || "assets/fake-cert.pem"; - - const credential = new EnvironmentCredential(recorder.configureClientOptions({})); - - await credential.getToken(scope, tracingOptions); - }, - ["EnvironmentCredential.getToken"], - ); + await expect(async (tracingOptions) => { + // The following environment variables must be set for this to work. + // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. + process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; + process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; + process.env.AZURE_CLIENT_CERTIFICATE_PATH = + cachedValues.AZURE_CLIENT_CERTIFICATE_PATH || "assets/fake-cert.pem"; + const credential = new EnvironmentCredential(recorder.configureClientOptions({})); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["EnvironmentCredential.getToken"]); }); it("supports tracing with environment username/password", async () => { - await assert.supportsTracing( - async (tracingOptions) => { - // The following environment variables must be set for this to work. - // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. - process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; - process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; - process.env.AZURE_USERNAME = "user"; - process.env.AZURE_PASSWORD = "password"; - - const credential = new EnvironmentCredential(recorder.configureClientOptions({})); - - try { - await credential.getToken(scope, tracingOptions); - } catch (e: any) { - // To avoid having to store passwords anywhere, this getToken request will fail. - // We will focus our test on making sure the underlying getToken was called. - } - }, - ["EnvironmentCredential.getToken"], - ); + await expect(async (tracingOptions) => { + // The following environment variables must be set for this to work. + // On TEST_MODE="playback", the recorder automatically fills them with stubbed values. + process.env.AZURE_TENANT_ID = cachedValues.AZURE_TENANT_ID; + process.env.AZURE_CLIENT_ID = cachedValues.AZURE_CLIENT_ID; + process.env.AZURE_USERNAME = "user"; + process.env.AZURE_PASSWORD = "password"; + const credential = new EnvironmentCredential(recorder.configureClientOptions({})); + try { + await credential.getToken(scope, tracingOptions); + } catch (e: any) { + // To avoid having to store passwords anywhere, this getToken request will fail. + // We will focus our test on making sure the underlying getToken was called. + } + }).toSupportTracing(["EnvironmentCredential.getToken"]); }); it("throws an CredentialUnavailable when getToken is called and no credential was configured", async () => { diff --git a/sdk/identity/identity/test/public/node/extensions.spec.ts b/sdk/identity/identity/test/public/node/extensions.spec.ts index 29d84d7c44c6..031223ffa1ed 100644 --- a/sdk/identity/identity/test/public/node/extensions.spec.ts +++ b/sdk/identity/identity/test/public/node/extensions.spec.ts @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -import { AssertionError, assert } from "chai"; -import { DeviceCodeCredential } from "../../../src"; -import { VisualStudioCodeCredential } from "../../../src"; +import { DeviceCodeCredential } from "../../../src/index.js"; +import { VisualStudioCodeCredential } from "../../../src/index.js"; +import { describe, it, assert } from "vitest"; /** * A helper to assert that a Promise rejects. diff --git a/sdk/identity/identity/test/public/node/multiTenantAuthentication.spec.ts b/sdk/identity/identity/test/public/node/multiTenantAuthentication.spec.ts index 548b8ecfcf3d..091a13d37be1 100644 --- a/sdk/identity/identity/test/public/node/multiTenantAuthentication.spec.ts +++ b/sdk/identity/identity/test/public/node/multiTenantAuthentication.spec.ts @@ -1,22 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline"; -import { ClientSecretCredential } from "../../../src/credentials/clientSecretCredential"; -import type { Context } from "mocha"; -import { IdentityClient } from "../../../src/client/identityClient"; -import { assert } from "@azure-tools/test-utils"; +import { ClientSecretCredential } from "../../../src/credentials/clientSecretCredential.js"; +import { IdentityClient } from "../../../src/client/identityClient.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("MultiTenantAuthentication", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); @@ -35,7 +34,7 @@ describe("MultiTenantAuthentication", function () { if (!tenantId || !clientId || !clientSecret) { // multi-tenant credentials live in a shared keyvault whose values are mounted in CI, but not in local dev console.log("Multi-tenant credentials not provided, skipping test"); - this.skip(); + ctx.skip(); } const credential = new ClientSecretCredential( diff --git a/sdk/identity/identity/test/public/node/tokenProvider.spec.ts b/sdk/identity/identity/test/public/node/tokenProvider.spec.ts index 8350595b0f48..abbf2716e0da 100644 --- a/sdk/identity/identity/test/public/node/tokenProvider.spec.ts +++ b/sdk/identity/identity/test/public/node/tokenProvider.spec.ts @@ -1,18 +1,20 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { getBearerTokenProvider, TokenCredential } from "../../../src"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import { TokenCredential, getBearerTokenProvider } from "../../../src/index.js"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; +import type { Recorder } from "@azure-tools/test-recorder"; import { delay, isPlaybackMode } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe("getBearerTokenProvider", function () { + let recorder: Recorder; let cleanup: MsalTestCleanup; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); + recorder = setup.recorder; cleanup = setup.cleanup; }); afterEach(async function () { diff --git a/sdk/identity/identity/test/public/node/usernamePasswordCredential.spec.ts b/sdk/identity/identity/test/public/node/usernamePasswordCredential.spec.ts index 33f904a8cea1..6b9185d8aea0 100644 --- a/sdk/identity/identity/test/public/node/usernamePasswordCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/usernamePasswordCredential.spec.ts @@ -3,22 +3,23 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { delay } from "@azure-tools/test-recorder"; +import { UsernamePasswordCredential } from "../../../src/index.js"; +import { getUsernamePasswordStaticResources } from "../../msalTestUtils.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; +import { toSupportTracing } from "@azure-tools/test-utils-vitest"; -import type { Context } from "mocha"; -import { UsernamePasswordCredential } from "../../../src"; -import { assert } from "@azure-tools/test-utils"; -import { getUsernamePasswordStaticResources } from "../../msalTestUtils"; +expect.extend({ toSupportTracing }); describe("UsernamePasswordCredential", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; }); @@ -28,7 +29,7 @@ describe("UsernamePasswordCredential", function () { const scope = "https://vault.azure.net/.default"; - it("authenticates", async function (this: Context) { + it("authenticates", async function (ctx) { const { tenantId, clientId, username, password } = getUsernamePasswordStaticResources(); const credential = new UsernamePasswordCredential( @@ -75,22 +76,18 @@ describe("UsernamePasswordCredential", function () { assert.ok(error?.message.includes("endpoints_resolution_error")); }); - it("supports tracing", async function (this: Context) { + it("supports tracing", async function (ctx) { const { clientId, tenantId, username, password } = getUsernamePasswordStaticResources(); - await assert.supportsTracing( - async (tracingOptions) => { - const credential = new UsernamePasswordCredential( - tenantId, - clientId, - username, - password, - recorder.configureClientOptions({}), - ); - - await credential.getToken(scope, tracingOptions); - }, - ["UsernamePasswordCredential.getToken"], - ); + await expect(async (tracingOptions) => { + const credential = new UsernamePasswordCredential( + tenantId, + clientId, + username, + password, + recorder.configureClientOptions({}), + ); + await credential.getToken(scope, tracingOptions); + }).toSupportTracing(["UsernamePasswordCredential.getToken"]); }); }); diff --git a/sdk/identity/identity/test/public/node/utils/utils.ts b/sdk/identity/identity/test/public/node/utils/utils.ts index d6180710580a..97407fbbed72 100644 --- a/sdk/identity/identity/test/public/node/utils/utils.ts +++ b/sdk/identity/identity/test/public/node/utils/utils.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as fs from "fs"; -import * as net from "net"; -import * as tls from "tls"; +import * as fs from "node:fs"; +import * as net from "node:net"; +import * as tls from "node:tls"; import jwt from "jsonwebtoken"; import ms from "ms"; diff --git a/sdk/identity/identity/test/public/node/workloadIdentityCredential.spec.ts b/sdk/identity/identity/test/public/node/workloadIdentityCredential.spec.ts index 6317a5460403..38faca72b928 100644 --- a/sdk/identity/identity/test/public/node/workloadIdentityCredential.spec.ts +++ b/sdk/identity/identity/test/public/node/workloadIdentityCredential.spec.ts @@ -3,29 +3,28 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import path, { join } from "path"; -import { tmpdir } from "os"; -import type { MsalTestCleanup } from "../../node/msalNodeTestSetup"; -import { msalNodeTestSetup } from "../../node/msalNodeTestSetup"; +import path, { join } from "node:path"; +import { tmpdir } from "node:os"; +import type { MsalTestCleanup } from "../../node/msalNodeTestSetup.js"; +import { msalNodeTestSetup } from "../../node/msalNodeTestSetup.js"; import type { Recorder } from "@azure-tools/test-recorder"; import { env } from "@azure-tools/test-recorder"; -import type { Context } from "mocha"; -import { assert } from "@azure-tools/test-utils"; -import { createJWTTokenFromCertificate } from "./utils/utils"; -import { mkdtempSync, rmdirSync, unlinkSync, writeFileSync } from "fs"; -import type { WorkloadIdentityCredentialOptions } from "../../../src"; +import { createJWTTokenFromCertificate } from "./utils/utils.js"; +import { mkdtempSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs"; +import type { WorkloadIdentityCredentialOptions } from "../../../src/index.js"; import { DefaultAzureCredential, ManagedIdentityCredential, WorkloadIdentityCredential, -} from "../../../src"; +} from "../../../src/index.js"; +import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest"; describe.skip("WorkloadIdentityCredential", function () { let cleanup: MsalTestCleanup; let recorder: Recorder; - beforeEach(async function (this: Context) { - const setup = await msalNodeTestSetup(this.currentTest); + beforeEach(async function (ctx) { + const setup = await msalNodeTestSetup(ctx); cleanup = setup.cleanup; recorder = setup.recorder; await recorder.setMatcher("BodilessMatcher"); @@ -45,7 +44,7 @@ describe.skip("WorkloadIdentityCredential", function () { return jwtoken; } - it("authenticates with WorkloadIdentity Credential", async function (this: Context) { + it("authenticates with WorkloadIdentity Credential", async function (ctx) { const fileDir = await setupFileandEnv("workload-identity"); const credential = new WorkloadIdentityCredential( recorder.configureClientOptions({ @@ -64,7 +63,7 @@ describe.skip("WorkloadIdentityCredential", function () { } }); - it("authenticates with ManagedIdentity Credential", async function (this: Context) { + it("authenticates with ManagedIdentity Credential", async function (ctx) { const fileDir = await setupFileandEnv("token-exchange-msi"); const credential = new ManagedIdentityCredential(clientId, recorder.configureClientOptions({})); try { @@ -77,7 +76,7 @@ describe.skip("WorkloadIdentityCredential", function () { } }); - it("authenticates with DefaultAzure Credential", async function (this: Context) { + it("authenticates with DefaultAzure Credential", async function (ctx) { const fileDir = await setupFileandEnv("token-exchange-msi"); const credential = new DefaultAzureCredential(recorder.configureClientOptions({})); try { @@ -91,7 +90,7 @@ describe.skip("WorkloadIdentityCredential", function () { rmdirSync(fileDir.tempDir); } }); - it("authenticates with DefaultAzure Credential and client ID", async function (this: Context) { + it("authenticates with DefaultAzure Credential and client ID", async function (ctx) { const fileDir = await setupFileandEnv("token-exchange-msi"); const credential = new DefaultAzureCredential( recorder.configureClientOptions({ diff --git a/sdk/identity/identity/test/snippets.spec.ts b/sdk/identity/identity/test/snippets.spec.ts index 1e012a5dedab..e1c750efd136 100644 --- a/sdk/identity/identity/test/snippets.spec.ts +++ b/sdk/identity/identity/test/snippets.spec.ts @@ -12,10 +12,11 @@ import { InteractiveBrowserCredential, OnBehalfOfCredential, useIdentityPlugin, -} from "@azure/identity"; +} from "../src/index.js"; import { KeyClient } from "@azure/keyvault-keys"; import { setLogLevel } from "@azure/logger"; import dotenv from "dotenv"; +import { describe, it } from "vitest"; describe("snippets", function () { it("defaultazurecredential_authenticate", function () { diff --git a/sdk/identity/identity/tsconfig.browser.config.json b/sdk/identity/identity/tsconfig.browser.config.json new file mode 100644 index 000000000000..f772e6eb3b76 --- /dev/null +++ b/sdk/identity/identity/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/identity/identity/tsconfig.json b/sdk/identity/identity/tsconfig.json index 7a75336900d5..07611f0f76a1 100644 --- a/sdk/identity/identity/tsconfig.json +++ b/sdk/identity/identity/tsconfig.json @@ -2,13 +2,22 @@ "extends": "../../../tsconfig", "compilerOptions": { "lib": ["DOM"], - "declarationDir": "./types", - "outDir": "./dist-esm", "resolveJsonModule": true, "paths": { "@azure/identity": ["./src/index"] - } + }, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "." }, - "include": ["src/**/*", "test/**/*", "samples-dev/**/*.ts"], + "include": [ + "src/**/*.ts", + "src/**/*.mts", + "src/**/*.cts", + "samples-dev/**/*.ts", + "test/**/*.ts", + "test/**/*.mts", + "test/**/*.cts" + ], "exclude": ["test/manual*/**/*", "integration/**", "node_modules"] } diff --git a/sdk/identity/identity/vitest.browser.config.ts b/sdk/identity/identity/vitest.browser.config.ts new file mode 100644 index 000000000000..304ad6de01f5 --- /dev/null +++ b/sdk/identity/identity/vitest.browser.config.ts @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig, mergeConfig } from "vitest/config"; +import viteConfig from "../../../vitest.browser.shared.config.ts"; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + include: ["dist-test/browser/test/**/*.spec.js"], + exclude: ["dist-test/browser/test/snippets.spec.js"], + }, + }), +); diff --git a/sdk/identity/identity/vitest.config.ts b/sdk/identity/identity/vitest.config.ts new file mode 100644 index 000000000000..cf36d0cf28a7 --- /dev/null +++ b/sdk/identity/identity/vitest.config.ts @@ -0,0 +1,19 @@ +// 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"], + exclude: [ + "test/**/browser/**/*.spec.ts", + "test/snippets.spec.ts", + "test/integration/**/*.spec.ts", + ], + }, + }), +); diff --git a/sdk/instrumentation/opentelemetry-instrumentation-azure-sdk/package.json b/sdk/instrumentation/opentelemetry-instrumentation-azure-sdk/package.json index f3853802e88f..e952c2d52083 100644 --- a/sdk/instrumentation/opentelemetry-instrumentation-azure-sdk/package.json +++ b/sdk/instrumentation/opentelemetry-instrumentation-azure-sdk/package.json @@ -43,8 +43,6 @@ }, "files": [ "dist/", - "dist-esm/src/", - "types/latest/", "README.md", "LICENSE" ], diff --git a/sdk/maps/maps-geolocation-rest/CHANGELOG.md b/sdk/maps/maps-geolocation-rest/CHANGELOG.md index ce08aa382e4f..85a720b4323d 100644 --- a/sdk/maps/maps-geolocation-rest/CHANGELOG.md +++ b/sdk/maps/maps-geolocation-rest/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +- Marked fields in various interfaces as readonly, which may impact code that previously modified these properties. + ### Bugs Fixed - Fix the Microsoft Entra ID authentication when providing `baseUrl`. diff --git a/sdk/maps/maps-geolocation-rest/src/generated/clientDefinitions.ts b/sdk/maps/maps-geolocation-rest/generated/clientDefinitions.ts similarity index 63% rename from sdk/maps/maps-geolocation-rest/src/generated/clientDefinitions.ts rename to sdk/maps/maps-geolocation-rest/generated/clientDefinitions.ts index 941fade9c67e..e95e57e86f55 100644 --- a/sdk/maps/maps-geolocation-rest/src/generated/clientDefinitions.ts +++ b/sdk/maps/maps-geolocation-rest/generated/clientDefinitions.ts @@ -4,19 +4,17 @@ import { GeolocationGetLocationParameters } from "./parameters"; import { GeolocationGetLocation200Response, - GeolocationGetLocationDefaultResponse + GeolocationGetLocationDefaultResponse, } from "./responses"; import { Client, StreamableMethod } from "@azure-rest/core-client"; export interface GetLocation { /** - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). * - * - * This service will return the ISO country code for the provided IP address. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. + * The `Get IP To Location` API is an HTTP `GET` request that, given an IP address, returns the ISO country code from which that IP address is located. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. */ get( - options: GeolocationGetLocationParameters + options: GeolocationGetLocationParameters, ): StreamableMethod< GeolocationGetLocation200Response | GeolocationGetLocationDefaultResponse >; diff --git a/sdk/maps/maps-geolocation-rest/src/generated/index.ts b/sdk/maps/maps-geolocation-rest/generated/index.ts similarity index 100% rename from sdk/maps/maps-geolocation-rest/src/generated/index.ts rename to sdk/maps/maps-geolocation-rest/generated/index.ts diff --git a/sdk/maps/maps-geolocation-rest/generated/isUnexpected.ts b/sdk/maps/maps-geolocation-rest/generated/isUnexpected.ts new file mode 100644 index 000000000000..1b0e6578d1a0 --- /dev/null +++ b/sdk/maps/maps-geolocation-rest/generated/isUnexpected.ts @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + GeolocationGetLocation200Response, + GeolocationGetLocationDefaultResponse, +} from "./responses"; + +const responseMap: Record = { + "GET /geolocation/ip/{format}": ["200"], +}; + +export function isUnexpected( + response: + | GeolocationGetLocation200Response + | GeolocationGetLocationDefaultResponse, +): response is GeolocationGetLocationDefaultResponse; +export function isUnexpected( + response: + | GeolocationGetLocation200Response + | GeolocationGetLocationDefaultResponse, +): response is GeolocationGetLocationDefaultResponse { + const lroOriginal = response.headers["x-ms-original-url"]; + const url = new URL(lroOriginal ?? response.request.url); + const method = response.request.method; + let pathDetails = responseMap[`${method} ${url.pathname}`]; + if (!pathDetails) { + pathDetails = getParametrizedPathSuccess(method, url.pathname); + } + return !pathDetails.includes(response.status); +} + +function getParametrizedPathSuccess(method: string, path: string): string[] { + const pathParts = path.split("/"); + + // Traverse list to match the longest candidate + // matchedLen: the length of candidate path + // matchedValue: the matched status code array + let matchedLen = -1, + matchedValue: string[] = []; + + // Iterate the responseMap to find a match + for (const [key, value] of Object.entries(responseMap)) { + // Extracting the path from the map key which is in format + // GET /path/foo + if (!key.startsWith(method)) { + continue; + } + const candidatePath = getPathFromMapKey(key); + // Get each part of the url path + const candidateParts = candidatePath.split("/"); + + // track if we have found a match to return the values found. + let found = true; + for ( + let i = candidateParts.length - 1, j = pathParts.length - 1; + i >= 1 && j >= 1; + i--, j-- + ) { + if ( + candidateParts[i]?.startsWith("{") && + candidateParts[i]?.indexOf("}") !== -1 + ) { + const start = candidateParts[i]!.indexOf("}") + 1, + end = candidateParts[i]?.length; + // If the current part of the candidate is a "template" part + // Try to use the suffix of pattern to match the path + // {guid} ==> $ + // {guid}:export ==> :export$ + const isMatched = new RegExp( + `${candidateParts[i]?.slice(start, end)}`, + ).test(pathParts[j] || ""); + + if (!isMatched) { + found = false; + break; + } + continue; + } + + // If the candidate part is not a template and + // the parts don't match mark the candidate as not found + // to move on with the next candidate path. + if (candidateParts[i] !== pathParts[j]) { + found = false; + break; + } + } + + // We finished evaluating the current candidate parts + // Update the matched value if and only if we found the longer pattern + if (found && candidatePath.length > matchedLen) { + matchedLen = candidatePath.length; + matchedValue = value; + } + } + + return matchedValue; +} + +function getPathFromMapKey(mapKey: string): string { + const pathStart = mapKey.indexOf("/"); + return mapKey.slice(pathStart); +} diff --git a/sdk/maps/maps-geolocation-rest/generated/logger.ts b/sdk/maps/maps-geolocation-rest/generated/logger.ts new file mode 100644 index 000000000000..01e1238b373b --- /dev/null +++ b/sdk/maps/maps-geolocation-rest/generated/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("maps-geolocation"); diff --git a/sdk/maps/maps-geolocation-rest/generated/mapsGeolocationClient.ts b/sdk/maps/maps-geolocation-rest/generated/mapsGeolocationClient.ts new file mode 100644 index 000000000000..f3332c57a116 --- /dev/null +++ b/sdk/maps/maps-geolocation-rest/generated/mapsGeolocationClient.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { getClient, ClientOptions } from "@azure-rest/core-client"; +import { logger } from "./logger"; +import { KeyCredential } from "@azure/core-auth"; +import { MapsGeolocationClient } from "./clientDefinitions"; + +/** The optional parameters for the client */ +export interface MapsGeolocationClientOptions extends ClientOptions { + /** The api version option of the client */ + apiVersion?: string; +} + +/** + * Initialize a new instance of `MapsGeolocationClient` + * @param credentials - uniquely identify client credential + * @param options - the parameter for all optional parameters + */ +export default function createClient( + credentials: KeyCredential, + { apiVersion = "1.0", ...options }: MapsGeolocationClientOptions = {}, +): MapsGeolocationClient { + const endpointUrl = + options.endpoint ?? options.baseUrl ?? `https://atlas.microsoft.com`; + const userAgentInfo = `azsdk-js-maps-geolocation-rest/1.0.0-beta.4`; + const userAgentPrefix = + options.userAgentOptions && options.userAgentOptions.userAgentPrefix + ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` + : `${userAgentInfo}`; + options = { + ...options, + userAgentOptions: { + userAgentPrefix, + }, + loggingOptions: { + logger: options.loggingOptions?.logger ?? logger.info, + }, + credentials: { + apiKeyHeaderName: + options.credentials?.apiKeyHeaderName ?? "subscription-key", + }, + }; + const client = getClient( + endpointUrl, + credentials, + options, + ) as MapsGeolocationClient; + + client.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + client.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version") && apiVersion) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } + + return next(req); + }, + }); + + return client; +} diff --git a/sdk/maps/maps-geolocation-rest/src/generated/outputModels.ts b/sdk/maps/maps-geolocation-rest/generated/outputModels.ts similarity index 77% rename from sdk/maps/maps-geolocation-rest/src/generated/outputModels.ts rename to sdk/maps/maps-geolocation-rest/generated/outputModels.ts index e2f1bd507fd0..6287d13f9919 100644 --- a/sdk/maps/maps-geolocation-rest/src/generated/outputModels.ts +++ b/sdk/maps/maps-geolocation-rest/generated/outputModels.ts @@ -4,15 +4,15 @@ /** This object is returned from a successful call to IP Address to country/region API */ export interface IpAddressToLocationResultOutput { /** The object containing the country/region information. */ - countryRegion?: CountryRegionOutput; + readonly countryRegion?: CountryRegionOutput; /** The IP Address of the request. */ - ipAddress?: string; + readonly ipAddress?: string; } /** The object containing the country/region information. */ export interface CountryRegionOutput { /** The IP Address's 2-character code [(ISO 3166-1)](https://www.iso.org/iso-3166-country-codes.html) of the country or region. Please note, IP address in ranges reserved for special purpose will return Null for country/region. */ - isoCode?: string; + readonly isoCode?: string; } /** Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.). */ @@ -24,21 +24,21 @@ export interface ErrorResponseOutput { /** The error detail. */ export interface ErrorDetailOutput { /** The error code. */ - code?: string; + readonly code?: string; /** The error message. */ - message?: string; + readonly message?: string; /** The error target. */ - target?: string; + readonly target?: string; /** The error details. */ - details?: Array; + readonly details?: Array; /** The error additional info. */ - additionalInfo?: Array; + readonly additionalInfo?: Array; } /** The resource management error additional info. */ export interface ErrorAdditionalInfoOutput { /** The additional info type. */ - type?: string; + readonly type?: string; /** The additional info. */ - info?: Record; + readonly info?: Record; } diff --git a/sdk/maps/maps-geolocation-rest/src/generated/parameters.ts b/sdk/maps/maps-geolocation-rest/generated/parameters.ts similarity index 79% rename from sdk/maps/maps-geolocation-rest/src/generated/parameters.ts rename to sdk/maps/maps-geolocation-rest/generated/parameters.ts index 73f63a2842b1..61bbbc038b5d 100644 --- a/sdk/maps/maps-geolocation-rest/src/generated/parameters.ts +++ b/sdk/maps/maps-geolocation-rest/generated/parameters.ts @@ -12,5 +12,5 @@ export interface GeolocationGetLocationQueryParam { queryParameters: GeolocationGetLocationQueryParamProperties; } -export type GeolocationGetLocationParameters = GeolocationGetLocationQueryParam & - RequestParameters; +export type GeolocationGetLocationParameters = + GeolocationGetLocationQueryParam & RequestParameters; diff --git a/sdk/maps/maps-geolocation-rest/generated/responses.ts b/sdk/maps/maps-geolocation-rest/generated/responses.ts new file mode 100644 index 000000000000..74ca486501af --- /dev/null +++ b/sdk/maps/maps-geolocation-rest/generated/responses.ts @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { HttpResponse } from "@azure-rest/core-client"; +import { + IpAddressToLocationResultOutput, + ErrorResponseOutput, +} from "./outputModels"; + +/** + * + * The `Get IP To Location` API is an HTTP `GET` request that, given an IP address, returns the ISO country code from which that IP address is located. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. + */ +export interface GeolocationGetLocation200Response extends HttpResponse { + status: "200"; + body: IpAddressToLocationResultOutput; +} + +/** + * + * The `Get IP To Location` API is an HTTP `GET` request that, given an IP address, returns the ISO country code from which that IP address is located. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. + */ +export interface GeolocationGetLocationDefaultResponse extends HttpResponse { + status: string; + body: ErrorResponseOutput; +} diff --git a/sdk/maps/maps-geolocation-rest/package.json b/sdk/maps/maps-geolocation-rest/package.json index 29b8cc19ef6b..fe07781f5934 100644 --- a/sdk/maps/maps-geolocation-rest/package.json +++ b/sdk/maps/maps-geolocation-rest/package.json @@ -65,6 +65,7 @@ "@azure/core-auth": "^1.3.0", "@azure/core-rest-pipeline": "^1.8.0", "@azure/maps-common": "1.0.0-beta.2", + "@azure/logger": "^1.0.0", "tslib": "^2.2.0" }, "devDependencies": { diff --git a/sdk/maps/maps-geolocation-rest/review/maps-geolocation.api.md b/sdk/maps/maps-geolocation-rest/review/maps-geolocation.api.md index 4892bbc5a5d4..4eaaac736a6d 100644 --- a/sdk/maps/maps-geolocation-rest/review/maps-geolocation.api.md +++ b/sdk/maps/maps-geolocation-rest/review/maps-geolocation.api.md @@ -7,7 +7,7 @@ import type { AzureKeyCredential } from '@azure/core-auth'; import type { AzureSASCredential } from '@azure/core-auth'; import { Client } from '@azure-rest/core-client'; -import type { ClientOptions } from '@azure-rest/core-client'; +import { ClientOptions } from '@azure-rest/core-client'; import { HttpResponse } from '@azure-rest/core-client'; import { RequestParameters } from '@azure-rest/core-client'; import { StreamableMethod } from '@azure-rest/core-client'; @@ -15,22 +15,22 @@ import type { TokenCredential } from '@azure/core-auth'; // @public export interface CountryRegionOutput { - isoCode?: string; + readonly isoCode?: string; } // @public export interface ErrorAdditionalInfoOutput { - info?: Record; - type?: string; + readonly info?: Record; + readonly type?: string; } // @public export interface ErrorDetailOutput { - additionalInfo?: Array; - code?: string; - details?: Array; - message?: string; - target?: string; + readonly additionalInfo?: Array; + readonly code?: string; + readonly details?: Array; + readonly message?: string; + readonly target?: string; } // @public @@ -75,8 +75,8 @@ export interface GetLocation { // @public export interface IpAddressToLocationResultOutput { - countryRegion?: CountryRegionOutput; - ipAddress?: string; + readonly countryRegion?: CountryRegionOutput; + readonly ipAddress?: string; } // @public (undocumented) @@ -97,6 +97,11 @@ export type MapsGeolocationClient = Client & { path: Routes; }; +// @public +export interface MapsGeolocationClientOptions extends ClientOptions { + apiVersion?: string; +} + // @public (undocumented) export interface Routes { (path: "/geolocation/ip/{format}", format: "json"): GetLocation; diff --git a/sdk/maps/maps-geolocation-rest/src/MapsGeolocation.ts b/sdk/maps/maps-geolocation-rest/src/MapsGeolocation.ts index bab0f4a5ff8a..16d7a040d7c8 100644 --- a/sdk/maps/maps-geolocation-rest/src/MapsGeolocation.ts +++ b/sdk/maps/maps-geolocation-rest/src/MapsGeolocation.ts @@ -5,8 +5,8 @@ import type { ClientOptions } from "@azure-rest/core-client"; import type { AzureKeyCredential, AzureSASCredential, TokenCredential } from "@azure/core-auth"; import { isSASCredential, isTokenCredential } from "@azure/core-auth"; import { createMapsClientIdPolicy } from "@azure/maps-common"; -import type { MapsGeolocationClient } from "./generated"; -import createClient from "./generated"; +import type { MapsGeolocationClient } from "../generated"; +import createClient from "../generated"; import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline"; /** diff --git a/sdk/maps/maps-geolocation-rest/src/generated/isUnexpected.ts b/sdk/maps/maps-geolocation-rest/src/generated/isUnexpected.ts deleted file mode 100644 index e7c6416a23c4..000000000000 --- a/sdk/maps/maps-geolocation-rest/src/generated/isUnexpected.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { - GeolocationGetLocation200Response, - GeolocationGetLocationDefaultResponse -} from "./responses"; - -const responseMap: Record = { - "GET /geolocation/ip/{format}": ["200"] -}; - -export function isUnexpected( - response: - | GeolocationGetLocation200Response - | GeolocationGetLocationDefaultResponse -): response is GeolocationGetLocationDefaultResponse; -export function isUnexpected( - response: - | GeolocationGetLocation200Response - | GeolocationGetLocationDefaultResponse -): response is GeolocationGetLocationDefaultResponse { - const lroOriginal = response.headers["x-ms-original-url"]; - const url = new URL(lroOriginal ?? response.request.url); - const method = response.request.method; - let pathDetails = responseMap[`${method} ${url.pathname}`]; - if (!pathDetails) { - pathDetails = geParametrizedPathSuccess(method, url.pathname); - } - return !pathDetails.includes(response.status); -} - -function geParametrizedPathSuccess(method: string, path: string): string[] { - const pathParts = path.split("/"); - - // Iterate the responseMap to find a match - for (const [key, value] of Object.entries(responseMap)) { - // Extracting the path from the map key which is in format - // GET /path/foo - if (!key.startsWith(method)) { - continue; - } - const candidatePath = getPathFromMapKey(key); - // Get each part of the url path - const candidateParts = candidatePath.split("/"); - - // If the candidate and actual paths don't match in size - // we move on to the next candidate path - if ( - candidateParts.length === pathParts.length && - hasParametrizedPath(key) - ) { - // track if we have found a match to return the values found. - let found = true; - for (let i = 0; i < candidateParts.length; i++) { - if ( - candidateParts[i]?.startsWith("{") && - candidateParts[i]?.endsWith("}") - ) { - // If the current part of the candidate is a "template" part - // it is a match with the actual path part on hand - // skip as the parameterized part can match anything - continue; - } - - // If the candidate part is not a template and - // the parts don't match mark the candidate as not found - // to move on with the next candidate path. - if (candidateParts[i] !== pathParts[i]) { - found = false; - break; - } - } - - // We finished evaluating the current candidate parts - // if all parts matched we return the success values form - // the path mapping. - if (found) { - return value; - } - } - } - - // No match was found, return an empty array. - return []; -} - -function hasParametrizedPath(path: string): boolean { - return path.includes("/{"); -} - -function getPathFromMapKey(mapKey: string): string { - const pathStart = mapKey.indexOf("/"); - return mapKey.slice(pathStart); -} diff --git a/sdk/maps/maps-geolocation-rest/src/generated/mapsGeolocationClient.ts b/sdk/maps/maps-geolocation-rest/src/generated/mapsGeolocationClient.ts deleted file mode 100644 index ed2923494182..000000000000 --- a/sdk/maps/maps-geolocation-rest/src/generated/mapsGeolocationClient.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { getClient, ClientOptions } from "@azure-rest/core-client"; -import { KeyCredential } from "@azure/core-auth"; -import { MapsGeolocationClient } from "./clientDefinitions"; - -/** - * Initialize a new instance of the class MapsGeolocationClient class. - * @param credentials type: KeyCredential - */ -export default function createClient( - credentials: KeyCredential, - options: ClientOptions = {} -): MapsGeolocationClient { - const baseUrl = options.baseUrl ?? `https://atlas.microsoft.com`; - options.apiVersion = options.apiVersion ?? "1.0"; - options = { - ...options, - credentials: { - apiKeyHeaderName: "subscription-key" - } - }; - - const userAgentInfo = `azsdk-js-maps-geolocation-rest/1.0.0-beta.1`; - const userAgentPrefix = - options.userAgentOptions && options.userAgentOptions.userAgentPrefix - ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` - : `${userAgentInfo}`; - options = { - ...options, - userAgentOptions: { - userAgentPrefix - } - }; - - const client = getClient( - baseUrl, - credentials, - options - ) as MapsGeolocationClient; - - return client; -} diff --git a/sdk/maps/maps-geolocation-rest/src/generated/responses.ts b/sdk/maps/maps-geolocation-rest/src/generated/responses.ts deleted file mode 100644 index 9601c31fda8e..000000000000 --- a/sdk/maps/maps-geolocation-rest/src/generated/responses.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { HttpResponse } from "@azure-rest/core-client"; -import { - IpAddressToLocationResultOutput, - ErrorResponseOutput -} from "./outputModels"; - -/** - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * - * This service will return the ISO country code for the provided IP address. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. - */ -export interface GeolocationGetLocation200Response extends HttpResponse { - status: "200"; - body: IpAddressToLocationResultOutput; -} - -/** - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * - * This service will return the ISO country code for the provided IP address. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. - */ -export interface GeolocationGetLocationDefaultResponse extends HttpResponse { - status: string; - body: ErrorResponseOutput; -} diff --git a/sdk/maps/maps-geolocation-rest/src/index.ts b/sdk/maps/maps-geolocation-rest/src/index.ts index 8a198cf14916..ffddb554ecf2 100644 --- a/sdk/maps/maps-geolocation-rest/src/index.ts +++ b/sdk/maps/maps-geolocation-rest/src/index.ts @@ -3,5 +3,5 @@ import MapsGeolocation from "./MapsGeolocation"; -export * from "./generated"; +export * from "../generated"; export default MapsGeolocation; diff --git a/sdk/maps/maps-geolocation-rest/swagger/README.md b/sdk/maps/maps-geolocation-rest/swagger/README.md index ead459f51f2f..7e42ffc835e1 100644 --- a/sdk/maps/maps-geolocation-rest/swagger/README.md +++ b/sdk/maps/maps-geolocation-rest/swagger/README.md @@ -8,6 +8,8 @@ The configuration is following the [RLC quick start guide](https://github.com/Az For the configuration property, please refer to [Index of AutoRestFlag](https://github.com/Azure/autorest/blob/main/docs/generate/flags.md). ```yaml +flavor: azure +openapi-type: data-plane package-name: "@azure-rest/maps-geolocation" title: MapsGeolocationClient description: Azure Maps Geolocation Client @@ -23,7 +25,7 @@ generate-test: false generate-sample: false license-header: MICROSOFT_MIT_NO_VERSION output-folder: ../ -source-code-folder-path: ./src/generated +source-code-folder-path: ./generated input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/maps/data-plane/Geolocation/preview/1.0/geolocation.json package-version: 1.0.0-beta.4 rest-level-client: true @@ -32,7 +34,7 @@ rest-level-client: true security: AzureKey security-header-name: subscription-key use-extension: - "@autorest/typescript": "6.0.0-rc.3" + "@autorest/typescript": "latest" ``` ## Customization for Track 2 Generator diff --git a/sdk/maps/maps-render-rest/CHANGELOG.md b/sdk/maps/maps-render-rest/CHANGELOG.md index 5a389b9cd71b..127eb1ad8cdd 100644 --- a/sdk/maps/maps-render-rest/CHANGELOG.md +++ b/sdk/maps/maps-render-rest/CHANGELOG.md @@ -10,6 +10,7 @@ - The API endpoint for `GetMapStaticImage` has been updated. The `format` parameter has been removed from the path, changing the usage from `(path: "/map/static/{format}", format: "png")` to `(path: "/map/static")`. - Replaced `layer` and `style` parameters with `tilesetId` in `RenderGetMapStaticImageQueryParamProperties`, which now supports more detailed map and traffic visualization. +- Marked fields in various interfaces as readonly, which may impact code that previously modified these properties. ### Bugs Fixed diff --git a/sdk/maps/maps-render-rest/src/generated/clientDefinitions.ts b/sdk/maps/maps-render-rest/generated/clientDefinitions.ts similarity index 93% rename from sdk/maps/maps-render-rest/src/generated/clientDefinitions.ts rename to sdk/maps/maps-render-rest/generated/clientDefinitions.ts index abe0533cbec6..b30d34a59ec4 100644 --- a/sdk/maps/maps-render-rest/src/generated/clientDefinitions.ts +++ b/sdk/maps/maps-render-rest/generated/clientDefinitions.ts @@ -10,7 +10,7 @@ import { RenderGetMapStaticImageParameters, RenderGetCopyrightFromBoundingBoxParameters, RenderGetCopyrightForTileParameters, - RenderGetCopyrightForWorldParameters + RenderGetCopyrightForWorldParameters, } from "./parameters"; import { RenderGetMapTile200Response, @@ -30,7 +30,7 @@ import { RenderGetCopyrightForTile200Response, RenderGetCopyrightForTileDefaultResponse, RenderGetCopyrightForWorld200Response, - RenderGetCopyrightForWorldDefaultResponse + RenderGetCopyrightForWorldDefaultResponse, } from "./responses"; import { Client, StreamableMethod } from "@azure-rest/core-client"; @@ -40,7 +40,7 @@ export interface GetMapTile { * The `Get Map Tiles` API in an HTTP GET request that allows users to request map tiles in vector or raster formats typically to be integrated into a map control or SDK. Some example tiles that can be requested are Azure Maps road tiles, real-time Weather Radar tiles or the map tiles created using [Azure Maps Creator](https://aka.ms/amcreator). By default, Azure Maps uses vector tiles for its web map control ([Web SDK](/azure/azure-maps/about-azure-maps#web-sdk)) and [Android SDK](/azure/azure-maps/about-azure-maps#android-sdk). */ get( - options: RenderGetMapTileParameters + options: RenderGetMapTileParameters, ): StreamableMethod< RenderGetMapTile200Response | RenderGetMapTileDefaultResponse >; @@ -52,7 +52,7 @@ export interface GetMapTileset { * The Get Map Tileset API allows users to request metadata for a tileset. */ get( - options: RenderGetMapTilesetParameters + options: RenderGetMapTilesetParameters, ): StreamableMethod< RenderGetMapTileset200Response | RenderGetMapTilesetDefaultResponse >; @@ -64,7 +64,7 @@ export interface GetMapAttribution { * The `Get Map Attribution` API allows users to request map copyright attribution information for a section of a tileset. */ get( - options: RenderGetMapAttributionParameters + options: RenderGetMapAttributionParameters, ): StreamableMethod< RenderGetMapAttribution200Response | RenderGetMapAttributionDefaultResponse >; @@ -76,7 +76,7 @@ export interface GetMapStateTile { * Fetches state tiles in vector format typically to be integrated into indoor maps module of map control or SDK. The map control will call this API after user turns on dynamic styling. For more information, see [Zoom Levels and Tile Grid](/azure/location-based-services/zoom-levels-and-tile-grid). */ get( - options: RenderGetMapStateTileParameters + options: RenderGetMapStateTileParameters, ): StreamableMethod< RenderGetMapStateTile200Response | RenderGetMapStateTileDefaultResponse >; @@ -90,7 +90,7 @@ export interface GetCopyrightCaption { * As an alternative to copyrights for map request, it can also return captions for displaying provider information on the map. */ get( - options?: RenderGetCopyrightCaptionParameters + options?: RenderGetCopyrightCaptionParameters, ): StreamableMethod< | RenderGetCopyrightCaption200Response | RenderGetCopyrightCaptionDefaultResponse @@ -138,7 +138,7 @@ export interface GetMapStaticImage { * _Note_ : Either **center** or **bbox** parameter must be supplied to the API. */ get( - options?: RenderGetMapStaticImageParameters + options?: RenderGetMapStaticImageParameters, ): StreamableMethod< RenderGetMapStaticImage200Response | RenderGetMapStaticImageDefaultResponse >; @@ -150,7 +150,7 @@ export interface GetCopyrightFromBoundingBox { * Returns copyright information for a given bounding box. Bounding-box requests should specify the minimum and maximum longitude and latitude (EPSG-3857) coordinates */ get( - options: RenderGetCopyrightFromBoundingBoxParameters + options: RenderGetCopyrightFromBoundingBoxParameters, ): StreamableMethod< | RenderGetCopyrightFromBoundingBox200Response | RenderGetCopyrightFromBoundingBoxDefaultResponse @@ -165,7 +165,7 @@ export interface GetCopyrightForTile { * Copyrights API is designed to serve copyright information for Render service. In addition to basic copyright for the whole map, API is serving specific groups of copyrights for some countries/regions. */ get( - options: RenderGetCopyrightForTileParameters + options: RenderGetCopyrightForTileParameters, ): StreamableMethod< | RenderGetCopyrightForTile200Response | RenderGetCopyrightForTileDefaultResponse @@ -180,7 +180,7 @@ export interface GetCopyrightForWorld { * Copyrights API is designed to serve copyright information for Render service. In addition to basic copyright for the whole map, API is serving specific groups of copyrights for some countries/regions. */ get( - options?: RenderGetCopyrightForWorldParameters + options?: RenderGetCopyrightForWorldParameters, ): StreamableMethod< | RenderGetCopyrightForWorld200Response | RenderGetCopyrightForWorldDefaultResponse @@ -199,24 +199,24 @@ export interface Routes { /** Resource for '/map/copyright/caption/\{format\}' has methods for the following verbs: get */ ( path: "/map/copyright/caption/{format}", - format: "json" | "xml" + format: "json" | "xml", ): GetCopyrightCaption; /** Resource for '/map/static' has methods for the following verbs: get */ (path: "/map/static"): GetMapStaticImage; /** Resource for '/map/copyright/bounding/\{format\}' has methods for the following verbs: get */ ( path: "/map/copyright/bounding/{format}", - format: "json" | "xml" + format: "json" | "xml", ): GetCopyrightFromBoundingBox; /** Resource for '/map/copyright/tile/\{format\}' has methods for the following verbs: get */ ( path: "/map/copyright/tile/{format}", - format: "json" | "xml" + format: "json" | "xml", ): GetCopyrightForTile; /** Resource for '/map/copyright/world/\{format\}' has methods for the following verbs: get */ ( path: "/map/copyright/world/{format}", - format: "json" | "xml" + format: "json" | "xml", ): GetCopyrightForWorld; } diff --git a/sdk/maps/maps-render-rest/src/generated/index.ts b/sdk/maps/maps-render-rest/generated/index.ts similarity index 100% rename from sdk/maps/maps-render-rest/src/generated/index.ts rename to sdk/maps/maps-render-rest/generated/index.ts diff --git a/sdk/maps/maps-render-rest/src/generated/isUnexpected.ts b/sdk/maps/maps-render-rest/generated/isUnexpected.ts similarity index 67% rename from sdk/maps/maps-render-rest/src/generated/isUnexpected.ts rename to sdk/maps/maps-render-rest/generated/isUnexpected.ts index 91a126238a0f..5ecfe547c008 100644 --- a/sdk/maps/maps-render-rest/src/generated/isUnexpected.ts +++ b/sdk/maps/maps-render-rest/generated/isUnexpected.ts @@ -19,7 +19,7 @@ import { RenderGetCopyrightForTile200Response, RenderGetCopyrightForTileDefaultResponse, RenderGetCopyrightForWorld200Response, - RenderGetCopyrightForWorldDefaultResponse + RenderGetCopyrightForWorldDefaultResponse, } from "./responses"; const responseMap: Record = { @@ -31,49 +31,49 @@ const responseMap: Record = { "GET /map/static": ["200"], "GET /map/copyright/bounding/{format}": ["200"], "GET /map/copyright/tile/{format}": ["200"], - "GET /map/copyright/world/{format}": ["200"] + "GET /map/copyright/world/{format}": ["200"], }; export function isUnexpected( - response: RenderGetMapTile200Response | RenderGetMapTileDefaultResponse + response: RenderGetMapTile200Response | RenderGetMapTileDefaultResponse, ): response is RenderGetMapTileDefaultResponse; export function isUnexpected( - response: RenderGetMapTileset200Response | RenderGetMapTilesetDefaultResponse + response: RenderGetMapTileset200Response | RenderGetMapTilesetDefaultResponse, ): response is RenderGetMapTilesetDefaultResponse; export function isUnexpected( response: | RenderGetMapAttribution200Response - | RenderGetMapAttributionDefaultResponse + | RenderGetMapAttributionDefaultResponse, ): response is RenderGetMapAttributionDefaultResponse; export function isUnexpected( response: | RenderGetMapStateTile200Response - | RenderGetMapStateTileDefaultResponse + | RenderGetMapStateTileDefaultResponse, ): response is RenderGetMapStateTileDefaultResponse; export function isUnexpected( response: | RenderGetCopyrightCaption200Response - | RenderGetCopyrightCaptionDefaultResponse + | RenderGetCopyrightCaptionDefaultResponse, ): response is RenderGetCopyrightCaptionDefaultResponse; export function isUnexpected( response: | RenderGetMapStaticImage200Response - | RenderGetMapStaticImageDefaultResponse + | RenderGetMapStaticImageDefaultResponse, ): response is RenderGetMapStaticImageDefaultResponse; export function isUnexpected( response: | RenderGetCopyrightFromBoundingBox200Response - | RenderGetCopyrightFromBoundingBoxDefaultResponse + | RenderGetCopyrightFromBoundingBoxDefaultResponse, ): response is RenderGetCopyrightFromBoundingBoxDefaultResponse; export function isUnexpected( response: | RenderGetCopyrightForTile200Response - | RenderGetCopyrightForTileDefaultResponse + | RenderGetCopyrightForTileDefaultResponse, ): response is RenderGetCopyrightForTileDefaultResponse; export function isUnexpected( response: | RenderGetCopyrightForWorld200Response - | RenderGetCopyrightForWorldDefaultResponse + | RenderGetCopyrightForWorldDefaultResponse, ): response is RenderGetCopyrightForWorldDefaultResponse; export function isUnexpected( response: @@ -94,7 +94,7 @@ export function isUnexpected( | RenderGetCopyrightForTile200Response | RenderGetCopyrightForTileDefaultResponse | RenderGetCopyrightForWorld200Response - | RenderGetCopyrightForWorldDefaultResponse + | RenderGetCopyrightForWorldDefaultResponse, ): response is | RenderGetMapTileDefaultResponse | RenderGetMapTilesetDefaultResponse @@ -110,14 +110,20 @@ export function isUnexpected( const method = response.request.method; let pathDetails = responseMap[`${method} ${url.pathname}`]; if (!pathDetails) { - pathDetails = geParametrizedPathSuccess(method, url.pathname); + pathDetails = getParametrizedPathSuccess(method, url.pathname); } return !pathDetails.includes(response.status); } -function geParametrizedPathSuccess(method: string, path: string): string[] { +function getParametrizedPathSuccess(method: string, path: string): string[] { const pathParts = path.split("/"); + // Traverse list to match the longest candidate + // matchedLen: the length of candidate path + // matchedValue: the matched status code array + let matchedLen = -1, + matchedValue: string[] = []; + // Iterate the responseMap to find a match for (const [key, value] of Object.entries(responseMap)) { // Extracting the path from the map key which is in format @@ -129,49 +135,52 @@ function geParametrizedPathSuccess(method: string, path: string): string[] { // Get each part of the url path const candidateParts = candidatePath.split("/"); - // If the candidate and actual paths don't match in size - // we move on to the next candidate path - if ( - candidateParts.length === pathParts.length && - hasParametrizedPath(key) + // track if we have found a match to return the values found. + let found = true; + for ( + let i = candidateParts.length - 1, j = pathParts.length - 1; + i >= 1 && j >= 1; + i--, j-- ) { - // track if we have found a match to return the values found. - let found = true; - for (let i = 0; i < candidateParts.length; i++) { - if ( - candidateParts[i]?.startsWith("{") && - candidateParts[i]?.endsWith("}") - ) { - // If the current part of the candidate is a "template" part - // it is a match with the actual path part on hand - // skip as the parameterized part can match anything - continue; - } + if ( + candidateParts[i]?.startsWith("{") && + candidateParts[i]?.indexOf("}") !== -1 + ) { + const start = candidateParts[i]!.indexOf("}") + 1, + end = candidateParts[i]?.length; + // If the current part of the candidate is a "template" part + // Try to use the suffix of pattern to match the path + // {guid} ==> $ + // {guid}:export ==> :export$ + const isMatched = new RegExp( + `${candidateParts[i]?.slice(start, end)}`, + ).test(pathParts[j] || ""); - // If the candidate part is not a template and - // the parts don't match mark the candidate as not found - // to move on with the next candidate path. - if (candidateParts[i] !== pathParts[i]) { + if (!isMatched) { found = false; break; } + continue; } - // We finished evaluating the current candidate parts - // if all parts matched we return the success values form - // the path mapping. - if (found) { - return value; + // If the candidate part is not a template and + // the parts don't match mark the candidate as not found + // to move on with the next candidate path. + if (candidateParts[i] !== pathParts[j]) { + found = false; + break; } } - } - // No match was found, return an empty array. - return []; -} + // We finished evaluating the current candidate parts + // Update the matched value if and only if we found the longer pattern + if (found && candidatePath.length > matchedLen) { + matchedLen = candidatePath.length; + matchedValue = value; + } + } -function hasParametrizedPath(path: string): boolean { - return path.includes("/{"); + return matchedValue; } function getPathFromMapKey(mapKey: string): string { diff --git a/sdk/maps/maps-render-rest/generated/logger.ts b/sdk/maps/maps-render-rest/generated/logger.ts new file mode 100644 index 000000000000..7b7d617ef8e3 --- /dev/null +++ b/sdk/maps/maps-render-rest/generated/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("maps-render"); diff --git a/sdk/maps/maps-render-rest/generated/mapsRenderClient.ts b/sdk/maps/maps-render-rest/generated/mapsRenderClient.ts new file mode 100644 index 000000000000..f32ecf1ba3c6 --- /dev/null +++ b/sdk/maps/maps-render-rest/generated/mapsRenderClient.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { getClient, ClientOptions } from "@azure-rest/core-client"; +import { logger } from "./logger"; +import { KeyCredential } from "@azure/core-auth"; +import { MapsRenderClient } from "./clientDefinitions"; + +/** The optional parameters for the client */ +export interface MapsRenderClientOptions extends ClientOptions { + /** The api version option of the client */ + apiVersion?: string; +} + +/** + * Initialize a new instance of `MapsRenderClient` + * @param credentials - uniquely identify client credential + * @param options - the parameter for all optional parameters + */ +export default function createClient( + credentials: KeyCredential, + { apiVersion = "2024-04-01", ...options }: MapsRenderClientOptions = {}, +): MapsRenderClient { + const endpointUrl = + options.endpoint ?? options.baseUrl ?? `https://atlas.microsoft.com`; + const userAgentInfo = `azsdk-js-maps-render-rest/2.0.0-beta.1`; + const userAgentPrefix = + options.userAgentOptions && options.userAgentOptions.userAgentPrefix + ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` + : `${userAgentInfo}`; + options = { + ...options, + userAgentOptions: { + userAgentPrefix, + }, + loggingOptions: { + logger: options.loggingOptions?.logger ?? logger.info, + }, + credentials: { + apiKeyHeaderName: + options.credentials?.apiKeyHeaderName ?? "subscription-key", + }, + }; + const client = getClient( + endpointUrl, + credentials, + options, + ) as MapsRenderClient; + + client.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + client.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version") && apiVersion) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } + + return next(req); + }, + }); + + return client; +} diff --git a/sdk/maps/maps-render-rest/src/generated/outputModels.ts b/sdk/maps/maps-render-rest/generated/outputModels.ts similarity index 86% rename from sdk/maps/maps-render-rest/src/generated/outputModels.ts rename to sdk/maps/maps-render-rest/generated/outputModels.ts index 010874250f03..e2e68915b470 100644 --- a/sdk/maps/maps-render-rest/src/generated/outputModels.ts +++ b/sdk/maps/maps-render-rest/generated/outputModels.ts @@ -10,23 +10,23 @@ export interface ErrorResponseOutput { /** The error detail. */ export interface ErrorDetailOutput { /** The error code. */ - code?: string; + readonly code?: string; /** The error message. */ - message?: string; + readonly message?: string; /** The error target. */ - target?: string; + readonly target?: string; /** The error details. */ - details?: Array; + readonly details?: Array; /** The error additional info. */ - additionalInfo?: Array; + readonly additionalInfo?: Array; } /** The resource management error additional info. */ export interface ErrorAdditionalInfoOutput { /** The additional info type. */ - type?: string; + readonly type?: string; /** The additional info. */ - info?: Record; + readonly info?: Record; } /** Metadata for a tileset in the TileJSON format. */ @@ -72,32 +72,32 @@ export interface MapAttributionOutput { /** This object is returned from a successful copyright call */ export interface CopyrightCaptionOutput { /** Format Version property */ - formatVersion?: string; + readonly formatVersion?: string; /** Copyrights Caption property */ - copyrightsCaption: string; + readonly copyrightsCaption: string; } /** This object is returned from a successful copyright request */ export interface CopyrightOutput { /** Format Version property */ - formatVersion?: string; + readonly formatVersion?: string; /** General Copyrights array */ - generalCopyrights?: Array; + readonly generalCopyrights?: Array; /** Regions array */ - regions?: Array; + readonly regions?: Array; } export interface RegionCopyrightsOutput { /** Copyrights array */ - copyrights: Array; + readonly copyrights: Array; /** Country property */ - country: RegionCopyrightsCountryOutput; + readonly country: RegionCopyrightsCountryOutput; } /** Country property */ export interface RegionCopyrightsCountryOutput { /** ISO3 property */ - ISO3: string; + readonly ISO3: string; /** Label property */ - label: string; + readonly label: string; } diff --git a/sdk/maps/maps-render-rest/src/generated/parameters.ts b/sdk/maps/maps-render-rest/generated/parameters.ts similarity index 97% rename from sdk/maps/maps-render-rest/src/generated/parameters.ts rename to sdk/maps/maps-render-rest/generated/parameters.ts index 48eaedbb4c3d..0ab3cd52f719 100644 --- a/sdk/maps/maps-render-rest/src/generated/parameters.ts +++ b/sdk/maps/maps-render-rest/generated/parameters.ts @@ -163,8 +163,8 @@ export interface RenderGetMapAttributionQueryParam { queryParameters: RenderGetMapAttributionQueryParamProperties; } -export type RenderGetMapAttributionParameters = RenderGetMapAttributionQueryParam & - RequestParameters; +export type RenderGetMapAttributionParameters = + RenderGetMapAttributionQueryParam & RequestParameters; export interface RenderGetMapStateTileQueryParamProperties { /** @@ -480,8 +480,8 @@ export interface RenderGetMapStaticImageQueryParam { queryParameters?: RenderGetMapStaticImageQueryParamProperties; } -export type RenderGetMapStaticImageParameters = RenderGetMapStaticImageQueryParam & - RequestParameters; +export type RenderGetMapStaticImageParameters = + RenderGetMapStaticImageQueryParam & RequestParameters; export interface RenderGetCopyrightFromBoundingBoxQueryParamProperties { /** Minimum coordinates (south-west point) of bounding box in latitude longitude coordinate system. E.g. 52.41064,4.84228 */ @@ -496,8 +496,8 @@ export interface RenderGetCopyrightFromBoundingBoxQueryParam { queryParameters: RenderGetCopyrightFromBoundingBoxQueryParamProperties; } -export type RenderGetCopyrightFromBoundingBoxParameters = RenderGetCopyrightFromBoundingBoxQueryParam & - RequestParameters; +export type RenderGetCopyrightFromBoundingBoxParameters = + RenderGetCopyrightFromBoundingBoxQueryParam & RequestParameters; export interface RenderGetCopyrightForTileQueryParamProperties { /** @@ -526,8 +526,8 @@ export interface RenderGetCopyrightForTileQueryParam { queryParameters: RenderGetCopyrightForTileQueryParamProperties; } -export type RenderGetCopyrightForTileParameters = RenderGetCopyrightForTileQueryParam & - RequestParameters; +export type RenderGetCopyrightForTileParameters = + RenderGetCopyrightForTileQueryParam & RequestParameters; export interface RenderGetCopyrightForWorldQueryParamProperties { /** Yes/no value to exclude textual data from response. Only images and country/region names will be in response. */ @@ -538,5 +538,5 @@ export interface RenderGetCopyrightForWorldQueryParam { queryParameters?: RenderGetCopyrightForWorldQueryParamProperties; } -export type RenderGetCopyrightForWorldParameters = RenderGetCopyrightForWorldQueryParam & - RequestParameters; +export type RenderGetCopyrightForWorldParameters = + RenderGetCopyrightForWorldQueryParam & RequestParameters; diff --git a/sdk/maps/maps-render-rest/src/generated/responses.ts b/sdk/maps/maps-render-rest/generated/responses.ts similarity index 99% rename from sdk/maps/maps-render-rest/src/generated/responses.ts rename to sdk/maps/maps-render-rest/generated/responses.ts index f45eb391f827..10325414ade7 100644 --- a/sdk/maps/maps-render-rest/src/generated/responses.ts +++ b/sdk/maps/maps-render-rest/generated/responses.ts @@ -8,7 +8,7 @@ import { MapTilesetOutput, MapAttributionOutput, CopyrightCaptionOutput, - CopyrightOutput + CopyrightOutput, } from "./outputModels"; export interface RenderGetMapTile200Headers { diff --git a/sdk/maps/maps-render-rest/package.json b/sdk/maps/maps-render-rest/package.json index df2541d0fd3d..5d50cdf3afba 100644 --- a/sdk/maps/maps-render-rest/package.json +++ b/sdk/maps/maps-render-rest/package.json @@ -65,6 +65,7 @@ "@azure/core-auth": "^1.3.0", "@azure/core-rest-pipeline": "^1.8.0", "@azure/maps-common": "1.0.0-beta.2", + "@azure/logger": "^1.0.0", "tslib": "^2.2.0" }, "devDependencies": { diff --git a/sdk/maps/maps-render-rest/review/maps-render.api.md b/sdk/maps/maps-render-rest/review/maps-render.api.md index c3da09bf2218..301375bc33f0 100644 --- a/sdk/maps/maps-render-rest/review/maps-render.api.md +++ b/sdk/maps/maps-render-rest/review/maps-render.api.md @@ -7,7 +7,7 @@ import type { AzureKeyCredential } from '@azure/core-auth'; import type { AzureSASCredential } from '@azure/core-auth'; import { Client } from '@azure-rest/core-client'; -import type { ClientOptions } from '@azure-rest/core-client'; +import { ClientOptions } from '@azure-rest/core-client'; import { HttpResponse } from '@azure-rest/core-client'; import type { LatLon } from '@azure/maps-common'; import { RawHttpHeaders } from '@azure/core-rest-pipeline'; @@ -31,15 +31,15 @@ export interface CircularPathOptions { // @public export interface CopyrightCaptionOutput { - copyrightsCaption: string; - formatVersion?: string; + readonly copyrightsCaption: string; + readonly formatVersion?: string; } // @public export interface CopyrightOutput { - formatVersion?: string; - generalCopyrights?: Array; - regions?: Array; + readonly formatVersion?: string; + readonly generalCopyrights?: Array; + readonly regions?: Array; } // @public @@ -50,17 +50,17 @@ export function createPinsQuery(pinSets: PinSet[]): string; // @public export interface ErrorAdditionalInfoOutput { - info?: Record; - type?: string; + readonly info?: Record; + readonly type?: string; } // @public export interface ErrorDetailOutput { - additionalInfo?: Array; - code?: string; - details?: Array; - message?: string; - target?: string; + readonly additionalInfo?: Array; + readonly code?: string; + readonly details?: Array; + readonly message?: string; + readonly target?: string; } // @public @@ -160,6 +160,11 @@ export type MapsRenderClient = Client & { path: Routes; }; +// @public +export interface MapsRenderClientOptions extends ClientOptions { + apiVersion?: string; +} + // @public export interface MapTilesetOutput { attribution?: string; @@ -227,14 +232,14 @@ export function positionToTileXY(position: LatLon, zoom: number, tileSize: "512" // @public export interface RegionCopyrightsCountryOutput { - ISO3: string; - label: string; + readonly ISO3: string; + readonly label: string; } // @public (undocumented) export interface RegionCopyrightsOutput { - copyrights: Array; - country: RegionCopyrightsCountryOutput; + readonly copyrights: Array; + readonly country: RegionCopyrightsCountryOutput; } // @public diff --git a/sdk/maps/maps-render-rest/samples-dev/getCopyrightCaption.ts b/sdk/maps/maps-render-rest/samples-dev/getCopyrightCaption.ts index 2b007dca41ab..d5e6b9d4e7fe 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getCopyrightCaption.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getCopyrightCaption.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright caption. diff --git a/sdk/maps/maps-render-rest/samples-dev/getCopyrightForTile.ts b/sdk/maps/maps-render-rest/samples-dev/getCopyrightForTile.ts index b63311189226..66efe0e439a3 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getCopyrightForTile.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getCopyrightForTile.ts @@ -3,8 +3,7 @@ import { positionToTileXY } from "@azure-rest/maps-render"; import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright of a certain tile. diff --git a/sdk/maps/maps-render-rest/samples-dev/getCopyrightForWorld.ts b/sdk/maps/maps-render-rest/samples-dev/getCopyrightForWorld.ts index 3e748888151d..c7aefb6d97bc 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getCopyrightForWorld.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getCopyrightForWorld.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright all around the world. diff --git a/sdk/maps/maps-render-rest/samples-dev/getCopyrightFromBoundingBox.ts b/sdk/maps/maps-render-rest/samples-dev/getCopyrightFromBoundingBox.ts index e9f2cf86ded8..e825ee35ec5f 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getCopyrightFromBoundingBox.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getCopyrightFromBoundingBox.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright of tiles in a given bounding box. diff --git a/sdk/maps/maps-render-rest/samples-dev/getMapAttribution.ts b/sdk/maps/maps-render-rest/samples-dev/getMapAttribution.ts index 3bfb242c4755..aef7e02c0a16 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getMapAttribution.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getMapAttribution.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright attribution of a certain tileset. diff --git a/sdk/maps/maps-render-rest/samples-dev/getMapTileset.ts b/sdk/maps/maps-render-rest/samples-dev/getMapTileset.ts index d6bcb9d41e8a..501d69c505d0 100644 --- a/sdk/maps/maps-render-rest/samples-dev/getMapTileset.ts +++ b/sdk/maps/maps-render-rest/samples-dev/getMapTileset.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the metadata of a certain tileset. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightCaption.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightCaption.js index 90708d3688b3..6ad79d7a08a7 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightCaption.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightCaption.js @@ -2,8 +2,8 @@ // Licensed under the MIT License. const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the copyright caption. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForTile.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForTile.js index 0b6f07229285..811d34d405e8 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForTile.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForTile.js @@ -3,8 +3,8 @@ const { positionToTileXY } = require("@azure-rest/maps-render"); const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the copyright of a certain tile. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForWorld.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForWorld.js index ca6e22ec5739..df723106d802 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForWorld.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightForWorld.js @@ -2,8 +2,8 @@ // Licensed under the MIT License. const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the copyright all around the world. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightFromBoundingBox.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightFromBoundingBox.js index b63b2be9eaa5..4502983f36ab 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightFromBoundingBox.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getCopyrightFromBoundingBox.js @@ -2,8 +2,8 @@ // Licensed under the MIT License. const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the copyright of tiles in a given bounding box. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapAttribution.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapAttribution.js index e926bdea611d..191d95c6335c 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapAttribution.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapAttribution.js @@ -2,8 +2,8 @@ // Licensed under the MIT License. const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the copyright attribution of a certain tileset. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapTileset.js b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapTileset.js index aacd37488ee5..7baac75b0cae 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapTileset.js +++ b/sdk/maps/maps-render-rest/samples/v2-beta/javascript/getMapTileset.js @@ -2,8 +2,8 @@ // Licensed under the MIT License. const { DefaultAzureCredential } = require("@azure/identity"); -const { isUnexpected } = require("../src/generated"); -const MapsRender = require("../src/mapsRender").default; +const MapsRender = require("@azure-rest/maps-render").default, + { isUnexpected } = require("@azure-rest/maps-render"); /** * @summary How to get the metadata of a certain tileset. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightCaption.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightCaption.ts index 2b007dca41ab..d5e6b9d4e7fe 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightCaption.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightCaption.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright caption. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForTile.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForTile.ts index b63311189226..66efe0e439a3 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForTile.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForTile.ts @@ -3,8 +3,7 @@ import { positionToTileXY } from "@azure-rest/maps-render"; import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright of a certain tile. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForWorld.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForWorld.ts index 3e748888151d..c7aefb6d97bc 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForWorld.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightForWorld.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright all around the world. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightFromBoundingBox.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightFromBoundingBox.ts index e9f2cf86ded8..e825ee35ec5f 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightFromBoundingBox.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getCopyrightFromBoundingBox.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright of tiles in a given bounding box. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapAttribution.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapAttribution.ts index 36e0e807b7e8..5b947f229d7a 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapAttribution.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapAttribution.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the copyright attribution of a certain tileset. diff --git a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapTileset.ts b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapTileset.ts index 84b93780abd9..dd7c4af84070 100644 --- a/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapTileset.ts +++ b/sdk/maps/maps-render-rest/samples/v2-beta/typescript/src/getMapTileset.ts @@ -2,8 +2,7 @@ // Licensed under the MIT License. import { DefaultAzureCredential } from "@azure/identity"; -import { isUnexpected } from "../src/generated"; -import MapsRender from "../src/mapsRender"; +import MapsRender, { isUnexpected } from "@azure-rest/maps-render"; /** * @summary How to get the metadata of a certain tileset. diff --git a/sdk/maps/maps-render-rest/src/generated/mapsRenderClient.ts b/sdk/maps/maps-render-rest/src/generated/mapsRenderClient.ts deleted file mode 100644 index e76c100f688e..000000000000 --- a/sdk/maps/maps-render-rest/src/generated/mapsRenderClient.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { getClient, ClientOptions } from "@azure-rest/core-client"; -import { KeyCredential } from "@azure/core-auth"; -import { MapsRenderClient } from "./clientDefinitions"; - -/** - * Initialize a new instance of the class MapsRenderClient class. - * @param credentials type: KeyCredential - */ -export default function createClient( - credentials: KeyCredential, - options: ClientOptions = {} -): MapsRenderClient { - const baseUrl = options.baseUrl ?? `https://atlas.microsoft.com`; - options.apiVersion = options.apiVersion ?? "2024-04-01"; - options = { - ...options, - credentials: { - apiKeyHeaderName: "subscription-key" - } - }; - - const userAgentInfo = `azsdk-js-maps-render-rest/2.0.0-beta.1`; - const userAgentPrefix = - options.userAgentOptions && options.userAgentOptions.userAgentPrefix - ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` - : `${userAgentInfo}`; - options = { - ...options, - userAgentOptions: { - userAgentPrefix - } - }; - - const client = getClient(baseUrl, credentials, options) as MapsRenderClient; - - return client; -} diff --git a/sdk/maps/maps-render-rest/src/index.ts b/sdk/maps/maps-render-rest/src/index.ts index 9a5415ed5157..b7242c5581b3 100644 --- a/sdk/maps/maps-render-rest/src/index.ts +++ b/sdk/maps/maps-render-rest/src/index.ts @@ -3,7 +3,7 @@ import MapsRender from "./mapsRender"; -export * from "./generated"; +export * from "../generated"; export * from "./positionToTileXY"; export * from "./createPinsQuery"; export * from "./createPathQuery"; diff --git a/sdk/maps/maps-render-rest/src/mapsRender.ts b/sdk/maps/maps-render-rest/src/mapsRender.ts index 2665c5a74388..bcd87f4b8e7d 100644 --- a/sdk/maps/maps-render-rest/src/mapsRender.ts +++ b/sdk/maps/maps-render-rest/src/mapsRender.ts @@ -6,8 +6,8 @@ import type { AzureKeyCredential, AzureSASCredential, TokenCredential } from "@a import { isSASCredential, isTokenCredential } from "@azure/core-auth"; import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline"; import { createMapsClientIdPolicy } from "@azure/maps-common"; -import type { MapsRenderClient } from "./generated"; -import createClient from "./generated/mapsRenderClient"; +import type { MapsRenderClient } from "../generated"; +import createClient from "../generated/mapsRenderClient"; /** * Creates an instance of MapsRenderClient from a subscription key. diff --git a/sdk/maps/maps-render-rest/swagger/README.md b/sdk/maps/maps-render-rest/swagger/README.md index c57d50f38a48..efd3133aff5e 100644 --- a/sdk/maps/maps-render-rest/swagger/README.md +++ b/sdk/maps/maps-render-rest/swagger/README.md @@ -8,6 +8,8 @@ The configuration is following the [RLC quick start guide](https://github.com/Az For the configuration property, please refer to [Index of AutoRestFlag](https://github.com/Azure/autorest/blob/main/docs/generate/flags.md). ```yaml +flavor: azure +openapi-type: data-plane package-name: "@azure-rest/maps-render" title: MapsRenderClient description: Azure Maps Render Client @@ -20,7 +22,7 @@ generate-metadata: false generate-test: false license-header: MICROSOFT_MIT_NO_VERSION output-folder: ../ -source-code-folder-path: ./src/generated +source-code-folder-path: ./generated input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/maps/data-plane/Render/stable/2024-04-01/render.json package-version: 2.0.0-beta.1 rest-level-client: true @@ -29,7 +31,7 @@ rest-level-client: true security: AzureKey security-header-name: subscription-key use-extension: - "@autorest/typescript": "6.0.0-rc.3" + "@autorest/typescript": "latest" ``` ## Customization for Track 2 Generator diff --git a/sdk/maps/maps-search-rest/CHANGELOG.md b/sdk/maps/maps-search-rest/CHANGELOG.md index 71050a9f0d11..244f7fc50d1b 100644 --- a/sdk/maps/maps-search-rest/CHANGELOG.md +++ b/sdk/maps/maps-search-rest/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +- Marked fields in various interfaces as readonly, which may impact code that previously modified these properties. + ### Bugs Fixed - Fix the Microsoft Entra ID authentication when providing `baseUrl`. diff --git a/sdk/maps/maps-search-rest/src/generated/clientDefinitions.ts b/sdk/maps/maps-search-rest/generated/clientDefinitions.ts similarity index 73% rename from sdk/maps/maps-search-rest/src/generated/clientDefinitions.ts rename to sdk/maps/maps-search-rest/generated/clientDefinitions.ts index 9090d66c2c2c..324d124601d9 100644 --- a/sdk/maps/maps-search-rest/src/generated/clientDefinitions.ts +++ b/sdk/maps/maps-search-rest/generated/clientDefinitions.ts @@ -6,7 +6,7 @@ import { SearchGetGeocodingBatchParameters, SearchGetPolygonParameters, SearchGetReverseGeocodingParameters, - SearchGetReverseGeocodingBatchParameters + SearchGetReverseGeocodingBatchParameters, } from "./parameters"; import { SearchGetGeocoding200Response, @@ -18,20 +18,19 @@ import { SearchGetReverseGeocoding200Response, SearchGetReverseGeocodingDefaultResponse, SearchGetReverseGeocodingBatch200Response, - SearchGetReverseGeocodingBatchDefaultResponse + SearchGetReverseGeocodingBatchDefaultResponse, } from "./responses"; import { Client, StreamableMethod } from "@azure-rest/core-client"; export interface GetGeocoding { /** - * **Geocoding** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). + * The `Get Geocoding` API is an HTTP `GET` request that returns the longitude and latitude coordinates of the location being searched. * - * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties, states etc. + * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties and states. The response also returns detailed address properties such as street, postal code, municipality, and country/region information. */ get( - options?: SearchGetGeocodingParameters + options?: SearchGetGeocodingParameters, ): StreamableMethod< SearchGetGeocoding200Response | SearchGetGeocodingDefaultResponse >; @@ -39,14 +38,8 @@ export interface GetGeocoding { export interface GetGeocodingBatch { /** - * **Geocoding Batch API** * - * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * - * - * The Geocoding Batch API sends batches of queries to [Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to the [Geocoding](/rest/api/maps/search/get-geocoding) API in a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -74,7 +67,7 @@ export interface GetGeocodingBatch { * } * ``` * - * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#uri-parameters). + * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](/rest/api/maps/search/get-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -83,7 +76,7 @@ export interface GetGeocodingBatch { * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * @@ -91,7 +84,7 @@ export interface GetGeocodingBatch { * */ post( - options: SearchGetGeocodingBatchParameters + options: SearchGetGeocodingBatchParameters, ): StreamableMethod< SearchGetGeocodingBatch200Response | SearchGetGeocodingBatchDefaultResponse >; @@ -99,14 +92,11 @@ export interface GetGeocodingBatch { export interface GetPolygon { /** - * **Get Polygon** - * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). * - * Supplies polygon data of a geographical area outline such as a city or a country region. + * The `Get Polygon` API is an HTTP `GET` request that supplies polygon data of a geographical area outline such as a city or a country region. */ get( - options: SearchGetPolygonParameters + options: SearchGetPolygonParameters, ): StreamableMethod< SearchGetPolygon200Response | SearchGetPolygonDefaultResponse >; @@ -114,14 +104,11 @@ export interface GetPolygon { export interface GetReverseGeocoding { /** - * **Reverse Geocoding** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * Translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Most often this is needed in tracking applications where you receive a GPS feed from the device or asset and wish to know what address where the coordinate is located. This endpoint will return address information for a given coordinate. + * The `Get Reverse Geocoding` API is an HTTP `GET` request used to translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Useful in tracking applications where you receive a GPS feed from the device or asset and wish to know the address associated with the coordinates. This endpoint will return address information for a given coordinate. */ get( - options: SearchGetReverseGeocodingParameters + options: SearchGetReverseGeocodingParameters, ): StreamableMethod< | SearchGetReverseGeocoding200Response | SearchGetReverseGeocodingDefaultResponse @@ -130,14 +117,8 @@ export interface GetReverseGeocoding { export interface GetReverseGeocodingBatch { /** - * **Reverse Geocoding Batch API** - * - * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * * - * The Reverse Geocoding Batch API sends batches of queries to [Reverse Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Reverse Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to [Reverse Geocoding](/rest/api/maps/search/get-reverse-geocoding) API using a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -162,7 +143,7 @@ export interface GetReverseGeocodingBatch { * } * ``` * - * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#uri-parameters). + * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](/rest/api/maps/search/get-reverse-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -171,7 +152,7 @@ export interface GetReverseGeocodingBatch { * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * @@ -179,7 +160,7 @@ export interface GetReverseGeocodingBatch { * */ post( - options: SearchGetReverseGeocodingBatchParameters + options: SearchGetReverseGeocodingBatchParameters, ): StreamableMethod< | SearchGetReverseGeocodingBatch200Response | SearchGetReverseGeocodingBatchDefaultResponse diff --git a/sdk/maps/maps-search-rest/src/generated/index.ts b/sdk/maps/maps-search-rest/generated/index.ts similarity index 100% rename from sdk/maps/maps-search-rest/src/generated/index.ts rename to sdk/maps/maps-search-rest/generated/index.ts diff --git a/sdk/maps/maps-search-rest/src/generated/isUnexpected.ts b/sdk/maps/maps-search-rest/generated/isUnexpected.ts similarity index 92% rename from sdk/maps/maps-search-rest/src/generated/isUnexpected.ts rename to sdk/maps/maps-search-rest/generated/isUnexpected.ts index ff2049167b7d..06ec16983749 100644 --- a/sdk/maps/maps-search-rest/src/generated/isUnexpected.ts +++ b/sdk/maps/maps-search-rest/generated/isUnexpected.ts @@ -11,7 +11,7 @@ import { SearchGetReverseGeocoding200Response, SearchGetReverseGeocodingDefaultResponse, SearchGetReverseGeocodingBatch200Response, - SearchGetReverseGeocodingBatchDefaultResponse + SearchGetReverseGeocodingBatchDefaultResponse, } from "./responses"; const responseMap: Record = { @@ -19,29 +19,29 @@ const responseMap: Record = { "POST /geocode:batch": ["200"], "GET /search/polygon": ["200"], "GET /reverseGeocode": ["200"], - "POST /reverseGeocode:batch": ["200"] + "POST /reverseGeocode:batch": ["200"], }; export function isUnexpected( - response: SearchGetGeocoding200Response | SearchGetGeocodingDefaultResponse + response: SearchGetGeocoding200Response | SearchGetGeocodingDefaultResponse, ): response is SearchGetGeocodingDefaultResponse; export function isUnexpected( response: | SearchGetGeocodingBatch200Response - | SearchGetGeocodingBatchDefaultResponse + | SearchGetGeocodingBatchDefaultResponse, ): response is SearchGetGeocodingBatchDefaultResponse; export function isUnexpected( - response: SearchGetPolygon200Response | SearchGetPolygonDefaultResponse + response: SearchGetPolygon200Response | SearchGetPolygonDefaultResponse, ): response is SearchGetPolygonDefaultResponse; export function isUnexpected( response: | SearchGetReverseGeocoding200Response - | SearchGetReverseGeocodingDefaultResponse + | SearchGetReverseGeocodingDefaultResponse, ): response is SearchGetReverseGeocodingDefaultResponse; export function isUnexpected( response: | SearchGetReverseGeocodingBatch200Response - | SearchGetReverseGeocodingBatchDefaultResponse + | SearchGetReverseGeocodingBatchDefaultResponse, ): response is SearchGetReverseGeocodingBatchDefaultResponse; export function isUnexpected( response: @@ -54,7 +54,7 @@ export function isUnexpected( | SearchGetReverseGeocoding200Response | SearchGetReverseGeocodingDefaultResponse | SearchGetReverseGeocodingBatch200Response - | SearchGetReverseGeocodingBatchDefaultResponse + | SearchGetReverseGeocodingBatchDefaultResponse, ): response is | SearchGetGeocodingDefaultResponse | SearchGetGeocodingBatchDefaultResponse @@ -109,7 +109,7 @@ function getParametrizedPathSuccess(method: string, path: string): string[] { // {guid} ==> $ // {guid}:export ==> :export$ const isMatched = new RegExp( - `${candidateParts[i]?.slice(start, end)}` + `${candidateParts[i]?.slice(start, end)}`, ).test(pathParts[j] || ""); if (!isMatched) { diff --git a/sdk/maps/maps-search-rest/generated/logger.ts b/sdk/maps/maps-search-rest/generated/logger.ts new file mode 100644 index 000000000000..a371a74f1a29 --- /dev/null +++ b/sdk/maps/maps-search-rest/generated/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("maps-search"); diff --git a/sdk/maps/maps-search-rest/generated/mapsSearchClient.ts b/sdk/maps/maps-search-rest/generated/mapsSearchClient.ts new file mode 100644 index 000000000000..6581f5e89847 --- /dev/null +++ b/sdk/maps/maps-search-rest/generated/mapsSearchClient.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { getClient, ClientOptions } from "@azure-rest/core-client"; +import { logger } from "./logger"; +import { KeyCredential } from "@azure/core-auth"; +import { MapsSearchClient } from "./clientDefinitions"; + +/** The optional parameters for the client */ +export interface MapsSearchClientOptions extends ClientOptions { + /** The api version option of the client */ + apiVersion?: string; +} + +/** + * Initialize a new instance of `MapsSearchClient` + * @param credentials - uniquely identify client credential + * @param options - the parameter for all optional parameters + */ +export default function createClient( + credentials: KeyCredential, + { apiVersion = "2023-06-01", ...options }: MapsSearchClientOptions = {}, +): MapsSearchClient { + const endpointUrl = + options.endpoint ?? options.baseUrl ?? `https://atlas.microsoft.com`; + const userAgentInfo = `azsdk-js-maps-search-rest/2.0.0-beta.2`; + const userAgentPrefix = + options.userAgentOptions && options.userAgentOptions.userAgentPrefix + ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` + : `${userAgentInfo}`; + options = { + ...options, + userAgentOptions: { + userAgentPrefix, + }, + loggingOptions: { + logger: options.loggingOptions?.logger ?? logger.info, + }, + credentials: { + apiKeyHeaderName: + options.credentials?.apiKeyHeaderName ?? "subscription-key", + }, + }; + const client = getClient( + endpointUrl, + credentials, + options, + ) as MapsSearchClient; + + client.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + client.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version") && apiVersion) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } + + return next(req); + }, + }); + + return client; +} diff --git a/sdk/maps/maps-search-rest/src/generated/models.ts b/sdk/maps/maps-search-rest/generated/models.ts similarity index 95% rename from sdk/maps/maps-search-rest/src/generated/models.ts rename to sdk/maps/maps-search-rest/generated/models.ts index ad90d6ec3dc4..29098430d489 100644 --- a/sdk/maps/maps-search-rest/src/generated/models.ts +++ b/sdk/maps/maps-search-rest/generated/models.ts @@ -22,7 +22,7 @@ export interface GeocodingBatchRequestItem { */ addressLine?: string; /** - * Restrict the geocoding result to an [ISO 3166-1 Alpha-2 region/country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) that is specified e.g. FR. This will limit the search to the specified region. + * Signal for the geocoding result to an [ISO 3166-1 Alpha-2 region/country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) that is specified e.g. FR./ * * **If query is given, should not use this parameter.** */ diff --git a/sdk/maps/maps-search-rest/src/generated/outputModels.ts b/sdk/maps/maps-search-rest/generated/outputModels.ts similarity index 100% rename from sdk/maps/maps-search-rest/src/generated/outputModels.ts rename to sdk/maps/maps-search-rest/generated/outputModels.ts diff --git a/sdk/maps/maps-search-rest/src/generated/parameters.ts b/sdk/maps/maps-search-rest/generated/parameters.ts similarity index 88% rename from sdk/maps/maps-search-rest/src/generated/parameters.ts rename to sdk/maps/maps-search-rest/generated/parameters.ts index bc1154ecbe65..3a3040443689 100644 --- a/sdk/maps/maps-search-rest/src/generated/parameters.ts +++ b/sdk/maps/maps-search-rest/generated/parameters.ts @@ -4,7 +4,7 @@ import { RequestParameters } from "@azure-rest/core-client"; import { GeocodingBatchRequestBody, - ReverseGeocodingBatchRequestBody + ReverseGeocodingBatchRequestBody, } from "./models"; export interface SearchGetGeocodingQueryParamProperties { @@ -19,7 +19,7 @@ export interface SearchGetGeocodingQueryParamProperties { */ addressLine?: string; /** - * Restrict the geocoding result to an [ISO 3166-1 Alpha-2 region/country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) that is specified e.g. FR. This will limit the search to the specified region. + * Signal for the geocoding result to an [ISO 3166-1 Alpha-2 region/country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) that is specified e.g. FR./ * * **If query is given, should not use this parameter.** */ @@ -87,9 +87,10 @@ export interface SearchGetGeocodingBatchMediaTypesParam { contentType?: "application/json"; } -export type SearchGetGeocodingBatchParameters = SearchGetGeocodingBatchMediaTypesParam & - SearchGetGeocodingBatchBodyParam & - RequestParameters; +export type SearchGetGeocodingBatchParameters = + SearchGetGeocodingBatchMediaTypesParam & + SearchGetGeocodingBatchBodyParam & + RequestParameters; export interface SearchGetPolygonQueryParamProperties { /** A point on the earth specified as a longitude and latitude. Example: &coordinates=lon,lat */ @@ -100,7 +101,7 @@ export interface SearchGetPolygonQueryParamProperties { * Please refer to [Supported Views](https://aka.ms/AzureMapsLocalizationViews) for details and to see the available Views. */ view?: string; - /** The geopolitical concept to return a boundary for. */ + /** The geopolitical concept to return a boundary for. If not specified, the default is `countryRegion` result type. */ resultType?: | "countryRegion" | "adminDistrict" @@ -111,7 +112,7 @@ export interface SearchGetPolygonQueryParamProperties { | "postalCode4" | "neighborhood" | "locality"; - /** Resolution determines the amount of points to send back. */ + /** Resolution determines the amount of points to send back. If not specified, the default is medium resolution. */ resolution?: "small" | "medium" | "large" | "huge"; } @@ -161,8 +162,8 @@ export interface SearchGetReverseGeocodingQueryParam { queryParameters: SearchGetReverseGeocodingQueryParamProperties; } -export type SearchGetReverseGeocodingParameters = SearchGetReverseGeocodingQueryParam & - RequestParameters; +export type SearchGetReverseGeocodingParameters = + SearchGetReverseGeocodingQueryParam & RequestParameters; export interface SearchGetReverseGeocodingBatchBodyParam { /** The list of reverse geocoding queries/requests to process. The list can contain a max of 100 queries and must contain at least 1 query. */ @@ -174,6 +175,7 @@ export interface SearchGetReverseGeocodingBatchMediaTypesParam { contentType?: "application/json"; } -export type SearchGetReverseGeocodingBatchParameters = SearchGetReverseGeocodingBatchMediaTypesParam & - SearchGetReverseGeocodingBatchBodyParam & - RequestParameters; +export type SearchGetReverseGeocodingBatchParameters = + SearchGetReverseGeocodingBatchMediaTypesParam & + SearchGetReverseGeocodingBatchBodyParam & + RequestParameters; diff --git a/sdk/maps/maps-search-rest/src/generated/responses.ts b/sdk/maps/maps-search-rest/generated/responses.ts similarity index 72% rename from sdk/maps/maps-search-rest/src/generated/responses.ts rename to sdk/maps/maps-search-rest/generated/responses.ts index f4721ae03cb5..16de475d489a 100644 --- a/sdk/maps/maps-search-rest/src/generated/responses.ts +++ b/sdk/maps/maps-search-rest/generated/responses.ts @@ -7,7 +7,7 @@ import { GeocodingResponseOutput, ErrorResponseOutput, GeocodingBatchResponseOutput, - BoundaryOutput + BoundaryOutput, } from "./outputModels"; export interface SearchGetGeocoding200Headers { @@ -16,11 +16,10 @@ export interface SearchGetGeocoding200Headers { } /** - * **Geocoding** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). + * The `Get Geocoding` API is an HTTP `GET` request that returns the longitude and latitude coordinates of the location being searched. * - * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties, states etc. + * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties and states. The response also returns detailed address properties such as street, postal code, municipality, and country/region information. */ export interface SearchGetGeocoding200Response extends HttpResponse { status: "200"; @@ -29,11 +28,10 @@ export interface SearchGetGeocoding200Response extends HttpResponse { } /** - * **Geocoding** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). + * The `Get Geocoding` API is an HTTP `GET` request that returns the longitude and latitude coordinates of the location being searched. * - * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties, states etc. + * In many cases, the complete search service might be too much, for instance if you are only interested in traditional geocoding. Search can also be accessed for address look up exclusively. The geocoding is performed by hitting the geocoding endpoint with just the address or partial address in question. The geocoding search index will be queried for everything above the street level data. No Point of Interest (POIs) will be returned. Note that the geocoder is very tolerant of typos and incomplete addresses. It will also handle everything from exact street addresses or street or intersections as well as higher level geographies such as city centers, counties and states. The response also returns detailed address properties such as street, postal code, municipality, and country/region information. */ export interface SearchGetGeocodingDefaultResponse extends HttpResponse { status: string; @@ -41,14 +39,8 @@ export interface SearchGetGeocodingDefaultResponse extends HttpResponse { } /** - * **Geocoding Batch API** * - * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * - * - * The Geocoding Batch API sends batches of queries to [Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to the [Geocoding](/rest/api/maps/search/get-geocoding) API in a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -76,7 +68,7 @@ export interface SearchGetGeocodingDefaultResponse extends HttpResponse { * } * ``` * - * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#uri-parameters). + * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](/rest/api/maps/search/get-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -85,7 +77,7 @@ export interface SearchGetGeocodingDefaultResponse extends HttpResponse { * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * @@ -98,14 +90,8 @@ export interface SearchGetGeocodingBatch200Response extends HttpResponse { } /** - * **Geocoding Batch API** - * * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * - * - * The Geocoding Batch API sends batches of queries to [Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to the [Geocoding](/rest/api/maps/search/get-geocoding) API in a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -133,7 +119,7 @@ export interface SearchGetGeocodingBatch200Response extends HttpResponse { * } * ``` * - * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#uri-parameters). + * A _geocoding_ batchItem object can accept any of the supported _geocoding_ [URI parameters](/rest/api/maps/search/get-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -142,7 +128,7 @@ export interface SearchGetGeocodingBatch200Response extends HttpResponse { * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * @@ -155,11 +141,8 @@ export interface SearchGetGeocodingBatchDefaultResponse extends HttpResponse { } /** - * **Get Polygon** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * Supplies polygon data of a geographical area outline such as a city or a country region. + * The `Get Polygon` API is an HTTP `GET` request that supplies polygon data of a geographical area outline such as a city or a country region. */ export interface SearchGetPolygon200Response extends HttpResponse { status: "200"; @@ -167,11 +150,8 @@ export interface SearchGetPolygon200Response extends HttpResponse { } /** - * **Get Polygon** - * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). * - * Supplies polygon data of a geographical area outline such as a city or a country region. + * The `Get Polygon` API is an HTTP `GET` request that supplies polygon data of a geographical area outline such as a city or a country region. */ export interface SearchGetPolygonDefaultResponse extends HttpResponse { status: string; @@ -179,11 +159,8 @@ export interface SearchGetPolygonDefaultResponse extends HttpResponse { } /** - * **Reverse Geocoding** * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * Translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Most often this is needed in tracking applications where you receive a GPS feed from the device or asset and wish to know what address where the coordinate is located. This endpoint will return address information for a given coordinate. + * The `Get Reverse Geocoding` API is an HTTP `GET` request used to translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Useful in tracking applications where you receive a GPS feed from the device or asset and wish to know the address associated with the coordinates. This endpoint will return address information for a given coordinate. */ export interface SearchGetReverseGeocoding200Response extends HttpResponse { status: "200"; @@ -191,11 +168,8 @@ export interface SearchGetReverseGeocoding200Response extends HttpResponse { } /** - * **Reverse Geocoding** - * - * **Applies to:** see pricing [tiers](https://aka.ms/AzureMapsPricingTier). * - * Translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Most often this is needed in tracking applications where you receive a GPS feed from the device or asset and wish to know what address where the coordinate is located. This endpoint will return address information for a given coordinate. + * The `Get Reverse Geocoding` API is an HTTP `GET` request used to translate a coordinate (example: 37.786505, -122.3862) into a human understandable street address. Useful in tracking applications where you receive a GPS feed from the device or asset and wish to know the address associated with the coordinates. This endpoint will return address information for a given coordinate. */ export interface SearchGetReverseGeocodingDefaultResponse extends HttpResponse { status: string; @@ -203,14 +177,8 @@ export interface SearchGetReverseGeocodingDefaultResponse extends HttpResponse { } /** - * **Reverse Geocoding Batch API** - * - * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * * - * - * The Reverse Geocoding Batch API sends batches of queries to [Reverse Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Reverse Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to [Reverse Geocoding](/rest/api/maps/search/get-reverse-geocoding) API using a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -235,7 +203,7 @@ export interface SearchGetReverseGeocodingDefaultResponse extends HttpResponse { * } * ``` * - * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#uri-parameters). + * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](/rest/api/maps/search/get-reverse-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -244,7 +212,7 @@ export interface SearchGetReverseGeocodingDefaultResponse extends HttpResponse { * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * @@ -258,14 +226,8 @@ export interface SearchGetReverseGeocodingBatch200Response } /** - * **Reverse Geocoding Batch API** - * - * - * **Applies to**: see pricing [tiers](https://aka.ms/AzureMapsPricingTier). - * - * * - * The Reverse Geocoding Batch API sends batches of queries to [Reverse Geocoding API](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding) using just a single API call. The API allows caller to batch up to **100** queries. + * The `Get Reverse Geocoding Batch` API is an HTTP `POST` request that sends batches of up to **100** queries to [Reverse Geocoding](/rest/api/maps/search/get-reverse-geocoding) API using a single request. * * ### Submit Synchronous Batch Request * The Synchronous API is recommended for lightweight batch requests. When the service receives a request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later. The Synchronous API will return a timeout error (a 408 response) if the request takes longer than 60 seconds. The number of batch items is limited to **100** for this API. @@ -290,7 +252,7 @@ export interface SearchGetReverseGeocodingBatch200Response * } * ``` * - * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#uri-parameters). + * A _reverse geocoding_ batchItem object can accept any of the supported _reverse geocoding_ [URI parameters](/rest/api/maps/search/get-reverse-geocoding#uri-parameters). * * * The batch should contain at least **1** query. @@ -299,7 +261,7 @@ export interface SearchGetReverseGeocodingBatch200Response * ### Batch Response Model * The batch response contains a `summary` component that indicates the `totalRequests` that were part of the original batch request and `successfulRequests` i.e. queries which were executed successfully. The batch response also includes a `batchItems` array which contains a response for each and every query in the batch request. The `batchItems` will contain the results in the exact same order the original queries were sent in the batch request. Each item is of one of the following types: * - * - [`GeocodingResponse`](https://docs.microsoft.com/rest/api/maps/search-v2/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. + * - [`GeocodingResponse`](/rest/api/maps/search/get-reverse-geocoding#geocodingresponse) - If the query completed successfully. * * - `Error` - If the query failed. The response will contain a `code` and a `message` in this case. * diff --git a/sdk/maps/maps-search-rest/review/maps-search.api.md b/sdk/maps/maps-search-rest/review/maps-search.api.md index b32f8a78378b..99f873cd8132 100644 --- a/sdk/maps/maps-search-rest/review/maps-search.api.md +++ b/sdk/maps/maps-search-rest/review/maps-search.api.md @@ -7,7 +7,7 @@ import type { AzureKeyCredential } from '@azure/core-auth'; import type { AzureSASCredential } from '@azure/core-auth'; import { Client } from '@azure-rest/core-client'; -import type { ClientOptions } from '@azure-rest/core-client'; +import { ClientOptions } from '@azure-rest/core-client'; import { HttpResponse } from '@azure-rest/core-client'; import { RawHttpHeaders } from '@azure/core-rest-pipeline'; import { RequestParameters } from '@azure-rest/core-client'; @@ -346,6 +346,11 @@ export type MapsSearchClient = Client & { path: Routes; }; +// @public +export interface MapsSearchClientOptions extends ClientOptions { + apiVersion?: string; +} + // @public export interface ReverseGeocodingBatchRequestBody { batchItems?: Array; diff --git a/sdk/maps/maps-search-rest/src/MapsSearch.ts b/sdk/maps/maps-search-rest/src/MapsSearch.ts index a451ac4787a9..1dc9301f8cce 100644 --- a/sdk/maps/maps-search-rest/src/MapsSearch.ts +++ b/sdk/maps/maps-search-rest/src/MapsSearch.ts @@ -5,8 +5,8 @@ import type { ClientOptions } from "@azure-rest/core-client"; import type { AzureKeyCredential, AzureSASCredential, TokenCredential } from "@azure/core-auth"; import { isSASCredential, isTokenCredential } from "@azure/core-auth"; import { createMapsClientIdPolicy } from "@azure/maps-common"; -import type { MapsSearchClient } from "./generated"; -import createClient from "./generated"; +import type { MapsSearchClient } from "../generated"; +import createClient from "../generated"; import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline"; /** diff --git a/sdk/maps/maps-search-rest/src/generated/mapsSearchClient.ts b/sdk/maps/maps-search-rest/src/generated/mapsSearchClient.ts deleted file mode 100644 index 3d9532a15d6b..000000000000 --- a/sdk/maps/maps-search-rest/src/generated/mapsSearchClient.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { getClient, ClientOptions } from "@azure-rest/core-client"; -import { logger } from "../logger"; -import { KeyCredential } from "@azure/core-auth"; -import { MapsSearchClient } from "./clientDefinitions"; - -/** - * Initialize a new instance of `MapsSearchClient` - * @param credentials - uniquely identify client credential - * @param options - the parameter for all optional parameters - */ -export default function createClient( - credentials: KeyCredential, - options: ClientOptions = {} -): MapsSearchClient { - const baseUrl = options.baseUrl ?? `https://atlas.microsoft.com`; - options.apiVersion = options.apiVersion ?? "2023-06-01"; - const userAgentInfo = `azsdk-js-maps-search-rest/2.0.0-beta.1`; - const userAgentPrefix = - options.userAgentOptions && options.userAgentOptions.userAgentPrefix - ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` - : `${userAgentInfo}`; - options = { - ...options, - userAgentOptions: { - userAgentPrefix - }, - loggingOptions: { - logger: options.loggingOptions?.logger ?? logger.info - }, - credentials: { - apiKeyHeaderName: - options.credentials?.apiKeyHeaderName ?? "subscription-key" - } - }; - - const client = getClient(baseUrl, credentials, options) as MapsSearchClient; - - return client; -} diff --git a/sdk/maps/maps-search-rest/src/generated/pollingHelper.ts b/sdk/maps/maps-search-rest/src/generated/pollingHelper.ts deleted file mode 100644 index 8e3cd945ae46..000000000000 --- a/sdk/maps/maps-search-rest/src/generated/pollingHelper.ts +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { Client, HttpResponse } from "@azure-rest/core-client"; -import { - LongRunningOperation, - LroEngine, - LroEngineOptions, - LroResponse, - PollerLike, - PollOperationState -} from "@azure/core-lro"; - -/** - * Helper function that builds a Poller object to help polling a long running operation. - * @param client - Client to use for sending the request to get additional pages. - * @param initialResponse - The initial response. - * @param options - Options to set a resume state or custom polling interval. - * @returns - A poller object to poll for operation state updates and eventually get the final response. - */ -export function getLongRunningPoller( - client: Client, - initialResponse: TResult, - options: LroEngineOptions> = {} -): PollerLike, TResult> { - const poller: LongRunningOperation = { - requestMethod: initialResponse.request.method, - requestPath: initialResponse.request.url, - sendInitialRequest: async () => { - // In the case of Rest Clients we are building the LRO poller object from a response that's the reason - // we are not triggering the initial request here, just extracting the information from the - // response we were provided. - return getLroResponse(initialResponse); - }, - sendPollRequest: async (path) => { - // This is the callback that is going to be called to poll the service - // to get the latest status. We use the client provided and the polling path - // which is an opaque URL provided by caller, the service sends this in one of the following headers: operation-location, azure-asyncoperation or location - // depending on the lro pattern that the service implements. If non is provided we default to the initial path. - const response = await client - .pathUnchecked(path ?? initialResponse.request.url) - .get(); - const lroResponse = getLroResponse(response as TResult); - lroResponse.rawResponse.headers["x-ms-original-url"] = - initialResponse.request.url; - return lroResponse; - } - }; - - return new LroEngine(poller, options); -} - -/** - * Converts a Rest Client response to a response that the LRO engine knows about - * @param response - a rest client http response - * @returns - An LRO response that the LRO engine can work with - */ -function getLroResponse( - response: TResult -): LroResponse { - if (Number.isNaN(response.status)) { - throw new TypeError( - `Status code of the response is not a number. Value: ${response.status}` - ); - } - - return { - flatResponse: response, - rawResponse: { - ...response, - statusCode: Number.parseInt(response.status), - body: response.body - } - }; -} diff --git a/sdk/maps/maps-search-rest/src/index.ts b/sdk/maps/maps-search-rest/src/index.ts index 97fc6d648bb0..9a0c5844337b 100644 --- a/sdk/maps/maps-search-rest/src/index.ts +++ b/sdk/maps/maps-search-rest/src/index.ts @@ -2,5 +2,5 @@ // Licensed under the MIT License. import MapsSearch from "./MapsSearch"; -export * from "./generated"; +export * from "../generated"; export default MapsSearch; diff --git a/sdk/maps/maps-search-rest/swagger/README.md b/sdk/maps/maps-search-rest/swagger/README.md index cfff4abd97b0..f102ba07afa0 100644 --- a/sdk/maps/maps-search-rest/swagger/README.md +++ b/sdk/maps/maps-search-rest/swagger/README.md @@ -8,6 +8,8 @@ The configuration is following the [RLC quick start guide](https://github.com/Az For the configuration property, please refer to [Index of AutoRest Flag](https://github.com/Azure/autorest/blob/main/docs/generate/flags.md). ```yaml +flavor: azure +openapi-type: data-plane package-name: "@azure-rest/maps-search" title: MapsSearchClient description: Azure Maps Search Client @@ -18,12 +20,12 @@ generate-metadata: false # This flag generated test files such as sampleTest.spec.ts and recordedClient.ts. # Switch to false after the first generation due to the same reason above. generate-test: false -# This flag generated the the sample files +# This flag generated the sample files # Switch to false after the first generation due to the same reason above. generate-sample: false license-header: MICROSOFT_MIT_NO_VERSION output-folder: ../ -source-code-folder-path: ./src/generated +source-code-folder-path: ./generated input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/maps/data-plane/Search/stable/2023-06-01/search.json package-version: 2.0.0-beta.2 rest-level-client: true @@ -32,7 +34,7 @@ rest-level-client: true security: AzureKey security-header-name: subscription-key use-extension: - "@autorest/typescript": "6.0.12" + "@autorest/typescript": "latest" ``` ## Customization for Track 2 Generator diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/src/common/constants.ts b/sdk/playwrighttesting/microsoft-playwright-testing/src/common/constants.ts index 16e5332fa162..c2ffeb218b1e 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/src/common/constants.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/src/common/constants.ts @@ -57,7 +57,6 @@ export class Constants { public static readonly TEST_TYPE = "WebTest"; public static readonly TEST_SDK_LANGUAGE = "JAVASCRIPT"; // Placeholder version - public static readonly REPORTER_PACKAGE_VERSION = "1.0.0-beta.3"; public static readonly DEFAULT_DASHBOARD_ENDPOINT = "https://playwright.microsoft.com"; public static readonly DEFAULT_SERVICE_ENDPOINT = "https://{region}.reporting.api.playwright-test.io"; diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/src/core/playwrightService.ts b/sdk/playwrighttesting/microsoft-playwright-testing/src/core/playwrightService.ts index 346b250ca4df..7a030ffc4e30 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/src/core/playwrightService.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/src/core/playwrightService.ts @@ -20,6 +20,7 @@ import { validatePlaywrightVersion, validateServiceUrl, exitWithFailureMessage, + getPackageVersion, } from "../utils/utils"; /** @@ -96,11 +97,11 @@ const getServiceConfig = ( connectOptions: { wsEndpoint: getServiceWSEndpoint( playwrightServiceConfig.runId, - playwrightServiceConfig.runName, playwrightServiceConfig.serviceOs, ), headers: { Authorization: `Bearer ${getAccessToken()}`, + "x-ms-package-version": `@azure/microsoft-playwright-testing/${getPackageVersion()}`, }, timeout: playwrightServiceConfig.timeout, exposeNetwork: playwrightServiceConfig.exposeNetwork, @@ -149,12 +150,12 @@ const getConnectOptions = async ( return { wsEndpoint: getServiceWSEndpoint( playwrightServiceConfig.runId, - playwrightServiceConfig.runName, playwrightServiceConfig.serviceOs, ), options: { headers: { Authorization: `Bearer ${token}`, + "x-ms-package-version": `@azure/microsoft-playwright-testing/${getPackageVersion()}`, }, timeout: playwrightServiceConfig.timeout, exposeNetwork: playwrightServiceConfig.exposeNetwork, diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/reporterUtils.ts b/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/reporterUtils.ts index a76ed19a82c6..6b88ff8796f4 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/reporterUtils.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/reporterUtils.ts @@ -31,7 +31,7 @@ import type { CIInfo } from "./cIInfoProvider"; import { CI_PROVIDERS } from "./cIInfoProvider"; import { CIInfoProvider } from "./cIInfoProvider"; import type { StorageUri } from "../model/storageUri"; - +import { getPackageVersion } from "./utils"; class ReporterUtils { private envVariables: EnvironmentVariables; @@ -372,10 +372,12 @@ class ReporterUtils { const completed = Math.round(width * percent); const remaining = width - completed; - process.stdout.write("\r"); - process.stdout.write( - `[${"=".repeat(completed)}${" ".repeat(remaining)}] ${Math.round(percent * 100)}%`, - ); + if (current % Math.round(total / 5) === 0 || current === total) { + process.stdout.write("\r"); + process.stdout.write( + `[${"=".repeat(completed)}${" ".repeat(remaining)}] ${Math.round(percent * 100)}%`, + ); + } } private getTestRunConfig(): TestRunConfig { @@ -393,7 +395,7 @@ class ReporterUtils { }, testType: Constants.TEST_TYPE, testSdkLanguage: Constants.TEST_SDK_LANGUAGE, - reporterPackageVersion: Constants.REPORTER_PACKAGE_VERSION, + reporterPackageVersion: getPackageVersion(), }; return testRunConfig; } diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/utils.ts b/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/utils.ts index 42052df92ff3..3411f4444081 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/utils.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/src/utils/utils.ts @@ -68,8 +68,8 @@ export const getAndSetRunId = (): string => { return runId; }; -export const getServiceWSEndpoint = (runId: string, runName: string, os: string): string => { - return `${getServiceBaseURL()}?runId=${encodeURIComponent(runId)}&runName=${encodeURIComponent(runName)}&os=${os}&api-version=${API_VERSION}`; +export const getServiceWSEndpoint = (runId: string, os: string): string => { + return `${getServiceBaseURL()}?runId=${encodeURIComponent(runId)}&os=${os}&api-version=${API_VERSION}`; }; export const validateServiceUrl = (): void => { @@ -143,6 +143,16 @@ export const getPlaywrightVersion = (): string => { return process.env[InternalEnvironmentVariables.MPT_PLAYWRIGHT_VERSION]!; }; +export const getPackageVersion = (): string => { + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const version = require("../../package.json").version; + return version; + } catch (error) { + console.error("Error fetching package version:", error); + return "unknown version"; + } +}; export const getVersionInfo = (version: string): VersionInfo => { const regex = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?/; const match = version.match(regex); diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/test/core/playwrightService.spec.ts b/sdk/playwrighttesting/microsoft-playwright-testing/test/core/playwrightService.spec.ts index 0549e2fdb9db..a8c608904d1c 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/test/core/playwrightService.spec.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/test/core/playwrightService.spec.ts @@ -130,14 +130,17 @@ describe("getServiceConfig", () => { it("should return service config with service connect options", () => { process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_ACCESS_TOKEN] = "token"; const { getServiceConfig } = require("../../src/core/playwrightService"); - const config = getServiceConfig(samplePlaywrightConfigInput); const playwrightServiceConfig = new PlaywrightServiceConfig(); + const mockVersion = "1.0.0"; + sandbox.stub(require("../../package.json"), "version").value(mockVersion); + const config = getServiceConfig(samplePlaywrightConfigInput); expect(config).to.deep.equal({ use: { connectOptions: { - wsEndpoint: `wss://eastus.playwright.microsoft.com/accounts/1234/browsers?runId=${playwrightServiceConfig.runId}&runName=${playwrightServiceConfig.runName}&os=${playwrightServiceConfig.serviceOs}&api-version=${API_VERSION}`, + wsEndpoint: `wss://eastus.playwright.microsoft.com/accounts/1234/browsers?runId=${playwrightServiceConfig.runId}&os=${playwrightServiceConfig.serviceOs}&api-version=${API_VERSION}`, headers: { Authorization: "Bearer token", + "x-ms-package-version": `@azure/microsoft-playwright-testing/${encodeURIComponent(mockVersion)}`, }, timeout: playwrightServiceConfig.timeout, exposeNetwork: playwrightServiceConfig.exposeNetwork, @@ -198,20 +201,25 @@ describe("getConnectOptions", () => { }); it("should set service connect options with fetched token", async () => { + const sandbox = sinon.createSandbox(); const { getConnectOptions } = require("../../src/core/playwrightService"); + const mockVersion = "1.0.0"; + sandbox.stub(require("../../package.json"), "version").value(mockVersion); const connectOptions = await getConnectOptions({}); const playwrightServiceConfig = new PlaywrightServiceConfig(); expect(connectOptions).to.deep.equal({ - wsEndpoint: `wss://eastus.playwright.microsoft.com/accounts/1234/browsers?runId=${playwrightServiceConfig.runId}&runName=${playwrightServiceConfig.runName}&os=${playwrightServiceConfig.serviceOs}&api-version=${API_VERSION}`, + wsEndpoint: `wss://eastus.playwright.microsoft.com/accounts/1234/browsers?runId=${playwrightServiceConfig.runId}&os=${playwrightServiceConfig.serviceOs}&api-version=${API_VERSION}`, options: { headers: { Authorization: "Bearer token", + "x-ms-package-version": `@azure/microsoft-playwright-testing/${encodeURIComponent(mockVersion)}`, }, timeout: new PlaywrightServiceConfig().timeout, exposeNetwork: new PlaywrightServiceConfig().exposeNetwork, slowMo: new PlaywrightServiceConfig().slowMo, }, }); + sandbox.restore(); }); it("should throw error if token is not set", async () => { diff --git a/sdk/playwrighttesting/microsoft-playwright-testing/test/utils/utils.spec.ts b/sdk/playwrighttesting/microsoft-playwright-testing/test/utils/utils.spec.ts index 55c2effbb7ab..09c487045c98 100644 --- a/sdk/playwrighttesting/microsoft-playwright-testing/test/utils/utils.spec.ts +++ b/sdk/playwrighttesting/microsoft-playwright-testing/test/utils/utils.spec.ts @@ -75,24 +75,21 @@ describe("Service Utils", () => { "wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers"; const runId = "2021-10-11T07:00:00.000Z"; const escapeRunId = encodeURIComponent(runId); - const runName = "runName"; const os = "windows"; - const expected = `wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers?runId=${escapeRunId}&runName=${runName}&os=${os}&api-version=${API_VERSION}`; - expect(getServiceWSEndpoint(runId, runName, os)).to.equal(expected); + const expected = `wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers?runId=${escapeRunId}&os=${os}&api-version=${API_VERSION}`; + expect(getServiceWSEndpoint(runId, os)).to.equal(expected); delete process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL]; }); - it("should escape special character in runName and runId", () => { + it("should escape special character in runId", () => { process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL] = "wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers"; const runId = "2021-10-11T07:00:00.000Z"; const escapeRunId = encodeURIComponent(runId); - const runName = "run#Name-12/09"; - const escapeRunName = encodeURIComponent(runName); const os = "windows"; - const expected = `wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers?runId=${escapeRunId}&runName=${escapeRunName}&os=${os}&api-version=${API_VERSION}`; - expect(getServiceWSEndpoint(runId, runName, os)).to.equal(expected); + const expected = `wss://eastus.api.playwright.microsoft.com/accounts/1234/browsers?runId=${escapeRunId}&os=${os}&api-version=${API_VERSION}`; + expect(getServiceWSEndpoint(runId, os)).to.equal(expected); delete process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL]; }); @@ -495,4 +492,11 @@ describe("Service Utils", () => { const result = populateValuesFromServiceUrl(); expect(result).to.be.null; }); + it("should return the correct version from package.json", async () => { + const mockVersion = "1.0.0"; + const packageJson = require("../../package.json"); + sandbox.stub(packageJson, "version").value(mockVersion); + const version = utils.getPackageVersion(); + expect(version).to.equal(mockVersion); + }); }); diff --git a/sdk/test-utils/recorder/package.json b/sdk/test-utils/recorder/package.json index 2acb72dae29a..60da394742f4 100644 --- a/sdk/test-utils/recorder/package.json +++ b/sdk/test-utils/recorder/package.json @@ -35,8 +35,6 @@ }, "files": [ "dist/", - "dist-esm/src/", - "types/src", "README.md", "LICENSE" ], diff --git a/sdk/translation/ai-translation-document-rest/CHANGELOG.md b/sdk/translation/ai-translation-document-rest/CHANGELOG.md index 32de784ead1e..47f16b8249da 100644 --- a/sdk/translation/ai-translation-document-rest/CHANGELOG.md +++ b/sdk/translation/ai-translation-document-rest/CHANGELOG.md @@ -1,18 +1,9 @@ # Release History -## 2.0.0-beta.1 (Unreleased) +## 1.0.0 (2024-11-15) -### Features Added - -### Breaking Changes - -### Bugs Fixed - -### Other Changes - -## 2.0.0 (Unreleased) ### Other Changes -This is a GA release. No new features added. +- Renamed SingleDocumentTranslationClient's API from `document_translate` to `translate` ## 1.0.0-beta.2 (2024-07-01) diff --git a/sdk/translation/ai-translation-document-rest/package.json b/sdk/translation/ai-translation-document-rest/package.json index 45d3248e60b6..1abf60f8691f 100644 --- a/sdk/translation/ai-translation-document-rest/package.json +++ b/sdk/translation/ai-translation-document-rest/package.json @@ -3,7 +3,7 @@ "sdk-type": "client", "author": "Microsoft Corporation", "description": "A generated SDK for DocumentTranslationClient.", - "version": "2.0.0-beta.1", + "version": "1.0.0", "keywords": [ "node", "azure", diff --git a/sdk/web-pubsub/web-pubsub-client-protobuf/package.json b/sdk/web-pubsub/web-pubsub-client-protobuf/package.json index b8061ae5b4b1..18d89acd9675 100644 --- a/sdk/web-pubsub/web-pubsub-client-protobuf/package.json +++ b/sdk/web-pubsub/web-pubsub-client-protobuf/package.json @@ -21,7 +21,7 @@ "build:samples": "dev-tool samples publish -f", "build:test": "npm run build-protobuf && dev-tool run build-package && npm run copy-files", "check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", - "clean": "dev-tool run vendored rimraf --glob dist dist-esm test-dist temp types *.tgz *.log", + "clean": "dev-tool run vendored rimraf --glob dist test-dist temp types *.tgz *.log", "copy-files": "npm run copy-files:cjs && npm run copy-files:esm", "copy-files:cjs": "cpy --flat --rename=clientProto.js ./src/generated/clientProto.cjs ./dist/commonjs/generated/ && cpy --flat ./src/generated/clientProto.d.ts ./dist/esm/generated/", "copy-files:esm": "cpy --flat ./src/generated/clientProto.js ./dist/esm/generated/ && cpy --flat ./src/generated/clientProto.d.ts ./dist/esm/generated/", @@ -44,7 +44,6 @@ }, "files": [ "dist/", - "dist-esm/", "types/web-pubsub-client-protobuf.d.ts", "types/web-pubsub-client-protobuf.d.ts.map", "README.md",