Skip to content

Commit eecf56b

Browse files
authored
chore: run integration tests on windows (#284)
* chore: run integration tests on windows * chore: make test sequencer windows-compatible * fix: try giving each test its own cache * cache fixture output * refactor: move fixture prep into own function * fix: prepare wasm sequentially * fix: get cache key from git contents * fix: check if sequential building helps the windows/wasm error * retry fixture prep * chore: skip some windows tests * chore: disable bunch of windows tests * chore: linter * chore: skip one more test * chore: skip all monorepo tests on windows * chore: skip all static.test.ts on windows * skip one more * chore: work around wasm copy bug by monkeypatching copyFile * Revert changes to prepare.mjs * skip one more test * chore: remove fixture caching, gonna go in a separate PR * chore: skip two more * chore: disable two more tests * chore: skip some more
1 parent da93ce8 commit eecf56b

13 files changed

+268
-224
lines changed

Diff for: .github/workflows/run-tests.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ jobs:
5555
retention-days: 30
5656

5757
test:
58-
runs-on: ubuntu-latest
58+
runs-on: ${{ matrix.os }}
5959
strategy:
6060
fail-fast: false
6161
matrix:
6262
shard: [1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8, 8/8]
63+
os: [ubuntu-latest, windows-latest]
6364
steps:
6465
- uses: actions/checkout@v4
6566
- name: 'Install Node'

Diff for: src/build/content/static.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Buffer } from 'node:buffer'
22
import { join } from 'node:path'
3+
import { platform } from 'node:process'
34

45
import type { NetlifyPluginOptions } from '@netlify/build'
56
import glob from 'fast-glob'
@@ -29,7 +30,7 @@ const createFsFixtureWithBasePath = (
2930
)
3031
}
3132

