Tests
Les tests vous aident à écrire et maintenir votre code et vous protègent contre les régressions. Les frameworks de test vous aident à ça, vous permettant de décrire des assertions ou des attentes sur le comportement de votre code. Svelte ne vous oriente pas sur tel ou tel framework à utiliser — vous pouvez écrire des tests unitaires, des tests d’intégration, des tests end-to-end en utilisant des solutions comme Vitest, Jasmine, Cypress et Playwright
Tests unitaires et d’intégration avec Vitest
Les tests unitaires vous permettent de tester des petites parties isolées de votre code. Les tests d’intégration vous permettent de vérifier comment des morceaux de votre application fonctionnent ensemble. Si vous utilisez Vite (notamment via SvelteKit), nous vous recommandons d’utiliser Vitest.
Pour commencer, installer Vitest :
npm install -D vitest
Puis ajuster votre fichier vite.config.js
:
import { function defineConfig(config: UserConfig): UserConfig (+3 overloads)
defineConfig } from 'vitest/config';
export default function defineConfig(config: UserConfig): UserConfig (+3 overloads)
defineConfig({
// ...
// Dit à Vitest d'utiliser les points d'entrée `browser` dans les fichiers `package.json`, même si
// Vitest utilise Node
UserConfig.resolve?: (ResolveOptions & {
alias?: AliasOptions;
}) | undefined
Configure resolver
resolve: var process: NodeJS.Process
process.NodeJS.Process.env: NodeJS.ProcessEnv
The process.env
property returns an object containing the user environment.
See environ(7)
.
An example of this object looks like:
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
It is possible to modify this object, but such modifications will not be
reflected outside the Node.js process, or (unless explicitly requested)
to other Worker
threads.
In other words, the following example would not work:
node -e 'process.env.foo = "bar"' && echo $foo
While the following will:
import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);
Assigning a property on process.env
will implicitly convert the value
to a string. This behavior is deprecated. Future versions of Node.js may
throw an error when the value is not a string, number, or boolean.
import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'
Use delete
to delete a property from process.env
.
import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined
On Windows operating systems, environment variables are case-insensitive.
import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1
Unless explicitly specified when creating a Worker
instance,
each Worker
thread has its own copy of process.env
, based on its
parent thread’s process.env
, or whatever was specified as the env
option
to the Worker
constructor. Changes to process.env
will not be visible
across Worker
threads, and only the main thread can make changes that
are visible to the operating system or to native add-ons. On Windows, a copy of process.env
on a Worker
instance operates in a case-sensitive manner
unlike the main thread.
env.string | undefined
VITEST
? {
ResolveOptions.conditions?: string[] | undefined
conditions: ['browser']
}
: var undefined
undefined
});
Si charger la version navigateur de tous vos paquets n’est pas possible, parce que vous testez également des librairies backend, vous pourriez avoir également besoin d’une configuration d’alias
Vous pouvez maintenant écrire vos tests unitaires dans des fichiers .js/.ts
:
import { function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync } from 'svelte';
import { const expect: ExpectStatic
expect, const test: TestAPI
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test } from 'vitest';
import { import multiplier
multiplier } from './multiplier.svelte.js';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestOptions): void (+2 overloads)
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test('Multiplier', () => {
let let double: any
double = import multiplier
multiplier(0, 2);
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let double: any
double.value).JestAssertion<any>.toEqual: <number>(expected: number) => void
toEqual(0);
let double: any
double.set(5);
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let double: any
double.value).JestAssertion<any>.toEqual: <number>(expected: number) => void
toEqual(10);
});
/**
* @param {number} initial
* @param {number} k
*/
export function function multiplier(initial: number, k: number): {
readonly value: number;
set: (c: number) => void;
}
multiplier(initial: number
initial, k: number
k) {
let let count: number
count = function $state<number>(initial: number): number (+1 overload)
namespace $state
$state(initial: number
initial);
return {
get value: number
value() {
return let count: number
count * k: number
k;
},
/** @param {number} c */
set: (c: number) => void
set: (c: number
c) => {
let count: number
count = c: number
c;
}
};
}
export function function multiplier(initial: number, k: number): {
readonly value: number;
set: (c: number) => void;
}
multiplier(initial: number
initial: number, k: number
k: number) {
let let count: number
count = function $state<number>(initial: number): number (+1 overload)
namespace $state
$state(initial: number
initial);
return {
get value: number
value() {
return let count: number
count * k: number
k;
},
set: (c: number) => void
set: (c: number
c: number) => {
let count: number
count = c: number
c;
}
};
}
Utiliser les runes dans vos fichiers de test
Puisque Vitest traite vos fichiers de test de la même façon que vos fichiers source, vous pouvez
utiliser des runes au sein de vos tests tant que leur nom de fichier inclut .svelte
:
import { function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync } from 'svelte';
import { const expect: ExpectStatic
expect, const test: TestAPI
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test } from 'vitest';
import { import multiplier
multiplier } from './multiplier.svelte.js';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestOptions): void (+2 overloads)
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test('Multiplier', () => {
let let count: number
count = function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
$state(0);
let let double: any
double = import multiplier
multiplier(() => let count: number
count, 2);
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let double: any
double.value).JestAssertion<any>.toEqual: <number>(expected: number) => void
toEqual(0);
let count: number
count = 5;
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let double: any
double.value).JestAssertion<any>.toEqual: <number>(expected: number) => void
toEqual(10);
});
/**
* @param {() => number} getCount
* @param {number} k
*/
export function function multiplier(getCount: () => number, k: number): {
readonly value: number;
}
multiplier(getCount: () => number
getCount, k: number
k) {
return {
get value: number
value() {
return getCount: () => number
getCount() * k: number
k;
}
};
}
export function function multiplier(getCount: () => number, k: number): {
readonly value: number;
}
multiplier(getCount: () => number
getCount: () => number, k: number
k: number) {
return {
get value: number
value() {
return getCount: () => number
getCount() * k: number
k;
}
};
}
Si le code testé utilise des effets, vous aurez besoin de placer le test dans un $effect.root
:
import { function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync } from 'svelte';
import { const expect: ExpectStatic
expect, const test: TestAPI
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test } from 'vitest';
import { import logger
logger } from './logger.svelte.js';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestOptions): void (+2 overloads)
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test('Effet', () => {
const const cleanup: () => void
cleanup = namespace $effect
function $effect(fn: () => void | (() => void)): void
Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state
or $derived
values.
The timing of the execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.
Does not run during server side rendering.
$effect.function $effect.root(fn: () => void | (() => void)): () => void
The $effect.root
rune is an advanced feature that creates a non-tracked scope that doesn’t auto-cleanup. This is useful for
nested effects that you want to manually control. This rune also allows for creation of effects outside of the component
initialisation phase.
Example:
<script>
let count = $state(0);
const cleanup = $effect.root(() => {
$effect(() => {
console.log(count);
})
return () => {
console.log('effect root cleanup');
}
});
</script>
<button onclick={() => cleanup()}>cleanup</button>
root(() => {
let let count: number
count = function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
$state(0);
// logger utilise un $effect pour afficher les mises à jour de son input
let let log: any
log = import logger
logger(() => let count: number
count);
// les effets sont en général exécutés après une micro-tâche,
// utiliser `flushSync` pour exécuter tous les effets en attente de manière synchrone
function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync();
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let log: any
log.value).JestAssertion<any>.toEqual: <number[]>(expected: number[]) => void
toEqual([0]);
let count: number
count = 1;
function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync();
expect<any>(actual: any, message?: string): Assertion<any> (+1 overload)
expect(let log: any
log.value).JestAssertion<any>.toEqual: <number[]>(expected: number[]) => void
toEqual([0, 1]);
});
const cleanup: () => void
cleanup();
});
/**
* @param {() => any} getValue
*/
export function function logger(getValue: () => any): {
readonly value: any[];
}
logger(getValue: () => any
getValue) {
/** @type {any[]} */
let let log: any[]
log = function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
$state([]);
function $effect(fn: () => void | (() => void)): void
namespace $effect
Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state
or $derived
values.
The timing of the execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.
Does not run during server side rendering.
$effect(() => {
let log: any[]
log.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.
push(getValue: () => any
getValue());
});
return {
get value: any[]
value() {
return let log: any[]
log;
}
};
}
export function function logger(getValue: () => any): {
readonly value: any[];
}
logger(getValue: () => any
getValue: () => any) {
let let log: any[]
log: any[] = function $state<never[]>(initial: never[]): never[] (+1 overload)
namespace $state
$state([]);
function $effect(fn: () => void | (() => void)): void
namespace $effect
Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state
or $derived
values.
The timing of the execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.
Does not run during server side rendering.
$effect(() => {
let log: any[]
log.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.
push(getValue: () => any
getValue());
});
return {
get value: any[]
value() {
return let log: any[]
log;
}
};
}
Tests de composants
Il est possible de tester vos composants en isolation en utilisant Vitest.
Avant d’écrire des tests de composant, posez-vous la question de si vous avez réellement besoin de tester le composant, ou si vous souhaitez plutôt tester la logique au sein de votre composant. Si c’est le cas, envisagez d’extraire cette logique afin de pouvoir la tester indépendamment du composant.
Pour commencer, installer jsdom (une librairie qui simule les APIs du DOM) :
npm install -D jsdom
Puis ajustez votre vite.config.js
:
import { function defineConfig(config: UserConfig): UserConfig (+3 overloads)
defineConfig } from 'vitest/config';
export default function defineConfig(config: UserConfig): UserConfig (+3 overloads)
defineConfig({
UserConfig.plugins?: PluginOption[] | undefined
Array of vite plugins to use.
plugins: [
/* ... */
],
UserConfig.test?: InlineConfig | undefined
Options for Vitest
test: {
// Si vous testez des composants côté client, vous aurez besoin de mettre en place un
// environnement DOM. Si tous vos fichiers ne sont pas compatibles avec cet environnement, vous
// pouvez plutôt ajouter un commentaire `// @vitest-environment jsdom` en haut des fichiers de
// test.
InlineConfig.environment?: VitestEnvironment | undefined
Running environment
Supports ‘node’, ‘jsdom’, ‘happy-dom’, ‘edge-runtime’
If used unsupported string, will try to load the package vitest-environment-${env}
environment: 'jsdom'
},
// Dit à Vitest d'utiliser les points d'entrée `browser` dans les fichiers `package.json`, même si
// Vitest utilise Node
UserConfig.resolve?: (ResolveOptions & {
alias?: AliasOptions;
}) | undefined
Configure resolver
resolve: var process: NodeJS.Process
process.NodeJS.Process.env: NodeJS.ProcessEnv
The process.env
property returns an object containing the user environment.
See environ(7)
.
An example of this object looks like:
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
It is possible to modify this object, but such modifications will not be
reflected outside the Node.js process, or (unless explicitly requested)
to other Worker
threads.
In other words, the following example would not work:
node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo
While the following will:
import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);
Assigning a property on process.env
will implicitly convert the value
to a string. This behavior is deprecated. Future versions of Node.js may
throw an error when the value is not a string, number, or boolean.
import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'
Use delete
to delete a property from process.env
.
import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined
On Windows operating systems, environment variables are case-insensitive.
import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1
Unless explicitly specified when creating a Worker
instance,
each Worker
thread has its own copy of process.env
, based on its
parent thread’s process.env
, or whatever was specified as the env
option
to the Worker
constructor. Changes to process.env
will not be visible
across Worker
threads, and only the main thread can make changes that
are visible to the operating system or to native add-ons. On Windows, a copy of process.env
on a Worker
instance operates in a case-sensitive manner
unlike the main thread.
env.string | undefined
VITEST
? {
ResolveOptions.conditions?: string[] | undefined
conditions: ['browser']
}
: var undefined
undefined
});
Vous pouvez ensuite créer un fichier de test dans lequel importer le composant à tester, interagir avec lui programmatiquement et définir les résultats attendus :
import { function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync, function mount<Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: MountOptions<Props>): Exports
Mounts a component to the given target and returns the exports and potentially the props (if compiled with accessors: true
) of the component.
Transitions will play during the initial render unless the intro
option is set to false
.
mount, function unmount(component: Record<string, any>, options?: {
outro?: boolean;
} | undefined): Promise<void>
Unmounts a component that was previously mounted using mount
or hydrate
.
Since 5.13.0, if options.outro
is true
, transitions will play before the component is removed from the DOM.
Returns a Promise
that resolves after transitions have completed if options.outro
is true, or immediately otherwise (prior to 5.13.0, returns void
).
import { mount, unmount } from 'svelte';
import App from './App.svelte';
const app = mount(App, { target: document.body });
// later...
unmount(app, { outro: true });
unmount } from 'svelte';
import { const expect: ExpectStatic
expect, const test: TestAPI
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test } from 'vitest';
import type Component = SvelteComponent<Record<string, any>, any, any>
const Component: LegacyComponentType
Component from './Component.svelte';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestOptions): void (+2 overloads)
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test('Component', () => {
// Instantier le composant en utilisant l'API Svelte `mount`
const const component: {
$on?(type: string, callback: (e: any) => void): () => void;
$set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
component = mount<Record<string, any>, {
$on?(type: string, callback: (e: any) => void): () => void;
$set?(props: Partial<Record<string, any>>): void;
} & Record<...>>(component: ComponentType<...> | Component<...>, options: MountOptions<...>): {
...;
} & Record<...>
Mounts a component to the given target and returns the exports and potentially the props (if compiled with accessors: true
) of the component.
Transitions will play during the initial render unless the intro
option is set to false
.
mount(const Component: LegacyComponentType
Component, {
target: Document | Element | ShadowRoot
Target element where the component will be mounted.
target: var document: Document
document.Document.body: HTMLElement
Specifies the beginning and end of the document body.
body, // `document` existe grâce à jsdom
props?: Record<string, any> | undefined
Component properties.
props: { initial: number
initial: 0 }
});
expect<string>(actual: string, message?: string): Assertion<string> (+1 overload)
expect(var document: Document
document.Document.body: HTMLElement
Specifies the beginning and end of the document body.
body.InnerHTML.innerHTML: string
innerHTML).JestAssertion<string>.toBe: <string>(expected: string) => void
toBe('<button>0</button>');
// Clic sur le bouton, puis synchronisation des changements pour définir les attentes de manière
// synchrone
var document: Document
document.Document.body: HTMLElement
Specifies the beginning and end of the document body.
body.ParentNode.querySelector<"button">(selectors: "button"): HTMLButtonElement | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors.
querySelector('button').HTMLElement.click(): void
click();
function flushSync(fn?: (() => void) | undefined): void
Synchronously flushes any pending state changes and those that result from it.
flushSync();
expect<string>(actual: string, message?: string): Assertion<string> (+1 overload)
expect(var document: Document
document.Document.body: HTMLElement
Specifies the beginning and end of the document body.
body.InnerHTML.innerHTML: string
innerHTML).JestAssertion<string>.toBe: <string>(expected: string) => void
toBe('<button>1</button>');
// Suppression du composant du DOM
function unmount(component: Record<string, any>, options?: {
outro?: boolean;
} | undefined): Promise<void>
Unmounts a component that was previously mounted using mount
or hydrate
.
Since 5.13.0, if options.outro
is true
, transitions will play before the component is removed from the DOM.
Returns a Promise
that resolves after transitions have completed if options.outro
is true, or immediately otherwise (prior to 5.13.0, returns void
).
import { mount, unmount } from 'svelte';
import App from './App.svelte';
const app = mount(App, { target: document.body });
// later...
unmount(app, { outro: true });
unmount(const component: {
$on?(type: string, callback: (e: any) => void): () => void;
$set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
component);
});
Même le processus est plutôt simple à mettre en place, celui-ci est aussi bas niveau et plutôt fragile, puisque la structure de composant peut beaucoup évoluer. Des outils comme @testing-library/svelte peuvent aider à industrialiser l’écriture de vos tests. Le test ci-dessus peut ainsi être ré-écrit comme ceci :
import { function render<C extends unknown, Q extends Queries = typeof import("/vercel/path0/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@testing-library/dom/types/queries")>(Component: ComponentType<...>, options?: SvelteComponentOptions<C>, renderOptions?: RenderOptions<Q>): RenderResult<C, Q>
Render a component into the document.
render, const screen: Screen<typeof import("/vercel/path0/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@testing-library/dom/types/queries")>
screen } from '@testing-library/svelte';
import const userEvent: {
readonly setup: typeof setupMain;
readonly clear: typeof clear;
readonly click: typeof click;
readonly copy: typeof copy;
... 12 more ...;
readonly tab: typeof tab;
}
userEvent from '@testing-library/user-event';
import { const expect: ExpectStatic
expect, const test: TestAPI
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test } from 'vitest';
import type Component = SvelteComponent<Record<string, any>, any, any>
const Component: LegacyComponentType
Component from './Component.svelte';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestOptions): void (+2 overloads)
Defines a test case with a given name and test function. The test function can optionally be configured with test options.
test('Component', async () => {
const const user: UserEvent
user = const userEvent: {
readonly setup: typeof setupMain;
readonly clear: typeof clear;
readonly click: typeof click;
readonly copy: typeof copy;
... 12 more ...;
readonly tab: typeof tab;
}
userEvent.setup: (options?: Options) => UserEvent
Start a “session” with userEvent.
All APIs returned by this function share an input device state and a default configuration.
setup();
render<SvelteComponent<Record<string, any>, any, any>, typeof import("/vercel/path0/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@testing-library/dom/types/queries")>(Component: ComponentType<...>, options?: SvelteComponentOptions<...> | undefined, renderOptions?: RenderOptions<...> | undefined): RenderResult<...>
Render a component into the document.
render(const Component: LegacyComponentType
Component);
const const button: HTMLElement
button = const screen: Screen<typeof import("/vercel/path0/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@testing-library/dom/types/queries")>
screen.getByRole<HTMLElement>(role: ByRoleMatcher, options?: ByRoleOptions | undefined): HTMLElement (+1 overload)
getByRole('button');
expect<HTMLElement>(actual: HTMLElement, message?: string): Assertion<HTMLElement> (+1 overload)
expect(const button: HTMLElement
button).toHaveTextContent(0);
await const user: UserEvent
user.click: (element: Element) => Promise<void>
click(const button: HTMLElement
button);
expect<HTMLElement>(actual: HTMLElement, message?: string): Assertion<HTMLElement> (+1 overload)
expect(const button: HTMLElement
button).toHaveTextContent(1);
});
Lorsque vous écrivez des tests de composant qui impliquent des liaisons à double sens, du contexte
ou des props de snippet, il est recommandé de créer un composant parent spécifiquement pour votre
test, et interagir avec ce composant. @testing-library/svelte
montre quelques exemples de cette
technique.
Tests E2E avec Playwright
Les tests E2E (“end to end” en anglais, qui se traduit par “de bout en bout”) vous permettent de tester votre application toute entière depuis le point de vue de vos utilisateurs. Cette section prend Playwright comme exemple, mais vous pouvez aussi utiliser d’autres solutions comme Cypress ou NightwatchJS.
Pour commencer à utiliser Playwright, vous pouvez soit l’installer via l’extension VS
Code, soit l’installer depuis votre ligne de
commande en utilisant npm init playwright
. Vous pouvez aussi l’installer via le CLI d’installation
de Svelte, qui se lance avec npx sv create
.
Une fois l’installation terminée, vous devriez voir apparaître un dossier tests
ainsi qu’un
fichier de configuration de Playwright. Il se peut que vous ayez besoin d’ajuster cette
configuration pour dire à Playwright ce qu’il doit faire avant de lancer les tests — principalement
lancer votre application sur un port particulier :
const const config: {
webServer: {
command: string;
port: number;
};
testDir: string;
testMatch: RegExp;
}
config = {
webServer: {
command: string;
port: number;
}
webServer: {
command: string
command: 'npm run build && npm run preview',
port: number
port: 4173
},
testDir: string
testDir: 'tests',
testMatch: RegExp
testMatch: /(.+\.)?(test|spec)\.[jt]s/
};
export default const config: {
webServer: {
command: string;
port: number;
};
testDir: string;
testMatch: RegExp;
}
config;
Vous pouvez maintenant commencer à écrire vos tests. Ils n’ont aucune conscience que Svelte existe en tant que framework, il vous faudra donc surtout interagir avec le DOM, et écrire vos assertions.
import { import expect
expect, import test
test } from '@playwright/test';
import test
test("la page d'accueil a le h1 prévu", async ({ page }) => {
await page: any
page.goto('/');
await import expect
expect(page: any
page.locator('h1')).toBeVisible();
});
Modifier cette page sur Github