> ## Documentation Index
> Fetch the complete documentation index at: https://www.chapterjs.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Tests

> Tout ce qu’un scénario peut faire : le bot testé, les personnes et salons de son serveur, et ce qu’une réponse peut vérifier

`scenario()` déclare un test de votre bot, depuis un fichier `*.test.ts` de `src/`, et `chapterjs test` le lance contre un Discord en mémoire. Tout ce qui est sur cette page s’importe depuis `chapterjs/test`.

```ts src/checks/hello.test.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { scenario } from 'chapterjs/test';
import { hello } from './hello';

export default scenario('hello salue', async bot => {
  const reply = await bot.use(hello, { who: bot.member('alice') });
  reply.says('Bonjour alice').isPublic();
});
```

```ts src/checks/hello.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export const hello = command({
  name: 'hello',
  description: 'Dit bonjour',
  options: { who: { type: 'user', description: 'Qui', required: true } },
  async run({ interaction, options }) {
    await interaction.reply(`Bonjour ${options.who.username} !`);
  },
});
```

> [!NOTE]
>
> Comment tester un bot, ce qui est vérifié sans scénario et ce qu’a le serveur de test est dans le [guide](https://www.chapterjs.org/fr/testing.md). Cette page liste ce qui existe.

## scenario()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
scenario(label: string, run: (bot: TestBot) => unknown): ScenarioDeclaration
```

Déclare un test de votre bot. Exportez le résultat depuis un fichier `*.test.ts` de `src/` : `chapterjs test` le lance contre un Discord en mémoire, où le bot est dans un serveur avec quelques personnes.

`bot` est le bot dans son serveur de test : `bot.use()` lance une commande, `bot.click()` appuie sur un bouton, `bot.say()` envoie un message en tant que quelqu’un, et ce qui revient dit ce que le bot a répondu.

Un fichier peut exporter plusieurs scénarios, dans une liste aussi. Le libellé est ce que montre le rapport : il ne peut pas être vide, et 120 caractères est le maximum.

### ScenarioDeclaration

Ce que renvoie `scenario()` : une déclaration que le lanceur trouve dans les exports d’un fichier.

**config** `\{ label: string; run: (bot: TestBot) =\> unknown \}`

Ce que le fichier a donné à `scenario()`, pas encore vérifié.

## TestBot

Le bot du projet, qui tourne dans un Discord en mémoire : un serveur, quelques personnes, et tout ce que fait le bot gardé là où le test peut le lire.

**guild** `\{ id: string; name: string \}` *required*

Le serveur de test.

**me** `TestMember` *required*

Le bot lui-même, en tant que membre du serveur.

**owner** `TestMember` *required*

Le propriétaire du serveur.

**someone** `TestMember` *required*

Une personne sans droit particulier : qui fait les choses quand personne n’est nommé.

**requests** `\{ method: string; path: string; body: unknown \}[]` *required*

Chaque requête que le bot a envoyée à Discord jusqu’ici.

### member()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
member(name: string, options?: TestMemberOptions): TestMember
```

Une personne du serveur, créée la première fois que le nom est donné. Les options ne comptent que la première fois.

### role()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
role(name: string, options?: TestRoleOptions): TestRole
```

Un rôle du serveur, créé la première fois que le nom est donné.

### channel()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
channel(name: string, options?: TestChannelOptions): TestChannel
```

Un salon du serveur, créé la première fois que le nom est donné. `#general` existe.

### use()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
use(command: CommandDeclaration, options?: OptionInputsOf<Options>, where?: TestWhere): Promise<TestReply>
use(command: MenuDeclaration, target: TestMenuTarget, where?: TestWhere): Promise<TestReply>
```

Utilise une commande, comme une personne le ferait : une commande slash avec ses options, ou une commande de menu sur ce sur quoi elle s’utilise (`{ on: message }`, `{ on: member }` ; un menu de message s’utilise dans le salon de son message). Se résout une fois que le bot a répondu.

`options` est typé depuis les options de la commande (`OptionInputsOf`) : un texte, un nombre, `true` ou `false`, l’un des `choices`, un `TestMember` pour une option `user`, un `TestRole` pour une option `role`, un `TestChannel` pour une option `channel`, un `TestFile` pour une option `attachment`. Il peut être omis quand la commande n’en exige aucune. Ce que Discord ne laisserait pas une personne envoyer (une option obligatoire manquante, un nombre hors de sa plage, un texte trop long, une valeur qui n’est pas un des choix) fait échouer le scénario avant que le bot n’en entende parler.

### click()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
click(button: ButtonTarget, where?: TestWhere): Promise<TestReply>
```

Clique sur un bouton. Se résout une fois que le bot a répondu. Un bouton trouvé sur un message (`reply.button('Confirmer')`) est cliqué sur ce message, comme le ferait une personne.

### select()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
select(menu: SelectTarget, values: readonly SelectInput[], where?: TestWhere): Promise<TestReply>
```

Choisit des valeurs dans un menu déroulant. Se résout une fois que le bot a répondu. `values` sont des textes pour un menu de textes (les valeurs de ses options), des personnes, des rôles ou des salons pour les autres ; les `min` et `max` du menu sont appliqués.

### submit()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
submit(form: FormTarget<Fields>, fields?: FieldInputsOf<Fields>, where?: TestWhere): Promise<TestReply>
```

Remplit et envoie un formulaire. Se résout une fois que le bot a répondu. `fields` est typé depuis les champs du formulaire (`FieldInputsOf`) : un texte pour un champ `text`, une liste de valeurs d’options pour un `select` ou `checkboxes`, une valeur d’option pour un `radio`, `true` ou `false` pour un `checkbox`, des personnes, rôles ou salons pour les autres, des fichiers pour un champ `files`. Un champ omis reste vide ; un champ obligatoire omis fait échouer le scénario, comme l’application Discord refuserait d’envoyer le formulaire.

### suggest()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
suggest(command: CommandDeclaration, option: string, typed: string, where?: TestWhere): Promise<TestSuggestion[]>
```

Tape dans une option avec suggestions, et récupère ce que le bot suggère.

### say()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
say(content: string, where?: TestWhere): Promise<TestMessage>
```

Envoie un message en tant que quelqu’un. Se résout une fois que le bot l’a traité.

### react()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
react(message: TestMessage, emoji: string, where?: { by?: TestMember }): Promise<void>
```

Réagit à un message en tant que quelqu’un. Se résout une fois que le bot l’a traité.

### join()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
join(member: string | TestMember, options?: TestMemberOptions): Promise<TestMember>
```

Fait rejoindre le serveur à quelqu’un. Se résout une fois que le bot l’a traité.

### leave()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
leave(member: TestMember): Promise<void>
```

Fait quitter le serveur à quelqu’un. Se résout une fois que le bot l’a traité.

### run()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
run(task: TaskDeclaration, at?: Date): Promise<void>
```

Lance une tâche maintenant, comme si son heure était venue. Se résout une fois qu’elle a fini.

### settle()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
settle(): Promise<void>
```

Attend que tout ce que le bot a commencé soit terminé.

Tout sauf ce qui attend que le test agisse : une fonction qui attend un message, un clic ou une réaction (`waitForMessage()`…) reste en attente, et `use()`, `say()`, `click()`… se résolvent pendant ce temps.

### endWaits()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
endWaits(): Promise<void>
```

Termine tout ce qu’attend le bot (`waitForMessage()`, `waitForClick()`…) comme si son temps était écoulé : le temps ne passe pas dans le serveur de test. Se résout une fois que le bot l’a traité.

## TestWhere

Qui fait quelque chose, et où.

**by** `TestMember`

Qui le fait. Par défaut : `bot.someone`.

**in** `TestChannel | 'dm'`

Où : un salon, ou `'dm'` pour un message privé avec le bot. Par défaut : `#general`.

**on** `TestMessage | TestReply`

Pour un bouton ou un menu : le message sur lequel il est. Par défaut : un message du bot.

## TestMemberOptions

Comment créer une personne pour un test.

**roles** `(string | TestRole)[]`

Les rôles de la personne, par nom ou tels que `bot.role()` les a donnés.

**permissions** `PermissionName[]`

Des permissions données par un rôle rien qu’à elle.

**nickname** `string`

Le pseudo sur le serveur.

**bot** `boolean`

Si la personne est un bot.

**locale** `Locale`

La langue de la personne : celle dans laquelle `t` lui répond. Par défaut : `'en-US'`.

## TestRoleOptions

**permissions** `PermissionName[]`

Ce que le rôle permet.

## TestChannelOptions

**type** `TestChannelType`

`'text'`, `'announcement'`, `'voice'`, `'category'` ou `'forum'`. Par défaut : `'text'`.

**parent** `TestChannel`

La catégorie dans laquelle il est.

**topic** `string`

Le sujet du salon.

## TestFile

Un fichier que quelqu’un joint à une commande ou à un formulaire.

**name** `string` *required*

Le nom du fichier, avec son extension : `photo.png`.

**content** `string`

Son contenu, en texte.

**type** `string`

Son type de média : deviné depuis le nom par défaut.

## TestReply

Ce que le bot a répondu à une commande, un bouton, un menu ou un formulaire. Il a chaque vérification de [`TestAssertions`](#testassertions), et :

**message** `TestMessage | null` *required*

Le message avec lequel le bot a répondu (ou qu’il a changé), ou `null` sans message.

**content** `string` *required*

Le texte de la réponse ; `''` sans message.

**embeds** `Embed[]` *required*

Les embeds, tels que le bot les a envoyés.

**buttons** `TestButton[]` *required*

Ses boutons, dans l’ordre.

**menus** `TestMenu[]` *required*

Ses menus déroulants, dans l’ordre.

**followUps** `TestMessage[]` *required*

Les messages envoyés après la première réponse, dans l’ordre.

**form** `TestForm | null` *required*

Le formulaire que le bot a ouvert, ou `null`.

**deferred** `boolean` *required*

Si le bot a dit que la réponse arrivait avant de répondre.

**updated** `boolean` *required*

Si la réponse a changé le message du composant.

**ephemeral** `boolean` *required*

Si une seule personne la voit.

### isDeferred()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
isDeferred(): TestReply
```

Vérifie que le bot a dit que la réponse arrivait (« thinking… »).

### updatesMessage()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
updatesMessage(): TestReply
```

Vérifie que le bot a changé le message du bouton ou du menu.

### opensForm()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
opensForm(form?: ModalDeclaration | ModalComponent | TestForm): TestReply
```

Vérifie que le bot a ouvert un formulaire, celui-ci quand il est donné : son export (quelles que soient les données qu’il porte), le formulaire appelé avec ses données, ou celui trouvé sur une réponse.

### changesNothing()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
changesNothing(): TestReply
```

Vérifie que le bot a répondu sans rien de visible (une mise à jour différée).

### button()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
button(label: string): TestButton
```

Le bouton avec ce libellé, pour cliquer dessus. Échoue quand il n’y en a pas.

### menu()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
menu(placeholder?: string): TestMenu
```

Le menu, ou celui qui a ce texte d’attente. Échoue quand il n’y en a pas.

## TestAssertions

Ce qui se vérifie d’un message ou d’une réponse. Chaque vérification lance une `TestFailure` avec une phrase en clair quand elle échoue, et renvoie ce qu’elle a vérifié sinon, pour enchaîner.

### says()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
says(text: string | RegExp): Self
```

Vérifie que le texte contient `text` (ou lui correspond).

### saysExactly()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
saysExactly(text: string): Self
```

Vérifie que le texte est exactement `text`.

### isEphemeral()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
isEphemeral(): Self
```

Vérifie que seule la personne qui a demandé le voit.

### isPublic()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
isPublic(): Self
```

Vérifie que tout le monde le voit.

### hasButton()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
hasButton(label: string): Self
```

Vérifie qu’il y a un bouton avec ce libellé.

### hasEmbed()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
hasEmbed(title?: string): Self
```

Vérifie qu’il y a un embed, avec ce titre quand il est donné.

### hasNoEmbed()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
hasNoEmbed(): Self
```

Vérifie qu’il n’y a pas d’embed.

### hasNoComponent()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
hasNoComponent(): Self
```

Vérifie qu’il n’y a ni bouton ni menu.

## TestMessage

Un message du serveur de test. Il a chaque vérification de [`TestAssertions`](#testassertions), et :

**id** `string` *required*

L’id du message.

**content** `string` *required*

Le texte du message.

**author** `TestMember | null` *required*

Qui l’a écrit ; `null` pour quelqu’un qui n’est plus dans le monde.

**fromBot** `boolean` *required*

Si le bot l’a écrit.

**embeds** `Embed[]` *required*

Les embeds, tels que le bot les a envoyés.

**buttons** `TestButton[]` *required*

Ses boutons, dans l’ordre.

**menus** `TestMenu[]` *required*

Ses menus déroulants, dans l’ordre.

**ephemeral** `boolean` *required*

Si une seule personne le voit.

**pinned** `boolean` *required*

Si le message est épinglé.

**channel** `TestChannel` *required*

Le salon dans lequel il est.

**deleted** `boolean` *required*

Si le message a été supprimé depuis.

### button()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
button(label: string): TestButton
```

Le bouton avec ce libellé : pour cliquer dessus. Échoue quand il n’y en a pas.

### menu()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
menu(placeholder?: string): TestMenu
```

Le menu, ou celui qui a ce texte d’attente. Échoue quand il n’y en a pas.

## TestMember

Une personne du serveur de test.

**id** `string` *required*

L’id de la personne.

**name** `string` *required*

Le nom d’utilisateur de la personne : ce qui a été donné à `bot.member()`.

**nickname** `string | null` *required*

Le pseudo sur le serveur, ou `null` sans pseudo.

**roles** `string[]` *required*

Les noms des rôles de la personne.

**permissions** `PermissionName[]` *required*

Les permissions de la personne sur le serveur.

**inServer** `boolean` *required*

Si la personne est sur le serveur en ce moment.

**banned** `boolean` *required*

Si la personne est bannie du serveur.

**timedOut** `boolean` *required*

Si la personne est exclue temporairement en ce moment.

**privateMessages** `TestMessage[]` *required*

Les messages que le bot a envoyés à la personne en privé, du plus ancien au plus récent.

### can()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
can(permission: PermissionName): boolean
```

Si la personne a le droit de faire cela sur le serveur.

### hasRole()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
hasRole(role: string | TestRole): boolean
```

Si la personne a ce rôle.

## TestRole

Un rôle du serveur de test.

**id** `string` *required*

L’id du rôle.

**name** `string` *required*

Le nom du rôle.

**permissions** `PermissionName[]` *required*

Ce que le rôle permet.

**exists** `boolean` *required*

Si le rôle existe encore.

## TestChannel

Un salon du serveur de test, un fil, ou une conversation privée.

**id** `string` *required*

L’id du salon.

**name** `string` *required*

Le nom du salon.

**type** `string` *required*

Quel genre de salon c’est : `'text'`, `'voice'`, `'thread'`, `'dm'`…

**topic** `string | null` *required*

Le sujet, ou `null`.

**slowmode** `number` *required*

Les secondes entre deux messages d’une même personne (mode lent) ; `0` pour aucun.

**exists** `boolean` *required*

Si le salon existe encore.

**messages** `TestMessage[]` *required*

Chaque message que tout le monde y voit, du plus ancien au plus récent (les supprimés et les éphémères mis à part).

**last** `TestMessage | null` *required*

Le message le plus récent, ou `null`.

**threads** `TestChannel[]` *required*

Les fils ouverts dedans.

**members** `TestMember[]` *required*

Pour un fil : qui est dedans.

**archived** `boolean` *required*

Pour un fil : s’il est archivé.

**locked** `boolean` *required*

Pour un fil : s’il est verrouillé.

### allows()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
allows(member: TestMember | TestRole, permission: PermissionName): boolean
```

Si un membre a le droit de faire cela dans le salon (ses permissions spécifiques comptées).

## TestButton

Un bouton sur un message envoyé par le bot.

**label** `string | null` *required*

Le texte du bouton, ou `null` pour un emoji seul.

**style** `string` *required*

`'primary'`, `'secondary'`, `'success'`, `'danger'`, `'link'` ou `'premium'`.

**disabled** `boolean` *required*

Si le bouton est désactivé.

**customId** `string | null` *required*

L’id que le framework a écrit dedans.

## TestMenu

Un menu déroulant sur un message envoyé par le bot.

**type** `string` *required*

`'string'`, `'user'`, `'role'`, `'mentionable'` ou `'channel'`.

**placeholder** `string | null` *required*

Le texte affiché quand rien n’est choisi.

**disabled** `boolean` *required*

Si le menu est désactivé.

**options** `\{ label: string; value: string \}[]` *required*

Pour un menu de textes : ses options.

**customId** `string` *required*

L’id que le framework a écrit dedans.

## TestForm

Un formulaire que le bot a ouvert.

**title** `string` *required*

Le titre du formulaire.

**fields** `string[]` *required*

Les noms de ses champs, dans l’ordre.

**customId** `string` *required*

L’id que le framework a écrit dedans.

## TestSuggestion

Une suggestion que le bot a faite pendant que quelqu’un tapait dans une option.

**name** `string` *required*

Ce que la personne voit.

**value** `string | number` *required*

Ce que le bot reçoit.

## Types

* `OptionInputsOf<Options>` : les options d’une commande telles qu’un test les remplit. Une option obligatoire ne peut pas être omise.
* `FieldInputsOf<Fields>` : les champs d’un formulaire tels qu’un test les remplit : un champ omis reste vide.
* `SelectInput` : ce qu’un test choisit dans un menu : des textes, ou des personnes, rôles et salons.
* `TestMenuTarget<Type>` : ce sur quoi s’utilise une commande de menu dans un test : `{ on }`, un `TestMember` pour un menu `'user'`, un `TestMessage` pour un menu `'message'`.
* `ButtonTarget` : un bouton, tel qu’un test le nomme : la déclaration, une instance, ou un bouton trouvé sur un message (`reply.button('Confirmer')`).
* `SelectTarget` : un menu, de la même façon (`reply.menu()`).
* `FormTarget<Fields>` : un formulaire, de la même façon (`reply.form`).
* `TestChannelType` : `'text' | 'announcement' | 'voice' | 'category' | 'forum'`.
* `TestFailure` : une attente d’un test que le bot n’a pas satisfaite. Ce que lance chaque vérification, avec une phrase en clair : le rapport l’affiche avec la ligne du scénario.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.