diff --git a/packages/runner/src/suite.ts b/packages/runner/src/suite.ts index c935c3301341..3056bae4192a 100644 --- a/packages/runner/src/suite.ts +++ b/packages/runner/src/suite.ts @@ -520,16 +520,17 @@ function createSuite() { optionsOrFactory, ) + const isConcurrentSpecified = options.concurrent || this.concurrent || options.sequential === false + const isSequentialSpecified = options.sequential || this.sequential || options.concurrent === false + // inherit options from current suite if (currentSuite?.options) { options = { ...currentSuite.options, ...options } } // inherit concurrent / sequential from suite - const isConcurrent - = options.concurrent || (this.concurrent && !this.sequential) - const isSequential - = options.sequential || (this.sequential && !this.concurrent) + const isConcurrent = isConcurrentSpecified || (options.concurrent && !isSequentialSpecified) + const isSequential = isSequentialSpecified || (options.sequential && !isConcurrentSpecified) options.concurrent = isConcurrent && !isSequential options.sequential = isSequential && !isConcurrent diff --git a/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-concurrent.test.ts b/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-concurrent.test.ts new file mode 100644 index 000000000000..b9620007db9e --- /dev/null +++ b/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-concurrent.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test, vi } from 'vitest' + +const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)) + +let count = 0 + +describe.concurrent('concurrent suite', () => { + test('first test completes last', async ({ task }) => { + await delay(40) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(4) + }) + + test('second test completes third', async ({ task }) => { + await delay(30) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(3) + }) +}) + +test.concurrent('third test completes second', async ({ task }) => { + await delay(20) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(2) +}) + +test.concurrent('last test completes first', async ({ task }) => { + await delay(10) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(1) +}) diff --git a/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-sequential.test.ts b/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-sequential.test.ts new file mode 100644 index 000000000000..3dae2cf52e71 --- /dev/null +++ b/test/config/fixtures/sequence-concurrent/sequence-concurrent-false-sequential.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test, vi } from 'vitest' + +const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)) + +let count = 0 + +describe('sequential suite', () => { + test('first test completes first', async ({ task }) => { + await delay(40) + expect(task.concurrent).toBeFalsy() + expect(++count).toBe(1) + }) + + test('second test completes second', async ({ task }) => { + await delay(30) + expect(task.concurrent).toBeFalsy() + expect(++count).toBe(2) + }) +}) + +test('third test completes third', async ({ task }) => { + await delay(20) + expect(task.concurrent).toBeFalsy() + expect(++count).toBe(3) +}) + +test('last test completes last', async ({ task }) => { + await delay(10) + expect(task.concurrent).toBeFalsy() + expect(++count).toBe(4) +}) diff --git a/test/config/fixtures/sequence-concurrent/sequence-concurrent-true-concurrent.test.ts b/test/config/fixtures/sequence-concurrent/sequence-concurrent-true-concurrent.test.ts new file mode 100644 index 000000000000..7f435a75b187 --- /dev/null +++ b/test/config/fixtures/sequence-concurrent/sequence-concurrent-true-concurrent.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test, vi } from 'vitest' + +const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)) + +let count = 0 + +describe('concurrent suite', () => { + test('first test completes last', async ({ task }) => { + await delay(40) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(4) + }) + + test('second test completes third', async ({ task }) => { + await delay(30) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(3) + }) +}) + +test('third test completes second', async ({ task }) => { + await delay(20) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(2) +}) + +test('last test completes first', async ({ task }) => { + await delay(10) + expect(task.concurrent).toBeTruthy() + expect(++count).toBe(1) +}) diff --git a/test/core/test/sequential-sequence-concurrent.test.ts b/test/config/fixtures/sequence-concurrent/sequence-concurrent-true-sequential.test.ts similarity index 65% rename from test/core/test/sequential-sequence-concurrent.test.ts rename to test/config/fixtures/sequence-concurrent/sequence-concurrent-true-sequential.test.ts index d9304507761d..ed2772a7c939 100644 --- a/test/core/test/sequential-sequence-concurrent.test.ts +++ b/test/config/fixtures/sequence-concurrent/sequence-concurrent-true-sequential.test.ts @@ -1,35 +1,31 @@ import { describe, expect, test, vi } from 'vitest' -vi.setConfig({ - sequence: { - concurrent: true, - }, -}) - const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)) let count = 0 -describe.sequential('running sequential suite when sequence.concurrent is true', () => { +describe.sequential('sequential suite', () => { test('first test completes first', async ({ task }) => { - await delay(50) + await delay(40) expect(task.concurrent).toBeFalsy() expect(++count).toBe(1) }) - test('second test completes second', ({ task }) => { + test('second test completes second', async ({ task }) => { + await delay(30) expect(task.concurrent).toBeFalsy() expect(++count).toBe(2) }) }) test.sequential('third test completes third', async ({ task }) => { - await delay(50) + await delay(20) expect(task.concurrent).toBeFalsy() expect(++count).toBe(3) }) -test.sequential('fourth test completes fourth', ({ task }) => { +test.sequential('last test completes last', async ({ task }) => { + await delay(10) expect(task.concurrent).toBeFalsy() expect(++count).toBe(4) }) diff --git a/test/config/test/sequence-concurrent.test.ts b/test/config/test/sequence-concurrent.test.ts new file mode 100644 index 000000000000..a665e8f710a9 --- /dev/null +++ b/test/config/test/sequence-concurrent.test.ts @@ -0,0 +1,47 @@ +import { expect, test } from 'vitest' + +import { runVitest } from '../../test-utils' + +test('should run suites and tests concurrently unless sequential specified when sequence.concurrent is true', async () => { + const { stderr, stdout } = await runVitest({ + root: './fixtures/sequence-concurrent', + include: ['sequence-concurrent-true-*.test.ts'], + sequence: { + concurrent: true, + }, + }) + + expect(stderr).toBe('') + + expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > sequential suite > first test completes first') + expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > sequential suite > second test completes second') + expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > third test completes third') + expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > last test completes last') + expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > concurrent suite > first test completes last') + expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > concurrent suite > second test completes third') + expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > third test completes second') + expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > last test completes first') + expect(stdout).toContain('Test Files 2 passed (2)') +}) + +test('should run suites and tests sequentially unless concurrent specified when sequence.concurrent is false', async () => { + const { stderr, stdout } = await runVitest({ + root: './fixtures/sequence-concurrent', + include: ['sequence-concurrent-false-*.test.ts'], + sequence: { + concurrent: false, + }, + }) + + expect(stderr).toBe('') + + expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > sequential suite > first test completes first') + expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > sequential suite > second test completes second') + expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > third test completes third') + expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > last test completes last') + expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > concurrent suite > first test completes last') + expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > concurrent suite > second test completes third') + expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > third test completes second') + expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > last test completes first') + expect(stdout).toContain('Test Files 2 passed (2)') +})