Skip to content

Commit

Permalink
fix: ensure all paths use uppercase drive letter (#587)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmitry Gozman (from Dev Box) <[email protected]>
  • Loading branch information
dgozman and Dmitry Gozman (from Dev Box) authored Jan 10, 2025
1 parent 7ec54c5 commit 4068938
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 53 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ module.exports = {
*/
'rules': {
'@typescript-eslint/no-unused-vars': [2, { args: 'none' }],

'no-restricted-properties': [2, {
'property': 'fsPath',
'message': 'Please use uriToPath(uri) instead.',
}],

/**
* Enforced rules
*/
Expand Down
5 changes: 3 additions & 2 deletions src/debugHighlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { replaceActionWithLocator, locatorMethodRegex } from './methodNames';
import type { Location } from './upstream/reporter';
import { ReusedBrowser } from './reusedBrowser';
import * as vscodeTypes from './vscodeTypes';
import { normalizePath, uriToPath } from './utils';

export type DebuggerError = { error: string, location: Location };

Expand Down Expand Up @@ -144,7 +145,7 @@ export type StackFrame = {
const sessionsWithHighlight = new Set<vscodeTypes.DebugSession>();

async function locatorToHighlight(debugSessions: Map<string, vscodeTypes.DebugSession>, document: vscodeTypes.TextDocument, position: vscodeTypes.Position, token?: vscodeTypes.CancellationToken): Promise<string | undefined> {
const fsPath = document.uri.fsPath;
const fsPath = uriToPath(document.uri);

if (!debugSessions.size) {
// When not debugging, discover all the locator-alike expressions.
Expand Down Expand Up @@ -183,7 +184,7 @@ async function locatorToHighlight(debugSessions: Map<string, vscodeTypes.DebugSe
if (!stackFrame.source)
continue;
const sourcePath = mapRemoteToLocalPath(stackFrame.source.path);
if (!sourcePath || document.uri.fsPath !== sourcePath)
if (!sourcePath || fsPath !== normalizePath(sourcePath))
continue;
if (token?.isCancellationRequested)
return;
Expand Down
24 changes: 12 additions & 12 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { SettingsModel } from './settingsModel';
import { SettingsView } from './settingsView';
import { TestModel, TestModelCollection } from './testModel';
import { TestTree } from './testTree';
import { NodeJSNotFoundError, getPlaywrightInfo, stripAnsi, stripBabelFrame } from './utils';
import { NodeJSNotFoundError, getPlaywrightInfo, stripAnsi, stripBabelFrame, uriToPath } from './utils';
import * as vscodeTypes from './vscodeTypes';
import { WorkspaceChange, WorkspaceObserver } from './workspaceObserver';
import { registerTerminalLinkProvider } from './terminalLinkProvider';
Expand Down Expand Up @@ -254,9 +254,9 @@ export class Extension implements RunHooks {

const rebuildModelForConfig = (uri: vscodeTypes.Uri) => {
// TODO: parse .gitignore
if (uri.fsPath.includes('node_modules'))
if (uriToPath(uri).includes('node_modules'))
return;
if (!this._isUnderTest && uri.fsPath.includes('test-results'))
if (!this._isUnderTest && uriToPath(uri).includes('test-results'))
return;
this._rebuildModels(false);
};
Expand All @@ -275,16 +275,16 @@ export class Extension implements RunHooks {

const configFiles = await this._vscode.workspace.findFiles('**/*playwright*.config.{ts,js,mts,mjs}', '**/node_modules/**');
// findFiles returns results in a non-deterministic order - sort them to ensure consistent order when we enable the first model by default.
configFiles.sort((a, b) => a.fsPath.localeCompare(b.fsPath));
configFiles.sort((a, b) => uriToPath(a).localeCompare(uriToPath(b)));
for (const configFileUri of configFiles) {
const configFilePath = configFileUri.fsPath;
const configFilePath = uriToPath(configFileUri);
// TODO: parse .gitignore
if (!this._isUnderTest && configFilePath.includes('test-results'))
continue;

// Dog-food support
const workspaceFolder = this._vscode.workspace.getWorkspaceFolder(configFileUri)!;
const workspaceFolderPath = workspaceFolder.uri.fsPath;
const workspaceFolderPath = uriToPath(workspaceFolder.uri);
if (configFilePath.includes('test-results') && !workspaceFolderPath.includes('test-results'))
continue;

Expand Down Expand Up @@ -313,7 +313,7 @@ export class Extension implements RunHooks {

if (this.overridePlaywrightVersion)
playwrightInfo.version = this.overridePlaywrightVersion;
await this._models.createModel(workspaceFolderPath, configFileUri.fsPath, playwrightInfo);
await this._models.createModel(workspaceFolderPath, uriToPath(configFileUri), playwrightInfo);
}

await this._models.ensureHasEnabledModels();
Expand Down Expand Up @@ -452,7 +452,7 @@ export class Extension implements RunHooks {
private async _resolveChildren(fileItem: vscodeTypes.TestItem | undefined): Promise<void> {
if (!fileItem)
return;
await this._ensureTestsInAllModels([fileItem!.uri!.fsPath]);
await this._ensureTestsInAllModels([uriToPath(fileItem!.uri!)]);
}

private async _workspaceChanged(change: WorkspaceChange) {
Expand Down Expand Up @@ -612,7 +612,7 @@ export class Extension implements RunHooks {
}

private async _updateVisibleEditorItems() {
const files = this._vscode.window.visibleTextEditors.map(e => e.document.uri.fsPath);
const files = this._vscode.window.visibleTextEditors.map(e => uriToPath(e.document.uri));
await this._ensureTestsInAllModels(files);
}

Expand Down Expand Up @@ -671,13 +671,13 @@ export class Extension implements RunHooks {
for (const editor of this._vscode.window.visibleTextEditors) {
const activeDecorations: vscodeTypes.DecorationOptions[] = [];
for (const { location } of active) {
if (location.uri.fsPath === editor.document.uri.fsPath)
if (uriToPath(location.uri) === uriToPath(editor.document.uri))
activeDecorations.push({ range: location.range });
}

const completedDecorations: vscodeTypes.DecorationOptions[] = [];
for (const { location, duration } of completed) {
if (location.uri.fsPath === editor.document.uri.fsPath) {
if (uriToPath(location.uri) === uriToPath(editor.document.uri)) {
completedDecorations.push({
range: location.range,
renderOptions: {
Expand Down Expand Up @@ -708,7 +708,7 @@ export class Extension implements RunHooks {

private _abbreviateStack(text: string): string {
const result: string[] = [];
const prefixes = (this._vscode.workspace.workspaceFolders || []).map(f => f.uri.fsPath.toLowerCase() + path.sep);
const prefixes = (this._vscode.workspace.workspaceFolders || []).map(f => uriToPath(f.uri).toLowerCase() + path.sep);
for (let line of text.split('\n')) {
const lowerLine = line.toLowerCase();
for (const prefix of prefixes) {
Expand Down
3 changes: 2 additions & 1 deletion src/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import fs from 'fs';
import os from 'os';
import * as vscodeTypes from './vscodeTypes';
import { TestModel } from './testModel';
import { uriToPath } from './utils';

export async function installPlaywright(vscode: vscodeTypes.VSCode) {
const [workspaceFolder] = vscode.workspace.workspaceFolders || [];
Expand All @@ -45,7 +46,7 @@ export async function installPlaywright(vscode: vscodeTypes.VSCode) {

const terminal = vscode.window.createTerminal({
name: 'Install Playwright',
cwd: workspaceFolder.uri.fsPath,
cwd: uriToPath(workspaceFolder.uri),
env: process.env,
});

Expand Down
9 changes: 5 additions & 4 deletions src/playwrightTestCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { spawn } from 'child_process';
import path from 'path';
import { ConfigFindRelatedTestFilesReport, ConfigListFilesReport } from './listTests';
import { ReporterServer } from './reporterServer';
import { escapeRegex, findNode, pathSeparator, runNode } from './utils';
import { escapeRegex, findNode, pathSeparator, runNode, uriToPath } from './utils';
import * as vscodeTypes from './vscodeTypes';
import * as reporterTypes from './upstream/reporter';
import type { PlaywrightTestOptions, PlaywrightTestRunOptions } from './playwrightTestTypes';
Expand Down Expand Up @@ -266,9 +266,10 @@ export class PlaywrightTestCLI {
if (items.length === 1) {
const test = items[0];
if (test.uri && test.range) {
const testPath = uriToPath(test.uri);
let testsAtLocation = 0;
test.parent?.children.forEach(t => {
if (t.uri?.fsPath === test.uri?.fsPath && t.range?.start.line === test.range?.start.line)
if (t.uri && uriToPath(t.uri) === testPath && t.range?.start.line === test.range?.start.line)
++testsAtLocation;
});
if (testsAtLocation > 1)
Expand All @@ -278,12 +279,12 @@ export class PlaywrightTestCLI {

const locations = new Set<string>();
for (const item of items) {
const itemFsPath = item.uri!.fsPath;
const itemFsPath = uriToPath(item.uri!);
const enabledFiles = this._model.enabledFiles();
for (const file of enabledFiles) {
if (file === itemFsPath || file.startsWith(itemFsPath)) {
const line = item.range ? ':' + (item.range.start.line + 1) : '';
locations.add(item.uri!.fsPath + line);
locations.add(itemFsPath + line);
}
}
}
Expand Down
14 changes: 9 additions & 5 deletions src/playwrightTestServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class PlaywrightTestServer {
}, {
mergeProjects: true,
mergeTestCases: true,
resolvePath: (rootDir: string, relativePath: string) => this._vscode.Uri.file(path.join(rootDir, relativePath)).fsPath,
resolvePath,
});
for (const message of report)
teleReceiver.dispatch(message);
Expand All @@ -94,7 +94,7 @@ export class PlaywrightTestServer {
const teleReceiver = new TeleReporterReceiver(reporter, {
mergeProjects: true,
mergeTestCases: true,
resolvePath: (rootDir: string, relativePath: string) => this._vscode.Uri.file(path.join(rootDir, relativePath)).fsPath,
resolvePath,
});
for (const message of report)
teleReceiver.dispatch(message);
Expand All @@ -111,7 +111,7 @@ export class PlaywrightTestServer {
const teleReceiver = new TeleReporterReceiver(testListener, {
mergeProjects: true,
mergeTestCases: true,
resolvePath: (rootDir: string, relativePath: string) => this._vscode.Uri.file(path.join(rootDir, relativePath)).fsPath,
resolvePath,
});
const disposable = testServer.onStdio(params => {
if (params.type === 'stdout')
Expand Down Expand Up @@ -390,7 +390,7 @@ export class PlaywrightTestServer {
const teleReceiver = new TeleReporterReceiver(reporter, {
mergeProjects: true,
mergeTestCases: true,
resolvePath: (rootDir: string, relativePath: string) => this._vscode.Uri.file(path.join(rootDir, relativePath)).fsPath,
resolvePath,
});
return new Promise<void>(resolve => {
const disposables = [
Expand All @@ -412,7 +412,7 @@ export class PlaywrightTestServer {
}

private _testFilesChanged(testFiles: string[]) {
this._model.testFilesChanged(testFiles.map(f => this._vscode.Uri.file(f).fsPath));
this._model.testFilesChanged(testFiles);
}

private _disposeTestServer() {
Expand All @@ -426,3 +426,7 @@ export class PlaywrightTestServer {
function unwrapString(params: { text?: string, buffer?: string }): string | Buffer {
return params.buffer ? Buffer.from(params.buffer, 'base64') : params.text || '';
}

function resolvePath(rootDir: string, relativePath: string) {
return path.join(rootDir, relativePath);
}
2 changes: 1 addition & 1 deletion src/reporterServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class ReporterServer {
const teleReceiver = new TeleReporterReceiver(listener, {
mergeProjects: true,
mergeTestCases: true,
resolvePath: (rootDir: string, relativePath: string) => this._vscode.Uri.file(path.join(rootDir, relativePath)).fsPath,
resolvePath: (rootDir: string, relativePath: string) => path.join(rootDir, relativePath),
});

transport.onmessage = message => {
Expand Down
18 changes: 8 additions & 10 deletions src/testModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { WorkspaceChange } from './workspaceObserver';
import * as vscodeTypes from './vscodeTypes';
import { resolveSourceMap } from './utils';
import { resolveSourceMap, uriToPath } from './utils';
import { ConfigListFilesReport, ProjectConfigWithFiles } from './listTests';
import * as reporterTypes from './upstream/reporter';
import { TeleSuite } from './upstream/teleReceiver';
Expand Down Expand Up @@ -186,10 +186,6 @@ export class TestModel extends DisposableBase {
let report: ConfigListFilesReport;
try {
report = await this._playwrightTest.listFiles();
for (const project of report.projects)
project.files = project.files.map(f => this._vscode.Uri.file(f).fsPath);
if (report.error?.location)
report.error.location.file = this._vscode.Uri.file(report.error.location.file).fsPath;
} catch (error: any) {
report = {
error: {
Expand Down Expand Up @@ -319,20 +315,21 @@ export class TestModel extends DisposableBase {
for (const include of watch.include) {
if (!include.uri)
continue;
if (!enabledFiles.has(include.uri.fsPath))
const fsPath = uriToPath(include.uri);
if (!enabledFiles.has(fsPath))
continue;
// Folder is watched => add file.
if (testFile.startsWith(include.uri.fsPath + path.sep)) {
if (testFile.startsWith(fsPath + path.sep)) {
files.push(testFile);
continue;
}
// File is watched => add file.
if (testFile === include.uri.fsPath && !include.range) {
if (testFile === fsPath && !include.range) {
items.push(include);
continue;
}
// Test is watched, use that include as it might be more specific (test).
if (testFile === include.uri.fsPath && include.range) {
if (testFile === fsPath && include.range) {
items.push(include);
continue;
}
Expand Down Expand Up @@ -638,9 +635,10 @@ export class TestModel extends DisposableBase {
for (const include of watch.include) {
if (!include.uri)
continue;
filesToWatch.add(include.uri.fsPath);
filesToWatch.add(uriToPath(include.uri));
}
}

await this._playwrightTest.watchFiles([...filesToWatch]);
}

Expand Down
24 changes: 13 additions & 11 deletions src/testTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import path from 'path';
import { TestModelCollection } from './testModel';
import { createGuid } from './utils';
import { createGuid, uriToPath } from './utils';
import * as vscodeTypes from './vscodeTypes';
import * as reporterTypes from './upstream/reporter';
import * as upstream from './upstream/testTree';
Expand Down Expand Up @@ -90,25 +90,26 @@ export class TestTree extends DisposableBase {

private _update() {
for (const workspaceFolder of this._vscode.workspace.workspaceFolders ?? []) {
const workspaceFSPath = uriToPath(workspaceFolder.uri);
const rootSuite = new TeleSuite('', 'root');
for (const model of this._models.enabledModels().filter(m => m.config.workspaceFolder === workspaceFolder.uri.fsPath)) {
for (const model of this._models.enabledModels().filter(m => m.config.workspaceFolder === workspaceFSPath)) {
for (const project of model.enabledProjects())
rootSuite.suites.push(project.suite as TeleSuite);
}
const upstreamTree = new upstream.TestTree(workspaceFolder.uri.fsPath, rootSuite, [], undefined, path.sep);
const upstreamTree = new upstream.TestTree(workspaceFSPath, rootSuite, [], undefined, path.sep);
upstreamTree.sortAndPropagateStatus();
upstreamTree.flattenForSingleProject();
// Create root item if there are test files.
if (upstreamTree.rootItem.children.length === 0) {
this._deleteRootItem(workspaceFolder.uri.fsPath);
this._deleteRootItem(workspaceFSPath);
continue;
}
const workspaceRootItem = this._createRootItemIfNeeded(workspaceFolder.uri);
this._syncSuite(upstreamTree.rootItem, workspaceRootItem);
}
// Remove stale root items.
for (const itemFsPath of this._rootItems.keys()) {
if (!this._vscode.workspace.workspaceFolders!.find(f => f.uri.fsPath === itemFsPath))
if (!this._vscode.workspace.workspaceFolders!.find(f => uriToPath(f.uri) === itemFsPath))
this._deleteRootItem(itemFsPath);
}
this._indexTree();
Expand Down Expand Up @@ -172,19 +173,20 @@ export class TestTree extends DisposableBase {
for (const [, child] of item.children)
visit(child);
if (item.uri && !item.range)
this._testItemByFile.set(item.uri.fsPath, item);
this._testItemByFile.set(uriToPath(item.uri), item);
};
for (const item of this._rootItems.values())
visit(item);
}

private _createRootItemIfNeeded(uri: vscodeTypes.Uri): vscodeTypes.TestItem {
if (this._rootItems.has(uri.fsPath))
return this._rootItems.get(uri.fsPath)!;
const fsPath = uriToPath(uri);
if (this._rootItems.has(fsPath))
return this._rootItems.get(fsPath)!;
let item: vscodeTypes.TestItem;
if (this._vscode.workspace.workspaceFolders!.length === 1) {
item = {
id: this._idWithGeneration(uri.fsPath),
id: this._idWithGeneration(fsPath),
uri: uri,
children: this._testController.items,
parent: undefined,
Expand All @@ -196,10 +198,10 @@ export class TestTree extends DisposableBase {
error: undefined,
};
} else {
item = this._testController.createTestItem(this._idWithGeneration(uri.fsPath), path.basename(uri.fsPath), this._vscode.Uri.file(uri.fsPath));
item = this._testController.createTestItem(this._idWithGeneration(fsPath), path.basename(fsPath), uri);
this._testController.items.add(item);
}
this._rootItems.set(uri.fsPath, item);
this._rootItems.set(fsPath, item);
return item;
}

Expand Down
Loading

0 comments on commit 4068938

Please sign in to comment.