Skip to content

test(windows): run the integration suite on Windows - #169

Open
freema wants to merge 1 commit into
mainfrom
fix/windows-compat
Open

test(windows): run the integration suite on Windows#169
freema wants to merge 1 commit into
mainfrom
fix/windows-compat

Conversation

@freema

@freema freema commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Trimmed to the one commit left after the split: #172 (paths), #173 (dev tooling) and #174 (Firefox binary detection) carry the rest, and the tests/setup.ts cleanup now comes from #165.

What it does:

  • drops the Windows exclusion in vitest.config.ts and the standalone runner (scripts/run-integration-tests-windows.mjs, test:integration:win); the vitest fork hang from #33 no longer reproduces on Vitest 4
  • builds fixture URLs with pathToFileURL (fixtureUrl()), packs the extension fixture in-process instead of shelling out to zip, and retries temp-dir removal (removeDir())
  • runs ci.yml on windows-latest next to ubuntu-latest

Verified on Windows (7 integration files, 54 tests) and macOS (unit 608, integration 54).

@f3tchcodes

Copy link
Copy Markdown
Contributor

FYI, there's some overlap with #165 which already covers Windows process cleanup in tests/setup.ts, and #164 covers the .gitattributes LF fix. Mentioning in case it's useful to avoid duplicate work while reviewing this PR.

@juliandescottes juliandescottes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch. I haven't fully tested, but it would be great to have more granular PRs. Could you split this ?

Comment thread CHANGELOG.md Outdated

## [Unreleased]

### Added

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too much for a changelog. Can you keep it short and focus on the impact for users?

Comment thread src/firefox/binary.ts Outdated
Comment on lines +4 to +8
* On Windows geckodriver only searches the Program Files directories and
* HKEY_LOCAL_MACHINE, so it cannot see a per-user install (%LOCALAPPDATA%,
* registered under HKCU) — what the installer produces without admin rights.
* Finding the binary here and passing it as moz:firefoxOptions.binary fixes
* that. Windows-only: geckodriver's own lookup suffices elsewhere.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like something which should be fixed upstream in geckodriver rather than handled in the MCP with a workaround.

@juliandescottes juliandescottes Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is captured at https://bugzilla.mozilla.org/show_bug.cgi?id=1921933

