Skip to content

Commit

Permalink
chore(internal): switch to vitest (#10162)
Browse files Browse the repository at this point in the history
This PR switches out the `@redwoodjs/internal` package to use vitest
over jest for its tests.

There are two points to note here:
1. I had to add a `resolve.alias` to the `vitest.config.mts` in order to
only have one copy of `graphql` load. Without this change a copy from
their `index.js` and another copy from their `index.mjs` would load and
`graphql` forbids two instances running at the same time. There are
additional comments within the config file which include links for more
details.
2. We have to avoid the `require('@prisma/client')` call and so it
became a dynamic import. This required the function to be async and that
cascaded to other functions. Namely; `getPrismaModels`,
`getPluginConfig`, and `getPrismaClient`. From what I can see there is
no usage of these functions outside this internal package and the
additional asyncs added here are sufficient.
  • Loading branch information
Josh-Walker-GM authored Mar 9, 2024
1 parent 7e3ec43 commit bec7b02
Show file tree
Hide file tree
Showing 32 changed files with 199 additions and 133 deletions.
8 changes: 0 additions & 8 deletions packages/internal/jest.config.js

This file was deleted.

8 changes: 4 additions & 4 deletions packages/internal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
"fix:permissions": "chmod +x dist/generate/generate.js dist/generate/watch.js",
"prepublishOnly": "NODE_ENV=production yarn build",
"test": "jest src",
"test:watch": "yarn test --watch"
"test": "vitest run",
"test:watch": "vitest watch"
},
"dependencies": {
"@babel/core": "^7.22.20",
Expand Down Expand Up @@ -73,8 +73,8 @@
"@babel/cli": "7.23.9",
"@types/fs-extra": "11.0.4",
"graphql-tag": "2.12.6",
"jest": "29.7.0",
"tsx": "4.6.2"
"tsx": "4.6.2",
"vitest": "1.2.2"
},
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Generate gql typedefs api 1`] = `
"import { Prisma } from "@prisma/client"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Generates GraphQL schema 1`] = `
"directive @requireAuth(roles: [String]) on FIELD_DEFINITION
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Generate gql possible types web from the GraphQL Schema when toml has graphql possible types turned om when there are union types 1`] = `
exports[`Generate gql possible types web from the GraphQL Schema > when toml has graphql possible types turned om > when there are union types 1`] = `
"export interface PossibleTypesResultData {
possibleTypes: {
[key: string]: string[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`generates global page imports source maps 1`] = `
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`SDL with no reserved names used SDL is invalid because uses a reserved name as a type 1`] = `
"The type named 'Float' is a reserved GraphQL name.
exports[`SDL with no reserved names used > SDL is invalid > because uses a reserved name as a type 1`] = `
[TypeError: The type named 'Float' is a reserved GraphQL name.
Please rename it to something more specific, like: ApplicationFloat.
"
]
`;

exports[`SDL with no reserved names used because uses a reserved name as an input 1`] = `
"The input type named 'Float' is a reserved GraphQL name.
exports[`SDL with no reserved names used > because uses a reserved name as an input 1`] = `
[TypeError: The input type named 'Float' is a reserved GraphQL name.
Please rename it to something more specific, like: ApplicationFloat.
"
]
`;

