Skip to content

Commit

Permalink
feat(test-utils): built-in chai extension (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma authored Aug 29, 2020
1 parent ec003cc commit 607bd58
Show file tree
Hide file tree
Showing 26 changed files with 109 additions and 238 deletions.
1 change: 0 additions & 1 deletion packages/adapter-cqhttp/tests/mock.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { snakeCase } from 'koishi-utils'
import { CQResponse } from 'koishi-adapter-cqhttp'
import { expect } from 'chai'
import '@shigma/chai-extended'

export type RequestParams = Record<string, any>
export type RequestData = readonly [string, RequestParams]
Expand Down
25 changes: 0 additions & 25 deletions packages/chai-extended/package.json

This file was deleted.

43 changes: 0 additions & 43 deletions packages/chai-extended/src/index.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/koishi-core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export namespace Group {

export type Field = keyof Group
export const fields: Field[] = []
export type Observed<K extends Field = Field> = utils.Observed<Pick<Group, K>>
export type Observed<K extends Field = Field> = utils.Observed<Pick<Group, K>, Promise<void>>
type Getter = (id: number, authority: number) => Partial<Group>
const getters: Getter[] = []

Expand Down
1 change: 0 additions & 1 deletion packages/koishi-core/tests/command.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Logger, noop } from 'koishi-utils'
import { Session } from 'koishi-core'
import { inspect } from 'util'
import { expect } from 'chai'
import '@shigma/chai-extended'

describe('Command API', () => {
describe('Register Commands', () => {
Expand Down
1 change: 0 additions & 1 deletion packages/koishi-core/tests/context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Session } from 'koishi-core'
import { noop } from 'koishi-utils'
import { expect } from 'chai'
import { fn } from 'jest-mock'
import '@shigma/chai-extended'

const app = new App()
const groupSession = new Session(app, { userId: 123, groupId: 456, messageType: 'group' })
Expand Down
1 change: 0 additions & 1 deletion packages/koishi-core/tests/parser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Command } from 'koishi-core'
import { App } from 'koishi-test-utils'
import { expect } from 'chai'
import '@shigma/chai-extended'

const app = new App()

Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions packages/koishi-test-utils/chai/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "chai-extended",
"private": true,
"main": "dist/index.js",
"typings": "index.d.ts",
"author": "Shigma <1700011071@pku.edu.cn>",
"license": "MIT",
"files": [
"index.d.ts",
"dist"
]
}
45 changes: 45 additions & 0 deletions packages/koishi-test-utils/chai/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { use } from 'chai'
import { inspect } from 'util'

use(({ Assertion }) => {
function checkShape(expect, actual, path) {
if (actual === expect || Number.isNaN(expect) && Number.isNaN(actual)) return

function formatError(expect, actual) {
return `expected to have ${expect} but got ${actual} at path ${path}`
}

if (!expect || ['string', 'number', 'boolean', 'bigint'].includes(typeof expect)) {
return formatError(inspect(expect), inspect(actual))
}

// dates
if (expect instanceof Date) {
if (!(actual instanceof Date) || +expect !== +actual) {
return formatError(inspect(expect), inspect(actual))
}
return
}

if (actual === null) {
const type = Object.prototype.toString.call(expect).slice(8, -1).toLowerCase()
return formatError(`a ${type}`, 'null')
}

// array / object
for (const prop in expect) {
if (typeof actual[prop] === 'undefined' && typeof expect[prop] !== 'undefined') {
return `expected "${prop}" field to be defined at path ${path}`
}
const message = checkShape(expect[prop], actual[prop], `${path}${prop}/`)
if (message) return message
}
}

Assertion.addMethod('shape', function (expect) {
const message = checkShape(expect, this._obj, '/')
if (message) this.assert(false, message, undefined, expect, this._obj)
})
})

use(require('chai-as-promised'))
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.base",
"extends": "../../../tsconfig.base",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
Expand Down
10 changes: 8 additions & 2 deletions packages/koishi-test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"node": ">=12.0.0"
},
"files": [
"dist"
"dist",
"chai/index.d.ts",
"chai/package.json"
],
"author": "Shigma <1700011071@pku.edu.cn>",
"license": "MIT",
Expand Down Expand Up @@ -36,9 +38,13 @@
"utilities"
],
"dependencies": {
"@shigma/chai-extended": "^0.1.4",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"koishi-core": "^2.0.1",
"koishi-utils": "^3.1.1"
},
"devDependencies": {
"@types/chai": "^4.2.12",
"@types/chai-as-promised": "^7.1.3"
}
}
4 changes: 2 additions & 2 deletions packages/koishi-test-utils/src/database.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { App, User, Group } from 'koishi-core'
import { BASE_SELF_ID } from './app'
import { expect } from 'chai'
import '@shigma/chai-extended'
import '../chai'

export function createArray <T>(length: number, create: (index: number) => T) {
export function createArray<T>(length: number, create: (index: number) => T) {
return Array(length).fill(undefined).map((_, index) => create(index))
}

Expand Down
12 changes: 2 additions & 10 deletions packages/koishi-test-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import * as utils from './koishi'
import * as memory from './memory'
import { mockModule, actualModule } from './module'
import memory from './memory'

export { utils, memory }
export { memory }

export * from './app'
export * from './database'
export * from './memory'

mockModule('koishi-utils', () => {
const utils1 = actualModule('koishi-utils')
const utils2 = actualModule('./koishi')
return { ...utils1, ...utils2 }
})
65 changes: 0 additions & 65 deletions packages/koishi-test-utils/src/koishi.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/koishi-test-utils/src/memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ extendDatabase(MemoryDatabase, {
},
})

export function apply(app: App, config: MemoryConfig = {}) {
export default function apply(app: App, config: MemoryConfig = {}) {
app.database = new MemoryDatabase(app, config) as any
}
57 changes: 0 additions & 57 deletions packages/koishi-test-utils/src/module.ts

This file was deleted.

30 changes: 30 additions & 0 deletions packages/koishi-test-utils/tests/chai.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'koishi-test-utils'
import { expect } from 'chai'
import { Random } from 'koishi-utils'

describe('Chai Extensions', () => {
it('shape', () => {
expect(1).to.have.shape(1)
expect(NaN).to.have.shape(NaN)
expect(true).to.have.shape(true)
expect('foo').to.have.shape('foo')

const random = Random.int(1 << 20)
expect(new Date(random)).to.have.shape(new Date(random))
expect({ a: 1, b: 2 }).to.have.shape({ a: 1 })
expect([1, 2]).to.have.shape([1])

expect(() => expect(1).to.have.shape(2))
.to.throw('expected to have 2 but got 1 at path /')
expect(() => expect(null).to.have.shape(/(?:)/))
.to.throw('expected to have a regexp but got null at path /')
expect(() => expect(new Date(0)).to.have.shape(new Date(1000)))
.to.throw('expected to have 1970-01-01T00:00:01.000Z but got 1970-01-01T00:00:00.000Z at path /')
expect(() => expect({ a: 1 }).to.have.shape({ a: 1, b: 2 }))
.to.throw('expected "b" field to be defined at path /')
expect(() => expect([1]).to.have.shape([1, 2]))
.to.throw('expected "1" field to be defined at path /')
expect(() => expect([[1, 2], { a: 3, b: 4 }]).to.have.shape([[1], { a: 4 }]))
.to.throw('expected to have 4 but got 3 at path /1/a/')
})
})
Loading

0 comments on commit 607bd58

Please sign in to comment.