scottohara/loot

View on GitHub
cypress/e2e/categories/edit.cy.ts

Summary

Maintainability
A
0 mins
Test Coverage
import {
    DIRECTION_INFLOW,
    DIRECTION_OUTFLOW,
    categoriesTableRows,
    checkRowMatches,
    firstParentCategory,
    firstSubcategory,
    getValuesFrom,
    lastParentCategory,
    lastSubcategory,
} from "~/support/categories/index";
import {
    cancelButton,
    categoryEditForm,
    categoryEditHeading,
    checkFormMatches,
    invalidateForm,
    populateFormWith,
    saveButton,
} from "~/support/categories/edit";
import type { Category } from "~/support/categories/types";

describe("Category Edit", (): void => {
    let expected: Category, originalRowCount: number;

    function commonBehaviour(targetRow: string): void {
        it("should not save changes when the cancel button is clicked", (): void => {
            cy.get(cancelButton).click();
            cy.get(categoryEditForm).should("not.exist");

            // Row count should not have changed
            cy.get(categoriesTableRows).should("have.length", originalRowCount);

            // Category in the target row should not have changed
            cy.get(targetRow).within((row: JQuery<HTMLTableRowElement>): void =>
                checkRowMatches(getValuesFrom(row)),
            );
        });

        describe("invalid data", (): void => {
            beforeEach((): void => invalidateForm());

            it("should not enable the save button", (): Cypress.Chainable<JQuery> =>
                cy.get(saveButton).should("not.be.enabled"));

            // MISSING - category name, parent & direction should show red cross when invalid

            // MISSING - form group around category name & parent should have 'has-error' class when invalid

            // MISSING - parent should behave like non-editable typeahead
        });

        // MISSING - error message should display when present

        // MISSING - category name & parent text should be selected when input gets focus
    }

    beforeEach((): void => {
        cy.login();
        cy.visit("/#!/categories");
        cy.get(categoriesTableRows).then(
            (rows: JQuery<HTMLTableRowElement>): number =>
                (originalRowCount = rows.length),
        );
    });

    describe("adding a category", (): void => {
        before((): void => cy.createCategories());

        beforeEach((): void => {
            cy.get("body").type("{insert}");
            cy.get(categoryEditHeading).should("have.text", "Add Category");
        });

        describe("parent", (): void => {
            describe("expense", (): void => {
                beforeEach((): void => {
                    expected = {
                        direction: DIRECTION_OUTFLOW,
                        name: "ZZZ Test category",
                    };
                    populateFormWith(expected);
                });

                commonBehaviour(lastParentCategory);

                it("should insert a new category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should have incremented by one
                    cy.get(categoriesTableRows).should(
                        "have.length",
                        originalRowCount + 1,
                    );

                    // Category in the last row should be the new category
                    cy.get(lastParentCategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });

            describe("income", (): void => {
                beforeEach((): void => {
                    expected = { direction: DIRECTION_INFLOW, name: "AAA Test category" };
                    populateFormWith(expected);
                });

                commonBehaviour(firstParentCategory);

                it("should insert a new category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should have incremented by one
                    cy.get(categoriesTableRows).should(
                        "have.length",
                        originalRowCount + 1,
                    );

                    // Category in the first row should be the new category
                    cy.get(firstParentCategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });
        });

        describe("subcategory", (): void => {
            describe("expense", (): void => {
                beforeEach((): void => {
                    cy.get(lastParentCategory).then(
                        (row: JQuery<HTMLTableRowElement>): void => {
                            expected = {
                                direction: DIRECTION_OUTFLOW,
                                name: "ZZZ Test subcategory",
                                parent: getValuesFrom(row).name,
                            };
                            populateFormWith(expected);
                        },
                    );
                });

                commonBehaviour(lastParentCategory);

                it("should insert a new category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should have incremented by one
                    cy.get(categoriesTableRows).should(
                        "have.length",
                        originalRowCount + 1,
                    );

                    // Category in the last row should be the new category
                    cy.get(lastSubcategory).within((): void => checkRowMatches(expected));
                });
            });

            describe("income", (): void => {
                beforeEach((): void => {
                    cy.get(firstParentCategory).then(
                        (row: JQuery<HTMLTableRowElement>): void => {
                            expected = {
                                direction: DIRECTION_INFLOW,
                                name: "AAA Test subcategory",
                                parent: getValuesFrom(row).name,
                            };
                            populateFormWith(expected);
                        },
                    );
                });

                commonBehaviour(firstParentCategory);

                it("should insert a new category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should have incremented by one
                    cy.get(categoriesTableRows).should(
                        "have.length",
                        originalRowCount + 1,
                    );

                    // Category in the second row should be the new category
                    cy.get(firstSubcategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });
        });
    });

    function editRow(rowToEdit: string): void {
        cy.get(rowToEdit).click();
        cy.get("body").type("{ctrl}e");
        cy.get(categoryEditHeading).should("have.text", "Edit Category");
        cy.get(rowToEdit).then((row: JQuery<HTMLTableRowElement>): void =>
            checkFormMatches(getValuesFrom(row)),
        );
    }

    describe("editing a category", (): void => {
        before((): void => cy.createCategories());

        describe("parent", (): void => {
            describe("expense", (): void => {
                beforeEach((): void => {
                    expected = {
                        direction: DIRECTION_INFLOW,
                        name: "AA Test category (edited)",
                        favourite: true,
                    };
                    editRow(lastParentCategory);
                    populateFormWith(expected);
                });

                commonBehaviour(lastParentCategory);

                it("should update an existing category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should not have changed
                    cy.get(categoriesTableRows).should("have.length", originalRowCount);

                    // After editing, the row should now be the first category
                    cy.get(firstParentCategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });

            describe("income", (): void => {
                beforeEach((): void => {
                    expected = {
                        direction: DIRECTION_OUTFLOW,
                        name: "ZZZ Test category (edited)",
                        favourite: true,
                    };
                    editRow(firstParentCategory);
                    populateFormWith(expected);
                });

                commonBehaviour(firstParentCategory);

                it("should update an existing category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should not have changed
                    cy.get(categoriesTableRows).should("have.length", originalRowCount);

                    // After editing, the row should now be the last category
                    cy.get(lastParentCategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });
        });

        describe("subcategory", (): void => {
            describe("income", (): void => {
                beforeEach((): void => {
                    cy.get(lastParentCategory).then(
                        (row: JQuery<HTMLTableRowElement>): void => {
                            expected = {
                                direction: DIRECTION_OUTFLOW,
                                name: "ZZZ Test subcategory (edited)",
                                parent: getValuesFrom(row).name,
                            };
                            editRow(firstSubcategory);
                            populateFormWith(expected);
                        },
                    );
                });

                commonBehaviour(firstSubcategory);

                it("should update an existing category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should not have changed
                    cy.get(categoriesTableRows).should("have.length", originalRowCount);

                    // After editing, the row should now be the last row
                    cy.get(lastSubcategory).within((): void => checkRowMatches(expected));
                });
            });

            describe("expense", (): void => {
                beforeEach((): void => {
                    cy.get(firstParentCategory).then(
                        (row: JQuery<HTMLTableRowElement>): void => {
                            expected = {
                                direction: DIRECTION_INFLOW,
                                name: "AAA Test subcategory (edited)",
                                parent: getValuesFrom(row).name,
                            };
                            editRow(lastSubcategory);
                            populateFormWith(expected);
                        },
                    );
                });

                commonBehaviour(lastSubcategory);

                it("should update an existing category when the save button is clicked", (): void => {
                    cy.get(saveButton).click();
                    cy.get(categoryEditForm).should("not.exist");

                    // Row count should not have changed
                    cy.get(categoriesTableRows).should("have.length", originalRowCount);

                    // After editing, the row should now be the second row
                    cy.get(firstSubcategory).within((): void =>
                        checkRowMatches(expected),
                    );
                });
            });
        });
    });
});