Skip to content

Commit

Permalink
Fixing tests for blitz apps that use vitest (#4072)
Browse files Browse the repository at this point in the history
Co-authored-by: Siddharth Suresh <[email protected]>
Closes #4065
  • Loading branch information
jhonnymichel authored Feb 6, 2023
1 parent 42a2cf9 commit c3c7897
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 24 deletions.
6 changes: 6 additions & 0 deletions .changeset/plenty-kiwis-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"blitz": patch
"@blitzjs/rpc": patch
---

Updates internal functions and tests to support blitz apps that run tests with vitest
2 changes: 1 addition & 1 deletion apps/toolkit-app/test/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ test.skip("renders blitz documentation link", () => {
}))

const { getByText } = render(<Home />)
const linkElement = getByText(/Documentation/i)
const linkElement = getByText(/Blitz Docs/i)
expect(linkElement).toBeInTheDocument()
})
3 changes: 2 additions & 1 deletion integration-tests/middleware/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
SESSION_SECRET_KEY=hsdenhJfpLHrGjgdgg3jdF8g2bYD2PaQ
HEADLESS=true
HEADLESS=true
VITE_BLITZ_TEST_ENVIRONMENT=true
1 change: 1 addition & 0 deletions integration-tests/qm/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BLITZ_TEST_ENVIRONMENT=true
1 change: 1 addition & 0 deletions integration-tests/rpc/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BLITZ_TEST_ENVIRONMENT=true
65 changes: 63 additions & 2 deletions packages/blitz-rpc/src/data-client/react-query-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {describe, expect, it} from "vitest"
import {describe, expect, it, vi} from "vitest"
import superJson from "superjson"

import {getQueryKey, getQueryKeyFromUrlAndParams} from "./react-query-utils"
import {getQueryKey, getQueryKeyFromUrlAndParams, validateQueryFn} from "./react-query-utils"
import {RpcClient} from "./rpc"

const API_ENDPOINT = "http://localhost:3000"
Expand Down Expand Up @@ -74,4 +74,65 @@ describe("react-query-utils", () => {
expect(queryKey).toEqual([API_ENDPOINT])
})
})

describe("validateQueryFn", () => {
const originalEnv = process.env

function mockEnv() {
const originalEnv = process.env

process.env = {
...originalEnv,
}

delete process.env.JEST_WORKER_ID
delete process.env.VITEST_WORKER_ID
delete process.env.BLITZ_TEST_ENVIRONMENT

return process.env
}

function restoreEnv() {
process.env = originalEnv
}

const notAQuery = vi.fn()
const realQuery = vi.fn()
//@ts-ignore
realQuery._isRpcClient = true

vi.mock("blitz", async () => {
const actualBlitz = await import("blitz")
return {
...actualBlitz,
isClient: true,
}
})

describe("when called from test environments", () => {
it("always validate as true, allowing query functions to be mocked in tests")
const jestEnv = mockEnv()
jestEnv.JEST_WORKER_ID = "123"
expect(() => validateQueryFn(notAQuery)).not.toThrowError()
expect(() => validateQueryFn(realQuery)).not.toThrowError()
restoreEnv()

const vitestEnv = mockEnv()
vitestEnv.VITEST_WORKER_ID = "123"
expect(() => validateQueryFn(notAQuery)).not.toThrowError()
expect(() => validateQueryFn(realQuery)).not.toThrowError()
restoreEnv()
})

describe("when called from outside of test environments", () => {
it("throws an error when the passed function is not a query function")
// removes jest and vitest env vars
mockEnv()

expect(() => validateQueryFn(notAQuery)).toThrowError()
expect(() => validateQueryFn(realQuery)).not.toThrowError()

restoreEnv()
})
})
})
9 changes: 1 addition & 8 deletions packages/blitz-rpc/src/data-client/react-query-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {QueryClient} from "@tanstack/react-query"
import {serialize} from "superjson"
import {isClient, isServer, AsyncFunc} from "blitz"
import {isClient, isServer, AsyncFunc, isNotInUserTestEnvironment} from "blitz"
import {ResolverType, RpcClient} from "./rpc"

