dbmedialab/reader-critics

View on GitHub
src/test/frontend/ArticleEditForm/FormReset.test.js

Summary

Maintainability
A
0 mins
Test Coverage
//
// LESERKRITIKK v2 (aka Reader Critics)
// Copyright (C) 2017 DB Medialab/Aller Media AS, Oslo, Norway
// https://github.com/dbmedialab/reader-critics/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//

/* eslint-disable indent */

const assert = require('assert');

const {
    isObject,
    isString,
} = require('lodash');

const {
    openPage,
} = require('../test-tools-frontend');

const timeToWait = 5000;

// CSS selectors for the various probed elements

const elArticle = 'article#article-el-4';

const elContent = `${elArticle} header div p span`;
const elContentDel = `${elArticle} header div p del`;
const elContentIns = `${elArticle} header div p ins`;
const elFeedbackForm = `${elArticle} form`;
const elTextArea = `${elFeedbackForm} fieldset.text textarea`;
const elCommentArea = `${elFeedbackForm} fieldset.comment textarea`;

const elEditBtn = `${elArticle} footer .button.edit`;
const elResetBtn = `${elArticle} footer .button.reset`;

const elFormSaveBtn = `${elFeedbackForm} fieldset a.button.save`;
const elFormCancelBtn = `${elFeedbackForm} fieldset a.button.cancel`;

// Some text snippets for display and input fields

const expectedText = 'Det er alt som trengs.';
const changedText = 'Det er alt lorem ipsum dolor.';
const userComment = 'Here be some comment';

const changedDiffyText = 'Det er alt';
const changedDiffyTextDeleted = 'som trengs.';
const changedDiffyTextInserted = 'lorem ipsum dolor.';

