IO-2327 timetickets validation
This commit is contained in:
@@ -52,10 +52,10 @@ describe(
|
||||
|
||||
// fill out form
|
||||
// data-cy="bill-form-invoice"
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD246-00-"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD246-00-"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
// get table
|
||||
cy.get('[data-cy="bill-line-table"]').each(($row) => {
|
||||
@@ -94,10 +94,10 @@ describe(
|
||||
// Select Line
|
||||
cy.antdSelect("bill-line", "-- Not On Estimate --");
|
||||
// Fill the Form
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD246-01-"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD246-01-"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
// get table
|
||||
cy.get('[data-cy="bill-line-table"]').each(($row) => {
|
||||
@@ -136,10 +136,10 @@ describe(
|
||||
// Select Line
|
||||
cy.antdSelect("bill-line", "-- Not On Estimate --");
|
||||
// Fill the Form
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD246-02-"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD246-02-"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
// get table
|
||||
cy.get('[data-cy="bill-line-table"]').each(($row) => {
|
||||
@@ -287,10 +287,10 @@ describe(
|
||||
.click();
|
||||
|
||||
// fill out form
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD261-0"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD261-0"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
cy.get('[data-cy="bill-form-bill-total"]').type("70.46");
|
||||
cy.get('[data-cy="bill-line-actual-cost"]').type("67.10");
|
||||
@@ -358,10 +358,10 @@ describe(
|
||||
.click();
|
||||
|
||||
// fill out form
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD261-01-"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD261-01-"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
cy.get('[data-cy="bill-form-bill-total"]').type("70.46");
|
||||
cy.get('[data-cy="bill-line-actual-cost"]').type("67.10");
|
||||
@@ -396,10 +396,10 @@ describe(
|
||||
.click();
|
||||
|
||||
// fill out form
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("QBD261-02-"));
|
||||
cy.get('[data-cy="bill-form-invoice"]').type(uniqueId("1QBD261-02-"));
|
||||
|
||||
cy.get("#bill-form-date").click();
|
||||
cy.get('[title="2023-06-30"]').should("be.visible").click();
|
||||
cy.get('[title="2023-07-06"]').should("be.visible").click();
|
||||
|
||||
cy.get('[data-cy="bill-form-bill-total"]').type("70.46");
|
||||
cy.get('[data-cy="bill-line-actual-cost"]').type("67.10");
|
||||
|
||||
137
client/cypress/e2e/time-tickets/time-tickets.cy.js
Normal file
137
client/cypress/e2e/time-tickets/time-tickets.cy.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import random from "lodash/random";
|
||||
import uniqid from "uniqid";
|
||||
import moment from "moment";
|
||||
|
||||
describe(
|
||||
"Entering payment for the job",
|
||||
{
|
||||
defaultCommandTimeout: 5000,
|
||||
},
|
||||
() => {
|
||||
const today = moment().format("YYYY-MM-DD");
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit("/manage");
|
||||
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.text().includes("Login")) {
|
||||
// Log in
|
||||
cy.get('[data-cy="username"]').type("john@imex.dev");
|
||||
cy.get('[data-cy="password"]').type("john123");
|
||||
cy.get('[data-cy="sign-in-button"]').click();
|
||||
}
|
||||
|
||||
cy.get(".ant-table-tbody")
|
||||
.should("be.visible")
|
||||
.find("tr")
|
||||
.should("not.have.class", "ant-table-placeholder");
|
||||
|
||||
cy.get(".ant-table-row")
|
||||
.not(':contains("N/A")')
|
||||
.first()
|
||||
.find("a")
|
||||
.first()
|
||||
.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.get('[data-cy="form-timeticket-employee"]').contains(
|
||||
"bb Emily Appleseed"
|
||||
);
|
||||
cy.antdSelect("cost-center");
|
||||
|
||||
cy.get('[data-cy="labor-allocations-table"]')
|
||||
.find(".ant-table-tbody")
|
||||
.find("> tr:not(.ant-table-measure-row)")
|
||||
.as("orders-table")
|
||||
.should("not.have.class", "ant-table-placeholder");
|
||||
|
||||
cy.get("@orders-table")
|
||||
.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(
|
||||
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.skip("adds new time ticket to a job", () => {
|
||||
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("orders-table")
|
||||
.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("@orders-table")
|
||||
.eq(0)
|
||||
.find("td:not(.ant-table-selection-column)")
|
||||
.eq(4)
|
||||
.find("strong")
|
||||
.invoke("text")
|
||||
.as("bodyDiff")
|
||||
.then((diff) => {
|
||||
const hours = random(diff);
|
||||
const actualHrs = random(hours);
|
||||
|
||||
cy.get('[data-cy="form-timeticket-productivehrs"]').type(
|
||||
hours.toFixed(1)
|
||||
);
|
||||
|
||||
cy.get('[data-cy="form-timeticket-actualhrs"]').type(
|
||||
actualHrs.toFixed(1)
|
||||
);
|
||||
});
|
||||
|
||||
cy.antdSelect("timeticket-employee");
|
||||
cy.get('[data-cy="form-timeticket-employee"]').contains(
|
||||
"bb Emily Appleseed"
|
||||
);
|
||||
cy.antdSelect("cost-center");
|
||||
// cy.get('@bodyDiff').then(diff => {})
|
||||
cy.get('[data-cy="form-timeticket-memo"]').type(uniqid());
|
||||
|
||||
cy.get('[data-cy="timeticket-save-button"]').first().click();
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -56,12 +56,21 @@ Cypress.Commands.add("antdSelect", (selector, filter) => {
|
||||
.invoke("attr", "id")
|
||||
.then((selElm) => {
|
||||
const dropDownSelector = `#${selElm}_list`;
|
||||
cy.get(dropDownSelector)
|
||||
.next()
|
||||
.find(".ant-select-item-option-content")
|
||||
.not(`:contains("${filter}")`)
|
||||
.first()
|
||||
.click();
|
||||
|
||||
if (filter) {
|
||||
cy.get(dropDownSelector)
|
||||
.next()
|
||||
.find(".ant-select-item-option-content")
|
||||
.not(`:contains("${filter}")`)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
} else {
|
||||
cy.get(dropDownSelector)
|
||||
.next()
|
||||
.find(".ant-select-item-option-content")
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"socket.io-client": "^4.6.1",
|
||||
"styled-components": "^5.3.6",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"uniqid": "^5.4.0",
|
||||
"web-vitals": "^2.1.4",
|
||||
"workbox-background-sync": "^6.5.3",
|
||||
"workbox-broadcast-update": "^6.5.3",
|
||||
|
||||
@@ -244,7 +244,9 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("timetickets.actions.enter")}
|
||||
<span data-cy="actions-timetickets">
|
||||
{t("timetickets.actions.enter")}
|
||||
</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="enterpayments"
|
||||
|
||||
@@ -206,6 +206,7 @@ export function LaborAllocationsTable({
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.laborallocations")}>
|
||||
<Table
|
||||
data-cy="labor-allocations-table"
|
||||
columns={columns}
|
||||
rowKey={(record) => `${record.cost_center} ${record.mod_lbr_ty}`}
|
||||
pagination={false}
|
||||
|
||||
@@ -113,7 +113,7 @@ export function TimeTicketModalComponent({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<FormDatePicker />
|
||||
<FormDatePicker data-cy="form-timeticket-date" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="employeeid"
|
||||
@@ -135,6 +135,8 @@ export function TimeTicketModalComponent({
|
||||
|
||||
form.setFieldsValue({ flat_rate: emps && emps.flat_rate });
|
||||
}}
|
||||
data-cy="form-timeticket-employee"
|
||||
className="ant-select-timeticket-employee"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@@ -158,7 +160,11 @@ export function TimeTicketModalComponent({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<CostCenterSelect emps={emps} />
|
||||
<CostCenterSelect
|
||||
emps={emps}
|
||||
data-cy="form-timeticket-cost-center"
|
||||
className="ant-select-cost-center"
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
@@ -235,7 +241,10 @@ export function TimeTicketModalComponent({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={1} />
|
||||
<InputNumber
|
||||
data-cy="form-timeticket-productivehrs"
|
||||
precision={1}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form.Item>
|
||||
@@ -262,7 +271,11 @@ export function TimeTicketModalComponent({
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={1} />
|
||||
<InputNumber
|
||||
data-cy="form-timeticket-actualhrs"
|
||||
min={0}
|
||||
precision={1}
|
||||
/>
|
||||
</Form.Item>
|
||||
{
|
||||
<>
|
||||
@@ -320,7 +333,7 @@ export function TimeTicketModalComponent({
|
||||
}
|
||||
|
||||
<Form.Item label={t("timetickets.fields.memo")} name="memo">
|
||||
<MemoInput />
|
||||
<MemoInput data-cy="form-timeticket-memo" />
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate>
|
||||
{() => (
|
||||
|
||||
@@ -174,7 +174,11 @@ export function TimeTicketModalContainer({
|
||||
footer={
|
||||
<span>
|
||||
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
|
||||
<Button loading={loading} onClick={() => form.submit()}>
|
||||
<Button
|
||||
loading={loading}
|
||||
onClick={() => form.submit()}
|
||||
data-cy="timeticket-save-button"
|
||||
>
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
{timeTicketModal.context && timeTicketModal.context.id ? null : (
|
||||
@@ -196,6 +200,7 @@ export function TimeTicketModalContainer({
|
||||
onFinish={handleFinish}
|
||||
layout="vertical"
|
||||
autoComplete={"off"}
|
||||
data-cy="form-timeticket"
|
||||
form={form}
|
||||
onFinishFailed={() => setEnterAgain(false)}
|
||||
initialValues={
|
||||
@@ -221,7 +226,11 @@ export function TimeTicketModalContainer({
|
||||
<Button onClick={handleCancel}>
|
||||
{t("general.actions.cancel")}
|
||||
</Button>
|
||||
<Button loading={loading} onClick={() => form.submit()}>
|
||||
<Button
|
||||
loading={loading}
|
||||
data-cy="timeticket-save-button"
|
||||
onClick={() => form.submit()}
|
||||
>
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
{timeTicketModal.context && timeTicketModal.context.id ? null : (
|
||||
|
||||
@@ -13075,6 +13075,11 @@ unicode-property-aliases-ecmascript@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8"
|
||||
integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==
|
||||
|
||||
uniqid@^5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-5.4.0.tgz#4e17bfcab66dfe33563411ae0c801f46ef964e66"
|
||||
integrity sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==
|
||||
|
||||
unique-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
||||
|
||||
Reference in New Issue
Block a user