import moment from "moment"; import job2 from "../../fixtures/jobs/job-4.json"; import Dinero from "dinero.js"; const uuid = () => Cypress._.random(0, 1e6); describe( "Entering payment for the job", { defaultCommandTimeout: 5000, }, () => { const today = moment().format("YYYY-MM-DD"); const LABOR_HOURS = 1; const COST_CENTER = "Body"; beforeEach(() => { cy.intercept("POST", Cypress.env("graphql_dev_endpoint"), (req) => { if (req.body.operationName === "QUERY_ACTIVE_EMPLOYEES") { req.alias = "employees"; } }); cy.intercept("POST", Cypress.env("graphql_dev_endpoint"), (req) => { if (req.body.operationName === "QUERY_BODYSHOP") { req.alias = "bodyshop"; } }); cy.visit("/manage"); cy.get('[data-cy="active-jobs-table"]') .find(".ant-table-tbody") .find("> tr:not(.ant-table-measure-row)") .as("active-jobs-table") .should("not.have.class", "ant-table-placeholder"); cy.get("@active-jobs-table") .contains(job2.clm_no) .first() .parent() .find('[data-cy="active-job-link"]') .click(); cy.url().should("include", "/manage/jobs"); }); it("checks input validations", () => { cy.get('[data-cy="job-actions-button"]').click(); cy.get('[data-cy="actions-timetickets"]') .should("be.visible") .and("not.be.disabled") .click(); cy.get('[data-cy="timeticket-save-button"]').first().click(); cy.get('[data-cy="form-timeticket"]') .find(".ant-form-item-explain-error") .should("have.length", 4); cy.get('[data-cy="form-timeticket-date"]').click(); cy.get(`[title="${today}"]`).should("be.visible").click({ force: true }); cy.antdSelect("timeticket-employee"); cy.antdSelect("cost-center"); cy.get('[data-cy="labor-allocations-table"]') .find(".ant-table-tbody") .find("> tr:not(.ant-table-measure-row)") .as("labor-allocations") .should("not.have.class", "ant-table-placeholder"); cy.get("@labor-allocations") .eq(0) .find("td:not(.ant-table-selection-column)") .eq(4) .find("strong") .invoke("text") .as("bodyDiff") .then((diff) => { // TODO dynamically select the employee prior to what is the labor and cost cy.get('[data-cy="form-timeticket-productivehrs"]').type( Number(diff) + 1 ); cy.get(".ant-form-item-explain-error").should( "have.text", "The number of hours entered is more than what is available for this cost center." ); }); }); it("adds new time ticket to a job with flat rate", () => { cy.get('[data-cy="job-actions-button"]').click(); cy.get('[data-cy="actions-timetickets"]') .should("be.visible") .and("not.be.disabled") .click(); cy.get('[data-cy="labor-allocations-table"]') .find(".ant-table-tbody") .find("> tr:not(.ant-table-measure-row)") .as("labor-allocations") .should("not.have.class", "ant-table-placeholder"); // Get Difference for Body cy.get('[data-cy="form-timeticket-date"]').click(); cy.get(`[title="${today}"]`).should("be.visible").click(); cy.get("@labor-allocations") .eq(0) .find("td:not(.ant-table-selection-column)") .eq(4) .find("strong") .invoke("text") .as("bodyDiff") .then((diff) => { cy.get('[data-cy="form-timeticket-productivehrs"]').type(LABOR_HOURS); cy.get('[data-cy="form-timeticket-actualhrs"]').type(LABOR_HOURS); }); cy.wait("@employees").then(({ response }) => { const employees = response.body.data.employees; const employee = employees.find((e) => e.flat_rate); const employee_name = `${employee.first_name} ${employee.last_name}`; cy.antdSelectValue("timeticket-employee", employee_name); cy.antdSelectValue("cost-center", COST_CENTER); }); cy.get('[data-cy="form-timeticket-memo"]').type(uuid()); cy.get('[data-cy="timeticket-save-button"]').first().click(); cy.get(".ant-notification-notice-message").contains( "Time ticket entered successfully." ); }); it("adds new time ticket to a job with straight rate", () => { cy.get('[data-cy="job-actions-button"]').click(); cy.get('[data-cy="actions-timetickets"]') .should("be.visible") .and("not.be.disabled") .click(); cy.get('[data-cy="labor-allocations-table"]') .find(".ant-table-tbody") .find("> tr:not(.ant-table-measure-row)") .as("labor-allocations") .should("not.have.class", "ant-table-placeholder"); // Get Difference for Body cy.get('[data-cy="form-timeticket-date"]').click(); cy.get(`[title="${today}"]`).should("be.visible").click(); cy.get("@labor-allocations") .eq(0) .find("td:not(.ant-table-selection-column)") .eq(4) .find("strong") .invoke("text") .as("bodyDiff") .then((diff) => { cy.get('[data-cy="form-timeticket-productivehrs"]').type(LABOR_HOURS); cy.get('[data-cy="form-timeticket-actualhrs"]').type(LABOR_HOURS); }); cy.wait("@employees").then(({ response }) => { const employees = response.body.data.employees; const employee = employees.find((e) => !e.flat_rate); const employee_name = `${employee.first_name} ${employee.last_name}`; cy.antdSelectValue("timeticket-employee", employee_name); cy.antdSelectValue("cost-center", COST_CENTER); }); cy.get('[data-cy="form-timeticket-memo"]').type(uuid()); cy.get('[data-cy="timeticket-save-button"]').first().click(); cy.get(".ant-notification-notice-message").contains( "Time ticket entered successfully." ); }); it("checks hours calculated to the allocations table", () => { cy.get('[data-cy="tab-labor"]').should("be.visible").click(); cy.get('[data-cy="labor-allocations-table"]') .find(".ant-table-tbody") .find("> tr:not(.ant-table-measure-row)") .as("labor-allocations") .should("not.have.class", "ant-table-placeholder"); cy.get('[data-cy="labor-total-hrs-claimed"]') .invoke("text") .then((hours) => { cy.wrap(hours).should("not.equal", "0"); }); }); it("checks the job costing calculations", () => { cy.get('[data-cy="job-actions-button"]').click(); cy.get('[data-cy="actions-jobcosting"]') .should("be.visible") .and("not.be.disabled") .click(); cy.wait("@bodyshop").then(({ request }) => { const token = request.headers.authorization; const query = `query QUERY_ACTIVE_EMPLOYEES { employees(where: { active: { _eq: true } }) { last_name id first_name employee_number active termination_date hire_date flat_rate rates pin user_email } }`; cy.request({ url: "http://localhost:4000/test/query", method: "POST", headers: { "Content-Type": "application/json", Authorization: token, }, body: { query, }, }).then((response) => { const cost_center = COST_CENTER; const employees = response.body.employees; const total_cost = employees.reduce((prev, employee) => { const rate = employee.rates.find((rate) => rate.cost_center === cost_center) .rate ?? 0; return prev + rate * LABOR_HOURS; }, 0); cy.get('[data-cy="responsibilitycenter"]') .contains(cost_center) .parent() .parent() .find('[data-cy="cost"]') .should( "have.text", Dinero({ amount: total_cost, precision: 0, }).toFormat() ); }); }); }); it.only("clocks in and out of the tech page for the timeticket", () => { // TODO go to tech page for the clock in and out cy.visit("/tech"); cy.get('[data-cy="tech-employee-id"]').type("a"); cy.get('[data-cy="tech-employee-password"]').type("a{enter}"); cy.contains("Logged in as"); // go to clock in cy.get('[data-cy="sider-joblock"]').click({ force: true }); // find the job ro cy.get('[data-cy="clock-ro-select"]').type("273"); cy.get('[data-cy="clock-ro-select"] .ant-select-selection-search input') .invoke("attr", "id") .then((selElm) => { const dropDownSelector = `#${selElm}_list`; cy.get(dropDownSelector) .next() .find(".ant-select-item-option-content") .first() .click({ force: true }); }); // select cost center cy.get('[data-cy="clock-cost-center-select"]').click(); cy.get( '[data-cy="clock-cost-center-select"] .ant-select-selection-search input' ) .invoke("attr", "id") .then((selElm) => { const dropDownSelector = `#${selElm}_list`; cy.get(dropDownSelector) .next() .find(".ant-select-item-option-content") .contains("Body") .first() .click({ force: true }); }); // clock in and out of the job }); } );