348 lines
11 KiB
TypeScript
348 lines
11 KiB
TypeScript
describe("Customer Form", () => {
|
|
beforeEach(() => {
|
|
// Authenticate via API and set cookies
|
|
cy.login()
|
|
|
|
// Intercept lookup APIs with fixture data
|
|
cy.fixture("customers").then((data) => {
|
|
cy.intercept("GET", "**/api/referral-sources", {
|
|
statusCode: 200,
|
|
body: data.referral_sources,
|
|
}).as("getReferralSources")
|
|
|
|
cy.intercept("GET", "**/api/payment-terms", {
|
|
statusCode: 200,
|
|
body: data.payment_terms,
|
|
}).as("getPaymentTerms")
|
|
|
|
cy.intercept("GET", "**/api/countries", {
|
|
statusCode: 200,
|
|
body: data.countries,
|
|
}).as("getCountries")
|
|
|
|
cy.intercept("GET", "**/api/states", {
|
|
statusCode: 200,
|
|
body: data.states,
|
|
}).as("getStates")
|
|
|
|
// Intercept customer list (GET) for the data table
|
|
cy.intercept("GET", "**/api/customers*", {
|
|
statusCode: 200,
|
|
body: { success: true, data: { data: [], pagination: { total: 0 } } },
|
|
}).as("getCustomers")
|
|
})
|
|
|
|
cy.visit("/sales/customers")
|
|
})
|
|
|
|
function openCustomerDialog() {
|
|
cy.contains("button", "Create Customer").click()
|
|
cy.get("[role='dialog']").should("be.visible")
|
|
}
|
|
|
|
// ── Rendering ──
|
|
|
|
it("should open the create customer dialog", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("Create Customer").should("exist")
|
|
})
|
|
})
|
|
|
|
it("should display all form fields", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
// Text fields
|
|
cy.get("input[name='first_name']").should("exist")
|
|
cy.get("input[name='last_name']").should("exist")
|
|
cy.get("input[name='company_name']").should("exist")
|
|
cy.get("input[name='email']").should("exist")
|
|
cy.get("input[name='phone']").should("exist")
|
|
cy.get("input[name='alternate_phone']").should("exist")
|
|
cy.get("input[name='address_line_1']").should("exist")
|
|
cy.get("input[name='address_line_2']").should("exist")
|
|
cy.get("input[name='city']").should("exist")
|
|
cy.get("input[name='zip_code']").should("exist")
|
|
|
|
// Labels
|
|
cy.contains("label", "First Name").should("exist")
|
|
cy.contains("label", "Last Name").should("exist")
|
|
cy.contains("label", "Email").should("exist")
|
|
cy.contains("label", "Salutation").should("exist")
|
|
cy.contains("label", "Customer Type").should("exist")
|
|
cy.contains("label", "Referral Source").should("exist")
|
|
cy.contains("label", "Payment Terms").should("exist")
|
|
cy.contains("label", "Country").should("exist")
|
|
cy.contains("label", "State").should("exist")
|
|
})
|
|
})
|
|
|
|
// ── Validation ──
|
|
|
|
it("should show validation errors for required fields", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("button", "Create Customer").click()
|
|
|
|
// first_name and last_name are required
|
|
cy.contains("First name is required").should("be.visible")
|
|
cy.contains("Last name is required").should("be.visible")
|
|
})
|
|
})
|
|
|
|
it("should show email validation error for invalid email", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='email']").type("not-an-email")
|
|
cy.contains("button", "Create Customer").click()
|
|
|
|
cy.contains("Enter a valid email address").should("be.visible")
|
|
})
|
|
})
|
|
|
|
it("should not show email error when email is empty", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
cy.contains("button", "Create Customer").click()
|
|
|
|
cy.contains("Enter a valid email address").should("not.exist")
|
|
})
|
|
})
|
|
|
|
// ── Text input ──
|
|
|
|
it("should fill in text fields", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John").should("have.value", "John")
|
|
cy.get("input[name='last_name']").type("Doe").should("have.value", "Doe")
|
|
cy.get("input[name='company_name']").type("Acme Corp").should("have.value", "Acme Corp")
|
|
cy.get("input[name='email']").type("john@example.com").should("have.value", "john@example.com")
|
|
cy.get("input[name='phone']").type("0501234567").should("have.value", "0501234567")
|
|
cy.get("input[name='address_line_1']").type("123 Main St").should("have.value", "123 Main St")
|
|
cy.get("input[name='city']").type("Dubai").should("have.value", "Dubai")
|
|
cy.get("input[name='zip_code']").type("00000").should("have.value", "00000")
|
|
})
|
|
})
|
|
|
|
// ── Select fields ──
|
|
|
|
it("should select a salutation from the dropdown", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
// Click the Salutation select trigger
|
|
cy.contains("label", "Salutation")
|
|
.parent()
|
|
.find("[role='combobox'], button[data-slot='select-trigger']")
|
|
.click()
|
|
})
|
|
|
|
// Select option from the popover (may render outside the dialog)
|
|
cy.get("[role='option'], [role='listbox'] [data-value='Mr']")
|
|
.contains("Mr")
|
|
.click()
|
|
})
|
|
|
|
it("should select a customer type", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("label", "Customer Type")
|
|
.parent()
|
|
.find("[role='combobox'], button[data-slot='select-trigger']")
|
|
.click()
|
|
})
|
|
|
|
cy.get("[role='option']").contains("Individual").click()
|
|
})
|
|
|
|
// ── Async select (Combobox) fields ──
|
|
|
|
it("should load and select a referral source", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.wait("@getReferralSources")
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("label", "Referral Source")
|
|
.parent()
|
|
.find("input")
|
|
.click()
|
|
.type("Google")
|
|
})
|
|
|
|
cy.get("[role='option']").contains("Google").click()
|
|
})
|
|
|
|
it("should load and select a country", () => {
|
|
openCustomerDialog()
|
|
|
|
cy.wait("@getCountries")
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("label", "Country")
|
|
.parent()
|
|
.find("input")
|
|
.click()
|
|
.type("United")
|
|
})
|
|
|
|
cy.get("[role='option']").contains("United Arab Emirates").click()
|
|
})
|
|
|
|
// ── Successful submission ──
|
|
|
|
it("should submit the form successfully with required fields", () => {
|
|
cy.fixture("customers").then((data) => {
|
|
cy.intercept("POST", "**/api/customers", {
|
|
statusCode: 201,
|
|
body: data.customer_created,
|
|
}).as("createCustomer")
|
|
})
|
|
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
|
|
cy.contains("button", "Create Customer").click()
|
|
})
|
|
|
|
cy.wait("@createCustomer").its("request.body").should((body) => {
|
|
expect(body.first_name).to.eq("John")
|
|
expect(body.last_name).to.eq("Doe")
|
|
})
|
|
})
|
|
|
|
it("should submit a fully filled form", () => {
|
|
cy.fixture("customers").then((data) => {
|
|
cy.intercept("POST", "**/api/customers", {
|
|
statusCode: 201,
|
|
body: data.customer_created,
|
|
}).as("createCustomer")
|
|
})
|
|
|
|
openCustomerDialog()
|
|
|
|
// Wait for async data
|
|
cy.wait("@getReferralSources")
|
|
cy.wait("@getPaymentTerms")
|
|
cy.wait("@getCountries")
|
|
cy.wait("@getStates")
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
// Text fields
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
cy.get("input[name='company_name']").type("Doe Holdings")
|
|
cy.get("input[name='email']").type("john@example.com")
|
|
cy.get("input[name='phone']").type("0501234567")
|
|
cy.get("input[name='alternate_phone']").type("0551234567")
|
|
cy.get("input[name='address_line_1']").type("Street 10")
|
|
cy.get("input[name='address_line_2']").type("Near Central Plaza")
|
|
cy.get("input[name='city']").type("Dubai")
|
|
cy.get("input[name='zip_code']").type("00000")
|
|
|
|
// Submit
|
|
cy.contains("button", "Create Customer").click()
|
|
})
|
|
|
|
cy.wait("@createCustomer").its("request.body").should((body) => {
|
|
expect(body.first_name).to.eq("John")
|
|
expect(body.last_name).to.eq("Doe")
|
|
expect(body.company_name).to.eq("Doe Holdings")
|
|
expect(body.email).to.eq("john@example.com")
|
|
expect(body.phone).to.eq("0501234567")
|
|
})
|
|
})
|
|
|
|
// ── Error handling ──
|
|
|
|
it("should display API error on submission failure", () => {
|
|
cy.intercept("POST", "**/api/customers", {
|
|
statusCode: 422,
|
|
body: {
|
|
success: false,
|
|
message: "The given data was invalid.",
|
|
errors: { email: ["The email has already been taken."] },
|
|
},
|
|
}).as("createCustomerFail")
|
|
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
cy.get("input[name='email']").type("john@example.com")
|
|
|
|
cy.contains("button", "Create Customer").click()
|
|
})
|
|
|
|
cy.wait("@createCustomerFail")
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.contains("Failed to create customer").should("be.visible")
|
|
})
|
|
})
|
|
|
|
it("should show loading state while submitting", () => {
|
|
cy.intercept("POST", "**/api/customers", {
|
|
statusCode: 201,
|
|
body: { success: true, data: { id: 1 } },
|
|
delay: 1000,
|
|
}).as("createCustomerSlow")
|
|
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
|
|
cy.contains("button", "Create Customer").click()
|
|
|
|
// Button should show loading text and be disabled
|
|
cy.contains("button", "Creating...").should("be.visible").and("be.disabled")
|
|
})
|
|
})
|
|
|
|
// ── Form reset after success ──
|
|
|
|
it("should reset the form after successful submission", () => {
|
|
cy.fixture("customers").then((data) => {
|
|
cy.intercept("POST", "**/api/customers", {
|
|
statusCode: 201,
|
|
body: data.customer_created,
|
|
}).as("createCustomer")
|
|
})
|
|
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").type("John")
|
|
cy.get("input[name='last_name']").type("Doe")
|
|
|
|
cy.contains("button", "Create Customer").click()
|
|
})
|
|
|
|
cy.wait("@createCustomer")
|
|
|
|
// After success, re-open the dialog and verify fields are empty
|
|
openCustomerDialog()
|
|
|
|
cy.get("[role='dialog']").within(() => {
|
|
cy.get("input[name='first_name']").should("have.value", "")
|
|
cy.get("input[name='last_name']").should("have.value", "")
|
|
})
|
|
})
|
|
})
|