Skip to content

Commit 30b9c8f

Browse files
committed
test: add feature of overriding files (#74716)
1 parent 79bdd86 commit 30b9c8f

File tree

4 files changed

+80
-70
lines changed

4 files changed

+80
-70
lines changed

test/development/app-dir/owner-stack-invalid-element-type/invalid-element-type.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import {
88
} from 'next-test-utils'
99

1010
// TODO: When owner stack is enabled by default, remove the condition and only keep one test
11-
const isOwnerStackEnabled =
12-
process.env.TEST_OWNER_STACK !== 'false' ||
13-
process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
11+
const isOwnerStackEnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
1412

1513
;(isOwnerStackEnabled ? describe.skip : describe)(
1614
'app-dir - invalid-element-type',

test/development/app-dir/owner-stack-react-missing-key-prop/owner-stack-react-missing-key-prop.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import {
66
} from 'next-test-utils'
77

88
// TODO: When owner stack is enabled by default, remove the condition and only keep one test
9-
const isOwnerStackEnabled =
10-
process.env.TEST_OWNER_STACK !== 'false' ||
11-
process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
9+
const isOwnerStackEnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
1210

1311
;(isOwnerStackEnabled ? describe : describe.skip)(
1412
'app-dir - owner-stack-react-missing-key-prop',

test/development/app-dir/owner-stack-react-missing-key-prop/react-missing-key-prop.test.ts

Lines changed: 51 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import { nextTestSetup } from 'e2e-utils'
22
import { getRedboxSource, openRedbox } from 'next-test-utils'
33

44
// TODO: When owner stack is enabled by default, remove the condition and only keep one test
5-
const isOwnerStackEnabled =
6-
process.env.TEST_OWNER_STACK !== 'false' ||
7-
process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
5+
const isOwnerStackEnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
86

97
async function getStackFramesContent(browser) {
108
const stackFrameElements = await browser.elementsByCss(
@@ -33,29 +31,26 @@ async function getStackFramesContent(browser) {
3331
return stackFramesContent
3432
}
3533

34+
// Without owner stack, the source is not available
3635
;(isOwnerStackEnabled ? describe.skip : describe)(
3736
'app-dir - react-missing-key-prop',
3837
() => {
3938
const { next } = nextTestSetup({
4039
files: __dirname,
41-
})
40+
overrideFiles: {
41+
'next.config.js': `
42+
/**
43+
* @type {import('next').NextConfig}
44+
*/
45+
const nextConfig = {
46+
experimental: {
47+
reactOwnerStack: false,
48+
},
49+
}
4250
43-
let nextConfig: string = ''
44-
beforeAll(async () => {
45-
await next.stop()
46-
await next.patchFile('next.config.js', (content: string) => {
47-
nextConfig = content
48-
return content.replace(
49-
`reactOwnerStack: true`,
50-
`reactOwnerStack: false`
51-
)
52-
})
53-
await next.start()
54-
})
55-
afterAll(async () => {
56-
await next.stop()
57-
// Restore original next.config.js
58-
await next.patchFile('next.config.js', nextConfig)
51+
module.exports = nextConfig
52+
`,
53+
},
5954
})
6055

6156
it('should catch invalid element from on rsc component', async () => {
@@ -68,30 +63,29 @@ async function getStackFramesContent(browser) {
6863
if (process.env.TURBOPACK) {
6964
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
7065
expect(source).toMatchInlineSnapshot(`
71-
"app/rsc/page.tsx (5:5) @ Page
66+
"app/rsc/page.tsx (5:6) @ Page
7267
73-
3 | export default function Page() {
74-
4 | return (
75-
> 5 | <div>
76-
| ^
77-
6 | {list.map((item, index) => (
78-
7 | <span>{item}</span>
79-
8 | ))}"
80-
`)
68+
3 | export default function Page() {
69+
4 | return (
70+
> 5 | <div>
71+
| ^
72+
6 | {list.map((item, index) => (
73+
7 | <span>{item}</span>
74+
8 | ))}"
75+
`)
8176
} else {
8277
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
83-
// FIXME: the methodName should be `@ Page` instead of `@ div`
8478
expect(source).toMatchInlineSnapshot(`
85-
"app/rsc/page.tsx (5:6) @ div
79+
"app/rsc/page.tsx (5:6) @ Page
8680
87-
3 | export default function Page() {
88-
4 | return (
89-
> 5 | <div>
90-
| ^
91-
6 | {list.map((item, index) => (
92-
7 | <span>{item}</span>
93-
8 | ))}"
94-
`)
81+
3 | export default function Page() {
82+
4 | return (
83+
> 5 | <div>
84+
| ^
85+
6 | {list.map((item, index) => (
86+
7 | <span>{item}</span>
87+
8 | ))}"
88+
`)
9589
}
9690
})
9791

@@ -104,30 +98,29 @@ async function getStackFramesContent(browser) {
10498
if (process.env.TURBOPACK) {
10599
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
106100
expect(source).toMatchInlineSnapshot(`
107-
"app/ssr/page.tsx (7:5) @ Page
101+
"app/ssr/page.tsx (7:5) @ Page
108102
109-
5 | export default function Page() {
110-
6 | return (
111-
> 7 | <div>
112-
| ^
113-
8 | {list.map((item, index) => (
114-
9 | <p>{item}</p>
115-
10 | ))}"
116-
`)
103+
5 | export default function Page() {
104+
6 | return (
105+
> 7 | <div>
106+
| ^
107+
8 | {list.map((item, index) => (
108+
9 | <p>{item}</p>
109+
10 | ))}"
110+
`)
117111
} else {
118112
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
119-
// FIXME: the methodName should be `@ Page` instead of `@ div`
120113
expect(source).toMatchInlineSnapshot(`
121-
"app/ssr/page.tsx (7:6) @ div
114+
"app/ssr/page.tsx (7:6) @ Page
122115
123-
5 | export default function Page() {
124-
6 | return (
125-
> 7 | <div>
126-
| ^
127-
8 | {list.map((item, index) => (
128-
9 | <p>{item}</p>
129-
10 | ))}"
130-
`)
116+
5 | export default function Page() {
117+
6 | return (
118+
> 7 | <div>
119+
| ^
120+
8 | {list.map((item, index) => (
121+
9 | <p>{item}</p>
122+
10 | ))}"
123+
`)
131124
}
132125
})
133126
}

test/lib/next-modes/base.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ export type PackageJson = {
2323
dependencies?: { [key: string]: string }
2424
[key: string]: unknown
2525
}
26+
27+
type ResolvedFileConfig = FileRef | { [filename: string]: string | FileRef }
28+
type FilesConfig = ResolvedFileConfig | string
2629
export interface NextInstanceOpts {
27-
files: FileRef | string | { [filename: string]: string | FileRef }
30+
files: FilesConfig
31+
overrideFiles?: FilesConfig
2832
dependencies?: { [name: string]: string }
2933
resolutions?: { [name: string]: string }
3034
packageJson?: PackageJson
@@ -55,7 +59,8 @@ type OmitFirstArgument<F> = F extends (
5559
const nextjsReactPeerVersion = "^19.0.0";
5660

5761
export class NextInstance {
58-
protected files: FileRef | { [filename: string]: string | FileRef }
62+
protected files: ResolvedFileConfig
63+
protected overrideFiles: ResolvedFileConfig
5964
protected nextConfig?: NextConfig
6065
protected installCommand?: InstallCommand
6166
protected buildCommand?: string
@@ -95,10 +100,10 @@ export class NextInstance {
95100
}
96101
}
97102

98-
protected async writeInitialFiles() {
103+
private async writeFiles(filesConfig: FilesConfig, testDir: string) {
99104
// Handle case where files is a directory string
100105
const files =
101-
typeof this.files === 'string' ? new FileRef(this.files) : this.files
106+
typeof filesConfig === 'string' ? new FileRef(filesConfig) : filesConfig
102107
if (files instanceof FileRef) {
103108
// if a FileRef is passed directly to `files` we copy the
104109
// entire folder to the test directory
@@ -110,7 +115,7 @@ export class NextInstance {
110115
)
111116
}
112117

113-
await fs.cp(files.fsPath, this.testDir, {
118+
await fs.cp(files.fsPath, testDir, {
114119
recursive: true,
115120
filter(source) {
116121
// we don't copy a package.json as it's manually written
@@ -124,7 +129,7 @@ export class NextInstance {
124129
} else {
125130
for (const filename of Object.keys(files)) {
126131
const item = files[filename]
127-
const outputFilename = path.join(this.testDir, filename)
132+
const outputFilename = path.join(testDir, filename)
128133

129134
if (typeof item === 'string') {
130135
await fs.mkdir(path.dirname(outputFilename), { recursive: true })
@@ -136,6 +141,16 @@ export class NextInstance {
136141
}
137142
}
138143

144+
protected async writeInitialFiles() {
145+
return this.writeFiles(this.files, this.testDir)
146+
}
147+
148+
protected async writeOverrideFiles() {
149+
if (this.overrideFiles) {
150+
return this.writeFiles(this.overrideFiles, this.testDir)
151+
}
152+
}
153+
139154
protected async createTestDir({
140155
skipInstall = false,
141156
parentSpan,
@@ -240,6 +255,12 @@ export class NextInstance {
240255
await this.writeInitialFiles()
241256
})
242257

258+
await rootSpan
259+
.traceChild('writeOverrideFiles')
260+
.traceAsyncFn(async () => {
261+
await this.writeOverrideFiles()
262+
})
263+
243264
const testDirFiles = await fs.readdir(this.testDir)
244265

245266
let nextConfigFile = testDirFiles.find((file) =>

0 commit comments

Comments
 (0)