test(windows): run the integration suite on Windows - #169
Conversation
juliandescottes
left a comment
There was a problem hiding this comment.
Thanks for the patch. I haven't fully tested, but it would be great to have more granular PRs. Could you split this ?
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Added |
There was a problem hiding this comment.
This is too much for a changelog. Can you keep it short and focus on the impact for users?
| * 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. |
There was a problem hiding this comment.
This sounds like something which should be fixed upstream in geckodriver rather than handled in the MCP with a workaround.
There was a problem hiding this comment.
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 :) )
| - **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. |
There was a problem hiding this comment.
This mostly repeats what the commit has been fixing. The documentation files are quite big already, I would skip that.
| - 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. |
There was a problem hiding this comment.
Repeats what the commit does, not worth keeping in the docs.
| // mkdirSync rather than shelling out to `mkdir -p`, which does not exist in | ||
| // the cmd.exe that npm runs scripts through on Windows. |
There was a problem hiding this comment.
I would remove this, it only make sense when looking at the diff.
| firefoxOptions.enableBidi(); | ||
|
|
||
| // True when no binary was found on Windows, so the failure can say why. | ||
| let binaryLookupFailed = false; |
There was a problem hiding this comment.
The variable name should make it clear this is windows only
| '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.'; |
There was a problem hiding this comment.
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?
| *.bat text eol=crlf | ||
| *.cmd text eol=crlf | ||
| *.ps1 text eol=crlf |
There was a problem hiding this comment.
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.
f1c0746 to
3bfc951
Compare
juliandescottes
left a comment
There was a problem hiding this comment.
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.
| @@ -0,0 +1,123 @@ | |||
| /** | |||
There was a problem hiding this comment.
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)) { | |||
There was a problem hiding this comment.
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.
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.tscleanup now comes from #165.What it does:
vitest.config.tsand the standalone runner (scripts/run-integration-tests-windows.mjs,test:integration:win); the vitest fork hang from #33 no longer reproduces on Vitest 4pathToFileURL(fixtureUrl()), packs the extension fixture in-process instead of shelling out tozip, and retries temp-dir removal (removeDir())ci.ymlonwindows-latestnext toubuntu-latestVerified on Windows (7 integration files, 54 tests) and macOS (unit 608, integration 54).