emilepharand/Babilonia

View on GitHub
tests/e2e/specs/languages.cy.ts

Summary

Maintainability
A
40 mins
Test Coverage
function clickSave() {
    cy.get('#save-languages-button').click();
}

context('Valid inputs in the language page', () => {
    specify('Adding languages works and the page updates', () => {
        cy.get('#languages-link').click();
        // Add three languages
        for (let i = 0; i < 3; i++) {
            const languageName = `Language ${i}`;
            addLanguage(languageName);
            // Check that language table has updated
            cy.get('.languages-table')
                .find('.language-row').should('have.length', i + 1);
            // Default ordering is last available, default isPractice is false
            checkLanguageRowHasValues(i, languageName, i.toString(), false);
        }

        // Edit languages configuration
        for (let i = 0; i < 3; i++) {
            const languageName = `Modified language ${i}`;
            inputLanguageChange(i, languageName, (2 - i).toString(), true);
        }
        clickSave();
        cy.get('#languages-saved-text').should('be.visible');
        cy.reload();
        checkLanguageRowHasValues(0, 'Modified language 2', '0', true);
        checkLanguageRowHasValues(1, 'Modified language 1', '1', true);
        checkLanguageRowHasValues(2, 'Modified language 0', '2', true);

        // Test delete modal focus
        cy.get('.languages-table').find('.language-row')
            .eq(0)
            .find('.delete-language-button')
            .click();
        cy.get('#modal-cancel-button')
            .should('be.focused')
            .type('{rightArrow}');
        cy.get('#modal-delete-button')
            .should('be.focused')
            .type('{leftArrow}');
        cy.get('#modal-cancel-button')
            .should('be.focused')
            .click();

        // Delete languages one by one
        deleteLanguage(1, true);
        cy.get('.languages-table').find('.language-row').should('have.length', 3);
        deleteLanguage(1);
        cy.get('.languages-table').find('.language-row').should('have.length', 2);
        checkLanguageRowHasValues(0, 'Modified language 2', '0', true);
        checkLanguageRowHasValues(1, 'Modified language 0', '1', true);
        deleteLanguage(0);
        cy.get('.languages-table').find('.language-row').should('have.length', 1);
        checkLanguageRowHasValues(0, 'Modified language 0', '0', true);
        deleteLanguage(0);
        cy.get('.languages-table').should('not.exist');
    });
});

context('Interactivity', () => {
    specify('Input focusing', () => {
        cy.get('#languages-link').click();

        getNewLanguageNameInput()
            .should('be.focused')
            .type('fr')
            .type('{enter}');

        checkLanguageRowHasValues(0, 'fr', '0', false);

        getNewLanguageNameInput()
            .should('be.focused');

        inputLanguageChange(0, 'en', '0', true);

        getNewLanguageNameInput()
            .should('not.be.focused');
    });
});

context('Error handling on the language page', () => {
    specify('Adding/editing with invalid input', () => {
        cy.get('#languages-link').click();

        // Empty name
        addLanguage('');
        assertAddLanguageErrorMsgVisible('valid language');
        assertSaveLanguagesErrorMsgNotVisible();
        // Valid language
        addLanguage('Valid language');
        assertAddLanguageErrorMsgNotVisible();
        assertSaveLanguagesErrorMsgNotVisible();
        // Blank name
        addLanguage(' ');
        assertAddLanguageErrorMsgVisible('valid language');
        assertSaveLanguagesErrorMsgNotVisible();
        // Valid language
        addLanguage('Valid language 2');
        assertAddLanguageErrorMsgNotVisible();
        assertSaveLanguagesErrorMsgNotVisible();
        // Duplicate name
        addLanguage('Valid language');
        assertAddLanguageErrorMsgVisible('already exists');
        assertSaveLanguagesErrorMsgNotVisible();

        // Blank name
        inputLanguageChange(0, '', '0', true);
        clickSave();
        assertSaveLanguageErrorMsgVisible('blank');
        assertAddLanguageErrorMsgNotVisible();
        // Blank ordering
        inputLanguageChange(0, 'any language', '', true);
        clickSave();
        assertSaveLanguageErrorMsgVisible('ordering');
        assertAddLanguageErrorMsgNotVisible();

        // Cannot write non-digit in ordering
        cy.get('.languages-table').find('.language-row').eq(0).within(() => {
            cy.get('.language-ordering').clear();
            cy.get('.language-ordering').type('a');
        });
        cy.get('.languages-table').find('.language-row')
            .eq(0).find('.language-ordering')
            .should('be.empty');

        // Wrong ordering
        inputLanguageChange(0, 'any language 1', '0', true);
        inputLanguageChange(1, 'any language 2', '2', true);
        clickSave();
        assertSaveLanguageErrorMsgVisible('ordering');
        assertAddLanguageErrorMsgNotVisible();

        // Duplicate language names
        inputLanguageChange(1, 'any language 1', '1', true);
        clickSave();
        assertSaveLanguageErrorMsgVisible('duplicate');
        assertAddLanguageErrorMsgNotVisible();
    });
});

function getNewLanguageNameInput() {
    return cy.get('#new-language-name');
}

function addLanguage(name: string) {
    getNewLanguageNameInput().clear();
    if (name !== '') {
        getNewLanguageNameInput().type(name);
    }
    cy.get('#add-language-button').click();
}

function deleteLanguage(rowNbr: number, cancel: boolean = false) {
    cy.get('#confirm-delete-modal').should('not.be.visible');
    cy.get('.languages-table').find('.language-row').eq(rowNbr)
        .find('.delete-language-button').click();
    cy.get('#confirm-delete-modal').should('be.visible');
    // eslint-disable-next-line cypress/no-unnecessary-waiting
    cy.wait(500).get(cancel ? '#modal-cancel-button' : '#modal-delete-button').click();
    cy.get('#confirm-delete-modal').should('not.be.visible');
}

function assertAddLanguageErrorMsgNotVisible() {
    cy.get('#error-add-language-text').should('not.exist');
}

function assertSaveLanguagesErrorMsgNotVisible() {
    cy.get('#error-save-text').should('not.exist');
}

function assertAddLanguageErrorMsgVisible(containsText: string) {
    cy.get('#error-add-language-text')
        .should('be.visible')
        .should('contain.text', containsText);
}

function assertSaveLanguageErrorMsgVisible(containsText: string) {
    cy.get('#error-save-text')
        .should('be.visible')
        .should('contain.text', containsText);
}

function inputLanguageChange(rowNbr: number, name: string, ordering: string, isPractice: boolean) {
    cy.get('.languages-table').find('.language-row').eq(rowNbr).within(() => {
        cy.get('.language-name').clear();
        cy.get('.language-ordering').clear();
        cy.get('.language-name').type(name);
        cy.get('.language-ordering').type(ordering.toString());
        if (isPractice) {
            cy.get('.language-is-practice').check();
        } else {
            cy.get('.language-is-practice').uncheck();
        }
    });
}

function checkLanguageRowHasValues(rowNbr: number, name: string, ordering: string, isPractice: boolean) {
    cy.get('.languages-table').find('.language-row')
        .eq(rowNbr).find('.language-name')
        .should('have.value', name);
    cy.get('.languages-table').find('.language-row')
        .eq(rowNbr).find('.language-ordering')
        .should('have.value', ordering);
    cy.get('.languages-table').find('.language-row')
        .eq(rowNbr).find('.language-is-practice')
        .should(isPractice ? 'be.checked' : 'not.be.checked');
}