Skip to content

fix(tests): keep Git from rewriting fixture line endings on Windows - #1450

Merged
UlisesGascon merged 1 commit into
expressjs:mainfrom
MohammedAlkindi:fix/windows-fixture-line-endings
Aug 24, 2026
Merged

fix(tests): keep Git from rewriting fixture line endings on Windows#1450
UlisesGascon merged 1 commit into
expressjs:mainfrom
MohammedAlkindi:fix/windows-fixture-line-endings

Conversation

@MohammedAlkindi

Copy link
Copy Markdown
Contributor

Closes #181

Replaces #1449, reopened only to correct the source branch name. Same commit (fcff40e), same diff, body unchanged.

Symptom

On a clean clone on Windows, npm test gives 12 failing / 71 passing before any code is touched:

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
1803 !== 1778

Cause

test/files/ holds opaque upload payloads whose exact byte size the suite hardcodes, and nothing marked them as binary. With core.autocrlf=true — Git's default on Windows — checkout rewrites LF to CRLF in the text-like fixtures:

fixture committed blob on disk after checkout
medium.dat 13196 13386
small0.dat 1778 1803
small1.dat 315 329
tiny0.dat 122 128
empty.dat, tiny1.dat 0, 7 unchanged (no line terminators)
large.jpg 2413677 unchanged (Git detects it as binary)

The committed blobs already hold exactly the LF bytes the tests expect — 1778 for small0.dat, matching every assert.strictEqual(..., 1778). Only the checkout conversion is wrong.

Fix

One .gitattributes marking test/files/** as binary. Because the blobs are already correct, suppressing the end-of-line conversion is sufficient on its own — the fixtures are not modified, so the hardcoded sizes stay valid and there is no fixture churn to review.

This follows the second option @jonchurch laid out on the issue — "changing the behavior of git with a .gitattributes file" — rather than @LinusU's original suggestion of regenerating the fixtures as random binary data. Both stop the conversion; this one leaves the recorded sizes and the fixtures themselves untouched. binary also implies -diff, which is what you want for opaque payloads.

I kept this to a single file on purpose: the previous attempt, #832, was closed after the feedback that it "changes too many things to be easily evaluated".

Deliberately unchanged

The 12th failure is a different bug and is not touched here. Functionality > should rename the destination directory to a different directory asserts req.files[0].path.indexOf('/testforme-') >= 0, hardcoding a forward slash as the path separator, so it can never match a Windows path regardless of line endings. It fails before and after this change. It deserves its own issue and PR.

Testing

Windows 11, Node v24.18.0, core.autocrlf=true.

passing failing
clean clone, before 71 12
with this change 79 1

The 11 fixed failures span disk-storage, functionality, memory-storage, reuse-middleware and select-field; the 1 remaining is the path-separator assertion above.

Verified end to end rather than only in place: after pushing this branch I made a fresh git clone of it on Windows and confirmed every fixture arrives at its committed size with no CR bytes, then ran npm install && npm test in that new clone — 79 passing, 1 failing. npm run lint (standard) is clean.

I have no way to run the macOS or Linux jobs locally; those platforms do not convert line endings on checkout, so their behaviour is unchanged by this, and CI is the authority.

test/files holds opaque upload payloads whose exact byte size the suite
asserts on, and nothing marked them as binary. With core.autocrlf=true,
Git's default on Windows, checkout rewrites LF to CRLF in medium.dat,
small0.dat, small1.dat and tiny0.dat, inflating small0.dat from 1778 to
1803 bytes and failing 11 tests across disk-storage, memory-storage,
functionality, reuse-middleware and select-field on a clean clone.

A .gitattributes entry marking test/files as binary is enough on its own:
the committed blobs already hold exactly the LF bytes the tests expect,
so suppressing the end-of-line conversion restores every fixture to its
recorded size. The fixtures themselves are left untouched, which keeps
the hardcoded sizes valid and the diff reviewable.

Closes expressjs#181
@MohammedAlkindi

Copy link
Copy Markdown
Contributor Author

For context: this supersedes #1449, which I closed after opening this. Nothing about the change differs — same commit fcff40e, same single .gitattributes file.

@UlisesGascon UlisesGascon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@UlisesGascon
UlisesGascon merged commit d6b4a65 into expressjs:main Aug 24, 2026
2 checks passed
@UlisesGascon UlisesGascon mentioned this pull request Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants