Skip to content

Commit

Permalink
chore: setup concurrent mode testing env
Browse files Browse the repository at this point in the history
  • Loading branch information
crimx committed Jun 6, 2020
1 parent 3448bbe commit bf4b4cd
Show file tree
Hide file tree
Showing 10 changed files with 1,060 additions and 490 deletions.
1 change: 1 addition & 0 deletions jest.config.js
@@ -1,4 +1,5 @@
module.exports = {
setupFilesAfterEnv: [require.resolve('./scripts/jest-setup.js')],
transform: {
'^.+\\.ts(x?)$': 'ts-jest'
},
Expand Down
19 changes: 11 additions & 8 deletions package.json
Expand Up @@ -40,8 +40,10 @@
"@types/react": "^16.9.19",
"@types/react-dom": "^16.9.5",
"@types/react-test-renderer": "^16.8.2",
"@typescript-eslint/eslint-plugin": "^2.18.0",
"@typescript-eslint/parser": "^2.18.0",
"@types/scheduler": "^0.16.1",
"@types/use-subscription": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^3.1.0",
"@typescript-eslint/parser": "^3.1.0",
"@vuepress/plugin-pwa": "^1.2.0",
"commitizen": "^4.0.3",
"coveralls": "^3.0.5",
Expand All @@ -58,17 +60,18 @@
"eslint-plugin-react": "^7.14.2",
"eslint-plugin-standard": "^4.0.0",
"husky": "^3.0.1",
"jest": "^25.1.0",
"jest": "^26.0.1",
"lerna": "^3.20.2",
"prettier": "^1.18.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-test-renderer": "^16.12.0",
"react": "^0.0.0-experimental-33c3af284",
"react-dom": "^0.0.0-experimental-33c3af284",
"react-test-renderer": "^0.0.0-experimental-33c3af284",
"rxjs": "^6.5.4",
"shx": "^0.3.2",
"standard-version": "^6.0.1",
"ts-jest": "^25.0.0",
"typescript": "^3.5.3",
"ts-jest": "^26.1.0",
"typescript": "^3.9.5",
"use-subscription": "^1.4.1",
"vuepress": "^1.2.0",
"vuepress-plugin-container": "^2.1.2"
}
Expand Down
47 changes: 47 additions & 0 deletions packages/observable-hooks/__tests__/utils.ts
@@ -0,0 +1,47 @@
/* eslint-disable camelcase */

// React internal mocking
export type Scheduler = typeof import('scheduler') & {
unstable_IdlePriority: number
unstable_ImmediatePriority: number
unstable_LowPriority: number
unstable_NormalPriority: number
unstable_Profiling: {
startLoggingProfilingEvents: () => void
stopLoggingProfilingEvents: () => any
sharedProfilingBuffer: ArrayBuffer
}
unstable_UserBlockingPriority: number
unstable_advanceTime: (ms: any) => void
unstable_cancelCallback: (task: any) => void
unstable_clearYields: () => any
unstable_continueExecution: () => void
unstable_flushAll: () => void
unstable_flushAllWithoutAsserting: () => boolean
unstable_flushExpired: () => void
unstable_flushNumberOfYields: (count: any) => void
unstable_flushUntilNextPaint: () => void
unstable_forceFrameRate: () => void
unstable_getCurrentPriorityLevel: () => number
unstable_getFirstCallbackNode: () => any
unstable_next: (eventHandler: any) => any
unstable_now: () => number
unstable_pauseExecution: () => void
unstable_requestPaint: () => void
unstable_runWithPriority: (priorityLevel: any, eventHandler: any) => any
unstable_scheduleCallback: (
priorityLevel: any,
callback: any,
options: any
) => {
id: number
callback: any
priorityLevel: any
startTime: number
expirationTime: any
sortIndex: number
}
unstable_shouldYield: () => boolean
unstable_wrapCallback: (callback: any) => (...args: any[]) => any
unstable_yieldValue: (value: any) => void
}
2 changes: 1 addition & 1 deletion packages/observable-hooks/tsconfig.json
Expand Up @@ -4,5 +4,5 @@
"outDir": "dist",
"noEmit": true
},
"include": ["src", "__tests__"]
"include": ["../../typings", "src", "__tests__"]
}
4 changes: 2 additions & 2 deletions packages/observable-hooks/tsconfig.test.json
@@ -1,4 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["__tests__"]
"extends": "../../tsconfig.test.json",
"include": ["../../typings", "__tests__"]
}
1 change: 1 addition & 0 deletions scripts/jest-setup.js
@@ -0,0 +1 @@
expect.extend(require('./schedulerTestMatchers'))
95 changes: 95 additions & 0 deletions scripts/schedulerTestMatchers.js
@@ -0,0 +1,95 @@
// https://github.com/facebook/react/blob/master/scripts/jest/matchers/schedulerTestMatchers.js

