Skip to content

Commit

Permalink
feat: add allowOnly option (#669)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerYeger committed Feb 3, 2022
1 parent 6565492 commit cc73207
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 15 deletions.
1 change: 1 addition & 0 deletions docs/guide/index.md
Expand Up @@ -116,6 +116,7 @@ You can specify additional CLI options like `--port` or `--https`. For a full li
| `--dom` | Mock browser api with happy-dom |
| `--environment <env>` | Runner environment (default: node) |
| `--passWithNoTests` | Pass when no tests found |
| `--allowOnly` | Allow tests and suites that are marked as `only` (default: false in CI, true otherwise) |
| `-h, --help` | Display available CLI options |

## Examples
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -19,8 +19,8 @@
"release": "bumpp package.json packages/*/package.json --commit --push --tag && pnpm -r publish --access public",
"test": "vitest --api -r test/core",
"test:run": "vitest run -r test/core",
"test:all": "cross-env CI=true pnpm -r --stream --filter !@vitest/monorepo run test --",
"test:ci": "cross-env CI=true pnpm -r --stream --filter !@vitest/monorepo --filter !test-fails run test --",
"test:all": "cross-env CI=true pnpm -r --stream --filter !@vitest/monorepo run test -- --allowOnly",
"test:ci": "cross-env CI=true pnpm -r --stream --filter !@vitest/monorepo --filter !test-fails run test -- --allowOnly",
"typecheck": "tsc --noEmit",
"ui:build": "vite build packages/ui",
"ui:dev": "vite packages/ui"
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/client/components/StatusIcon.vue
Expand Up @@ -33,7 +33,7 @@ defineProps<{ task: Task }>()
i-carbon:document-blank
/>
<div
v-else-if="task.mode === 'skip'"
v-else-if="task.mode === 'skip' || task.result?.state === 'skip'"
v-tooltip.right="'Skipped'"
text-gray-500
flex-shrink-0
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/node/cli.ts
Expand Up @@ -30,6 +30,7 @@ cli
.option('--dom', 'mock browser api with happy-dom')
.option('--environment <env>', 'runner environment', { default: 'node' })
.option('--passWithNoTests', 'pass when no tests found')
.option('--allowOnly', 'Allow tests and suites that are marked as only', { default: !process.env.CI })
.help()

cli
Expand Down
33 changes: 22 additions & 11 deletions packages/vitest/src/runtime/collect.ts
@@ -1,6 +1,6 @@
import { createHash } from 'crypto'
import { relative } from 'pathe'
import type { File, ResolvedConfig, Suite } from '../types'
import type { File, ResolvedConfig, Suite, TaskBase } from '../types'
import { clearContext, defaultSuite } from './suite'
import { getHooks, setHooks } from './map'
import { processError } from './error'
Expand Down Expand Up @@ -64,7 +64,8 @@ export async function collectTests(paths: string[], config: ResolvedConfig) {

calculateHash(file)

interpretTaskModes(file, config.testNamePattern)
const hasOnlyTasks = someTasksAreOnly(file)
interpretTaskModes(file, config.testNamePattern, hasOnlyTasks, false, config.allowOnly)

files.push(file)
}
Expand All @@ -75,23 +76,25 @@ export async function collectTests(paths: string[], config: ResolvedConfig) {
/**
* If any tasks been marked as `only`, mark all other tasks as `skip`.
*/
function interpretTaskModes(suite: Suite, namePattern?: string | RegExp, onlyMode?: boolean, isIncluded?: boolean) {
if (onlyMode === undefined) {
onlyMode = someTasksAreOnly(suite)
isIncluded ||= suite.mode === 'only'
}
function interpretTaskModes(suite: Suite, namePattern?: string | RegExp, onlyMode?: boolean, parentIsOnly?: boolean, allowOnly?: boolean) {
const suiteIsOnly = parentIsOnly || suite.mode === 'only'

suite.tasks.forEach((t) => {
// Check if either the parent suite or the task itself are marked as included
const includeTask = isIncluded || t.mode === 'only'
const includeTask = suiteIsOnly || t.mode === 'only'
if (onlyMode) {
if (t.type === 'suite' && (includeTask || someTasksAreOnly(t))) {
// Don't skip this suite
if (t.mode === 'only')
if (t.mode === 'only') {
checkAllowOnly(t, allowOnly)
t.mode = 'run'
}
}
else if (t.mode === 'run' && !includeTask) { t.mode = 'skip' }
else if (t.mode === 'only') { t.mode = 'run' }
else if (t.mode === 'only') {
checkAllowOnly(t, allowOnly)
t.mode = 'run'
}
}
if (t.type === 'test') {
if (namePattern && !t.name.match(namePattern))
Expand All @@ -101,7 +104,7 @@ function interpretTaskModes(suite: Suite, namePattern?: string | RegExp, onlyMod
if (t.mode === 'skip')
skipAllTasks(t)
else
interpretTaskModes(t, namePattern, onlyMode, includeTask)
interpretTaskModes(t, namePattern, onlyMode, includeTask, allowOnly)
}
})

Expand All @@ -126,6 +129,14 @@ function skipAllTasks(suite: Suite) {
})
}

function checkAllowOnly(task: TaskBase, allowOnly?: boolean) {
if (allowOnly) return
task.result = {
state: 'fail',
error: processError(new Error('[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly arguement to bypass this error')),
}
}

function calculateHash(parent: Suite) {
parent.tasks.forEach((t, idx) => {
t.id = `${parent.id}_${idx}`
Expand Down
19 changes: 18 additions & 1 deletion packages/vitest/src/runtime/run.ts
Expand Up @@ -47,6 +47,11 @@ export async function runTest(test: Test) {
if (test.mode !== 'run')
return

if (test.result?.state === 'fail') {
updateTask(test)
return
}

const start = performance.now()

test.result = {
Expand Down Expand Up @@ -114,9 +119,21 @@ export async function runTest(test: Test) {
updateTask(test)
}

function markTasksAsSkipped(suite: Suite) {
suite.tasks.forEach((t) => {
t.mode = 'skip'
t.result = { ...t.result, state: 'skip' }
updateTask(t)
if (t.type === 'suite') markTasksAsSkipped(t)
})
}

export async function runSuite(suite: Suite) {
if (suite.result?.state === 'fail')
if (suite.result?.state === 'fail') {
markTasksAsSkipped(suite)
updateTask(suite)
return
}

const start = performance.now()

Expand Down
5 changes: 5 additions & 0 deletions packages/vitest/src/types/config.ts
Expand Up @@ -305,6 +305,11 @@ export interface UserConfig extends InlineConfig {
*/
passWithNoTests?: boolean

/**
* Allow tests and suites that are marked as only
*/
allowOnly?: boolean

/**
* Run tests that cover a list of source files
*/
Expand Down

0 comments on commit cc73207

Please sign in to comment.