Importing a model or component from a plugin into a custom plugin: tests fail

Bonjour,
Nous utilisons Discourse version 3.5.0.
Nous avons notre propre plugin dans lequel nous surchargeons divers éléments de discourse et ajoutons nos propres fonctionnalités.

Dans ce plugin, nous souhaitons notamment ajouter l’icône d’ajout d’un événement dans la barre des outils du composer. Pour ce faire, nous avons besoin d’importer :

  • le modèle DiscoursePostEventEvent qui se situe dans plugins/discourse-calendar/assets/javascripts/discourse/models/discourse-post-event-event.js

  • le composant PostEventBuilder qui se situe dans plugins/discourse-calendar/assets/javascripts/discourse/components/modal/post-event-builder.js

Par ailleurs, nous avons écrit des tests d’intégration pour nos fonctionnalités que nous avons mis dans notre plugin sous le répertoire /test.

import { visit } from "@ember/test-helpers";
import { test } from "qunit";
import { acceptance } from "discourse/tests/helpers/qunit-helpers";

acceptance("TOTO", function (needs) {
  test("coopaname integration - composer", async function (assert) {
    await visit("/");
    assert
      .equal(1, 1, "OK")
  });

});

Nous arrivons à faire ce que nous voulons, mais les tests échouent quelque soit le mode d’import.

Import en tête de fichier

Lorsque nous importons nos modèle et composant via la méthode import en entête de fichier:

import DiscoursePostEventEvent from "discourse/plugins/discourse-calendar/discourse/models/discourse-post-event-event";
import PostEventBuilder from "discourse/plugins/discourse-calendar/discourse/components/modal/post-event-builder";

Tout va bien à l’exécution, mais lorsque nous lançons notre test, il n’est pas exécuté

Require en tête de fichier

Lorsque nous importons nos modèle et composant via la méthode require en entête de fichier:

const DiscoursePostEventEvent = require("discourse/plugins/discourse-calendar/discourse/models/discourse-post-event-event").default;
const PostEventBuilder = require("discourse/plugins/discourse-calendar/discourse/components/modal/post-event-builder".default;

Tout va bien à l’exécution, mais lorsque nous lançons notre test, il n’est pas exécuté

Cela produit la même chose qu’avec import.

Require dans le corps du fichier

Lorsque nous importons nos modèle et composant via la méthode require dans le corps de la fonction :

import { withPluginApi } from "discourse/lib/plugin-api";

function initializeEventBuilder(api) {
  const DiscoursePostEventEvent =
     require("discourse/plugins/discourse-calendar/discourse/models/discourse-post-event-event").default;
  const PostEventBuilder =
     require("discourse/plugins/discourse-calendar/discourse/components/modal/post-event-builder").default;

  ... Suite du code
}

export default {
  name: "add-custom-create-event-button",
  initialize(container) {
    withPluginApi(initializeEventBuilder);
  },
};

Tout va bien à l’exécution, mais lorsque nous lançons notre test, il échoue.

Le modèle n’a pas été trouvé.

Bref, nous voudrions savoir comment importer des modèles, composants etc… correctement depuis d’autres plugins pour qu’on puisse exécuter les tests d’intégration.
Merci !

2 « J'aime »

Bonjour @Marine

Il semble que le problème vienne des mauvais paramètres utilisés dans le bloc needs.settings de notre code :

acceptance("Certains tests", function (needs) {
  needs.settings({
    // Cela n'activera pas les bons paramètres, donc le plugin calendrier ne sera pas chargé, et les fichiers dont nous avons besoin ne seront pas disponibles
    // discourse_post_event_enabled: true, 
    // 
    // Activer le calendrier résoudra le problème :
    calendar_enabled: true

    our_plugin_enabled: true
  });


  test("Le test", async function (assert) {
    await visit("/");
    assert.equal(1, 1);
  });
});

Eh bien, ce n’est pas vrai. Comme le plugin remplace le formulaire d’événement, nous devons définir discourse_post_event_enabled sur true. Retour à la situation initiale où l’importation dans notre plugin échoue.

Une idée ?

Lorsque vous testez un plugin dans qunit, nous ne chargeons que le JS de ce plugin spécifique. Cela permet d’éviter les problèmes inattendus lorsque plusieurs plugins interagissent entre eux. Cela permet également de s’assurer qu’un plugin ne devient pas inopinément dépendant d’un autre.

Dans votre cas, il semble que l’interaction soit délibérée et que vous attendiez toujours que vos utilisateurs aient discourse-calendar activé. Dans ce cas, vous pouvez ajouter une configuration à un fichier about.json qui rendra le JS de discourse-calendar disponible dans les tests de votre propre plugin. Voici un exemple :

^^ dans ce cas, il ajoute discourse-assign. Pour votre cas, vous feriez discourse-calendar.

4 « J'aime »

Merci ! Je ne connaissais pas about.json et cela a résolu le problème. Maintenant, c’est à nous de recréer un contexte entièrement fonctionnel :wink:

Merci encore !

2 « J'aime »

Vous pourriez également être intéressé par les spécifications système pour les tests de bout en bout. De cette façon, le test est exécuté sur un vrai serveur Discourse, vous n’avez donc pas à simuler toutes les requêtes réseau pour le cœur et les deux plugins.

Le revers de la médaille est qu’ils sont beaucoup plus lents. Il est donc préférable de conserver les tests unitaires/composants dans qunit si vous le pouvez.

2 « J'aime »

Merci pour le conseil !

Je suis beaucoup plus à l’aise avec les spécifications système car j’utilise généralement RSpec ou Cucumber pour tester mes applications Rails :slight_smile:

Je vais voir ce qui vaut la peine d’être testé avec QUnit ou RSpec, en fonction du cas de test.

Pour l’instant, j’ai réussi à reproduire le bug frontend que nous voulions corriger, je vais donc creuser un peu plus les tests QUnit.

2 « J'aime »