/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; import { _electron } from 'playwright'; import { TestContext } from './context.js'; import { UITest } from './uiTest.js'; export function setup(context: TestContext) { context.test('wsl-server-arm64', ['windows', 'arm64', 'wsl'], async () => { const dir = await context.downloadAndUnpack('server-linux-arm64'); const entryPoint = context.getServerEntryPoint(dir, true); await testServer(entryPoint); }); context.test('wsl-server-x64', ['windows', 'x64', 'wsl'], async () => { const dir = await context.downloadAndUnpack('server-linux-x64'); const entryPoint = context.getServerEntryPoint(dir, true); await testServer(entryPoint); }); context.test('wsl-server-web-arm64', ['windows', 'arm64', 'wsl', 'browser'], async () => { const dir = await context.downloadAndUnpack('server-linux-arm64-web'); const entryPoint = context.getServerEntryPoint(dir, true); await testServerWeb(entryPoint); }); context.test('wsl-server-web-x64', ['windows', 'x64', 'wsl', 'browser'], async () => { const dir = await context.downloadAndUnpack('server-linux-x64-web'); const entryPoint = context.getServerEntryPoint(dir, true); await testServerWeb(entryPoint); }); context.test('wsl-desktop-arm64', ['windows', 'arm64', 'wsl', 'desktop'], async () => { const dir = await context.downloadAndUnpack('win32-arm64-archive'); context.validateAllAuthenticodeSignatures(dir); context.validateAllVersionInfo(dir); if (!context.options.downloadOnly) { const entryPoint = context.getDesktopEntryPoint(dir); const dataDir = context.createPortableDataDir(dir); await testDesktopApp(entryPoint, dataDir); } }); context.test('wsl-desktop-x64', ['windows', 'x64', 'wsl', 'desktop'], async () => { const dir = await context.downloadAndUnpack('win32-x64-archive'); context.validateAllAuthenticodeSignatures(dir); context.validateAllVersionInfo(dir); if (!context.options.downloadOnly) { const entryPoint = context.getDesktopEntryPoint(dir); const dataDir = context.createPortableDataDir(dir); await testDesktopApp(entryPoint, dataDir); } }); async function testServer(entryPoint: string) { if (context.options.downloadOnly) { return; } await context.runCliApp('WSL Server', 'wsl', [ context.toWslPath(entryPoint), '--accept-server-license-terms', '--connection-token', context.getRandomToken(), '--host', '0.0.0.0', '--port', context.getUniquePort(), '--server-data-dir', context.createWslTempDir(), '--extensions-dir', context.createWslTempDir(), ], async (line) => { const port = /Extension host agent listening on (\d+)/.exec(line)?.[1]; if (!port) { return; } const url = new URL('version', context.getWebServerUrl(port)).toString(); context.log(`Fetching version from ${url}`); const response = await context.fetchNoErrors(url); const version = await response.text(); assert.strictEqual(version, context.options.commit, `Expected commit ${context.options.commit} but got ${version}`); return true; } ); } async function testServerWeb(entryPoint: string) { if (context.options.downloadOnly) { return; } const wslWorkspaceDir = context.createWslTempDir(); const wslExtensionsDir = context.createWslTempDir(); const token = context.getRandomToken(); const test = new WslUITest(context, undefined, wslWorkspaceDir, wslExtensionsDir); await context.runCliApp('WSL Server', 'wsl', [ context.toWslPath(entryPoint), '--accept-server-license-terms', '--connection-token', token, '--host', '0.0.0.0', '--port', context.getUniquePort(), '--server-data-dir', context.createWslTempDir(), '--extensions-dir', wslExtensionsDir, '--user-data-dir', context.createWslTempDir(), ], async (line) => { const port = /Extension host agent listening on (\d+)/.exec(line)?.[1]; if (!port) { return false; } const url = context.getWebServerUrl(port, token, wslWorkspaceDir).toString(); const browser = await context.launchBrowser(); try { const page = await context.getPage(browser.newPage()); context.log(`Navigating to ${url}`); await page.goto(url, { waitUntil: 'networkidle' }); context.log('Waiting for the workbench to load'); await page.waitForSelector('.monaco-workbench'); await test.run(page); } finally { context.log('Closing browser'); await browser.close(); } test.validate(); return true; } ); } async function testDesktopApp(entryPoint: string, dataDir: string) { const wslExtensionsDir = context.getWslServerExtensionsDir(); context.deleteWslDir(wslExtensionsDir); const wslWorkspaceDir = context.createWslTempDir(); const wslDistro = context.getDefaultWslDistro(); const test = new WslUITest(context, dataDir, wslWorkspaceDir, wslExtensionsDir); const args = [ '--extensions-dir', context.createTempDir(), '--user-data-dir', test.userDataDir, '--folder-uri', `vscode-remote://wsl+${wslDistro}${wslWorkspaceDir}`, ]; context.log(`Starting VS Code ${entryPoint} with args ${args.join(' ')}`); const app = await _electron.launch({ executablePath: entryPoint, args }); try { const window = await context.getPage(app.firstWindow()); context.log('Installing WSL extension'); await window.getByRole('button', { name: 'Install and Reload' }).click(); context.log('Waiting for WSL connection'); await window.getByText(/WSL/).waitFor(); await test.run(window); } finally { context.log('Closing the application'); await app.close(); } test.validate(); } } /** * UI Test subclass for WSL that validates files in WSL filesystem. */ class WslUITest extends UITest { constructor( context: TestContext, dataDir: string | undefined, private readonly wslWorkspaceDir: string, private readonly wslExtensionsDir: string ) { super(context, dataDir); } protected override verifyTextFileCreated() { this.context.log('Verifying file contents in WSL'); const result = this.context.runNoErrors('wsl', 'cat', `${this.wslWorkspaceDir}/helloWorld.txt`); assert.strictEqual(result.stdout.trim(), 'Hello, World!', 'File contents in WSL do not match expected value'); } protected override verifyExtensionInstalled() { this.context.log(`Verifying extension is installed in WSL at ${this.wslExtensionsDir}`); const result = this.context.runNoErrors('wsl', 'ls', this.wslExtensionsDir); const hasExtension = result.stdout.split('\n').some(ext => ext.startsWith('github.vscode-pull-request-github')); assert.strictEqual(hasExtension, true, 'GitHub Pull Requests extension is not installed in WSL'); } }