diff --git a/.vscode-test.js b/.vscode-test.js index f2db8d695fe..89e1b855ee0 100644 --- a/.vscode-test.js +++ b/.vscode-test.js @@ -45,6 +45,10 @@ const extensions = [ label: 'github-authentication', workspaceFolder: path.join(os.tmpdir(), `msft-auth-${Math.floor(Math.random() * 100000)}`), mocha: { timeout: 60_000 } + }, + { + label: 'microsoft-authentication', + mocha: { timeout: 60_000 } } ]; diff --git a/extensions/microsoft-authentication/src/common/test/loopbackClientAndOpener.test.ts b/extensions/microsoft-authentication/src/common/test/loopbackClientAndOpener.test.ts new file mode 100644 index 00000000000..5c55567d1d0 --- /dev/null +++ b/extensions/microsoft-authentication/src/common/test/loopbackClientAndOpener.test.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { env, Uri } from 'vscode'; +import * as sinon from 'sinon'; +import { UriHandlerLoopbackClient } from '../loopbackClientAndOpener'; +import { UriEventHandler } from '../../UriEventHandler'; + +suite('UriHandlerLoopbackClient', () => { + const redirectUri = 'http://localhost'; + let uriHandler: UriEventHandler; + let client: UriHandlerLoopbackClient; + let envStub: sinon.SinonStubbedInstance; + let callbackUri: Uri; + + setup(async () => { + callbackUri = await env.asExternalUri(Uri.parse(`${env.uriScheme}://vscode.microsoft-authentication`)); + envStub = sinon.stub(env); + envStub.openExternal.resolves(true); + envStub.asExternalUri.callThrough(); + uriHandler = new UriEventHandler(); + client = new UriHandlerLoopbackClient(uriHandler, redirectUri); + }); + + teardown(() => { + sinon.restore(); + uriHandler.dispose(); + }); + + suite('openBrowser', () => { + test('should open browser with correct URL', async () => { + const testUrl = 'http://example.com?foo=5'; + + await client.openBrowser(testUrl); + + assert.ok(envStub.asExternalUri.calledOnce); + assert.ok(envStub.openExternal.calledOnce); + + const expectedUri = Uri.parse(testUrl + `&state=${encodeURI(callbackUri.toString(true))}`); + const value = envStub.openExternal.getCalls()[0].args[0]; + assert.strictEqual(value.toString(true), expectedUri.toString(true)); + }); + }); + + suite('getRedirectUri', () => { + test('should return the redirect URI', () => { + const result = client.getRedirectUri(); + assert.strictEqual(result, redirectUri); + }); + }); + + suite('listenForAuthCode', () => { + test('should return auth code from URL', async () => { + const code = '1234'; + const state = '5678'; + const testUrl = Uri.parse(`http://example.com?code=${code}&state=${state}`); + const promise = client.listenForAuthCode(); + uriHandler.handleUri(testUrl); + const result = await promise; + + assert.strictEqual(result.code, code); + assert.strictEqual(result.state, state); + }); + + test('should return auth error from URL', async () => { + const error = 'access_denied'; + const errorDescription = 'reason'; + const errorUri = 'uri'; + const testUrl = Uri.parse(`http://example.com?error=${error}&error_description=${errorDescription}&error_uri=${errorUri}`); + + const promise = client.listenForAuthCode(); + uriHandler.handleUri(testUrl); + const result = await promise; + + assert.strictEqual(result.error, 'access_denied'); + assert.strictEqual(result.error_description, 'reason'); + assert.strictEqual(result.error_uri, 'uri'); + }); + }); +});