Skip to content

[BUG]: Path Separators Create Problems for Windows Users #45

@StevanFreeborn

Description

@StevanFreeborn

Issue 1: Test Filter Path Separator

When the spec command is built on windows the result is like this:

C:\\Users\\sfree\\software_projects\\OnspringEnd2EndTests/node_modules/.bin/playwright test --reporter=list,json --headed --retries=0 -x --workers=1 --timeout=0 --config=C:\\Users\\sfree\\software_projects\\OnspringEnd2EndTests\\playwright.config.ts C:\\Users\\sfree\\software_projects\\OnspringEnd2EndTests\\tests\\contentRecord\\contentRecord.spec.ts:59

When run the output is the following:

Error: No tests found.
Make sure that arguments are regular expressions matching test files.
You may need to escape symbols like "$" or "*" and quote the arguments.

{
  "config": {
    ...many more lines
  "errors": [
    {
      "message": "Error: No tests found.\nMake sure that arguments are regular expressions matching test files.\nYou may need to escape symbols like \"$\" or \"*\" and quote the arguments.",
      "stack": "Error: No tests found.\nMake sure that arguments are regular expressions matching test files.\nYou may need to escape symbols like \"$\" or \"*\" and quote the arguments."
    }
  ],
  "stats": {
    "startTime": "2025-02-04T05:02:16.580Z",
    "duration": 514.2030000000001,
    "expected": 0,
    "skipped": 0,
    "unexpected": 0,
    "flaky": 0
  }
}

I'm not completely sure who is the problem, but an easy way to solve the issue is to just make sure that the test filter path always uses / as the path separator.

Solution

A check like this should suffice:

if (vim.fn.has('win32') === 1) {
  testFilter = testFilter.replaceAll('\\', '/');
}

Issue 2: Path Separator Prevents Proper Test Status From Being Reported

Currently for windows users the position id will use a \ as the path separator while the result id will use a / as the path separator which prevents neotest from reporting the proper test result status.

For example you'll have results that look like this:

{
  ["C:/Users/sfree/software_projects/OnspringEnd2EndTests/tests/../setups/auth.setup.ts::login as system administrator"] = {
    attachments = {},
    errors = {},
    short = "login as system administrator: passed",
    status = "passed"
  },
  ["C:/Users/sfree/software_projects/OnspringEnd2EndTests/tests/../teardowns/auth.teardown.ts::remove saved auth states"] = {
    attachments = {},
    errors = {},
    short = "remove saved auth states: passed",
    status = "passed"
  },
  ['C:/Users/sfree/software_projects/OnspringEnd2EndTests/tests/contentRecord/contentRecord.spec.ts::Create a content record from the "Create Content" button on the content home page'] = {
    attachments = {},
    errors = {},
    short = 'Create a content record from the "Create Content" button on the content home page: passed',
    status = "passed"
  }
}

But you'll be using a position id like this:

C:\Users\sfree\software_projects\OnspringEnd2EndTests\tests\contentRecord\contentRecord.spec.ts::Create a content record from the "Create Content" button on the content home page for output

Which will cause neotest to not find your result and mark the test as failed:

https://github.com/nvim-neotest/neotest/blob/d66cf4e05a116957f0d3a7755a24291c7d1e1f72/lua/neotest/client/runner.lua#L38C7-L46C10

Solution

Rewriting the path separator for the position id when on Windows should work:

let positionId = '';

if (position.id) {
  positionId = position.id;
} else {
  positionId = position.path + '::' + position.name;
}

if (vim.fn.has('win32') === 1) {
  positionId = positionId.replaceAll('\\', '/');
}

return positionId;

Issue 3: Path Separator Causes Dynamic Discovery to Fail

When dynamic discovery is enabled the mismatch between the path separators prevents check from properly passing leading to the incorrect position ids being used and not matching the result ids that are reported.

For example you'll end up with results like this:

{
  ["17e3fe6f4d9d8bd79c6b-4671ea933d5e0b93ed63"] = {
    attachments = {},
    errors = {},
    short = "login as system administrator: passed",
    status = "passed"
  },
  ["5228e77054e433ae56aa-15f48ca77d23f1a59de1"] = {
    attachments = {},
    errors = {},
    short = "remove saved auth states: passed",
    status = "passed"
  },
  ["87fc6404a5a1cf50123b-8ff1faad4c571958a8b2"] = {
    attachments = {},
    errors = {},
    short = 'Create a content record from the "Create Content" button on the content home page: passed',
    status = "passed"
  },
  ["87fc6404a5a1cf50123b-da0b10c9c831504b2c4f"] = {
    attachments = {},
    errors = {},
    short = 'Create a content record from the "Create Content" button on the content home page: passed',
    status = "passed"
  }
}

But your position ids will still look like this:

C:\Users\sfree\software_projects\OnspringEnd2EndTests\tests\contentRecord\contentRecord.spec.ts::Create a content record from the "Create Content" button on the content home page for output

Solution

We should be able to rewrite the paths before comparing for a file match if on Windows to address the issue:

// check if os is windows so that we can replace
// the path separator before comparing
let specPath = specAbsolutePath;
let basePath = basePosition.path;

if (vim.fn.has('win32') === 1) {
  specPath = specPath.replaceAll('\\', '/');
  basePath = basePath.replaceAll('\\', '/');
}

const fileMatch = specPath === basePath;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions