Skip to content

Commit

Permalink
Merge branch 'main' of github.com:vitest-dev/vitest into pr/hi-ogawa/…
Browse files Browse the repository at this point in the history
…7301
  • Loading branch information
sheremet-va committed Jan 23, 2025
2 parents 9ef7071 + 385bfa4 commit 5658a69
Show file tree
Hide file tree
Showing 93 changed files with 1,085 additions and 704 deletions.
6 changes: 3 additions & 3 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@
"@types/chai",
"@sinonjs/fake-timers",
"cac",
// Pinned due to https://github.com/vitest-dev/vitest/issues/4710
"log-update",
// Pinned because it requires "node" condition in the new version
// But we intentionally build Vitest ambiguously
"find-up",
// Transitive dependency that we patch
"acorn"
"acorn",
// Keep using codemirror 5
"codemirror"
]
}
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ on:
- main

pull_request:
branches:
- main

workflow_dispatch:

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/browser/locators.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ It is recommended to use this only after the other locators don't work for your
function nth(index: number): Locator
```

This method returns a new locator that matches only a specific index within a multi-element query result. Unlike `elements()[n]`, the `nth` locator will be retried until the element is present.
This method returns a new locator that matches only a specific index within a multi-element query result. It's zero based, `nth(0)` selects the first element. Unlike `elements()[n]`, the `nth` locator will be retried until the element is present.

```html
<div aria-label="one"><input/><input/><input/></div>
Expand Down
6 changes: 3 additions & 3 deletions docs/guide/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ Run tests on different machines using [`--shard`](/guide/cli#shard) and [`--repo
All test and coverage results can be merged at the end of your CI pipeline using `--merge-reports` command:

```bash
vitest --shard=1/2 --reporter=blob
vitest --shard=2/2 --reporter=blob
vitest --merge-reports --reporter=junit --coverage.reporter=text
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage
```

See [`Improving Performance | Sharding`](/guide/improving-performance#sharding) for more information.
Expand Down
80 changes: 69 additions & 11 deletions docs/guide/mocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,17 +430,20 @@ it('can return a value multiple times', () => {

## Requests

Because Vitest runs in Node, mocking network requests is tricky; web APIs are not available, so we need something that will mimic network behavior for us. We recommend [Mock Service Worker](https://mswjs.io/) to accomplish this. It will let you mock both `REST` and `GraphQL` network requests, and is framework agnostic.
Because Vitest runs in Node, mocking network requests is tricky; web APIs are not available, so we need something that will mimic network behavior for us. We recommend [Mock Service Worker](https://mswjs.io/) to accomplish this. It allows you to mock `http`, `WebSocket` and `GraphQL` network requests, and is framework agnostic.

Mock Service Worker (MSW) works by intercepting the requests your tests make, allowing you to use it without changing any of your application code. In-browser, this uses the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). In Node.js, and for Vitest, it uses the [`@mswjs/interceptors`](https://github.com/mswjs/interceptors) library. To learn more about MSW, read their [introduction](https://mswjs.io/docs/)

### Configuration

You can use it like below in your [setup file](/config/#setupfiles)
```js

::: code-group

```js [HTTP Setup]
import { afterAll, afterEach, beforeAll } from 'vitest'
import { setupServer } from 'msw/node'
import { graphql, http, HttpResponse } from 'msw'
import { http, HttpResponse } from 'msw'

const posts = [
{
Expand All @@ -458,28 +461,83 @@ export const restHandlers = [
}),
]

const server = setupServer(...restHandlers)

// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

// Close server after all tests
afterAll(() => server.close())

// Reset handlers after each test for test isolation
afterEach(() => server.resetHandlers())
```

```js [GrapQL Setup]
import { afterAll, afterEach, beforeAll } from 'vitest'
import { setupServer } from 'msw/node'
import { graphql, HttpResponse } from 'msw'

const posts = [
{
userId: 1,
id: 1,
title: 'first post title',
body: 'first post body',
},
// ...
]

const graphqlHandlers = [
graphql.query('ListPosts', () => {
return HttpResponse.json(
{
data: { posts },
},
)
return HttpResponse.json({
data: { posts },
})
}),
]

const server = setupServer(...restHandlers, ...graphqlHandlers)
const server = setupServer(...graphqlHandlers)

// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

// Close server after all tests
// Close server after all tests
afterAll(() => server.close())

// Reset handlers after each test `important for test isolation`
// Reset handlers after each test for test isolation
afterEach(() => server.resetHandlers())
```

```js [WebSocket Setup]
import { afterAll, afterEach, beforeAll } from 'vitest'
import { setupServer } from 'msw/node'
import { ws } from 'msw'

const chat = ws.link('wss://chat.example.com')

const wsHandlers = [
chat.addEventListener('connection', ({ client }) => {
client.addEventListener('message', (event) => {
console.log('Received message from client:', event.data)
// Echo the received message back to the client
client.send(`Server received: ${event.data}`)
})
}),
]

const server = setupServer(...wsHandlers)

// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

// Close server after all tests
afterAll(() => server.close())

// Reset handlers after each test for test isolation
afterEach(() => server.resetHandlers())
```
:::

> Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
### More
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vitest/monorepo",
"type": "module",
"version": "3.0.2",
"version": "3.0.3",
"private": true,
"packageManager": "[email protected]",
"description": "Next generation testing framework powered by Vite",
Expand Down Expand Up @@ -36,7 +36,7 @@
"test:browser:playwright": "pnpm -C test/browser run test:playwright"
},
"devDependencies": {
"@antfu/eslint-config": "^3.11.2",
"@antfu/eslint-config": "^3.16.0",
"@antfu/ni": "^23.2.0",
"@playwright/test": "^1.49.1",
"@rollup/plugin-commonjs": "^28.0.2",
Expand All @@ -51,7 +51,7 @@
"bumpp": "^9.10.1",
"changelogithub": "^0.13.11",
"esbuild": "^0.24.2",
"eslint": "^9.16.0",
"eslint": "^9.18.0",
"magic-string": "^0.30.17",
"pathe": "^2.0.1",
"rimraf": "^6.0.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/jest-dom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ declare namespace matchers {
* @see
* [testing-library/jest-dom#tohaveclass](https://github.com/testing-library/jest-dom#tohaveclass)
*/
toHaveClass(...classNames: Array<string | RegExp>): R
toHaveClass(classNames: string, options?: {exact: boolean}): R
toHaveClass(...classNames: Array<string | RegExp>): R
/**
* @description
* This allows you to check whether the given form element has the specified displayed value (the one the
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vitest/browser",
"type": "module",
"version": "3.0.2",
"version": "3.0.3",
"description": "Browser running for Vitest",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
Expand Down
8 changes: 4 additions & 4 deletions packages/browser/src/node/commands/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export const screenshot: BrowserCommand<[string, ScreenshotOptions]> = async (
const path = options.path
? resolve(dirname(context.testPath), options.path)
: resolveScreenshotPath(
context.testPath,
name,
context.project.config,
)
context.testPath,
name,
context.project.config,
)
const savePath = normalize(path)
await mkdir(dirname(path), { recursive: true })

Expand Down
24 changes: 16 additions & 8 deletions packages/browser/src/node/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,15 @@ export default (parentServer: ParentBrowserProject, base = '/'): Plugin[] => {
}

const url = new URL(req.url, 'http://localhost')
const file = url.searchParams.get('file')
const id = url.searchParams.get('id')
if (!id) {
res.statusCode = 404
res.end()
return
}

const task = parentServer.vitest.state.idMap.get(id)
const file = task?.meta.failScreenshotPath
if (!file) {
res.statusCode = 404
res.end()
Expand Down Expand Up @@ -571,12 +579,12 @@ function resolveCoverageFolder(vitest: Vitest) {
const options = vitest.config
const htmlReporter = options.coverage?.enabled
? toArray(options.coverage.reporter).find((reporter) => {
if (typeof reporter === 'string') {
return reporter === 'html'
}
if (typeof reporter === 'string') {
return reporter === 'html'
}

return reporter[0] === 'html'
})
return reporter[0] === 'html'
})
: undefined

if (!htmlReporter) {
Expand All @@ -591,8 +599,8 @@ function resolveCoverageFolder(vitest: Vitest) {

const subdir
= Array.isArray(htmlReporter)
&& htmlReporter.length > 1
&& 'subdir' in htmlReporter[1]
&& htmlReporter.length > 1
&& 'subdir' in htmlReporter[1]
? htmlReporter[1].subdir
: undefined

Expand Down
3 changes: 3 additions & 0 deletions packages/browser/src/node/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ export function createBrowserPool(vitest: Vitest): ProcessPool {
}
await project._initBrowserProvider()

if (!project.browser) {
throw new TypeError(`The browser server was not initialized${project.name ? ` for the "${project.name}" project` : ''}. This is a bug in Vitest. Please, open a new issue with reproduction.`)
}
await executeTests(method, project, files)
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/node/serverTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function resolveTester(
// if decoded test file is "__vitest_all__" or not in the list of known files, run all tests
const tests
= testFile === '__vitest_all__'
|| !testFiles.includes(testFile)
|| !testFiles.includes(testFile)
? '__vitest_browser_runner__.files'
: JSON.stringify([testFile])
const iframeId = JSON.stringify(testFile)
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// we cannot bundle it because vitest depend on the @vitest/browser and vise versa
// fortunately, the file is quite small

import { LocatorSelectors } from '@vitest/browser/context'
import { LocatorSelectors, Locator } from '@vitest/browser/context'
import { StringifyOptions } from 'vitest/utils'

export type PrettyDOMOptions = Omit<StringifyOptions, 'maxLength'>
Expand Down
2 changes: 1 addition & 1 deletion packages/coverage-istanbul/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vitest/coverage-istanbul",
"type": "module",
"version": "3.0.2",
"version": "3.0.3",
"description": "Istanbul coverage provider for Vitest",
"author": "Anthony Fu <[email protected]>",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/coverage-v8/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vitest/coverage-v8",
"type": "module",
"version": "3.0.2",
"version": "3.0.3",
"description": "V8 coverage provider for Vitest",
"author": "Anthony Fu <[email protected]>",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/expect/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vitest/expect",
"type": "module",
"version": "3.0.2",
"version": "3.0.3",
"description": "Jest's expect matchers as a Chai plugin",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
Expand Down
12 changes: 6 additions & 6 deletions packages/expect/src/jest-asymmetric-matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ export class ArrayContaining<T = unknown> extends AsymmetricMatcher<Array<T>> {
const matcherContext = this.getMatcherContext()
const result
= this.sample.length === 0
|| (Array.isArray(other)
&& this.sample.every(item =>
other.some(another =>
equals(item, another, matcherContext.customTesters),
),
))
|| (Array.isArray(other)
&& this.sample.every(item =>
other.some(another =>
equals(item, another, matcherContext.customTesters),
),
))

return this.inverse ? !result : result
}
Expand Down
8 changes: 4 additions & 4 deletions packages/expect/src/jest-expect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
if (!isNot) {
const message
= utils.flag(this, 'message')
|| 'expected promise to throw an error, but it didn\'t'
|| 'expected promise to throw an error, but it didn\'t'
const error = {
showDiff: false,
}
Expand Down Expand Up @@ -469,7 +469,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
const { value, exists } = getValue()
const pass
= exists
&& (args.length === 1 || jestEquals(expected, value, customTesters))
&& (args.length === 1 || jestEquals(expected, value, customTesters))

const valueString
= args.length === 1 ? '' : ` with value ${utils.objDisplay(expected)}`
Expand Down Expand Up @@ -751,7 +751,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
if (!isNot) {
const message
= utils.flag(this, 'message')
|| 'expected promise to throw an error, but it didn\'t'
|| 'expected promise to throw an error, but it didn\'t'
const error = {
showDiff: false,
}
Expand All @@ -774,7 +774,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
if (!isThrow && !isNot) {
const message
= utils.flag(this, 'message')
|| 'expected function to throw an error, but it didn\'t'
|| 'expected function to throw an error, but it didn\'t'
const error = {
showDiff: false,
}
Expand Down
Loading

0 comments on commit 5658a69

Please sign in to comment.