BOD-58 WIP For testing classes. No success.

This commit is contained in:
Patrick Fic
2020-03-24 11:27:30 -07:00
parent 7d33484294
commit c095ba68eb
15 changed files with 376 additions and 97 deletions

View File

@@ -4151,6 +4151,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>gotojob</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>manualnew</name>
<definition_loaded>false</definition_loaded>
@@ -7121,6 +7142,48 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>created_subtitle</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>creatednoclick</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>deleted</name>
<definition_loaded>false</definition_loaded>

View File

@@ -1,18 +0,0 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App.container";
import { MockedProvider } from "@apollo/react-testing";
const div = document.createElement("div");
it("renders without crashing", () => {
ReactDOM.render(
<MockedProvider>
<App />
</MockedProvider>,
div
);
});
it("unmounts without crashing", () => {
ReactDOM.unmountComponentAtNode(div);
});

View File

@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Alert component should render Alert component 1`] = `ShallowWrapper {}`;

View File

@@ -6,8 +6,18 @@ import { shallow, mount } from "enzyme";
const div = document.createElement("div");
it("renders without crashing", () => {
const wrapper = mount(<Alert type="error" message="Test Error" />);
console.log("wrapper", wrapper);
// expect(wrapper.children()).to.have.lengthOf(1);
describe("Alert component", () => {
let wrapper;
beforeEach(() => {
const mockProps = {
type: "error",
message: "Test error message."
};
wrapper = shallow(<Alert {...mockProps} />);
});
it("should render Alert component", () => {
expect(wrapper).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AllocationsAssignmentComponent component should create an allocation on save 1`] = `ReactWrapper {}`;
exports[`AllocationsAssignmentComponent component should render AllocationsAssignmentComponent component 1`] = `ReactWrapper {}`;

View File

