diff --git a/jest.config.js b/jest.config.js index 380449fa..1b987827 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ module.exports = { preset: 'ts-jest', + setupFilesAfterEnv: ['./scripts/setupJestEnv.ts'], globals: { __DEV__: true, __TEST__: true, diff --git a/packages/compiler-sfc/__tests__/compileStyle.spec.ts b/packages/compiler-sfc/__tests__/compileStyle.spec.ts index 328ac9a9..b235273b 100644 --- a/packages/compiler-sfc/__tests__/compileStyle.spec.ts +++ b/packages/compiler-sfc/__tests__/compileStyle.spec.ts @@ -7,12 +7,9 @@ import { compileStyleAsync, SFCStyleCompileOptions } from '../src/compileStyle' -import { mockWarn } from '@vue/shared' import path from 'path' describe('SFC scoped CSS', () => { - mockWarn() - function compileScoped( source: string, options?: Partial diff --git a/packages/global.d.ts b/packages/global.d.ts index 83085221..2957d35a 100644 --- a/packages/global.d.ts +++ b/packages/global.d.ts @@ -13,3 +13,12 @@ declare var __VERSION__: string declare var __FEATURE_OPTIONS_API__: boolean declare var __FEATURE_PROD_DEVTOOLS__: boolean declare var __FEATURE_SUSPENSE__: boolean + +// for tests +declare namespace jest { + interface Matchers { + toHaveBeenWarned(): R + toHaveBeenWarnedLast(): R + toHaveBeenWarnedTimes(n: number): R + } +} diff --git a/packages/reactivity/__tests__/collections/Map.spec.ts b/packages/reactivity/__tests__/collections/Map.spec.ts index a4c69e5b..6ee2c81e 100644 --- a/packages/reactivity/__tests__/collections/Map.spec.ts +++ b/packages/reactivity/__tests__/collections/Map.spec.ts @@ -1,10 +1,7 @@ import { reactive, effect, toRaw, isReactive } from '../../src' -import { mockWarn } from '@vue/shared' describe('reactivity/collections', () => { describe('Map', () => { - mockWarn() - test('instanceof', () => { const original = new Map() const observed = reactive(original) diff --git a/packages/reactivity/__tests__/collections/Set.spec.ts b/packages/reactivity/__tests__/collections/Set.spec.ts index 8164081d..8161ddf8 100644 --- a/packages/reactivity/__tests__/collections/Set.spec.ts +++ b/packages/reactivity/__tests__/collections/Set.spec.ts @@ -1,10 +1,7 @@ import { reactive, effect, isReactive, toRaw } from '../../src' -import { mockWarn } from '@vue/shared' describe('reactivity/collections', () => { describe('Set', () => { - mockWarn() - it('instanceof', () => { const original = new Set() const observed = reactive(original) diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index fe6161ff..9d60ad35 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -7,11 +7,8 @@ import { WritableComputedRef, isReadonly } from '../src' -import { mockWarn } from '@vue/shared' describe('reactivity/computed', () => { - mockWarn() - it('should return updated value', () => { const value = reactive<{ foo?: number }>({}) const cValue = computed(() => value.foo) diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index 8020bbf8..c0b10969 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -1,11 +1,8 @@ import { ref, isRef } from '../src/ref' import { reactive, isReactive, toRaw, markRaw } from '../src/reactive' -import { mockWarn } from '@vue/shared' import { computed } from '../src/computed' describe('reactivity/reactive', () => { - mockWarn() - test('Object', () => { const original = { foo: 1 } const observed = reactive(original) diff --git a/packages/reactivity/__tests__/readonly.spec.ts b/packages/reactivity/__tests__/readonly.spec.ts index 6e99c589..e5eb52d5 100644 --- a/packages/reactivity/__tests__/readonly.spec.ts +++ b/packages/reactivity/__tests__/readonly.spec.ts @@ -10,7 +10,6 @@ import { shallowReadonly, isProxy } from '../src' -import { mockWarn } from '@vue/shared' /** * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html @@ -18,8 +17,6 @@ import { mockWarn } from '@vue/shared' type Writable = { -readonly [P in keyof T]: T[P] } describe('reactivity/readonly', () => { - mockWarn() - describe('Object', () => { it('should make nested values readonly', () => { const original = { foo: 1, bar: { baz: 2 } } diff --git a/packages/runtime-core/__tests__/apiCreateApp.spec.ts b/packages/runtime-core/__tests__/apiCreateApp.spec.ts index fbc784f4..c3be3476 100644 --- a/packages/runtime-core/__tests__/apiCreateApp.spec.ts +++ b/packages/runtime-core/__tests__/apiCreateApp.spec.ts @@ -13,11 +13,8 @@ import { getCurrentInstance, defineComponent } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' describe('api: createApp', () => { - mockWarn() - test('mount', () => { const Comp = defineComponent({ props: { diff --git a/packages/runtime-core/__tests__/apiInject.spec.ts b/packages/runtime-core/__tests__/apiInject.spec.ts index 4d68901f..8498e4f8 100644 --- a/packages/runtime-core/__tests__/apiInject.spec.ts +++ b/packages/runtime-core/__tests__/apiInject.spec.ts @@ -10,13 +10,9 @@ import { reactive } from '../src/index' import { render, nodeOps, serialize } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' // reference: https://vue-composition-api-rfc.netlify.com/api.html#provide-inject - describe('api: provide/inject', () => { - mockWarn() - it('string keys', () => { const Provider = { setup() { diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 074596bb..37fb3635 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -10,7 +10,6 @@ import { ref, defineComponent } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' describe('api: options', () => { test('data', async () => { @@ -705,8 +704,6 @@ describe('api: options', () => { }) describe('warnings', () => { - mockWarn() - test('Expected a function as watch handler', () => { const Comp = { watch: { diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 331b6f3c..951f2ba0 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -14,13 +14,10 @@ import { TrackOpTypes, TriggerOpTypes } from '@vue/reactivity' -import { mockWarn } from '@vue/shared' // reference: https://vue-composition-api-rfc.netlify.com/api.html#watch describe('api: watch', () => { - mockWarn() - it('effect', async () => { const state = reactive({ count: 0 }) let dummy diff --git a/packages/runtime-core/__tests__/componentEmits.spec.ts b/packages/runtime-core/__tests__/componentEmits.spec.ts index effe6571..b47a16cb 100644 --- a/packages/runtime-core/__tests__/componentEmits.spec.ts +++ b/packages/runtime-core/__tests__/componentEmits.spec.ts @@ -1,13 +1,10 @@ // Note: emits and listener fallthrough is tested in // ./rendererAttrsFallthrough.spec.ts. -import { mockWarn } from '@vue/shared' import { render, defineComponent, h, nodeOps } from '@vue/runtime-test' import { isEmitListener } from '../src/componentEmits' describe('component: emit', () => { - mockWarn() - test('trigger handlers', () => { const Foo = defineComponent({ render() {}, diff --git a/packages/runtime-core/__tests__/componentProps.spec.ts b/packages/runtime-core/__tests__/componentProps.spec.ts index ff30044f..dee736c4 100644 --- a/packages/runtime-core/__tests__/componentProps.spec.ts +++ b/packages/runtime-core/__tests__/componentProps.spec.ts @@ -10,11 +10,8 @@ import { serializeInner } from '@vue/runtime-test' import { render as domRender, nextTick } from 'vue' -import { mockWarn } from '@vue/shared' describe('component props', () => { - mockWarn() - test('stateful', () => { let props: any let attrs: any diff --git a/packages/runtime-core/__tests__/componentProxy.spec.ts b/packages/runtime-core/__tests__/componentProxy.spec.ts index 706fad4a..02cc5f5f 100644 --- a/packages/runtime-core/__tests__/componentProxy.spec.ts +++ b/packages/runtime-core/__tests__/componentProxy.spec.ts @@ -6,12 +6,9 @@ import { createApp, shallowReadonly } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' import { ComponentInternalInstance } from '../src/component' describe('component: proxy', () => { - mockWarn() - test('data', () => { let instance: ComponentInternalInstance let instanceProxy: any diff --git a/packages/runtime-core/__tests__/errorHandling.spec.ts b/packages/runtime-core/__tests__/errorHandling.spec.ts index 4830b65e..56ae8b26 100644 --- a/packages/runtime-core/__tests__/errorHandling.spec.ts +++ b/packages/runtime-core/__tests__/errorHandling.spec.ts @@ -11,11 +11,8 @@ import { watchEffect } from '@vue/runtime-test' import { setErrorRecovery } from '../src/errorHandling' -import { mockWarn } from '@vue/shared' describe('error handling', () => { - mockWarn() - beforeEach(() => { setErrorRecovery(true) }) diff --git a/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts b/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts index f07c7772..a2c39f5b 100644 --- a/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts +++ b/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts @@ -1,9 +1,7 @@ import { renderSlot } from '../../src/helpers/renderSlot' import { h } from '../../src/h' -import { mockWarn } from '@vue/shared' describe('renderSlot', () => { - mockWarn() it('should render slot', () => { let child const vnode = renderSlot( diff --git a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts index 6f8957d0..5eee77f4 100644 --- a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts +++ b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts @@ -12,11 +12,8 @@ import { Comment, VNode } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' describe('resolveAssets', () => { - mockWarn() - test('should work', () => { const FooBar = () => null const BarBaz = { mounted: () => null } diff --git a/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts b/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts index 44351b76..3dc5bb51 100644 --- a/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts +++ b/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts @@ -1,9 +1,6 @@ import { toHandlers } from '../../src/helpers/toHandlers' -import { mockWarn } from '@vue/shared' describe('toHandlers', () => { - mockWarn() - it('should not accept non-objects', () => { toHandlers(null as any) toHandlers(undefined as any) diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 007ceec9..fa89631d 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -12,7 +12,6 @@ import { defineComponent } from '@vue/runtime-dom' import { renderToString, SSRContext } from '@vue/server-renderer' -import { mockWarn } from '@vue/shared' function mountWithHydration(html: string, render: () => any) { const container = document.createElement('div') @@ -34,8 +33,6 @@ const triggerEvent = (type: string, el: Element) => { } describe('SSR hydration', () => { - mockWarn() - beforeEach(() => { document.body.innerHTML = '' }) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index ab18c842..e2031eb6 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -13,11 +13,8 @@ import { createCommentVNode, Fragment } from '@vue/runtime-dom' -import { mockWarn } from '@vue/shared' describe('attribute fallthrough', () => { - mockWarn() - it('should allow attrs to fallthrough', async () => { const click = jest.fn() const childUpdated = jest.fn() diff --git a/packages/runtime-core/__tests__/rendererChildren.spec.ts b/packages/runtime-core/__tests__/rendererChildren.spec.ts index 22c2d101..90e88c4b 100644 --- a/packages/runtime-core/__tests__/rendererChildren.spec.ts +++ b/packages/runtime-core/__tests__/rendererChildren.spec.ts @@ -8,10 +8,6 @@ import { serialize, serializeInner } from '@vue/runtime-test' -import { mockWarn } from '@vue/shared' - -mockWarn() - function toSpan(content: any) { if (typeof content === 'string') { return h('span', content.toString()) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 4e6c207b..2cab3215 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -11,14 +11,12 @@ import { transformVNodeArgs } from '../src/vnode' import { Data } from '../src/component' -import { ShapeFlags, PatchFlags, mockWarn } from '@vue/shared' +import { ShapeFlags, PatchFlags } from '@vue/shared' import { h, reactive, isReactive } from '../src' import { createApp, nodeOps, serializeInner } from '@vue/runtime-test' import { setCurrentRenderingInstance } from '../src/componentRenderUtils' describe('vnode', () => { - mockWarn() - test('create with just tag', () => { const vnode = createVNode('p') expect(vnode.type).toBe('p') diff --git a/packages/runtime-dom/__tests__/helpers/useCssModule.spec.ts b/packages/runtime-dom/__tests__/helpers/useCssModule.spec.ts index b92c9c16..bb65082a 100644 --- a/packages/runtime-dom/__tests__/helpers/useCssModule.spec.ts +++ b/packages/runtime-dom/__tests__/helpers/useCssModule.spec.ts @@ -1,10 +1,7 @@ import { render, h, nodeOps } from '@vue/runtime-test' import { useCssModule } from '../../src/helpers/useCssModule' -import { mockWarn } from '@vue/shared' describe('useCssModule', () => { - mockWarn() - function mountWithModule(modules: any, name?: string) { let res render( diff --git a/packages/runtime-dom/__tests__/patchProps.spec.ts b/packages/runtime-dom/__tests__/patchProps.spec.ts index f2f3dfdf..f8c3c06b 100644 --- a/packages/runtime-dom/__tests__/patchProps.spec.ts +++ b/packages/runtime-dom/__tests__/patchProps.spec.ts @@ -1,10 +1,7 @@ import { patchProp } from '../src/patchProp' import { render, h } from '../src' -import { mockWarn } from '@vue/shared' describe('runtime-dom: props patching', () => { - mockWarn() - test('basic', () => { const el = document.createElement('div') patchProp(el, 'id', null, 'foo') diff --git a/packages/runtime-test/__tests__/testRuntime.spec.ts b/packages/runtime-test/__tests__/testRuntime.spec.ts index 8774faff..f3ca6eb2 100644 --- a/packages/runtime-test/__tests__/testRuntime.spec.ts +++ b/packages/runtime-test/__tests__/testRuntime.spec.ts @@ -14,11 +14,8 @@ import { serialize, triggerEvent } from '../src' -import { mockWarn } from '@vue/shared' describe('test renderer', () => { - mockWarn() - it('should work', () => { const root = nodeOps.createElement('div') render( diff --git a/packages/server-renderer/__tests__/renderToStream.spec.ts b/packages/server-renderer/__tests__/renderToStream.spec.ts index a679e961..5f7ecf67 100644 --- a/packages/server-renderer/__tests__/renderToStream.spec.ts +++ b/packages/server-renderer/__tests__/renderToStream.spec.ts @@ -10,14 +10,11 @@ import { createTextVNode, createStaticVNode } from 'vue' -import { escapeHtml, mockWarn } from '@vue/shared' +import { escapeHtml } from '@vue/shared' import { renderToStream as _renderToStream } from '../src/renderToStream' import { Readable } from 'stream' import { ssrRenderSlot } from '../src/helpers/ssrRenderSlot' import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent' - -mockWarn() - const promisifyStream = (stream: Readable) => { return new Promise((resolve, reject) => { let result = '' diff --git a/packages/server-renderer/__tests__/renderToString.spec.ts b/packages/server-renderer/__tests__/renderToString.spec.ts index f7985632..3e2ff0cc 100644 --- a/packages/server-renderer/__tests__/renderToString.spec.ts +++ b/packages/server-renderer/__tests__/renderToString.spec.ts @@ -10,13 +10,10 @@ import { createTextVNode, createStaticVNode } from 'vue' -import { escapeHtml, mockWarn } from '@vue/shared' +import { escapeHtml } from '@vue/shared' import { renderToString } from '../src/renderToString' import { ssrRenderSlot, SSRSlot } from '../src/helpers/ssrRenderSlot' import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent' - -mockWarn() - describe('ssr: renderToString', () => { test('should apply app context', async () => { const app = createApp({ diff --git a/packages/server-renderer/__tests__/ssrSuspense.spec.ts b/packages/server-renderer/__tests__/ssrSuspense.spec.ts index 89009ac1..a7d10787 100644 --- a/packages/server-renderer/__tests__/ssrSuspense.spec.ts +++ b/packages/server-renderer/__tests__/ssrSuspense.spec.ts @@ -1,10 +1,7 @@ import { createApp, h, Suspense } from 'vue' import { renderToString } from '../src/renderToString' -import { mockWarn } from '@vue/shared' describe('SSR Suspense', () => { - mockWarn() - const ResolvingAsync = { async setup() { return () => h('div', 'async') diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index c0655ba5..bd7abd12 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -6,7 +6,6 @@ export * from './shapeFlags' export * from './slotFlags' export * from './globalsWhitelist' export * from './codeframe' -export * from './mockWarn' export * from './normalizeProp' export * from './domTagConfig' export * from './domAttrConfig' diff --git a/packages/shared/src/mockWarn.ts b/packages/shared/src/mockWarn.ts deleted file mode 100644 index abd5db51..00000000 --- a/packages/shared/src/mockWarn.ts +++ /dev/null @@ -1,105 +0,0 @@ -declare global { - namespace jest { - interface Matchers { - toHaveBeenWarned(): R - toHaveBeenWarnedLast(): R - toHaveBeenWarnedTimes(n: number): R - } - } -} - -export const mockError = () => mockWarn(true) - -export function mockWarn(asError = false) { - expect.extend({ - toHaveBeenWarned(received: string) { - asserted.add(received) - const passed = warn.mock.calls.some( - args => args[0].indexOf(received) > -1 - ) - if (passed) { - return { - pass: true, - message: () => `expected "${received}" not to have been warned.` - } - } else { - const msgs = warn.mock.calls.map(args => args[0]).join('\n - ') - return { - pass: false, - message: () => - `expected "${received}" to have been warned.\n\nActual messages:\n\n - ${msgs}` - } - } - }, - - toHaveBeenWarnedLast(received: string) { - asserted.add(received) - const passed = - warn.mock.calls[warn.mock.calls.length - 1][0].indexOf(received) > -1 - if (passed) { - return { - pass: true, - message: () => `expected "${received}" not to have been warned last.` - } - } else { - const msgs = warn.mock.calls.map(args => args[0]).join('\n - ') - return { - pass: false, - message: () => - `expected "${received}" to have been warned last.\n\nActual messages:\n\n - ${msgs}` - } - } - }, - - toHaveBeenWarnedTimes(received: string, n: number) { - asserted.add(received) - let found = 0 - warn.mock.calls.forEach(args => { - if (args[0].indexOf(received) > -1) { - found++ - } - }) - - if (found === n) { - return { - pass: true, - message: () => - `expected "${received}" to have been warned ${n} times.` - } - } else { - return { - pass: false, - message: () => - `expected "${received}" to have been warned ${n} times but got ${found}.` - } - } - } - }) - - let warn: jest.SpyInstance - const asserted: Set = new Set() - - beforeEach(() => { - asserted.clear() - warn = jest.spyOn(console, asError ? 'error' : 'warn') - warn.mockImplementation(() => {}) - }) - - afterEach(() => { - const assertedArray = Array.from(asserted) - const nonAssertedWarnings = warn.mock.calls - .map(args => args[0]) - .filter(received => { - return !assertedArray.some(assertedMsg => { - return received.indexOf(assertedMsg) > -1 - }) - }) - warn.mockRestore() - if (nonAssertedWarnings.length) { - nonAssertedWarnings.forEach(warning => { - console.warn(warning) - }) - throw new Error(`test case threw unexpected warnings.`) - } - }) -} diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index 112e7400..0c124d18 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -1,10 +1,8 @@ import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils' import path from 'path' -import { mockWarn } from '@vue/shared' import { h, createApp, Transition } from 'vue' describe('e2e: Transition', () => { - mockWarn() const { page, html, diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index 6e4233db..dee092ff 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -1,10 +1,8 @@ import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils' import path from 'path' -import { mockWarn } from '@vue/shared' import { createApp, ref } from 'vue' describe('e2e: TransitionGroup', () => { - mockWarn() const { page, html, nextFrame, timeout } = setupPuppeteer() const baseUrl = `file://${path.resolve(__dirname, './transition.html')}` diff --git a/packages/vue/__tests__/index.spec.ts b/packages/vue/__tests__/index.spec.ts index 304bc79b..974fffc0 100644 --- a/packages/vue/__tests__/index.spec.ts +++ b/packages/vue/__tests__/index.spec.ts @@ -1,9 +1,6 @@ import { createApp, ref, nextTick } from '../src' -import { mockWarn } from '@vue/shared' describe('compiler + runtime integration', () => { - mockWarn() - it('should support runtime template compilation', () => { const container = document.createElement('div') const App = { @@ -55,7 +52,7 @@ describe('compiler + runtime integration', () => { expect(one.deactivated).toHaveBeenCalledTimes(0) expect(one.destroyed).toHaveBeenCalledTimes(0) - toggle.value = false; + toggle.value = false await nextTick() expect(container.innerHTML).toBe(``) expect(one.created).toHaveBeenCalledTimes(1) @@ -64,7 +61,7 @@ describe('compiler + runtime integration', () => { expect(one.deactivated).toHaveBeenCalledTimes(1) expect(one.destroyed).toHaveBeenCalledTimes(0) - toggle.value = true; + toggle.value = true await nextTick() expect(container.innerHTML).toBe(`one`) expect(one.created).toHaveBeenCalledTimes(1) diff --git a/scripts/setupJestEnv.ts b/scripts/setupJestEnv.ts new file mode 100644 index 00000000..95f12615 --- /dev/null +++ b/scripts/setupJestEnv.ts @@ -0,0 +1,88 @@ +expect.extend({ + toHaveBeenWarned(received: string) { + asserted.add(received) + const passed = warn.mock.calls.some(args => args[0].indexOf(received) > -1) + if (passed) { + return { + pass: true, + message: () => `expected "${received}" not to have been warned.` + } + } else { + const msgs = warn.mock.calls.map(args => args[0]).join('\n - ') + return { + pass: false, + message: () => + `expected "${received}" to have been warned.\n\nActual messages:\n\n - ${msgs}` + } + } + }, + + toHaveBeenWarnedLast(received: string) { + asserted.add(received) + const passed = + warn.mock.calls[warn.mock.calls.length - 1][0].indexOf(received) > -1 + if (passed) { + return { + pass: true, + message: () => `expected "${received}" not to have been warned last.` + } + } else { + const msgs = warn.mock.calls.map(args => args[0]).join('\n - ') + return { + pass: false, + message: () => + `expected "${received}" to have been warned last.\n\nActual messages:\n\n - ${msgs}` + } + } + }, + + toHaveBeenWarnedTimes(received: string, n: number) { + asserted.add(received) + let found = 0 + warn.mock.calls.forEach(args => { + if (args[0].indexOf(received) > -1) { + found++ + } + }) + + if (found === n) { + return { + pass: true, + message: () => `expected "${received}" to have been warned ${n} times.` + } + } else { + return { + pass: false, + message: () => + `expected "${received}" to have been warned ${n} times but got ${found}.` + } + } + } +}) + +let warn: jest.SpyInstance +const asserted: Set = new Set() + +beforeEach(() => { + asserted.clear() + warn = jest.spyOn(console, 'warn') + warn.mockImplementation(() => {}) +}) + +afterEach(() => { + const assertedArray = Array.from(asserted) + const nonAssertedWarnings = warn.mock.calls + .map(args => args[0]) + .filter(received => { + return !assertedArray.some(assertedMsg => { + return received.indexOf(assertedMsg) > -1 + }) + }) + warn.mockRestore() + if (nonAssertedWarnings.length) { + nonAssertedWarnings.forEach(warning => { + console.warn(warning) + }) + throw new Error(`test case threw unexpected warnings.`) + } +})