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

feat: move matcher types to Vi namespace #608

Merged
merged 3 commits into from Jan 22, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
19 changes: 9 additions & 10 deletions packages/vitest/src/index.ts
Expand Up @@ -16,8 +16,6 @@ export * from './integrations/vi'
export * from './types'
export * from './api/types'

export type { Spy, SpyFn } from 'tinyspy'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are internal types


declare module 'vite' {
interface UserConfig {
/**
Expand All @@ -43,9 +41,10 @@ type Promisify<O> = {
}

declare global {
namespace Chai {
interface ExpectStatic extends AsymmetricMatchersContaining {
<T>(actual: T, message?: string): VitestAssertion<T>
namespace Vi {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allows for:

namespace Vi {
   interface Assertion {
      customerAssertion(): void;
   }
}

chai augmentations should still work

namespace Chai {
   interface Assertion {
      customerAssertion(): void;
   }
}

Vi.Assertion['customerAssertion'] // exists


interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {
<T>(actual: T, message?: string): Vi.Assertion<T>

extend(expects: MatchersObject): void
assertions(expected: number): void
Expand Down Expand Up @@ -117,16 +116,16 @@ declare global {
}

type VitestifyAssertion<A> = {
[K in keyof A]: A[K] extends Assertion
? VitestAssertion<any>
[K in keyof A]: A[K] extends Chai.Assertion
? Assertion<any>
: A[K] extends (...args: any[]) => any
? A[K] // not converting function since they may contain overload
: VitestifyAssertion<A[K]>
}

interface VitestAssertion<T = any> extends VitestifyAssertion<Assertion>, JestAssertion<T> {
resolves: Promisify<VitestAssertion<T>>
rejects: Promisify<VitestAssertion<T>>
interface Assertion<T = any> extends VitestifyAssertion<Chai.Assertion>, JestAssertion<T> {
resolves: Promisify<Assertion<T>>
rejects: Promisify<Assertion<T>>

chaiEqual<E>(expected: E): void
}
Expand Down
6 changes: 3 additions & 3 deletions packages/vitest/src/integrations/chai/index.ts
Expand Up @@ -3,11 +3,11 @@ import { getState, setState } from './jest-expect'

export { assert, should } from 'chai'

const expect = ((value: any, message?: string): Chai.VitestAssertion => {
const expect = ((value: any, message?: string): Vi.Assertion => {
const { assertionCalls } = getState()
setState({ assertionCalls: assertionCalls + 1 })
return chai.expect(value, message)
}) as Chai.ExpectStatic
return chai.expect(value, message) as unknown as Vi.Assertion
}) as Vi.ExpectStatic
expect.getState = getState
expect.setState = setState

Expand Down
Expand Up @@ -294,7 +294,8 @@ export const JestAsymmetricMatchers: ChaiPlugin = (chai, utils) => {
(expected: any) => new StringMatching(expected),
)

chai.expect.not = {
// defineProperty does not work
;(chai.expect as any).not = {
stringContaining: (expected: string) => new StringContaining(expected, true),
objectContaining: (expected: any) => new ObjectContaining(expected, true),
arrayContaining: (expected: unknown[]) => new ArrayContaining(expected, true),
Expand Down
4 changes: 2 additions & 2 deletions packages/vitest/src/integrations/chai/jest-expect.ts
Expand Up @@ -34,8 +34,8 @@ export const setState = <State extends MatcherState = MatcherState>(

// Jest Expect Compact
export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
function def(name: keyof Chai.VitestAssertion | (keyof Chai.VitestAssertion)[], fn: ((this: Chai.AssertionStatic & Chai.VitestAssertion, ...args: any[]) => any)) {
const addMethod = (n: keyof Chai.VitestAssertion) => {
function def(name: keyof Vi.Assertion | (keyof Vi.Assertion)[], fn: ((this: Chai.AssertionStatic & Vi.Assertion, ...args: any[]) => any)) {
const addMethod = (n: keyof Vi.Assertion) => {
utils.addMethod(chai.Assertion.prototype, n, fn)
}

Expand Down
34 changes: 17 additions & 17 deletions packages/vitest/src/integrations/jest-mock.ts
Expand Up @@ -36,7 +36,7 @@ type Classes<T> = {
[K in keyof T]: T[K] extends new (...args: any[]) => any ? K : never
}[keyof T] & string

export interface JestMockCompat<TArgs extends any[] = any[], TReturns = any> {
export interface SpyInstance<TArgs extends any[] = any[], TReturns = any> {
getMockName(): string
mockName(n: string): this
mock: JestMockCompatContext<TArgs, TReturns>
Expand All @@ -55,14 +55,14 @@ export interface JestMockCompat<TArgs extends any[] = any[], TReturns = any> {
mockRejectedValueOnce(obj: any): this
}

export interface JestMockCompatFn<TArgs extends any[] = any, TReturns = any> extends JestMockCompat<TArgs, TReturns> {
export interface SpyInstanceFn<TArgs extends any[] = any, TReturns = any> extends SpyInstance<TArgs, TReturns> {
(...args: TArgs): TReturns
}

export type MaybeMockedConstructor<T> = T extends new (
...args: Array<any>
) => infer R
? JestMockCompatFn<ConstructorParameters<T>, R>
? SpyInstanceFn<ConstructorParameters<T>, R>
: T
export type MockedFunction<T extends Procedure> = MockWithArgs<T> & {
[K in keyof T]: T[K];
Expand Down Expand Up @@ -91,15 +91,15 @@ export type MaybeMocked<T> = T extends Procedure
? MockedObject<T>
: T

export type EnhancedSpy<TArgs extends any[] = any[], TReturns = any> = JestMockCompat<TArgs, TReturns> & SpyImpl<TArgs, TReturns>
export type EnhancedSpy<TArgs extends any[] = any[], TReturns = any> = SpyInstance<TArgs, TReturns> & SpyImpl<TArgs, TReturns>

export interface MockWithArgs<T extends Procedure>
extends JestMockCompatFn<Parameters<T>, ReturnType<T>> {
extends SpyInstanceFn<Parameters<T>, ReturnType<T>> {
new (...args: T extends new (...args: any) => any ? ConstructorParameters<T> : never): T
(...args: Parameters<T>): ReturnType<T>
}

export const spies = new Set<JestMockCompat>()
export const spies = new Set<SpyInstance>()

export function isMockFunction(fn: any): fn is EnhancedSpy {
return typeof fn === 'function'
Expand All @@ -111,28 +111,28 @@ export function spyOn<T, S extends Properties<Required<T>>>(
obj: T,
methodName: S,
accesType: 'get',
): JestMockCompat<[], T[S]>
): SpyInstance<[], T[S]>
export function spyOn<T, G extends Properties<Required<T>>>(
obj: T,
methodName: G,
accesType: 'set',
): JestMockCompat<[T[G]], void>
): SpyInstance<[T[G]], void>
export function spyOn<T, M extends Classes<Required<T>>>(
object: T,
method: M
): Required<T>[M] extends new (...args: infer A) => infer R
? JestMockCompat<A, R>
? SpyInstance<A, R>
: never
export function spyOn<T, M extends Methods<Required<T>>>(
obj: T,
methodName: M,
mock?: T[M]
): Required<T>[M] extends (...args: infer A) => infer R ? JestMockCompat<A, R> : never
): Required<T>[M] extends (...args: infer A) => infer R ? SpyInstance<A, R> : never
export function spyOn<T, K extends keyof T>(
obj: T,
method: K,
accessType?: 'get' | 'set',
): JestMockCompat {
): SpyInstance {
const dictionary = {
get: 'getter',
set: 'setter',
Expand All @@ -141,14 +141,14 @@ export function spyOn<T, K extends keyof T>(

const stub = tinyspy.spyOn(obj, objMethod as any)

return enhanceSpy(stub) as JestMockCompat
return enhanceSpy(stub) as SpyInstance
}

let callOrder = 0

function enhanceSpy<TArgs extends any[], TReturns>(
spy: SpyImpl<TArgs, TReturns>,
): JestMockCompat<TArgs, TReturns> {
): SpyInstance<TArgs, TReturns> {
const stub = spy as unknown as EnhancedSpy<TArgs, TReturns>

let implementation: ((...args: TArgs) => TReturns) | undefined
Expand Down Expand Up @@ -249,12 +249,12 @@ function enhanceSpy<TArgs extends any[], TReturns>(
return stub as any
}

export function fn<TArgs extends any[] = any[], R = any>(): JestMockCompatFn<TArgs, R>
export function fn<TArgs extends any[] = any[], R = any>(): SpyInstanceFn<TArgs, R>
export function fn<TArgs extends any[] = any[], R = any>(
implementation: (...args: TArgs) => R
): JestMockCompatFn<TArgs, R>
): SpyInstanceFn<TArgs, R>
export function fn<TArgs extends any[] = any[], R = any>(
implementation?: (...args: TArgs) => R,
): JestMockCompatFn<TArgs, R> {
return enhanceSpy(tinyspy.spyOn({ fn: implementation || (() => {}) }, 'fn')) as unknown as JestMockCompatFn
): SpyInstanceFn<TArgs, R> {
return enhanceSpy(tinyspy.spyOn({ fn: implementation || (() => {}) }, 'fn')) as unknown as SpyInstanceFn
}
2 changes: 1 addition & 1 deletion packages/vitest/src/integrations/snapshot/client.ts
Expand Up @@ -54,7 +54,7 @@ export class SnapshotClient {
try {
const pass = equals(received, properties, [iterableEquality, subsetEquality])
if (!pass)
expect(received).toBe(properties)
expect(received).equals(properties)
else
received = deepMergeSnapshot(received, properties)
}
Expand Down
10 changes: 5 additions & 5 deletions packages/vitest/src/integrations/timers.ts
@@ -1,7 +1,7 @@
// TODO setImmediate, nextTick, requestAnimationFrame, cancelAnimationFrame
// TODO async timers

import type { JestMockCompat } from './jest-mock'
import type { SpyInstance } from './jest-mock'
import { spyOn } from './jest-mock'

const originalSetTimeout = global.setTimeout
Expand Down Expand Up @@ -57,11 +57,11 @@ const getNodeTimeout = (id: number): NodeJS.Timeout => {
}

export class FakeTimers {
private _setTimeout!: JestMockCompat<Arguments, NodeJS.Timeout>
private _setInterval!: JestMockCompat<Arguments, NodeJS.Timeout>
private _setTimeout!: SpyInstance<Arguments, NodeJS.Timeout>
private _setInterval!: SpyInstance<Arguments, NodeJS.Timeout>

private _clearTimeout!: JestMockCompat<[NodeJS.Timeout], void>
private _clearInterval!: JestMockCompat<[NodeJS.Timeout], void>
private _clearTimeout!: SpyInstance<[NodeJS.Timeout], void>
private _clearInterval!: SpyInstance<[NodeJS.Timeout], void>

private _advancedTime = 0
private _nestedTime: Record<string, number> = {}
Expand Down