Importação de modelo ou componente de um plugin em um plugin customizado: falha nos testes

Olá,
Estamos usando o Discourse versão 3.5.0.
Temos nosso próprio plugin no qual substituímos vários elementos do Discourse e adicionamos nossas próprias funcionalidades.

Neste plugin, queremos adicionar o ícone de adição de um evento na barra de ferramentas do composer. Para fazer isso, precisamos importar:

  • o modelo DiscoursePostEventEvent que está em plugins/discourse-calendar/assets/javascripts/discourse/models/discourse-post-event-event.js

  • o componente PostEventBuilder que está em plugins/discourse-calendar/assets/javascripts/discourse/components/modal/post-event-builder.js

Além disso, escrevemos testes de integração para nossas funcionalidades que colocamos em nosso plugin no diretório /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");
  });
});

Conseguimos fazer o que queremos, mas os testes falham independentemente do método de importação.

Importação no topo do arquivo

Quando importamos nosso modelo e componente usando o método import no topo do arquivo:

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";

Tudo corre bem na execução, mas quando executamos nosso teste, ele não é executado.

Require no topo do arquivo

Quando importamos nosso modelo e componente usando o método require no topo do arquivo:

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;

Tudo corre bem na execução, mas quando executamos nosso teste, ele não é executado.

Isso produz o mesmo resultado que com import.

Require no corpo do arquivo

Quando importamos nosso modelo e componente usando o método require no corpo da função:

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;

  ... Restante do código
}

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

Tudo corre bem na execução, mas quando executamos nosso teste, ele falha.

O modelo não foi encontrado.

Em resumo, gostaríamos de saber como importar modelos, componentes, etc. corretamente de outros plugins para que possamos executar os testes de integração.
Obrigado!

2 curtidas

Olá @Marine

Parece que o problema está nas configurações incorretas usadas no bloco needs.settings do nosso código:

acceptance("Alguns testes", function (needs) {
  needs.settings({
    // Isso não habilitará as configurações corretas, então o plugin de calendário não será carregado e os arquivos que precisamos não estarão disponíveis
    // discourse_post_event_enabled: true, 
    // 
    // Habilitar o calendário resolverá o problema:
    calendar_enabled: true

    our_plugin_enabled: true
  });


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

Bem, isso não é verdade. Como o plugin substitui o formulário de evento, precisamos definir discourse_post_event_enabled como true. Voltando à situação inicial em que a importação em nosso plugin falha.

Alguma ideia?

Ao testar um plugin no qunit, carregamos apenas o JS para aquele plugin específico. Isso ajuda a evitar problemas inesperados quando vários plugins interagem entre si. Também ajuda a garantir que um plugin não se torne inesperadamente dependente de outro.

No seu caso, parece que a interação é deliberada e você sempre espera que seus usuários tenham o discourse-calendar ativado. Nesse caso, você pode adicionar alguma configuração a um arquivo about.json que tornará o JS do discourse-calendar disponível nos testes do seu próprio plugin. Aqui está um exemplo:

^^ neste caso, está adicionando discourse-assign. Para o seu caso, você faria discourse-calendar.

4 curtidas

Obrigado! Eu não sabia sobre about.json e isso resolveu o problema. Agora, cabe a nós recriar um contexto totalmente funcional :wink:

Obrigado novamente!

2 curtidas

Você também pode se interessar por especificações do sistema para testes ponta a ponta. Dessa forma, o teste é executado em um servidor Discourse real, para que você não precise simular todas as requisições de rede para o núcleo e ambos os plugins.

A desvantagem é que eles são muito mais lentos. Portanto, o melhor é manter quaisquer testes unitários/de componentes no qunit, se puder.

2 curtidas

Obrigado pela dica!

Eu me sinto muito mais confortável com especificações de sistema, pois geralmente uso RSpec ou Cucumber para testar meus aplicativos Rails :slight_smile:

Vou ver o que vale a pena testar com QUnit ou RSpec, dependendo do caso de teste.

Por enquanto, consegui reproduzir o bug de frontend que queríamos corrigir, então vou investigar um pouco mais nos testes QUnit.

2 curtidas