exports[`SDL with no reserved names used because uses a reserved name as an interface 1`] = `
"The interface named 'Float' is a reserved GraphQL name.
exports[`SDL with no reserved names used > because uses a reserved name as an interface 1`] = `
[TypeError: The interface named 'Float' is a reserved GraphQL name.
Please rename it to something more specific, like: ApplicationFloat.
"
]
`;
5 changes: 3 additions & 2 deletions packages/internal/src/__tests__/ast.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import path from 'path'

import { vi, test, expect } from 'vitest'

import {
getGqlQueries,
getNamedExports,
Expand All @@ -8,8 +10,7 @@ import {
fileToAst,
} from '../ast'

jest.mock('@redwoodjs/project-config', () => {
const path = require('path')
vi.mock('@redwoodjs/project-config', async () => {
const baseFixturePath = path.join(__dirname, 'fixtures')
return {
getPaths: () => ({
Expand Down
1 change: 1 addition & 0 deletions packages/internal/src/__tests__/build_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs'
import path from 'path'

import * as babel from '@babel/core'
import { beforeAll, test, expect, afterAll } from 'vitest'

import {
getApiSideBabelPlugins,
Expand Down
2 changes: 2 additions & 0 deletions packages/internal/src/__tests__/build_web.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import path from 'path'

import { beforeEach, test, expect, afterAll } from 'vitest'

import { prebuildWebFile } from '@redwoodjs/babel-config'
import { ensurePosixPath, getPaths } from '@redwoodjs/project-config'

Expand Down
38 changes: 22 additions & 16 deletions packages/internal/src/__tests__/clientPreset.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import path from 'path'

import { generateClientPreset } from '../generate/clientPreset'
import { generateGraphQLSchema } from '../generate/graphqlSchema'
import { vi, beforeEach, afterEach, describe, test, expect } from 'vitest'

let shouldGenerateTrustedDocuments = false
import type ProjectConfig from '@redwoodjs/project-config'

const mockTrustedDocumentsConfig = () => {
return shouldGenerateTrustedDocuments
}
import { generateClientPreset } from '../generate/clientPreset'
import { generateGraphQLSchema } from '../generate/graphqlSchema'

jest.mock('@redwoodjs/project-config', () => {
const projectConfig = jest.requireActual('@redwoodjs/project-config')
const { mockedGetConfig } = vi.hoisted(() => {
return {
mockedGetConfig: vi
.fn()
.mockReturnValue({ graphql: { trustedDocuments: false } }),
}
})

vi.mock('@redwoodjs/project-config', async (importOriginal) => {
const projectConfig = await importOriginal<typeof ProjectConfig>()
return {
...projectConfig,
getConfig: () => {
return { graphql: { trustedDocuments: mockTrustedDocumentsConfig() } }
},
getConfig: mockedGetConfig,
}
})

beforeEach(() => {
const FIXTURE_PATH = path.resolve(
__dirname,
Expand All @@ -30,15 +34,16 @@ beforeEach(() => {

afterEach(() => {
delete process.env.RWJS_CWD
jest.restoreAllMocks()
mockedGetConfig.mockReturnValue({ graphql: { trustedDocuments: false } })
})

describe('Generate client preset', () => {
test('for web side', async () => {
shouldGenerateTrustedDocuments = true
mockedGetConfig.mockReturnValue({ graphql: { trustedDocuments: true } })
await generateGraphQLSchema()

const { clientPresetFiles } = await generateClientPreset()
const { clientPresetFiles, errors } = await generateClientPreset()
expect(errors).toHaveLength(0)

expect(clientPresetFiles).toHaveLength(5)
const expectedEndings = [
Expand All @@ -57,10 +62,11 @@ describe('Generate client preset', () => {
})

test('for api side', async () => {
shouldGenerateTrustedDocuments = true
mockedGetConfig.mockReturnValue({ graphql: { trustedDocuments: true } })
await generateGraphQLSchema()

const { trustedDocumentsStoreFile } = await generateClientPreset()
const { trustedDocumentsStoreFile, errors } = await generateClientPreset()
expect(errors).toHaveLength(0)

expect(trustedDocumentsStoreFile).toContain('trustedDocumentsStore.ts')
})
Expand Down
10 changes: 6 additions & 4 deletions packages/internal/src/__tests__/configPath.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import path from 'path'

import { vi, describe, it, expect, afterAll, beforeAll } from 'vitest'

import { getConfigPath } from '@redwoodjs/project-config'

describe('getConfigPath', () => {
it('throws an error when not in a project', () => {
expect(getConfigPath).toThrowErrorMatchingInlineSnapshot(
`"Could not find a "redwood.toml" file, are you sure you're in a Redwood project?"`
`[Error: Could not find a "redwood.toml" file, are you sure you're in a Redwood project?]`
)
})

Expand Down Expand Up @@ -57,17 +59,17 @@ describe('getConfigPath', () => {
})
afterAll(() => {
process.env.RWJS_CWD = RWJS_CWD
jest.restoreAllMocks()
vi.restoreAllMocks()
})

