publiclab / PublicLab.Editor

A general purpose, JS/Bootstrap UI framework for rich text posting. An author-friendly, minimal, mobile/desktop interface for creating blog-like content, designed for PublicLab.org

Home Page:https://publiclab.github.io/PublicLab.Editor/examples/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Move all old Jasmine tests to Jest?

jywarren opened this issue · comments

As we're seeing two different tough Jasmine test failures in #741 and #721, I propose we move all our Jasmine tests into Jest (our newer test suite) to bypass this issue.

Most of our tests are quite simple, and will just need some reworking of syntax. Let's discuss and collect resources here.

old Jasmine tests: https://github.com/publiclab/PublicLab.Editor/blob/main/spec/javascripts/

Jest tests: https://github.com/publiclab/PublicLab.Editor/blob/main/test/ui-testing/

Example Jasmine test:

it("counts valid modules and enables publish button", function() {
expect(editor.titleModule.el.find('input').val()).toBe("");
expect(editor.titleModule.valid()).toBe(false);
expect(editor.validate()).toBe(false);
editor.richTextModule.wysiwyg.setMode('markdown');
editor.richTextModule.value(""); // empty it
expect(editor.richTextModule.value()).toBe("");
expect(editor.richTextModule.valid()).toBe(false);
editor.titleModule.value("My title");
editor.richTextModule.value("My content");
expect(editor.validate()).toBe(true);
});

Example Jest test:

test('Adds strong text in rich text mode', async () => {
// switches to wysiwyg mode if it is in markdown mode
if (await page.evaluate(() => $(".woofmark-mode-markdown").is(":disabled"))) {
await page.click('.woofmark-mode-wysiwyg');
}
// clicks on bold button and checks if 'strong text' is added in the editor
await page.waitForSelector('.ple-module-body');
await page.waitForSelector('.wk-wysiwyg');
await page.keyboard.press('Backspace');
await page.click('.woofmark-command-bold');
const stringIsIncluded = await page.evaluate(() => document.querySelector('.wk-wysiwyg').textContent.includes('strong text'));
expect(stringIsIncluded).toBe(true);
// resets the changes by removing the added text
await page.keyboard.press("Backspace");
}, timeout);

Jest documentation: https://jestjs.io/docs/getting-started

So let's start with a simple one. The button tests here:

https://github.com/publiclab/PublicLab.Editor/blob/main/spec/javascripts/button_spec.js

can be moved into its own file; ok, i did this in #744.

The Jest syntax is almost identical in this case. I think we could add this to generate a first-timers-only issue:

  test('publish button gets enabled', () => {
    // Check initially that Publish button is disabled.
    expect($('.ple-publish').prop('disabled')).toBe(true);
    // Add title.
    $('.ple-module-title input').val('A title');
    $('.ple-module-title input').keydown();
    // Check final state of Publish button.
    expect($('.ple-publish').prop('disabled')).toBe(false);
  }, timeout);

For other Jasmine files, we can also create corresponding Jest files with similar names - let's use the camelCase.test.js format. They'd each get something like this when empty, as a first step:

const timeout = process.env.SLOWMO ? 60000 : 10000;
const fs = require('fs');
beforeAll(async () => {
  path = fs.realpathSync('file://../examples/index.html');
  await page.goto('file://' + path, {waitUntil: 'domcontentloaded'});
});

describe('Publish button', () => {
  test('something we are testing described here', () => {

  });
}, timeout);

Ah, and let's not forget, each one could also delete the old test, OR that could be a good "follow-up" issue or PR.

#744 merged! Remember that we dont have to pass the "base tests" which are Jasmine, as those are the stuck ones. We just have to get the newer "ui tests" to pass.

Our first FTO from this process is #745!

https://github.com/publiclab/PublicLab.Editor/blob/main/spec/javascripts/history_spec.js is a good next one to do. Those are all very simple and i believe will copy directly into Jest format.

They can all go into this new file I created: https://github.com/publiclab/PublicLab.Editor/blob/main/test/ui-testing/history.test.js

@jywarren I created an FTO in #746 for the history test. What do you think?

I just wanted to note I'm having a lot of trouble getting the jQuery selectors (or puppeteer equivalents) to work in #749... so this may be a little more complex.

OK, so the tests have to be written in a bit of a weird syntax so this isn't going to be quite as easy:

    const text = await page.evaluate(() => document.body.textContent);
    expect(await page.evaluate('document.querySelector(".ple-publish").getAttribute("disabled")')).toBe(true);

https://jestjs.io/docs/puppeteer

https://stackoverflow.com/questions/56467696/get-the-value-of-html-attributes-using-puppeteer#56467778

@jywarren @TildaDares I think I should be able to move some of the tests. I see that button_spec.js has been set as FTO so can I start with history_spec.js ?
or maybe I should have them listed in my planning issue for the Outreachy internship either way I'm ready to get started!

Hi @NARUDESIGNS thanks for getting in here and sorry for the slow reply. I thought it would be a pretty straightforward thing but as I learned in this PR it seems that the syntax for making direct JS calls into the browser environment is a bit more complex in Jest+Puppeteer, unfortunately: #749

Take a look but once we figure out how they're supposed to be made, converting them all will be pretty easy - even good as FTOs for newcomers! But unfortunately when we tried this the first time we learned that we don't really yet understand how to properly convert them.

I hope we can figure out how to either choose the correct way of doing jQuery selectors in the browser env, OR wrap them in something that gets us into the browser context, OR prefix them with something that makes it work. But I'm worried that the syntax will be long and not very easy to read... Let's work this problem as I think it will unlock the whole testing project for us!

I think we just need to try a bunch of variations until we can see that the test runs correctly and tests the things we're trying to monitor. I think it's best to try getting them running in the commandline rather than continuing to push up new commits to wait for GitHub Actions to run them - that'll make it faster to try lots of different options.

#744 merged! Remember that we dont have to pass the "base tests" which are Jasmine, as those are the stuck ones. We just have to get the newer "ui tests" to pass.

Let me be sure we are on the same page. This only includes the initial template for the file (which all jest files should have, just like you mentioned) but not the actual test cases from the corresponding Jasmine file right?
@jywarren

Yes, well at this point i'm trying to get /any/ jQuery or equivalent selector/assertions to run or pass or even fail!

@jywarren I tried adding

const { JSDOM } = require("jsdom");
const myJSDom = new JSDOM ('html');
const $ = require('jquery')(myJSDom.window);

at the top of the test file, which I learnt about from - this conversation
and it stopped complaining about the "$" symbol but the test now fails. Have a look at this screenshot

Screenshot 2021-12-08 at 08 58 32

Hey @NARUDESIGNS @jywarren @TildaDares , can I help you guys too, I do not know much about testing but I know javascript and I am willing to learn, contribute and help, is there something I can do ?
Thanks

Solved in #818!!!