'use strict'

function captureAssertion(fn) {
// Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
// assertion; if it throws, we capture the error and return it, so the stack
// trace presented to the user points to the original assertion in the
// test file.
try {
fn()
} catch (error) {
return {
pass: false,
message: () => error.message
}
}
return { pass: true }
}

function assertYieldsWereCleared(Scheduler) {
const actualYields = Scheduler.unstable_clearYields()
if (actualYields.length !== 0) {
throw new Error(
'Log of yielded values is not empty. ' +
'Call expect(Scheduler).toHaveYielded(...) first.'
)
}
}

function toFlushAndYield(Scheduler, expectedYields) {
assertYieldsWereCleared(Scheduler)
Scheduler.unstable_flushAllWithoutAsserting()
const actualYields = Scheduler.unstable_clearYields()
return captureAssertion(() => {
expect(actualYields).toEqual(expectedYields)
})
}

function toFlushAndYieldThrough(Scheduler, expectedYields) {
assertYieldsWereCleared(Scheduler)
Scheduler.unstable_flushNumberOfYields(expectedYields.length)
const actualYields = Scheduler.unstable_clearYields()
return captureAssertion(() => {
expect(actualYields).toEqual(expectedYields)
})
}

function toFlushUntilNextPaint(Scheduler, expectedYields) {
assertYieldsWereCleared(Scheduler)
Scheduler.unstable_flushUntilNextPaint()
const actualYields = Scheduler.unstable_clearYields()
return captureAssertion(() => {
expect(actualYields).toEqual(expectedYields)
})
}

function toFlushWithoutYielding(Scheduler) {
return toFlushAndYield(Scheduler, [])
}

function toFlushExpired(Scheduler, expectedYields) {
assertYieldsWereCleared(Scheduler)
Scheduler.unstable_flushExpired()
const actualYields = Scheduler.unstable_clearYields()
return captureAssertion(() => {
expect(actualYields).toEqual(expectedYields)
})
}

function toHaveYielded(Scheduler, expectedYields) {
return captureAssertion(() => {
const actualYields = Scheduler.unstable_clearYields()
expect(actualYields).toEqual(expectedYields)
})
}

function toFlushAndThrow(Scheduler, ...rest) {
assertYieldsWereCleared(Scheduler)
return captureAssertion(() => {
expect(() => {
Scheduler.unstable_flushAllWithoutAsserting()
}).toThrow(...rest)
})
}

module.exports = {
toFlushAndYield,
toFlushAndYieldThrough,
toFlushUntilNextPaint,
toFlushWithoutYielding,
toFlushExpired,
toHaveYielded,
toFlushAndThrow
}
5 changes: 4 additions & 1 deletion tsconfig.test.json
@@ -1,4 +1,7 @@
{
"extends": "./tsconfig.json",
"include": ["packages/**/__tests__"]
"compilerOptions": {
"target": "ES2019"
},
"include": ["packages/**/__tests__", "typings"]
}
80 changes: 80 additions & 0 deletions typings/testing/expect-extend.d.ts
@@ -0,0 +1,80 @@
export {}

declare global {
namespace jest {
interface Matchers<R> {
/**
* 1. Assert Yields is initially empty.
* 2. Flush all tasks.
* 3. Collect Yields and compare.
*/
toFlushAndYield(
expectedYields: any[]
): {
pass: boolean
message?: () => any
}
/**
* 1. Assert Yields is initially empty.
* 2. Flush tasks until `expectedYields.length` Yields are collected.
* 3. Compare.
*/
toFlushAndYieldThrough(
expectedYields: any[]
): {
pass: boolean
message?: () => any
}
/**
* 1. Assert Yields is initially empty.
* 2. Flush tasks until meeting a paint request.
* 3. Collect Yields and compare.
*/
toFlushUntilNextPaint(
expectedYields: any[]
): {
pass: boolean
message?: () => any
}
/**
* 1. Assert Yields is initially empty.
* 2. Flush all tasks.
* 3. Expect empty Yield.
*/
toFlushWithoutYielding(): {
pass: boolean
message?: () => any
}
/**
* 1. Assert Yields is initially empty.
* 2. Flush the next scheduled task.
* 3. Collect Yields and compare.
*/
toFlushExpired(
expectedYields: any[]
): {
pass: boolean
message?: () => any
}
/**
* Compare Yields.
*/
toHaveYielded(
expectedYields: any[]
): {
pass: boolean
message?: () => any
}
/**
* 1. Assert Yields is initially empty.
* 2. Expect exception is thrown when flushing all tasks.
*/
toFlushAndThrow(
...rest: any[]
): {
pass: boolean
message?: () => any
}
}
}
}

0 comments on commit bf4b4cd

Please sign in to comment.