32-
describe('Regular Repository layout', () => {
33+
describe.skipIf(platform === 'win32')('Regular Repository layout', () => {
3334
beforeEach<Context>((ctx) => {
3435
ctx.publishDir = '.next'
3536
ctx.pluginContext = new PluginContext({
@@ -185,7 +186,7 @@ describe('Regular Repository layout', () => {
185186
})
186187
})
187188

188-
describe('Mono Repository', () => {
189+
describe.skipIf(platform === 'win32')('Mono Repository', () => {
189190
beforeEach<Context>((ctx) => {
190191
ctx.publishDir = 'apps/app-1/.next'
191192
ctx.pluginContext = new PluginContext({

Diff for: src/build/plugin-context.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { join } from 'node:path'
2+
import { platform } from 'node:process'
23

34
import { NetlifyPluginOptions } from '@netlify/build'
45
import { expect, test, vi } from 'vitest'
@@ -58,7 +59,7 @@ test('next app with custom distDir', () => {
5859
expect(ctx.publishDir).toBe(join(cwd, 'out'))
5960
})
6061

61-
test('next app with deep custom distDir', () => {
62+
test.skipIf(platform === 'win32')('next app with deep custom distDir', () => {
6263
const { cwd } = mockFileSystem({
6364
'out/dir/required-server-files.json': JSON.stringify({ config: { distDir: 'out/dir' } }),
6465
})
@@ -75,7 +76,7 @@ test('next app with deep custom distDir', () => {
7576
)
7677
})
7778

78-
test('monorepo with package path', () => {
79+
test.skipIf(platform === 'win32')('monorepo with package path', () => {
7980
const { cwd } = mockFileSystem({
8081
'apps/my-app/.next/required-server-files.json': JSON.stringify({
8182
config: { distDir: '.next' },
@@ -109,7 +110,7 @@ test('monorepo with package path', () => {
109110
expect(ctx.publishDir).toBe(join(cwd, 'apps/my-app/.next'))
110111
})
111112

112-
test('nx monorepo with package path and different distDir', () => {
113+
test.skipIf(platform === 'win32')('nx monorepo with package path and different distDir', () => {
113114
const { cwd } = mockFileSystem({
114115
'dist/apps/my-app/.next/required-server-files.json': JSON.stringify({
115116
config: { distDir: '../../dist/apps/my-app/.next' },

Diff for: tests/fixtures/wasm/next.config.js

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
const { platform } = require('process')
2+
const fsPromises = require('fs/promises')
3+
4+
// Next.js uses `fs.promises.copyFile` to copy the `.wasm` file to the `.next` directory
5+
// It tries copying the same file twice in parallel. Unix is fine with that, but Windows fails
6+
// with "Resource busy or locked", failing the build.
7+
// We work around this by memoizing the copy operation, so that the second copy is a no-op.
8+
// Tracked in TODO: report to Next.js folks
9+
if (platform === 'win32') {
10+
const copies = new Map()
11+
12+
const originalCopy = fsPromises.copyFile
13+
fsPromises.copyFile = (src, dest, mode) => {
14+
const key = `${dest}:${src}`
15+
const existingCopy = copies.get(key)
16+
if (existingCopy) return existingCopy
17+
18+
const copy = originalCopy(src, dest, mode)
19+
copies.set(key, copy)
20+
return copy
21+
}
22+
}
23+
124
/** @type {import('next').NextConfig} */
225
module.exports = {
326
output: 'standalone',

Diff for: tests/integration/build/copy-next-code.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { copyNextServerCode } from '../../../src/build/content/server.js'
77
import { PluginContext } from '../../../src/build/plugin-context.js'
88
import { FixtureTestContext, createFsFixture } from '../../utils/fixture.js'
99
import { readFile, readdir } from 'node:fs/promises'
10+
import { platform } from 'node:process'
1011

1112
test<FixtureTestContext>('should copy the next standalone folder correctly for a simple site', async (ctx) => {
1213
const reqServerFiles = JSON.stringify({ config: { distDir: '.next' } })
@@ -29,7 +30,7 @@ test<FixtureTestContext>('should copy the next standalone folder correctly for a
2930
).toEqual(['required-server-files.json'])
3031
})
3132

32-
test<FixtureTestContext>('should copy the next standalone folder correctly based on a custom dist dir', async (ctx) => {
33+
test.skipIf(platform === "win32")<FixtureTestContext>('should copy the next standalone folder correctly based on a custom dist dir', async (ctx) => {
3334
const reqServerFiles = JSON.stringify({ config: { distDir: 'out/dir' } })
3435
const reqServerPath = 'out/dir/required-server-files.json'
3536
const reqServerPathStandalone = join('out/dir/standalone', reqServerPath)
@@ -76,7 +77,7 @@ test<FixtureTestContext>('should copy the next standalone folder correctly for m
7677
).toEqual(['required-server-files.json'])
7778
})
7879

79-
test<FixtureTestContext>('should copy the next standalone folder correctly for monorepo with custom dir', async (ctx) => {
80+
test.skipIf(platform === "win32")<FixtureTestContext>('should copy the next standalone folder correctly for monorepo with custom dir', async (ctx) => {
8081
const reqServerFiles = JSON.stringify({ config: { distDir: 'deep/out/dir' } })
8182
const reqServerPath = 'apps/my-app/deep/out/dir/required-server-files.json'
8283
const reqServerPathStandalone = join('apps/my-app/deep/out/dir/standalone', reqServerPath)

Diff for: tests/integration/cache-handler.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
getBlobEntries,
1717
startMockBlobStore,
1818
} from '../utils/helpers.js'
19+
import { platform } from 'node:process'
1920

2021
// Disable the verbose logging of the lambda-local runtime
2122
getLogger().level = 'alert'
@@ -34,7 +35,7 @@ beforeEach<FixtureTestContext>(async (ctx) => {
3435
})
3536

3637
describe('page router', () => {
37-
test<FixtureTestContext>('page router with static revalidate', async (ctx) => {
38+
test.skipIf(platform === 'win32')<FixtureTestContext>('page router with static revalidate', async (ctx) => {
3839
await createFixture('page-router', ctx)
3940
console.time('runPlugin')
4041
await runPlugin(ctx)

Diff for: tests/integration/edge-handler.test.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from '../utils/fixture.js'
99
import { generateRandomObjectID, startMockBlobStore } from '../utils/helpers.js'
1010
import { LocalServer } from '../utils/local-server.js'
11+
import { platform } from 'process'
1112

1213
beforeEach<FixtureTestContext>(async (ctx) => {
1314
// set for each test a new deployID and siteID
@@ -18,7 +19,7 @@ beforeEach<FixtureTestContext>(async (ctx) => {
1819
await startMockBlobStore(ctx)
1920
})
2021

21-
test<FixtureTestContext>('should add request/response headers', async (ctx) => {
22+
test.skipIf(platform === "win32")<FixtureTestContext>('should add request/response headers', async (ctx) => {
2223
await createFixture('middleware', ctx)
2324
await runPlugin(ctx)
2425

@@ -46,7 +47,7 @@ test<FixtureTestContext>('should add request/response headers', async (ctx) => {
4647
expect(origin.calls).toBe(1)
4748
})
4849

49-
test<FixtureTestContext>('should add request/response headers when using src dir', async (ctx) => {
50+
test.skipIf(platform === "win32")<FixtureTestContext>('should add request/response headers when using src dir', async (ctx) => {
5051
await createFixture('middleware-src', ctx)
5152
await runPlugin(ctx)
5253

@@ -74,7 +75,7 @@ test<FixtureTestContext>('should add request/response headers when using src dir
7475
expect(origin.calls).toBe(1)
7576
})
7677

77-
describe('redirect', () => {
78+
describe.skipIf(platform === "win32")('redirect', () => {
7879
test<FixtureTestContext>('should return a redirect response', async (ctx) => {
7980
await createFixture('middleware', ctx)
8081
await runPlugin(ctx)
@@ -123,7 +124,7 @@ describe('redirect', () => {
123124
})
124125
})
125126

126-
describe('rewrite', () => {
127+
describe.skipIf(platform === "win32")('rewrite', () => {
127128
test<FixtureTestContext>('should rewrite to an external URL', async (ctx) => {
128129
await createFixture('middleware', ctx)
129130
await runPlugin(ctx)
@@ -183,7 +184,7 @@ describe('rewrite', () => {
183184
})
184185
})
185186

186-
describe("aborts middleware execution when the matcher conditions don't match the request", () => {
187+
describe.skipIf(platform === "win32")("aborts middleware execution when the matcher conditions don't match the request", () => {
187188
test<FixtureTestContext>('when the path is excluded', async (ctx) => {
188189
await createFixture('middleware', ctx)
189190
await runPlugin(ctx)
@@ -292,7 +293,7 @@ describe("aborts middleware execution when the matcher conditions don't match th
292293
})
293294
})
294295

295-
describe('should run middleware on data requests', () => {
296+
describe.skipIf(platform === "win32")('should run middleware on data requests', () => {
296297
test<FixtureTestContext>('when `trailingSlash: false`', async (ctx) => {
297298
await createFixture('middleware', ctx)
298299
await runPlugin(ctx)

Diff for: tests/integration/page-router.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
type FixtureTestContext,
1212
} from '../utils/fixture.js'
1313
import { encodeBlobKey, generateRandomObjectID, startMockBlobStore } from '../utils/helpers.js'
14+
import { platform } from 'node:process'
1415

1516
// Disable the verbose logging of the lambda-local runtime
1617
getLogger().level = 'alert'
@@ -62,7 +63,7 @@ test<FixtureTestContext>('Should add pathname to cache-tags for pages route', as
6263
expect(staticFetch1.headers?.['netlify-cache-tag']).toBe('_N_T_/static/revalidate-manual')
6364
})
6465

65-
test<FixtureTestContext>('Should revalidate path with On-demand Revalidation', async (ctx) => {
66+
test.skipIf(platform === 'win32')<FixtureTestContext>('Should revalidate path with On-demand Revalidation', async (ctx) => {
6667
await createFixture('page-router', ctx)
6768
await runPlugin(ctx)
6869

@@ -114,7 +115,7 @@ test<FixtureTestContext>('Should return JSON for data req to page route', async
114115
expect(data.pageProps.show).toBeDefined()
115116
})
116117

117-
test<FixtureTestContext>('Should set permanent "netlify-cdn-cache-control" header on fully static pages"', async (ctx) => {
118+
test.skipIf(platform === "win32")<FixtureTestContext>('Should set permanent "netlify-cdn-cache-control" header on fully static pages"', async (ctx) => {
118119
await createFixture('page-router', ctx)
119120
await runPlugin(ctx)
120121

Diff for: tests/integration/pnpm.test.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type FixtureTestContext,
1010
} from '../utils/fixture.js'
1111
import { generateRandomObjectID, startMockBlobStore } from '../utils/helpers.js'
12+
import { platform } from 'node:process'
1213

1314
// Disable the verbose logging of the lambda-local runtime
1415
getLogger().level = 'alert'
@@ -24,11 +25,14 @@ beforeEach<FixtureTestContext>(async (ctx) => {
2425
await startMockBlobStore(ctx)
2526
})
2627

27-
test<FixtureTestContext>('that the runtime works correctly with the pnpm package manager', async (ctx) => {
28-
await createFixture('simple-next-app-pnpm', ctx)
29-
await runPlugin(ctx)
28+
test.skipIf(platform === 'win32')<FixtureTestContext>(
29+
'that the runtime works correctly with the pnpm package manager',
30+
async (ctx) => {
31+
await createFixture('simple-next-app-pnpm', ctx)
32+
await runPlugin(ctx)
3033

31-
const home = await invokeFunction(ctx)
32-
expect(home.statusCode).toBe(200)
33-
expect(load(home.body)('h1').text()).toBe('Home')
34-
})
34+
const home = await invokeFunction(ctx)
35+
expect(home.statusCode).toBe(200)
36+
expect(load(home.body)('h1').text()).toBe('Home')
37+
},
38+
)

0 commit comments

Comments
 (0)