@@ -9,10 +9,7 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
export default connect(
mapStateToProps,
null
)(function AllocationsAssignmentComponent({
export function AllocationsAssignmentComponent({
bodyshop,
handleAssignment,
assignment,
@@ -30,16 +27,15 @@ export default connect(
const popContent = (
<div>
<Select
<Select id="employeeSelector"
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
placeholder='Select a person'
optionFilterProp='children'
onChange={onChange}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
}>
{bodyshop.employees.map(emp => (
<Select.Option value={emp.id} key={emp.id}>
{`${emp.first_name} ${emp.last_name}`}
@@ -55,10 +51,9 @@ export default connect(
/>
<Button
type="primary"
type='primary'
disabled={!assignment.employeeid}
onClick={handleAssignment}
>
onClick={handleAssignment}>
Assign
</Button>
<Button onClick={() => setVisibility(false)}>Close</Button>
@@ -72,4 +67,6 @@ export default connect(
</Button>
</Popover>
);
});
}
export default connect(mapStateToProps, null)(AllocationsAssignmentComponent);

View File

@@ -0,0 +1,38 @@
import { mount, shallow } from "enzyme";
import React from "react";
import { AllocationsAssignmentComponent } from "./allocations-assignment.component";
import { MockBodyshop } from "../../utils/TestingHelpers";
import { Select } from "antd";
const div = document.createElement("div");
describe("AllocationsAssignmentComponent component", () => {
let wrapper;
beforeEach(() => {
const mockProps = {
bodyshop: MockBodyshop,
handleAssignment: jest.fn(),
assignment: {},
setAssignment: jest.fn(),
visibilityState: [false, jest.fn()],
maxHours: 4
};
wrapper = mount(<AllocationsAssignmentComponent {...mockProps} />);
});
it("should render AllocationsAssignmentComponent component", () => {
expect(wrapper).toMatchSnapshot();
});
it("should render a list of employees", () => {
const empList = wrapper.find("#employeeSelector");
console.log(empList.debug());
expect(empList.children()).to.have.lengthOf(2);
});
it("should create an allocation on save", () => {
wrapper.find("Button").simulate("click");
expect(wrapper).toMatchSnapshot();
});
});

View File

@@ -1,20 +0,0 @@
import React from "react";
import { shallow } from "enzyme";
import AllocationsAssignmentContainer from "./allocations-assignment.container";
describe("LineAllocationsContainer", () => {
let mockRefetch;
let jobLineId;
let wrapper;
beforeEach(() => {
mockRefetch = jest.fn;
jobLineId = "b76e44a8-943f-4c67-b8f4-38d14db8b4b8";
const mockProps = {
refetch: mockRefetch,
jobLineId,
hours: 5
};
shallow(<AllocationsAssignmentContainer {...mockProps} />);
});
});

View File

@@ -348,6 +348,7 @@ export const INSERT_NEW_JOB = gql`
insert_jobs(objects: $job) {
returning {
id
est_number
}
}
}

View File

@@ -1,4 +1,4 @@
import { Button, Steps } from "antd";
import { Button, Steps, Result } from "antd";
import React, { useContext, useState } from "react";
import { useTranslation } from "react-i18next";
import AlertComponent from "../../components/alert/alert.component";
@@ -6,6 +6,7 @@ import JobsCreateJobsInfo from "../../components/jobs-create-jobs-info/jobs-crea
import JobsCreateOwnerInfoContainer from "../../components/jobs-create-owner-info/jobs-create-owner-info.container";
import JobsCreateVehicleInfoContainer from "../../components/jobs-create-vehicle-info/jobs-create-vehicle-info.container";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import { Link } from "react-router-dom";
export default function JobsCreateComponent({ form }) {
const [pageIndex, setPageIndex] = useState(0);
@@ -50,7 +51,7 @@ export default function JobsCreateComponent({ form }) {
)}
{pageIndex < steps.length - 1 && (
<Button
type="primary"
type='primary'
onClick={() => {
form
.validateFields()
@@ -63,13 +64,12 @@ export default function JobsCreateComponent({ form }) {
}
})
.catch(error => console.log("error", error));
}}
>
}}>
Next
</Button>
)}
{pageIndex === steps.length - 1 && (
<Button type="primary" htmlType="submit">
<Button type='primary' htmlType='submit'>
Done
</Button>
)}
@@ -79,43 +79,64 @@ export default function JobsCreateComponent({ form }) {
return (
<div>
<Steps current={pageIndex}>
{steps.map((item, idx) => (
<Step
key={item.title}
title={item.title}
style={{ cursor: "pointer" }}
onClick={() => {
form
.validateFields()
.then(r => {
if (steps[pageIndex].validation) {
setErrorMessage(null);
setPageIndex(idx);
} else {
setErrorMessage(steps[pageIndex].error);
}
})
.catch(error => console.log("error", error));
}}
/>
))}
</Steps>
<ProgressButtons />
{errorMessage ? (
{state.created ? (
<div>
<AlertComponent message={errorMessage} type="error" />
<Result
status='success'
title={t("jobs.successes.creatednoclick")}
subTitle={t("jobs.successes.created_subtitle", {
est_number: state.newJobEstNum
})}
extra={[
<Link to={`/manage/jobs/${state.newJobId}`} key='gotojob'>
<Button type='primary'>{t("jobs.actions.gotojob")}</Button>
</Link>,
<Link to={`/manage/jobs/`} key='gotojoblist'>
<Button>{t("menus.header.activejobs")}</Button>
</Link>
]}
/>
</div>
) : null}
) : (
<div>
<Steps current={pageIndex}>
{steps.map((item, idx) => (
<Step
key={item.title}
title={item.title}
style={{ cursor: "pointer" }}
onClick={() => {
form
.validateFields()
.then(r => {
if (steps[pageIndex].validation) {
setErrorMessage(null);
setPageIndex(idx);
} else {
setErrorMessage(steps[pageIndex].error);
}
})
.catch(error => console.log("error", error));
}}
/>
))}
</Steps>
<ProgressButtons />
{steps.map((item, idx) => (
<div key={idx} style={{ display: idx === pageIndex ? "" : "none" }}>
{item.content}
{errorMessage ? (
<div>
<AlertComponent message={errorMessage} type='error' />
</div>
) : null}
{steps.map((item, idx) => (
<div key={idx} style={{ display: idx === pageIndex ? "" : "none" }}>
{item.content}
</div>
))}
<ProgressButtons />
</div>
))}
<ProgressButtons />
)}
</div>
);
}

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import JobsCreateComponent from "./jobs-create.component";
import { Form } from "antd";
import { Form, notification } from "antd";
import JobCreateContext from "./jobs-create.context";
import { useMutation, useLazyQuery } from "@apollo/react-hooks";
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
@@ -8,19 +8,26 @@ import { QUERY_OWNER_FOR_JOB_CREATION } from "../../graphql/owners.queries";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { useTranslation } from "react-i18next";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
export default connect(mapStateToProps, null)(JobsCreateContainer);
function JobsCreateContainer({ bodyshop }) {
const { t } = useTranslation();
const contextState = useState({
vehicle: { new: false, search: "", selectedid: null },
owner: { new: false, search: "", selectedid: null },
job: null
job: null,
created: false,
error: null,
newJobId: null,
newJobEstNum: null
});
const [form] = Form.useForm();
const [state] = contextState;
const [state, setState] = contextState;
const [insertJob] = useMutation(INSERT_NEW_JOB);
const [loadOwner, RemoteOwnerData] = useLazyQuery(
QUERY_OWNER_FOR_JOB_CREATION
@@ -37,7 +44,22 @@ function JobsCreateContainer({ bodyshop }) {
const runInsertJob = job => {
console.log("Job To Save", job);
insertJob({ variables: { job: job } });
insertJob({ variables: { job: job } })
.then(resp => {
setState({
...state,
created: true,
error: null,
newJobId: resp.data.insert_jobs.returning[0].id,
newJobEstNum: resp.data.insert_jobs.returning[0].est_number
});
})
.catch(error => {
notification["error"]({
message: t("jobs.errors.creating", { error: error })
});
setState({ ...state, error: error });
});
};
const handleFinish = values => {

View File

@@ -306,6 +306,7 @@
"addNote": "Add Note",
"changestatus": "Change Status",
"convert": "Convert",
"gotojob": "Go to Job",
"manualnew": "Create New Job Manually",
"postInvoices": "Post Invoices",
"printCenter": "Print Center",
@@ -458,6 +459,8 @@
"all_deleted": "{{count}} jobs deleted successfully.",
"converted": "Job converted successfully.",
"created": "Job created successfully. Click to view.",
"created_subtitle": "Estimate Number {{est_number}} has been created.",
"creatednoclick": "Job created successfully. ",
"deleted": "Job deleted successfully.",
"save": "Job saved successfully.",
"savetitle": "Record saved successfully.",

View File

@@ -306,6 +306,7 @@
"addNote": "Añadir la nota",
"changestatus": "Cambiar Estado",
"convert": "Convertir",
"gotojob": "",
"manualnew": "",
"postInvoices": "Contabilizar facturas",
"printCenter": "Centro de impresión",
@@ -458,6 +459,8 @@
"all_deleted": "{{count}} trabajos eliminados con éxito.",
"converted": "Trabajo convertido con éxito.",
"created": "Trabajo creado con éxito. Click para ver.",
"created_subtitle": "",
"creatednoclick": "",
"deleted": "Trabajo eliminado con éxito.",
"save": "Trabajo guardado con éxito.",
"savetitle": "Registro guardado con éxito.",

View File

@@ -306,6 +306,7 @@
"addNote": "Ajouter une note",
"changestatus": "Changer le statut",
"convert": "Convertir",
"gotojob": "",
"manualnew": "",
"postInvoices": "Poster des factures",
"printCenter": "Centre d'impression",
@@ -458,6 +459,8 @@
"all_deleted": "{{count}} travaux supprimés avec succès.",
"converted": "Travail converti avec succès.",
"created": "Le travail a été créé avec succès. Clique pour voir.",
"created_subtitle": "",
"creatednoclick": "",
"deleted": "Le travail a bien été supprimé.",
"save": "Le travail a été enregistré avec succès.",
"savetitle": "Enregistrement enregistré avec succès.",

View File

@@ -0,0 +1,148 @@
export const MockBodyshop = {
address1: "123 Fake St",
address2: "Unit #100",
city: "Vancouver",
country: "Canada",
created_at: "2019-12-10T20:03:06.420853+00:00",
email: "snaptsoft@gmail.com",
federal_tax_id: "GST10150492",
id: "52b7357c-0edd-4c95-85c3-dfdbcdfad9ac",
insurance_vendor_id: "F123456",
logo_img_path: "https://www.snapt.ca/assets/logo-placeholder.png",
md_ro_statuses: {
statuses: [
"Open",
"Scheduled",
"Arrived",
"Repair Plan",
"Parts",
"Body",
"Prep",
"Paint",
"Reassembly",
"Sublet",
"Detail",
"Completed",
"Delivered",
"Invoiced",
"Exported"
],
open_statuses: [
"Open",
"Scheduled",
"Arrived",
"Repair Plan",
"Parts",
"Body",
"Prep",
"Paint"
],
default_arrived: "Arrived",
default_exported: "Exported",
default_imported: "Open",
default_invoiced: "Invoiced",
default_completed: "Completed",
default_delivered: "Delivered",
default_scheduled: "Scheduled"
},
md_order_statuses: {
statuses: ["Ordered", "Received", "Canceled", "Backordered"],
default_bo: "Backordered",
default_ordered: "Ordered",
default_canceled: "Canceled",
default_received: "Received"
},
shopname: "Testing Collision",
state: "BC",
state_tax_id: "PST1000-2991",
updated_at: "2020-03-23T22:06:03.509544+00:00",
zip_post: "V6B 1M9",
region_config: "CA_BC",
md_responsibility_centers: {
costs: [
"Aftermarket",
"ATP",
"Body",
"Detail",
"Daignostic",
"Electrical",
"Chrome",
"Frame",
"Mechanical",
"Refinish",
"Structural",
"Existing",
"Glass",
"LKQ",
"OEM",
"OEM Partial",
"Re-cored",
"Remanufactured",
"Other",
"Sublet",
"Towing"
],
profits: [
"Aftermarket",
"ATP",
"Body",
"Detail",
"Daignostic",
"Electrical",
"Chrome",
"Frame",
"Mechanical",
"Refinish",
"Structural",
"Existing",
"Glass",
"LKQ",
"OEM",
"OEM Partial",
"Re-cored",
"Remanufactured",
"Other",
"Sublet",
"Towing"
],
defaults: {
ATP: "ATP",
LAB: "Body",
LAD: "Diagnostic",
LAE: "Electrical",
LAF: "Frame",
LAG: "Glass",
LAM: "Mechanical",
LAR: "Refinish",
LAS: "Structural",
LAU: "Detail",
PAA: "Aftermarket",
PAC: "Chrome",
PAL: "LKQ",
PAM: "Remanufactured",
PAN: "OEM",
PAO: "Other",
PAP: "OEM Partial",
PAR: "16",
TOW: "Towing"
}
},
employees: [
{
id: "075b744c-8919-49ca-abb2-ccd51040326d",
first_name: "Patrick",
last_name: "BODY123",
employee_number: "101",
cost_center: "Body",
__typename: "employees"
},
{
id: "8cc787d3-1cfe-49d3-8a15-8469cd5c2e41",
first_name: "Patrick",
last_name: "Painter",
employee_number: "10211",
cost_center: "REFINISH",
__typename: "employees"
}
]
};