describe('ArticleEditForm Reset Tests', () => {
    let thePage;
    let originalText;

    // Set up the test page and extract some of the text values for
    // later use. The test case was split up into before() and it(..)
    // because Nightwatch evaluates the complete function chain inside
    // a testcase before actually executing it. This means that
    //
    //  let cyaLater;
    //  browser.url('http://something')
    //  .getValue('#elem', (res) => { cyaLater = res.value })
    //  .doSomethingElse()
    //  .assert.value('#elem', cyaLater);
    //
    // will not work. By the time reference to the variable "cyaLater"
    // is evaluated, it is still undefined. Only when the test then gets
    // executed, the variable will be set. Chicken and egg problem.
    //
    // Workaround? Split up the test case. Another workaround is to use
    // .perform() functions for these "late evaluations", but that blows
    // up the code.

    before((browser, done) => {
        thePage = openPage(browser, '/fb?articleURL=https://www.dagbladet.no&version=1')

        // Wait for elements to render
        .waitForElementVisible('body', timeToWait)
        .waitForElementVisible('div#app section#content', timeToWait)
        .waitForElementVisible('section#content > article.title', timeToWait)

        // Ensure we're addressing the right container. Remember that
        // containsText() is a substring match! strictEquals has to be done manually.
        .assert.containsText(elContent, expectedText)

        // Save current element text for later comparism
        .getText(elContent, (result) => {
            if (!(isObject(result) && isString(result.value))) {
                assert.fail(null, null, 'Could not get text content from ArticleElement');
                return;
            }

            originalText = result.value;
        })
        .perform(() => done());
    });

    after((browser, done) => browser.end().perform(() => done()));

    // Check if clicking on "Edit" opens the <ArticleEditForm>

    it('should become visible when clicking the "Edit" button', (browser) => {
        // Click on the "Edit" button and check if <ArticleEditForm>
        // and the sub components become visible
        thePage.click(elEditBtn)
        .waitForElementVisible(elFeedbackForm, timeToWait)
        .waitForElementVisible(elTextArea, timeToWait)
        .waitForElementVisible(elCommentArea, timeToWait)

        // Check if <ArticleEditForm> and the sub components have become visible,
        // also if the "text" field contains the same text as its parent component
        .assert.visible(elFeedbackForm)
        .assert.value(elTextArea, originalText);
    });

    // Check if the text components keep their input.
    // Form elements in React can be set up in a way that makes them read-only
    // (for example, declaring them with value=this.state.some)

    it('should accept and keep user input', (browser) => {
        // Focus comment field and type some text into it
        thePage.click(elCommentArea)
        .setValue(elCommentArea, userComment)

        // Change the content of the text field
        .click(elTextArea)
        .clearValue(elTextArea)
        .setValue(elTextArea, changedText)

        // Click outside the form to remove focus from the text fields
        .click(elContent)

        // Check if the input fields have kept the values that we just fed them
        .assert.value(elCommentArea, userComment)
        .assert.value(elTextArea, changedText);
    });

    // Check if "Cancel" button works properly. It should close the form
    // without text diff

    it('should close form without accepting text diff', (browser) => {
        // Click "Cancel" button
        thePage.click(elFormCancelBtn)
        .waitForElementNotVisible(elFeedbackForm, timeToWait)

        // Check if the form becomes hidden
        .assert.hidden(elFeedbackForm)

        // Check for the diff. The weird word order comes from the diff package,
        // which currently performs a word-wise diff. This might be changed into
        // a sentence-diff, or at least something that respects consecutive words.
        .assert.containsText(elContent, originalText);
    });

    // Check if the text components can keep their input again on the second form show.
    // Form elements in React can be set up in a way that makes them read-only
    // (for example, declaring them with value=this.state.some)

    it('should accept and keep user input again on the second form show', (browser) => {
        // Click on the "Edit" button and check if <ArticleEditForm>
        // and the sub components become visible
        thePage.click(elEditBtn)
        .waitForElementVisible(elFeedbackForm, timeToWait)
        .waitForElementVisible(elTextArea, timeToWait)
        .waitForElementVisible(elCommentArea, timeToWait);

        // Focus comment field and type some text into it
        thePage.click(elCommentArea)
        .clearValue(elCommentArea)
        .setValue(elCommentArea, userComment)

        // Change the content of the text field
        .click(elTextArea)
        .clearValue(elTextArea)
        .setValue(elTextArea, changedText)

        // Click outside the form to remove focus from the text fields
        .click(elContent)

        // Check if the input fields have kept the values that we just fed them
        .assert.value(elCommentArea, userComment)
        .assert.value(elTextArea, changedText);
    });

    // Check if the form closes after clicking "Safe"
    // A text diff should appear on its parent component

    it('should close the form and display a text diff', (browser) => {
        // Click "Save" button
        thePage.click(elFormSaveBtn)
        .waitForElementNotVisible(elFeedbackForm, timeToWait)

        // Check if the form becomes hidden
        .assert.hidden(elFeedbackForm)

        // Check for the diff. The weird word order comes from the diff package,
        // which currently performs a word-wise diff. This might be changed into
        // a sentence-diff, or at least something that respects consecutive words.
        .assert.containsText(elContent, changedDiffyText)
        .assert.containsText(elContentDel, changedDiffyTextDeleted)
        .assert.containsText(elContentIns, changedDiffyTextInserted);
    });

    // Check if the data in form is the same we entered before on next open
    // of the <ArticleEditForm>.

    it('should open the form and display a text entered before', (browser) => {
        // Click "Edit" button
        thePage.click(elEditBtn)
        .waitForElementVisible(elFeedbackForm, timeToWait)

        // Check if the form becomes visible
        .assert.visible(elFeedbackForm)

        // Check if the fields contain exactly that text we had entered
        .assert.value(elCommentArea, userComment)
        .assert.value(elTextArea, changedText)

        // Click "Cancel" button
        .click(elFormCancelBtn)
        .waitForElementNotVisible(elFeedbackForm, timeToWait);
    });

    // Check if the form is reset to its original values correctly when
    // clicking the "Reset" button

    it('should reset properly', (browser) => {
        // Click "Reset" button, check for original text, then re-open <ArticleEditForm>
        thePage.click(elResetBtn)
        .assert.hidden(elFeedbackForm)
        .assert.containsText(elContent, originalText)

        // Click on "Edit" to re-open the feedback form
        .click(elEditBtn)
        .waitForElementVisible(elFeedbackForm, timeToWait)

        .assert.value(elTextArea, originalText);
    });
});