/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Page } from 'playwright';6import { TestContext } from './context.js';7import { GitHubAuth } from './githubAuth.js';8import { UITest } from './uiTest.js';910export function setup(context: TestContext) {11/*12TODO: @dmitrivMS Reenable other platforms once throttling issues with GitHub account are resolved.1314context.test('dev-tunnel-alpine-arm64', ['alpine', 'arm64', 'browser', 'github-account'], async () => {15const dir = await context.downloadAndUnpack('cli-alpine-arm64');16const entryPoint = context.getCliEntryPoint(dir);17await testCliApp(entryPoint);18});1920context.test('dev-tunnel-alpine-x64', ['alpine', 'x64', 'browser', 'github-account'], async () => {21const dir = await context.downloadAndUnpack('cli-alpine-x64');22const entryPoint = context.getCliEntryPoint(dir);23await testCliApp(entryPoint);24});2526context.test('dev-tunnel-linux-arm64', ['linux', 'arm64', 'browser', 'github-account'], async () => {27const dir = await context.downloadAndUnpack('cli-linux-arm64');28const entryPoint = context.getCliEntryPoint(dir);29await testCliApp(entryPoint);30});3132context.test('dev-tunnel-linux-armhf', ['linux', 'arm32', 'browser', 'github-account'], async () => {33const dir = await context.downloadAndUnpack('cli-linux-armhf');34const entryPoint = context.getCliEntryPoint(dir);35await testCliApp(entryPoint);36});3738context.test('dev-tunnel-linux-x64', ['linux', 'x64', 'browser', 'github-account'], async () => {39const dir = await context.downloadAndUnpack('cli-linux-x64');40const entryPoint = context.getCliEntryPoint(dir);41await testCliApp(entryPoint);42});4344context.test('dev-tunnel-darwin-arm64', ['darwin', 'arm64', 'browser', 'github-account'], async () => {45const dir = await context.downloadAndUnpack('cli-darwin-arm64');46context.validateAllCodesignSignatures(dir);47const entryPoint = context.getCliEntryPoint(dir);48await testCliApp(entryPoint);49});50*/5152context.test('dev-tunnel-darwin-x64', ['darwin', 'x64', 'browser', 'github-account'], async () => {53const dir = await context.downloadAndUnpack('cli-darwin-x64');54context.validateAllCodesignSignatures(dir);55const entryPoint = context.getCliEntryPoint(dir);56await testCliApp(entryPoint);57});5859/** TODO: @dmitrivMS Fix flakiness and then reenable60context.test('dev-tunnel-win32-arm64', ['windows', 'arm64', 'browser', 'github-account'], async () => {61const dir = await context.downloadAndUnpack('cli-win32-arm64');62context.validateAllAuthenticodeSignatures(dir);63context.validateAllVersionInfo(dir);64const entryPoint = context.getCliEntryPoint(dir);65await testCliApp(entryPoint);66});6768context.test('dev-tunnel-win32-x64', ['windows', 'x64', 'browser', 'github-account'], async () => {69const dir = await context.downloadAndUnpack('cli-win32-x64');70context.validateAllAuthenticodeSignatures(dir);71context.validateAllVersionInfo(dir);72const entryPoint = context.getCliEntryPoint(dir);73await testCliApp(entryPoint);74});75*/7677async function testCliApp(entryPoint: string) {78if (context.options.downloadOnly) {79return;80}8182const cliDataDir = context.createTempDir();83context.log('Logging out of Dev Tunnel to ensure fresh authentication');84context.run(entryPoint, '--cli-data-dir', cliDataDir, 'tunnel', 'user', 'logout');8586const test = new UITest(context);87const auth = new GitHubAuth(context);88const browser = await context.launchBrowser();89try {90const page = await context.getPage(browser.newPage());91context.log('Starting Dev Tunnel to local server using CLI');92await context.runCliApp('CLI', entryPoint,93[94'--cli-data-dir', cliDataDir,95'tunnel',96'--accept-server-license-terms',97'--server-data-dir', context.createTempDir(),98'--extensions-dir', test.extensionsDir,99'--verbose'100],101async (line) => {102const deviceCode = /To grant access .* use code ([A-Z0-9-]+)/.exec(line)?.[1];103if (deviceCode) {104context.log(`Device code detected: ${deviceCode}, starting device flow authentication`);105await auth.runDeviceCodeFlow(page, deviceCode);106return;107}108109const tunnelUrl = /Open this link in your browser (https?:\/\/[^\s]+)/.exec(line)?.[1];110if (tunnelUrl) {111await connectToTunnel(tunnelUrl, page, test, auth);112await test.run(page);113test.validate();114return true;115}116}117);118} finally {119context.log('Closing browser');120await browser.close();121}122}123124async function connectToTunnel(tunnelUrl: string, page: Page, test: UITest, auth: GitHubAuth) {125try {126const tunnelId = new URL(tunnelUrl).pathname.split('/').pop()!;127const url = context.getTunnelUrl(tunnelUrl, test.workspaceDir);128context.log(`CLI started successfully with tunnel URL: ${url}`);129130context.log(`Navigating to ${url}`);131await page.goto(url);132133context.log('Waiting for the workbench to load');134await page.waitForSelector('.monaco-workbench');135136await test.dismissWelcomeDialog(page);137138context.log('Selecting GitHub Account');139await page.locator('span.monaco-highlighted-label', { hasText: 'GitHub' }).click();140141context.log('Clicking Allow on confirmation dialog');142const popup = page.waitForEvent('popup');143await page.getByRole('button', { name: 'Allow' }).click();144145await auth.runAuthorizeFlow(await popup);146147context.log('Waiting for connection to be established');148await page.getByRole('button', { name: `remote ${tunnelId}` }).waitFor({ timeout: 5 * 60 * 1000 });149} catch (error) {150context.log('Error during tunnel connection, capturing screenshot');151await context.captureScreenshot(page);152throw error;153}154}155}156157158