mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
33af645bea
This suite installed `sqlite` and `sqlite3` on every run to prerender a page from a checked-in SQLite database. Neither package was needed for what the test covers. The pinned `sqlite3@5.0.2` has no linux-arm64 prebuild, and every job that runs this suite is linux-arm64, so each one compiled the SQLite amalgamation from source. That pin is also Node-API based and therefore context-aware, so it could no longer reproduce the abort the suite was originally added for. The fixture now uses its own compiled `native-addon` plus a dependency-free JS wrapper standing in for `sqlite`'s role, and reads its rows from a plain JSON file. The `path.join(process.cwd(), ...)` expression stays in the page, because output file tracing only follows it from the app's own code, so moving it into the wrapper would stop the data file being traced. The emitted traces were read rather than assumed. Turbopack and `@vercel/nft` produce the same fixture entries, including the compiled binary at `native-addon/build/Release/native_addon.node` and the `process.cwd()`-derived `users.json`. The trace assertion now checks each pattern separately instead of collapsing them into a single `every(...)`, which could only report that something did not match. The `notTests` block went away with it, since `[].some(...)` asserted nothing.
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
import path from 'path'
|
|
import { isReact18, nextTestSetup } from 'e2e-utils'
|
|
|
|
const fixture = path.join(__dirname, 'prerender-native-module')
|
|
|
|
const expectedUsers = [
|
|
{ id: 1, first_name: 'john', last_name: 'deux' },
|
|
{ id: 2, first_name: 'zeit', last_name: 'geist' },
|
|
]
|
|
|
|
describe('prerender native module', () => {
|
|
const { next } = nextTestSetup({
|
|
files: fixture,
|
|
// `bindings` is a direct dependency rather than one of `native-addon`. The
|
|
// addon resolves it by walking up from the virtual store, and declaring it on
|
|
// the addon would make it a non-registry transitive dependency, which
|
|
// `blockExoticSubdeps` rejects.
|
|
//
|
|
// These use `file:` rather than `link:` so pnpm copies them into the virtual
|
|
// store. A linked package resolves to a path inside the app, which the bundler
|
|
// treats as app code and tries to bundle, and `bindings` contains a `require`
|
|
// it cannot resolve statically.
|
|
dependencies: require('./prerender-native-module/package.json')
|
|
.dependencies,
|
|
})
|
|
|
|
it('should render index correctly', async () => {
|
|
const browser = await next.browser('/')
|
|
expect(await browser.elementByCss('#index').text()).toBe('index page')
|
|
expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
|
|
index: true,
|
|
})
|
|
})
|
|
|
|
it('should render /blog/first correctly', async () => {
|
|
const browser = await next.browser('/blog/first')
|
|
|
|
expect(await browser.elementByCss('#blog').text()).toBe('blog page')
|
|
expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
|
|
params: { slug: 'first' },
|
|
blog: true,
|
|
contextAware: true,
|
|
users: expectedUsers,
|
|
})
|
|
})
|
|
|
|
it('should render /blog/second correctly', async () => {
|
|
const browser = await next.browser('/blog/second')
|
|
await browser.waitForElementByCss('#blog')
|
|
|
|
expect(await browser.elementByCss('#blog').text()).toBe('blog page')
|
|
expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
|
|
params: { slug: 'second' },
|
|
blog: true,
|
|
contextAware: true,
|
|
users: expectedUsers,
|
|
})
|
|
})
|
|
|
|
if ((global as any).isNextStart) {
|
|
it('should output traces', async () => {
|
|
const checks = [
|
|
{
|
|
page: '/_app',
|
|
tests: [
|
|
/(webpack-runtime\.js|\[turbopack\]_runtime\.js)/,
|
|
/node_modules\/react\/index\.js/,
|
|
/node_modules\/react\/package\.json/,
|
|
isReact18
|
|
? /node_modules\/react\/cjs\/react\.production\.min\.js/
|
|
: /node_modules\/react\/cjs\/react\.production\.js/,
|
|
],
|
|
},
|
|
{
|
|
page: '/blog/[slug]',
|
|
tests: [
|
|
/(webpack-runtime\.js|\[turbopack\]_runtime\.js)/,
|
|
/node_modules\/react\/index\.js/,
|
|
/node_modules\/react\/package\.json/,
|
|
isReact18
|
|
? /node_modules\/react\/cjs\/react\.production\.min\.js/
|
|
: /node_modules\/react\/cjs\/react\.production\.js/,
|
|
// The addon's JS entry, and the binary it locates through
|
|
// `require('bindings')(...)`.
|
|
/node_modules\/native-addon\/.*?\.js/,
|
|
/node_modules\/native-addon\/.*?\.node/,
|
|
// The pure-JS wrapper layered on top of it.
|
|
/node_modules\/native-addon-wrapper\/.*?\.js/,
|
|
/node_modules\/next/,
|
|
// Reached only by statically evaluating `path.join(process.cwd(), ...)`.
|
|
/\/users\.json/,
|
|
],
|
|
},
|
|
]
|
|
|
|
for (const check of checks) {
|
|
const contents = await next.readFile(
|
|
path.join('.next/server/pages/', check.page + '.js.nft.json')
|
|
)
|
|
const { version, files } = JSON.parse(contents)
|
|
expect(version).toBe(1)
|
|
|
|
for (const test of check.tests) {
|
|
expect(files).toEqual(
|
|
expect.arrayContaining([expect.stringMatching(test)])
|
|
)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|