Skip to content

Commit

Permalink
fix windows testNamePattern not found issue
Browse files Browse the repository at this point in the history
  • Loading branch information
connectdotz committed Sep 10, 2024
1 parent e8f9096 commit 030913b
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 53 deletions.
3 changes: 2 additions & 1 deletion src/DebugConfigurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
escapeRegExp,
parseCmdLine,
toAbsoluteRootPath,
escapeQuotes,
} from './helpers';
import { platform } from 'os';
import { PluginResourceSettings } from './Settings';
Expand Down Expand Up @@ -118,7 +119,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
return arg
.replace(testFileRegex, toFilePath(this.fileNameToRun))
.replace(testFilePatternRegex, escapeRegExp(this.fileNameToRun))
.replace(testNamePatternRegex, this.testToRun);
.replace(testNamePatternRegex, escapeQuotes(this.testToRun));
});
debugConfiguration.args = args;

Expand Down
16 changes: 6 additions & 10 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ export const emptyTestStats = (): TestStats => {
return { success: 0, fail: 0, unknown: 0 };
};

export const escapeQuotes = (str: string): string => str.replace(/(['"])/g, '\\$1');

const getShellPath = (shell?: string | LoginShell): string | undefined => {
if (!shell) {
return;
Expand Down Expand Up @@ -276,19 +278,13 @@ export const shellQuote = (str: string, shell?: string | LoginShell): string =>
switch (shellType) {
case 'powershell': {
const s = str.replace(/(['"])/g, '$1$1');
if (s.length > 2 && s.slice(-2) === '\\\\') {
return `'${s}\\\\'`;
}
return `'${s}'`;
return s.endsWith('\\') ? `'${s}'\\` : `'${s}'`;
}

case 'cmd': {
let s = str.replace(/"/g, '""');
s = s.replace(/([><!^&|])/g, '^$1');
if (s.length > 2 && s.slice(-2) === '\\\\') {
s = `${s}\\\\`;
}
return s.indexOf(' ') >= 0 || s.indexOf('"') >= 0 || s.length === 0 ? `"${s}"` : s;
// Escape double quotes by doubling them and always quote the string
// no need to escape special cmd characters (such as ><!^&|) within the quoted string
return `"${str.replace(/"/g, '""')}"`;
}

default: {
Expand Down
1 change: 0 additions & 1 deletion src/test-provider/test-item-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,6 @@ abstract class TestResultData extends TestItemDataBase {
}

forEachChild(onTestData: (child: TestData) => void): void {
console.log(`${this.item.id} has ${this.item.children.size} children`);
this.item.children.forEach((childItem) => {
const child = this.context.getData<TestData>(childItem);
if (child) {
Expand Down
3 changes: 3 additions & 0 deletions tests/DebugConfigurationProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
escapeRegExp,
parseCmdLine,
toAbsoluteRootPath,
escapeQuotes,
} from '../src/helpers';
import * as fs from 'fs';
import { makeWorkspaceFolder } from './test-helper';
Expand Down Expand Up @@ -118,6 +119,7 @@ describe('DebugConfigurationProvider', () => {
`('will only translate known variables: $args', ({ args, expected }) => {
(toFilePath as unknown as jest.Mock<{}>).mockReturnValueOnce(fileName);
(escapeRegExp as unknown as jest.Mock<{}>).mockReturnValueOnce(fileNamePattern);
(escapeQuotes as unknown as jest.Mock<{}>).mockImplementation((s) => s);

let configuration: any = { name: 'vscode-jest-tests.v2', args };

Expand All @@ -133,6 +135,7 @@ describe('DebugConfigurationProvider', () => {
it('will translate multiple variables in a single arg', () => {
(toFilePath as unknown as jest.Mock<{}>).mockReturnValueOnce(fileName);
(escapeRegExp as unknown as jest.Mock<{}>).mockReturnValueOnce(fileNamePattern);
(escapeQuotes as unknown as jest.Mock<{}>).mockImplementation((s) => s);

let configuration: any = {
name: 'vscode-jest-tests.v2',
Expand Down
92 changes: 55 additions & 37 deletions tests/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,43 +231,46 @@ describe('toUpperCaseDriveLetter', () => {

describe('shellQuote', () => {
it.each`
platform | shell | str | expected
${'win32'} | ${undefined} | ${'plain text'} | ${'"plain text"'}
${'linux'} | ${undefined} | ${'plain text'} | ${'plain\\ text'}
${'win32'} | ${'powershell'} | ${"with 'single quote'"} | ${"'with ''single quote'''"}
${'win32'} | ${'cmd.exe'} | ${"with 'single quote'"} | ${'"with \'single quote\'"'}
${'linux'} | ${'/bin/bash'} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${'darwin'} | ${'/bin/zsh'} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${'darwin'} | ${{ path: '/bin/zsh', args: ['-l'] }} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${'win32'} | ${undefined} | ${"with 'single quote'"} | ${'"with \'single quote\'"'}
${'linux'} | ${undefined} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${'win32'} | ${'powershell'} | ${'with "double quote"'} | ${'\'with ""double quote""\''}
${'win32'} | ${'cmd.exe'} | ${'with "double quote"'} | ${'"with ""double quote"""'}
${'linux'} | ${'bash'} | ${'with "double quote"'} | ${'with\\ \\"double\\ quote\\"'}
${'win32'} | ${'powershell'} | ${'with $name.txt'} | ${"'with $name.txt'"}
${'win32'} | ${'cmd.exe'} | ${'with $name.txt'} | ${'"with $name.txt"'}
${'linux'} | ${'bash'} | ${'with $name.txt'} | ${'with\\ \\$name.txt'}
${'win32'} | ${'powershell'} | ${'with \\$name\\.txt'} | ${"'with \\$name\\.txt'"}
${'win32'} | ${'cmd.exe'} | ${'with \\$name\\.txt'} | ${'"with \\$name\\.txt"'}
${'linux'} | ${'bash'} | ${'with \\$name\\.txt'} | ${'with\\ \\\\\\$name\\\\.txt'}
${'linux'} | ${{ path: '/bin/sh', args: ['--login'] }} | ${'with \\$name\\.txt'} | ${'with\\ \\\\\\$name\\\\.txt'}
${'win32'} | ${'powershell'} | ${''} | ${"''"}
${'win32'} | ${undefined} | ${''} | ${'""'}
${'darwin'} | ${undefined} | ${''} | ${'""'}
${'win32'} | ${'powershell'} | ${'with \\ and \\\\'} | ${"'with \\ and \\\\\\\\'"}
${'win32'} | ${undefined} | ${'with \\ and \\\\'} | ${'"with \\ and \\\\\\\\"'}
${'linux'} | ${undefined} | ${'with \\ and \\\\'} | ${'with\\ \\\\\\ and\\ \\\\\\\\'}
${'win32'} | ${'powershell'} | ${'something\\'} | ${"'something\\'"}
${'win32'} | ${undefined} | ${'something\\'} | ${'something\\'}
${'darwin'} | ${undefined} | ${'something\\'} | ${'something\\\\'}
${'win32'} | ${'powershell'} | ${'with `backtick'} | ${"'with `backtick'"}
${'win32'} | ${undefined} | ${'with `backtick'} | ${'"with `backtick"'}
${'darwin'} | ${undefined} | ${'with `backtick'} | ${'with\\ \\`backtick'}
`('can quote "$str" for $shell on $platform', ({ platform, shell, str, expected }) => {
jest.resetAllMocks();
mockPlatform.mockReturnValueOnce(platform);
expect(shellQuote(str, shell)).toEqual(expected);
});
case | platform | shell | str | expected
${1} | ${'win32'} | ${undefined} | ${'plain text'} | ${'"plain text"'}
${2} | ${'linux'} | ${undefined} | ${'plain text'} | ${'plain\\ text'}
${3} | ${'win32'} | ${'powershell'} | ${"with 'single quote'"} | ${"'with ''single quote'''"}
${4} | ${'win32'} | ${'cmd.exe'} | ${"with 'single quote'"} | ${'"with \'single quote\'"'}
${5} | ${'linux'} | ${'/bin/bash'} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${6} | ${'darwin'} | ${'/bin/zsh'} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${7} | ${'darwin'} | ${{ path: '/bin/zsh', args: ['-l'] }} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${8} | ${'win32'} | ${undefined} | ${"with 'single quote'"} | ${'"with \'single quote\'"'}
${9} | ${'linux'} | ${undefined} | ${"with 'single quote'"} | ${"with\\ \\'single\\ quote\\'"}
${10} | ${'win32'} | ${'powershell'} | ${'with "double quote"'} | ${'\'with ""double quote""\''}
${11} | ${'win32'} | ${'cmd.exe'} | ${'with "double quote"'} | ${'"with ""double quote"""'}
${12} | ${'linux'} | ${'bash'} | ${'with "double quote"'} | ${'with\\ \\"double\\ quote\\"'}
${13} | ${'win32'} | ${'powershell'} | ${'with $name.txt'} | ${"'with $name.txt'"}
${14} | ${'win32'} | ${'cmd.exe'} | ${'with $name.txt'} | ${'"with $name.txt"'}
${15} | ${'linux'} | ${'bash'} | ${'with $name.txt'} | ${'with\\ \\$name.txt'}
${16} | ${'win32'} | ${'powershell'} | ${'with \\$name\\.txt'} | ${"'with \\$name\\.txt'"}
${17} | ${'win32'} | ${'cmd.exe'} | ${'with \\$name\\.txt'} | ${'"with \\$name\\.txt"'}
${18} | ${'linux'} | ${'bash'} | ${'with \\$name\\.txt'} | ${'with\\ \\\\\\$name\\\\.txt'}
${19} | ${'linux'} | ${{ path: '/bin/sh', args: ['--login'] }} | ${'with \\$name\\.txt'} | ${'with\\ \\\\\\$name\\\\.txt'}
${20} | ${'win32'} | ${'powershell'} | ${''} | ${"''"}
${21} | ${'win32'} | ${undefined} | ${''} | ${'""'}
${22} | ${'darwin'} | ${undefined} | ${''} | ${'""'}
${23} | ${'win32'} | ${'powershell'} | ${'with \\ and \\\\'} | ${"'with \\ and \\\\'\\"}
${24} | ${'win32'} | ${undefined} | ${'with \\ and \\\\'} | ${'"with \\ and \\\\"'}
${25} | ${'linux'} | ${undefined} | ${'with \\ and \\\\'} | ${'with\\ \\\\\\ and\\ \\\\\\\\'}
${26} | ${'win32'} | ${'powershell'} | ${'something\\'} | ${"'something\\'\\"}
${27} | ${'win32'} | ${undefined} | ${'something\\'} | ${'"something\\"'}
${28} | ${'darwin'} | ${undefined} | ${'something\\'} | ${'something\\\\'}
${29} | ${'win32'} | ${'powershell'} | ${'with `backtick'} | ${"'with `backtick'"}
${30} | ${'win32'} | ${undefined} | ${'with `backtick'} | ${'"with `backtick"'}
${31} | ${'darwin'} | ${undefined} | ${'with `backtick'} | ${'with\\ \\`backtick'}
`(
'case $case: can quote "$str" for $shell on $platform',
({ platform, shell, str, expected }) => {
jest.resetAllMocks();
mockPlatform.mockReturnValueOnce(platform);
expect(shellQuote(str, shell)).toEqual(expected);
}
);
});
it.each`
name | e | matchString
Expand Down Expand Up @@ -481,3 +484,18 @@ describe('getValidJestCommand', () => {
]);
});
});

describe('escapeQuotes', () => {
it.each`
case | inputString | expected
${'no quotes'} | ${'no quotes'} | ${'no quotes'}
${'single quotes'} | ${"with 'single quotes'"} | ${"with \\'single quotes\\'"}
${'double quotes'} | ${'with "double quotes"'} | ${'with \\"double quotes\\"'}
${'mixed quotes'} | ${'with "double" and \'single\''} | ${'with \\"double\\" and \\\'single\\\''}
${'escaped quotes'} | ${'with \\"escaped\\" quotes'} | ${'with \\\\"escaped\\\\" quotes'}
${'escaped quotes 2'} | ${"with \\'escaped\\' quotes"} | ${"with \\\\'escaped\\\\' quotes"}
${'escaped quotes 3'} | ${'with \\\'escaped\\\' and "quotes"'} | ${'with \\\\\'escaped\\\\\' and \\"quotes\\"'}
`('$case', ({ inputString, expected }) => {
expect(helper.escapeQuotes(inputString)).toEqual(expected);
});
});
12 changes: 8 additions & 4 deletions webpack/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@ module.exports = (env) => {
// Function to find files matching a pattern within a specific package
function addMatchingFiles(packageName, filePattern) {
const files = glob.sync(`node_modules/**/${packageName}/${filePattern}`, { absolute: true });
return files;
const normalizedFiles = files.map((file) => path.normalize(file));
return normalizedFiles;
}

// this path should always use forward slashes. On windows, this requires replacing backslashes with forward slashes
const dummyModulePath = path.resolve(__dirname, 'dummy-module.js').replace(/\\/g, '/');

const replacements = [
{ packageName: '@babel/generator', replacement: path.resolve(__dirname, './dummy-module.js') },
{ packageName: '@babel/core', replacement: path.resolve(__dirname, './dummy-module.js') },
{ packageName: '@babel/generator', replacement: dummyModulePath },
{ packageName: '@babel/core', replacement: dummyModulePath },
{
packageName: './src/InlineSnapshots.ts',
replacement: path.resolve(__dirname, './dummy-module.js'),
replacement: dummyModulePath,
},
];

Expand Down

0 comments on commit 030913b

Please sign in to comment.