it('finds the correct config path when at base directory', () => {
const spy = jest.spyOn(process, 'cwd')
const spy = vi.spyOn(process, 'cwd')
spy.mockReturnValue(FIXTURE_BASEDIR)
expect(getConfigPath()).toBe(path.join(FIXTURE_BASEDIR, 'redwood.toml'))
})

it('finds the correct config path when inside a project directory', () => {
const spy = jest.spyOn(process, 'cwd')
const spy = vi.spyOn(process, 'cwd')
spy.mockReturnValue(
path.join(FIXTURE_BASEDIR, 'web', 'src', 'pages', 'AboutPage')
)
Expand Down
2 changes: 2 additions & 0 deletions packages/internal/src/__tests__/files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const FIXTURE_PATH = path.resolve(
'../../../../__fixtures__/example-todo-main'
)

import { beforeAll, afterAll, test, expect } from 'vitest'

beforeAll(() => {
process.env.RWJS_CWD = FIXTURE_PATH
})
Expand Down
1 change: 1 addition & 0 deletions packages/internal/src/__tests__/gql.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path'

import gql from 'graphql-tag'
import { test, expect } from 'vitest'

import { listQueryTypeFieldsInProject, parseDocumentAST } from '../gql'

Expand Down
57 changes: 33 additions & 24 deletions packages/internal/src/__tests__/graphqlCodeGen.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import fs from 'fs'
import path from 'path'

import {
beforeAll,
afterAll,
afterEach,
vi,
test,
expect,
describe,
} from 'vitest'

import {
generateTypeDefGraphQLApi,
generateTypeDefGraphQLWeb,
Expand All @@ -21,33 +31,34 @@ afterAll(() => {
})

afterEach(() => {
jest.restoreAllMocks()
vi.restoreAllMocks()
})

jest.mock('@prisma/client', () => {
vi.mock('@prisma/client', () => {
return {
ModelName: {
PrismaModelOne: 'PrismaModelOne',
PrismaModelTwo: 'PrismaModelTwo',
Post: 'Post',
Todo: 'Todo',
default: {
ModelName: {
PrismaModelOne: 'PrismaModelOne',
PrismaModelTwo: 'PrismaModelTwo',
Post: 'Post',
Todo: 'Todo',
},
},
}
})

test('Generate gql typedefs web', async () => {
await generateGraphQLSchema()

jest
.spyOn(fs, 'writeFileSync')
.mockImplementation(
(file: fs.PathOrFileDescriptor, data: string | ArrayBufferView) => {
expect(file).toMatch(path.join('web', 'types', 'graphql.d.ts'))
expect(data).toMatchSnapshot()
}
)
vi.spyOn(fs, 'writeFileSync').mockImplementation(
(file: fs.PathOrFileDescriptor, data: string | ArrayBufferView) => {
expect(file).toMatch(path.join('web', 'types', 'graphql.d.ts'))
expect(data).toMatchSnapshot()
}
)

const { typeDefFiles } = await generateTypeDefGraphQLWeb()
const { typeDefFiles, errors } = await generateTypeDefGraphQLWeb()
expect(errors).toHaveLength(0)

expect(typeDefFiles).toHaveLength(1)
expect(typeDefFiles[0]).toMatch(path.join('web', 'types', 'graphql.d.ts'))
Expand All @@ -61,13 +72,11 @@ test('Generate gql typedefs api', async () => {
data: string | ArrayBufferView
} = { file: '', data: '' }

jest
.spyOn(fs, 'writeFileSync')
.mockImplementation(
(file: fs.PathOrFileDescriptor, data: string | ArrayBufferView) => {
codegenOutput = { file, data }
}
)
vi.spyOn(fs, 'writeFileSync').mockImplementation(
(file: fs.PathOrFileDescriptor, data: string | ArrayBufferView) => {
codegenOutput = { file, data }
}
)

const { typeDefFiles } = await generateTypeDefGraphQLApi()

Expand Down Expand Up @@ -140,7 +149,7 @@ test("Doesn't throw or print any errors with empty project", async () => {
)
process.env.RWJS_CWD = fixturePath
const oldConsoleError = console.error
console.error = jest.fn()
console.error = vi.fn()

try {
await generateGraphQLSchema()
Expand Down
Loading

0 comments on commit bec7b02

Please sign in to comment.