(Which is a mentored bug, in case you're interested to do a geckodriver contribution :) )

Comment thread docs/testing.md Outdated
Comment on lines +47 to +65
- **Firefox discovery**: geckodriver only searches `%ProgramFiles%` and
`HKEY_LOCAL_MACHINE`, so it cannot find a per-user install
(`%LOCALAPPDATA%\Mozilla Firefox`). `src/firefox/binary.ts` resolves the binary
and passes it as `moz:firefoxOptions.binary`.
- **Fixture URLs**: build them with `fixtureUrl()` from `tests/helpers/firefox.ts`.
Interpolating `file://${path}` yields `file://C:\...`, which never resolves
because the drive letter is parsed as the host.
- **Process cleanup**: `tests/setup.ts` uses `taskkill` on Windows; pgrep/pkill
do not exist there.
- **Deleting temp dirs**: use `removeDir()` from `tests/helpers/fs.ts`. Plain
`rmSync({ force: true })` intermittently throws `ENOTEMPTY` while handles close.
- **Line endings**: `.gitattributes` checks out text files as LF. Without it
`core.autocrlf=true` makes `npm run format:check` fail on every file.
- **Path comparisons**: compare against a root with `isWithinRoot()`
(`src/utils/save-output.ts`). Windows paths are case-insensitive, so a plain
`startsWith` rejects valid paths that differ only in case.
- **`process.env` in tests**: the real environment is case-insensitive on Windows
(`process.env.SystemRoot` resolves the `SYSTEMROOT` key). Replacing it with a
plain object drops that, so set the variables a test needs explicitly.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mostly repeats what the commit has been fixing. The documentation files are quite big already, I would skip that.

Comment thread docs/ci-and-release.md Outdated
Comment on lines +42 to +44
- vitest used to hang when forking integration tests that spawn Firefox on Windows (issue #33), so those tests were excluded there and a standalone runner (`scripts/run-integration-tests-windows.mjs`) stood in for them. The hang no longer reproduces on vitest 4, so the exclusion and the standalone runner were both removed and Windows runs the same tests as every other platform.
- geckodriver only searches the Program Files directories and HKEY_LOCAL_MACHINE for Firefox, so it cannot see a per-user install (`%LOCALAPPDATA%\Mozilla Firefox`), which is what the installer produces without administrator rights. `src/firefox/binary.ts` locates the binary itself and passes it as `moz:firefoxOptions.binary`; use `--firefox-path` if an install still is not found.
- `.gitattributes` checks out text files with LF everywhere. Without it, Git for Windows' `core.autocrlf=true` gives the working tree CRLF endings and `npm run format:check` fails on every file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeats what the commit does, not worth keeping in the docs.

Comment thread scripts/build-mcpb.mjs Outdated
Comment on lines +38 to +39
// mkdirSync rather than shelling out to `mkdir -p`, which does not exist in
// the cmd.exe that npm runs scripts through on Windows.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove this, it only make sense when looking at the diff.

Comment thread src/firefox/core.ts Outdated
firefoxOptions.enableBidi();

// True when no binary was found on Windows, so the failure can say why.
let binaryLookupFailed = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name should make it clear this is windows only

Comment thread src/firefox/binary.ts Outdated
Comment on lines +129 to +133
'Firefox could not be found on this system. geckodriver only searches the Program Files ' +
'directories and HKEY_LOCAL_MACHINE, so a Firefox installed for the current user only is ' +
'not detected automatically. Pass the full path to firefox.exe via --firefox-path ' +
'(for example --firefox-path "%LOCALAPPDATA%\\Mozilla Firefox\\firefox.exe"), or reinstall ' +
'Firefox for all users.';

@juliandescottes juliandescottes Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this binary.ts helper was meant to bypass the geckodriver limitation, but the message says that user installed Firefox are not handled?

I would go for a shorter message. eg

Unable to detect Firefox binary automatically, please provide the full path via --firefox-path

Also, why define this constant here if it's only used in core.ts?

Comment thread .gitattributes Outdated
Comment on lines +7 to +9
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any file with those extensions in the repository, is this necessary? Otherwise this would be covered by #164 already?

The vitest fork hang (#33) no longer reproduces on Vitest 4, so drop the
Windows exclusion and the standalone runner, fix fixture URLs and .xpi
packing for Windows, and run CI on windows-latest too.
@freema
freema force-pushed the fix/windows-compat branch from f1c0746 to 3bfc951 Compare August 26, 2026 14:13
@freema freema changed the title fix(windows): make the server and test suite work on Windows test(windows): run the integration suite on Windows Aug 26, 2026
@freema

freema commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

Trimmed as discussed, this is now only the integration-suite commit on top of #165; the rest lives in #172, #173 and #174, and the docs/changelog additions went with it. Thanks for the split suggestion.

@juliandescottes juliandescottes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, overall this looks good, but I don't think we should re-implement a zip helper here, there are many options to choose from.

Comment thread tests/helpers/zip.ts
@@ -0,0 +1,123 @@
/**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a strong reason to re-implement a zip writer here? We already pull:

  • fflate
  • jszip
  • zip.js

fflate seems the most straightforward choice here. It's lightweight and has a sync API. Can you try to use it instead?

@@ -100,7 +101,7 @@ describe('Console Tools', () => {
afterEach(() => {
vi.restoreAllMocks();
if (existsSync(tempDir)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing new from your PR, but in theory force: true ignores errors if the path does not exist, so those guards are most likely redundant. We could remove them in another PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants