Skip to content

Commit

Permalink
test: add feature of overriding files (#74716)
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Jan 17, 2025
1 parent 79bdd86 commit 30b9c8f
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {
} from 'next-test-utils'

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

;(isOwnerStackEnabled ? describe.skip : describe)(
'app-dir - invalid-element-type',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import {
} from 'next-test-utils'

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

;(isOwnerStackEnabled ? describe : describe.skip)(
'app-dir - owner-stack-react-missing-key-prop',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { nextTestSetup } from 'e2e-utils'
import { getRedboxSource, openRedbox } from 'next-test-utils'

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

async function getStackFramesContent(browser) {
const stackFrameElements = await browser.elementsByCss(
Expand Down Expand Up @@ -33,29 +31,26 @@ async function getStackFramesContent(browser) {
return stackFramesContent
}

// Without owner stack, the source is not available
;(isOwnerStackEnabled ? describe.skip : describe)(
'app-dir - react-missing-key-prop',
() => {
const { next } = nextTestSetup({
files: __dirname,
})
overrideFiles: {
'next.config.js': `
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
experimental: {
reactOwnerStack: false,
},
}
let nextConfig: string = ''
beforeAll(async () => {
await next.stop()
await next.patchFile('next.config.js', (content: string) => {
nextConfig = content
return content.replace(
`reactOwnerStack: true`,
`reactOwnerStack: false`
)
})
await next.start()
})
afterAll(async () => {
await next.stop()
// Restore original next.config.js
await next.patchFile('next.config.js', nextConfig)
module.exports = nextConfig
`,
},
})

it('should catch invalid element from on rsc component', async () => {
Expand All @@ -68,30 +63,29 @@ async function getStackFramesContent(browser) {
if (process.env.TURBOPACK) {
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
expect(source).toMatchInlineSnapshot(`
"app/rsc/page.tsx (5:5) @ Page
"app/rsc/page.tsx (5:6) @ Page
3 | export default function Page() {
4 | return (
> 5 | <div>
| ^
6 | {list.map((item, index) => (
7 | <span>{item}</span>
8 | ))}"
`)
3 | export default function Page() {
4 | return (
> 5 | <div>
| ^
6 | {list.map((item, index) => (
7 | <span>{item}</span>
8 | ))}"
`)
} else {
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
// FIXME: the methodName should be `@ Page` instead of `@ div`
expect(source).toMatchInlineSnapshot(`
"app/rsc/page.tsx (5:6) @ div
"app/rsc/page.tsx (5:6) @ Page
3 | export default function Page() {
4 | return (
> 5 | <div>
| ^
6 | {list.map((item, index) => (
7 | <span>{item}</span>
8 | ))}"
`)
3 | export default function Page() {
4 | return (
> 5 | <div>
| ^
6 | {list.map((item, index) => (
7 | <span>{item}</span>
8 | ))}"
`)
}
})

Expand All @@ -104,30 +98,29 @@ async function getStackFramesContent(browser) {
if (process.env.TURBOPACK) {
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
expect(source).toMatchInlineSnapshot(`
"app/ssr/page.tsx (7:5) @ Page
"app/ssr/page.tsx (7:5) @ Page
5 | export default function Page() {
6 | return (
> 7 | <div>
| ^
8 | {list.map((item, index) => (
9 | <p>{item}</p>
10 | ))}"
`)
5 | export default function Page() {
6 | return (
> 7 | <div>
| ^
8 | {list.map((item, index) => (
9 | <p>{item}</p>
10 | ))}"
`)
} else {
expect(stackFramesContent).toMatchInlineSnapshot(`""`)
// FIXME: the methodName should be `@ Page` instead of `@ div`
expect(source).toMatchInlineSnapshot(`
"app/ssr/page.tsx (7:6) @ div
"app/ssr/page.tsx (7:6) @ Page
5 | export default function Page() {
6 | return (
> 7 | <div>
| ^
8 | {list.map((item, index) => (
9 | <p>{item}</p>
10 | ))}"
`)
5 | export default function Page() {
6 | return (
> 7 | <div>
| ^
8 | {list.map((item, index) => (
9 | <p>{item}</p>
10 | ))}"
`)
}
})
}
Expand Down
33 changes: 27 additions & 6 deletions test/lib/next-modes/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ export type PackageJson = {
dependencies?: { [key: string]: string }
[key: string]: unknown
}

type ResolvedFileConfig = FileRef | { [filename: string]: string | FileRef }
type FilesConfig = ResolvedFileConfig | string
export interface NextInstanceOpts {
files: FileRef | string | { [filename: string]: string | FileRef }
files: FilesConfig
overrideFiles?: FilesConfig
dependencies?: { [name: string]: string }
resolutions?: { [name: string]: string }
packageJson?: PackageJson
Expand Down Expand Up @@ -55,7 +59,8 @@ type OmitFirstArgument<F> = F extends (
const nextjsReactPeerVersion = "^19.0.0";

export class NextInstance {
protected files: FileRef | { [filename: string]: string | FileRef }
protected files: ResolvedFileConfig
protected overrideFiles: ResolvedFileConfig
protected nextConfig?: NextConfig
protected installCommand?: InstallCommand
protected buildCommand?: string
Expand Down Expand Up @@ -95,10 +100,10 @@ export class NextInstance {
}
}

protected async writeInitialFiles() {
private async writeFiles(filesConfig: FilesConfig, testDir: string) {
// Handle case where files is a directory string
const files =
typeof this.files === 'string' ? new FileRef(this.files) : this.files
typeof filesConfig === 'string' ? new FileRef(filesConfig) : filesConfig
if (files instanceof FileRef) {
// if a FileRef is passed directly to `files` we copy the
// entire folder to the test directory
Expand All @@ -110,7 +115,7 @@ export class NextInstance {
)
}

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

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

protected async writeInitialFiles() {
return this.writeFiles(this.files, this.testDir)
}

protected async writeOverrideFiles() {
if (this.overrideFiles) {
return this.writeFiles(this.overrideFiles, this.testDir)
}
}

protected async createTestDir({
skipInstall = false,
parentSpan,
Expand Down Expand Up @@ -240,6 +255,12 @@ export class NextInstance {
await this.writeInitialFiles()
})

await rootSpan
.traceChild('writeOverrideFiles')
.traceAsyncFn(async () => {
await this.writeOverrideFiles()
})

const testDirFiles = await fs.readdir(this.testDir)

let nextConfigFile = testDirFiles.find((file) =>
Expand Down

0 comments on commit 30b9c8f

Please sign in to comment.