Skip to content

Commit

Permalink
feat(warn): missing dots in extensions
Browse files Browse the repository at this point in the history
See #117
  • Loading branch information
posva committed Jan 10, 2023
1 parent cdb6afb commit 18f30a1
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 3 deletions.
18 changes: 18 additions & 0 deletions src/options.spec.ts
@@ -0,0 +1,18 @@
import { describe, expect, it } from 'vitest'
import { resolveOptions } from './options'
import { mockWarn } from '../tests/vitest-mock-warn'

describe('options', () => {
mockWarn()
it('ensure starting dots in extensions', () => {
expect(
resolveOptions({
extensions: ['vue', '.ts'],
})
).toMatchObject({
extensions: ['.vue', '.ts'],
})

expect('Invalid extension "vue"').toHaveBeenWarned()
})
})
19 changes: 16 additions & 3 deletions src/options.ts
Expand Up @@ -132,9 +132,22 @@ export function resolveOptions(options: Options): ResolvedOptions {
}))

if (options.extensions) {
// sort extensions by length to ensure that the longest one is used first
// e.g. ['.vue', '.page.vue'] -> ['.page.vue', '.vue'] as both would match and order matters
options.extensions.sort((a, b) => b.length - a.length)
options.extensions = options.extensions
// ensure that extensions start with a dot or warn the user
// this is needed when filtering the files with the pattern .{vue,js,ts}
// in src/index.ts
.map((ext) => {
if (!ext.startsWith('.')) {
console.warn(
`[unplugin-vue-router]: Invalid extension "${ext}". Extensions must start with a dot.`
)
return '.' + ext
}
return ext
})
// sort extensions by length to ensure that the longest one is used first
// e.g. ['.vue', '.page.vue'] -> ['.page.vue', '.vue'] as both would match and order matters
.sort((a, b) => b.length - a.length)
}

return {
Expand Down
118 changes: 118 additions & 0 deletions tests/vitest-mock-warn.ts
@@ -0,0 +1,118 @@
// https://github.com/posva/jest-mock-warn/blob/master/src/index.js

import { afterEach, beforeEach, expect, SpyInstance, vi } from 'vitest'

export function mockWarn() {
expect.extend({
toHaveBeenWarned(received: string | RegExp) {
asserted.set(received.toString(), received)
const passed = warn.mock.calls.some((args) =>
typeof received === 'string'
? args[0].indexOf(received) > -1
: received.test(args[0])
)
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 | RegExp) {
asserted.set(received.toString(), received)
const lastCall = warn.mock.calls[warn.mock.calls.length - 1][0]
const passed =
typeof received === 'string'
? lastCall.indexOf(received) > -1
: received.test(lastCall)
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 | RegExp, n: number) {
asserted.set(received.toString(), received)
let found = 0
warn.mock.calls.forEach((args) => {
const isFound =
typeof received === 'string'
? args[0].indexOf(received) > -1
: received.test(args[0])
if (isFound) {
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: SpyInstance
const asserted = new Map<string, string | RegExp>()

beforeEach(() => {
asserted.clear()
warn = vi.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(([key, assertedMsg]) => {
return typeof assertedMsg === 'string'
? received.indexOf(assertedMsg) > -1
: assertedMsg.test(received)
})
})
warn.mockRestore()
if (nonAssertedWarnings.length) {
nonAssertedWarnings.forEach((warning) => {
console.warn(warning)
})
throw new Error(`test case threw unexpected warnings.`)
}
})
}

declare global {
namespace Vi {
interface JestAssertion<T = any> {
toHaveBeenWarned(): void
toHaveBeenWarnedLast(): void
toHaveBeenWarnedTimes(n: number): void
}
}
}

0 comments on commit 18f30a1

Please sign in to comment.