Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagesDir to Jest transformer #36599

Merged
merged 6 commits into from May 1, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/next/build/jest/jest.ts
Expand Up @@ -4,6 +4,7 @@ import loadConfig from '../../server/config'
import { PHASE_TEST } from '../../shared/lib/constants'
import loadJsConfig from '../load-jsconfig'
import * as Log from '../output/log'
import { findPagesDir } from '../../lib/find-pages-dir'

async function getConfig(dir: string) {
const conf = await loadConfig(PHASE_TEST, dir)
Expand Down Expand Up @@ -50,8 +51,11 @@ export default function nextJest(options: { dir?: string } = {}) {
let jsConfig
let resolvedBaseUrl
let isEsmProject = false
let pagesDir

if (options.dir) {
const resolvedDir = resolve(options.dir)
pagesDir = findPagesDir(resolvedDir)
const packageConfig = loadClosestPackageJson(resolvedDir)
isEsmProject = packageConfig.type === 'module'

Expand Down Expand Up @@ -108,6 +112,7 @@ export default function nextJest(options: { dir?: string } = {}) {
jsConfig,
resolvedBaseUrl,
isEsmProject,
pagesDir,
},
],
// Allow for appending/overriding the default transforms
Expand Down
1 change: 1 addition & 0 deletions packages/next/build/swc/jest-transformer.js
Expand Up @@ -47,6 +47,7 @@ module.exports = {
nextConfig: inputOptions.nextConfig,
jsConfig: inputOptions.jsConfig,
resolvedBaseUrl: inputOptions.resolvedBaseUrl,
pagesDir: inputOptions.pagesDir,
esm:
isSupportEsm &&
isEsm(Boolean(inputOptions.isEsmProject), filename, jestConfig),
Expand Down
2 changes: 2 additions & 0 deletions packages/next/build/swc/options.js
Expand Up @@ -145,6 +145,7 @@ export function getJestSWCOptions({
esm,
nextConfig,
jsConfig,
pagesDir,
// This is not passed yet as "paths" resolving needs a test first
// resolvedBaseUrl,
}) {
Expand Down Expand Up @@ -174,6 +175,7 @@ export function getJestSWCOptions({
},
disableNextSsg: true,
disablePageConfig: true,
pagesDir,
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/lib/e2e-utils.ts
Expand Up @@ -7,7 +7,7 @@ import { NextStartInstance } from './next-modes/next-start'
import { NextDeployInstance } from './next-modes/next-deploy'

// increase timeout to account for yarn install time
jest.setTimeout((process.platform === 'win32' ? 240 : 180) * 1000)
jest.setTimeout(240 * 1000)

const testsFolder = path.join(__dirname, '..')

Expand Down
Expand Up @@ -5,6 +5,12 @@ import { renderViaHTTP } from 'next-test-utils'
describe('next/jest', () => {
let next: NextInstance

if (process.env.NEXT_TEST_REACT_VERSION === '^17') {
// react testing library is specific to react version
it('should bail on react v17', () => {})
return
}

beforeAll(async () => {
next = await createNext({
files: {
Expand Down
23 changes: 23 additions & 0 deletions test/production/jest/relay/app/components/environment.tsx
@@ -0,0 +1,23 @@
import { Environment, Network, RecordSource, Store } from 'relay-runtime'

async function fetchGraphQL(text, variables) {
return new Promise((next) => {
const res = () => {
return next({ data: { viewer: { user: { id: '123', name: 'Foo' } } } })
}

setTimeout(res, 1000)
})
}

// Relay passes a "params" object with the query name and text. So we define a helper function
// to call our fetchGraphQL utility with params.text.
async function fetchRelay(params, variables) {
return await fetchGraphQL(params.text, variables)
}

// Export a singleton instance of Relay Environment configured with our network function:
export default new Environment({
network: Network.create(fetchRelay),
store: new Store(new RecordSource()),
})
20 changes: 20 additions & 0 deletions test/production/jest/relay/app/jest.config.js
@@ -0,0 +1,20 @@
const nextJest = require('next/jest')

const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})

// Add any custom config to be passed to Jest
const customJestConfig = {
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: {
// When changing these, also look at the tsconfig!
'^types/(.+)$': '<rootDir>/types/$1',
},
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
19 changes: 19 additions & 0 deletions test/production/jest/relay/app/main.graphql
@@ -0,0 +1,19 @@
type Query {
viewer(after: String, before: String, first: Int, last: Int): Viewer!
node(id: ID!): Node
}

type Viewer implements Node {
id: ID!
user: User!
}

interface Node {
id: ID!
}

type User implements Node {
id: ID!
name: String!
title: String!
}
9 changes: 9 additions & 0 deletions test/production/jest/relay/app/next.config.js
@@ -0,0 +1,9 @@
module.exports = {
compiler: {
relay: {
src: './',
artifactDirectory: './types',
language: 'typescript',
},
},
}
10 changes: 10 additions & 0 deletions test/production/jest/relay/app/pages/_app.tsx
@@ -0,0 +1,10 @@
import { RelayEnvironmentProvider } from 'react-relay/hooks'
import RelayEnvironment from '../components/environment'

export default function MyApp({ Component, pageProps }) {
return (
<RelayEnvironmentProvider environment={RelayEnvironment}>
<Component {...pageProps} />
</RelayEnvironmentProvider>
)
}
35 changes: 35 additions & 0 deletions test/production/jest/relay/app/pages/index.tsx
@@ -0,0 +1,35 @@
import { graphql, useRelayEnvironment, QueryRenderer } from 'react-relay'

import type { pagesQueryResponse } from '../types/pagesQuery.graphql'

function Component() {
const env = useRelayEnvironment()
return (
<QueryRenderer
environment={env}
query={graphql`
query pagesQuery {
viewer {
user {
id
name
}
}
}
`}
render={({ props }: { props: pagesQueryResponse }) => {
if (props) {
return (
<div>
Data requested: <span>{props.viewer.user.id}</span>
</div>
)
}

return <div>Loading...</div>
}}
/>
)
}

export default Component
23 changes: 23 additions & 0 deletions test/production/jest/relay/app/tsconfig.json
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"paths": {
"types/*": ["./types/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "tests/entry.test.tsx"],
"exclude": ["node_modules"]
}
107 changes: 107 additions & 0 deletions test/production/jest/relay/app/types/pagesQuery.graphql.ts
@@ -0,0 +1,107 @@
/**
* @generated SignedSource<<a6468d297da1928100bce80db9f1b8ab>>
* @lightSyntaxTransform
* @nogrep
*/

/* tslint:disable */
/* eslint-disable */
// @ts-nocheck

import { ConcreteRequest, Query } from 'relay-runtime'
export type pagesQuery$variables = {}
export type pagesQueryVariables = pagesQuery$variables
export type pagesQuery$data = {
readonly viewer: {
readonly user: {
readonly id: string
readonly name: string
}
}
}
export type pagesQueryResponse = pagesQuery$data
export type pagesQuery = {
variables: pagesQueryVariables
response: pagesQuery$data
}

const node: ConcreteRequest = (function () {
var v0 = {
alias: null,
args: null,
kind: 'ScalarField',
name: 'id',
storageKey: null,
},
v1 = {
alias: null,
args: null,
concreteType: 'User',
kind: 'LinkedField',
name: 'user',
plural: false,
selections: [
v0 /*: any*/,
{
alias: null,
args: null,
kind: 'ScalarField',
name: 'name',
storageKey: null,
},
],
storageKey: null,
}
return {
fragment: {
argumentDefinitions: [],
kind: 'Fragment',
metadata: null,
name: 'pagesQuery',
selections: [
{
alias: null,
args: null,
concreteType: 'Viewer',
kind: 'LinkedField',
name: 'viewer',
plural: false,
selections: [v1 /*: any*/],
storageKey: null,
},
],
type: 'Query',
abstractKey: null,
},
kind: 'Request',
operation: {
argumentDefinitions: [],
kind: 'Operation',
name: 'pagesQuery',
selections: [
{
alias: null,
args: null,
concreteType: 'Viewer',
kind: 'LinkedField',
name: 'viewer',
plural: false,
selections: [v1 /*: any*/, v0 /*: any*/],
storageKey: null,
},
],
},
params: {
cacheID: '5a14ce729d0deb2c3170bcdcba33a61a',
id: null,
metadata: {},
name: 'pagesQuery',
operationKind: 'query',
text: 'query pagesQuery {\n viewer {\n user {\n id\n name\n }\n id\n }\n}\n',
},
}
})()

;(node as any).hash = '00b43dedd685e716dda36f66f4d5e30e'

export default node