export type Resolver<TInput, TResult> = (input: TInput, ctx?: any) => Promise<TResult>
Expand Down Expand Up @@ -83,13 +83,6 @@ export const emptyQueryFn: RpcClient<unknown, unknown> = (() => {
return fn
})()

const isNotInUserTestEnvironment = () => {
if (process.env.JEST_WORKER_ID === undefined) return true
if (process.env.VITEST_WORKER_ID === undefined) return true
if (process.env.BLITZ_TEST_ENVIRONMENT !== undefined) return true
return false
}

export const validateQueryFn = <TInput, TResult>(
queryFn: Resolver<TInput, TResult> | RpcClient<TInput, TResult>,
) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/blitz/src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import _SuperJson from "superjson"
import type {UrlObject} from "url"
import {isNotInUserTestEnvironment} from "./utils"

declare module globalThis {
let _BLITZ_ERROR_CLASS_REGISTERED: boolean
Expand All @@ -9,7 +10,7 @@ const SuperJson: typeof _SuperJson =
"default" in _SuperJson ? (_SuperJson as any).default : _SuperJson

const errorProps = ["name", "message", "code", "statusCode", "meta", "url"]
if (process.env.JEST_WORKER_ID === undefined) {
if (isNotInUserTestEnvironment()) {
SuperJson.allowErrorProps(...errorProps)
}

Expand Down Expand Up @@ -75,7 +76,7 @@ export class PaginationArgumentError extends Error {
}
}

if (process.env.JEST_WORKER_ID === undefined && !globalThis._BLITZ_ERROR_CLASS_REGISTERED) {
if (isNotInUserTestEnvironment() && !globalThis._BLITZ_ERROR_CLASS_REGISTERED) {
SuperJson.registerClass(AuthenticationError, {
identifier: "BlitzAuthenticationError",
allowProps: errorProps,
Expand Down
3 changes: 2 additions & 1 deletion packages/blitz/src/utils/enhance-prisma.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {spawn} from "cross-spawn"
import which from "npm-which"
import {isNotInUserTestEnvironment} from "../index-browser"

export interface Constructor<T = unknown> {
new (...args: never[]): T
Expand All @@ -19,7 +20,7 @@ export const enhancePrisma = <TPrismaClientCtor extends Constructor>(
): EnhancedPrismaClientConstructor<TPrismaClientCtor> => {
return new Proxy(client as EnhancedPrismaClientConstructor<TPrismaClientCtor>, {
construct(target, args) {
if (typeof window !== "undefined" && process.env.JEST_WORKER_ID === undefined) {
if (typeof window !== "undefined" && isNotInUserTestEnvironment()) {
// Return object with $use method if in the browser
// Skip in Jest tests because window is defined in Jest tests
return {$use: () => {}}
Expand Down
8 changes: 8 additions & 0 deletions packages/blitz/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,11 @@ export function interopDefault(mod: any) {
export function truncateString(str: string, maxLength: number): string {
return str.length > maxLength ? str.substring(0, maxLength - 3) + "..." : str
}

export function isNotInUserTestEnvironment() {
if (process.env.VITE_BLITZ_TEST_ENVIRONMENT) {
return true
}

return process.env.JEST_WORKER_ID === undefined && process.env.VITEST_WORKER_ID === undefined
}
17 changes: 8 additions & 9 deletions packages/generator/templates/app/test/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@

import { expect, vi, test } from "vitest"
import { render } from "test/utils"

import Home from "../src/pages/index"

vi.mock("public/logo.png", () => ({
default: {src: "/logo.png"}
}))


test.skip("renders blitz documentation link", () => {
// This is an example of how to ensure a specific item is in the document
// But it's disabled by default (by test.skip) so the test doesn't fail
// when you remove the the default content from the page

// This is an example on how to mock api hooks when testing
vi.mock("src/users/hooks/useCurrentUser", () => (
{
Expand All @@ -28,10 +28,9 @@
})
}
))

const { getByText } = render(<Home />)
const linkElement = getByText(/Documentation/i)
const linkElement = getByText(/Blitz Docs/i)
expect(linkElement).toBeInTheDocument()
})



0 comments on commit c3c7897

Please sign in to comment.