374 lines
12 KiB
TypeScript
374 lines
12 KiB
TypeScript
import { discountTemplates, apiMocks } from "../support/discount-codes-helpers";
|
||
|
||
describe("Discount Codes - Complete E2E Tests", () => {
|
||
beforeEach(() => {
|
||
cy.login();
|
||
});
|
||
|
||
describe("Navigation and Basic UI", () => {
|
||
it("should display discount codes list page correctly", () => {
|
||
cy.visit("/discount-codes");
|
||
cy.waitForLoading();
|
||
|
||
cy.contains("مدیریت کدهای تخفیف").should("be.visible");
|
||
cy.get('[title="کد تخفیف جدید"]').should("be.visible");
|
||
});
|
||
|
||
it("should navigate to create page", () => {
|
||
cy.navigateToCreateDiscount();
|
||
cy.contains("ایجاد کد تخفیف").should("be.visible");
|
||
});
|
||
});
|
||
|
||
describe("Form Validation", () => {
|
||
beforeEach(() => {
|
||
cy.navigateToCreateDiscount();
|
||
});
|
||
|
||
it("should validate required fields", () => {
|
||
cy.getByTestId("submit-discount-button").should("be.disabled");
|
||
|
||
cy.fillBasicDiscountInfo({
|
||
code: "TEST123",
|
||
name: "Test Discount",
|
||
});
|
||
cy.getByTestId("submit-discount-button").should("be.disabled");
|
||
|
||
cy.fillDiscountSettings({
|
||
type: "percentage",
|
||
value: "10",
|
||
status: "active",
|
||
applicationLevel: "invoice",
|
||
});
|
||
|
||
cy.getByTestId("submit-discount-button").should("not.be.disabled");
|
||
});
|
||
|
||
it("should validate field lengths and formats", () => {
|
||
// Test code length
|
||
cy.getByTestId("discount-code-input").type("AB");
|
||
cy.getByTestId("discount-name-input").type("Test");
|
||
cy.get(".text-red-600").should("contain", "کد باید حداقل ۳ کاراکتر باشد");
|
||
|
||
// Test code too long
|
||
cy.getByTestId("discount-code-input").clear().type("A".repeat(51));
|
||
cy.get(".text-red-600").should(
|
||
"contain",
|
||
"کد نباید بیشتر از ۵۰ کاراکتر باشد"
|
||
);
|
||
|
||
// Test name too long
|
||
cy.getByTestId("discount-name-input").clear().type("A".repeat(101));
|
||
cy.get(".text-red-600").should(
|
||
"contain",
|
||
"نام نباید بیشتر از ۱۰۰ کاراکتر باشد"
|
||
);
|
||
|
||
// Test description too long
|
||
cy.getByTestId("discount-description-textarea").type("A".repeat(501));
|
||
cy.get(".text-red-600").should(
|
||
"contain",
|
||
"توضیحات نباید بیشتر از ۵۰۰ کاراکتر باشد"
|
||
);
|
||
});
|
||
|
||
it("should validate numeric fields", () => {
|
||
cy.fillBasicDiscountInfo({
|
||
code: "NUMTEST",
|
||
name: "Number Test",
|
||
});
|
||
|
||
// Test negative value
|
||
cy.getByTestId("discount-value-input").type("-10");
|
||
cy.get(".text-red-600").should("contain", "مقدار باید بیشتر از صفر باشد");
|
||
|
||
// Test zero value
|
||
cy.getByTestId("discount-value-input").clear().type("0");
|
||
cy.get(".text-red-600").should("contain", "مقدار باید بیشتر از صفر باشد");
|
||
});
|
||
});
|
||
|
||
describe("Discount Creation", () => {
|
||
beforeEach(() => {
|
||
// Mock successful API responses
|
||
cy.intercept("GET", "**/discount/**", apiMocks.discountsList).as(
|
||
"getDiscounts"
|
||
);
|
||
cy.intercept("POST", "**/discount/**", (req) => {
|
||
return apiMocks.successfulCreation(req.body);
|
||
}).as("createDiscount");
|
||
});
|
||
|
||
it("should create basic percentage discount", () => {
|
||
cy.createDiscountCode(discountTemplates.basicPercentage);
|
||
cy.wait("@createDiscount");
|
||
cy.contains("کد تخفیف با موفقیت ایجاد شد").should("be.visible");
|
||
});
|
||
|
||
it("should create fixed amount discount", () => {
|
||
cy.createDiscountCode(discountTemplates.fixedAmount);
|
||
cy.wait("@createDiscount");
|
||
cy.contains("کد تخفیف با موفقیت ایجاد شد").should("be.visible");
|
||
});
|
||
|
||
it("should create fee percentage discount", () => {
|
||
cy.createDiscountCode(discountTemplates.feePercentage);
|
||
cy.wait("@createDiscount");
|
||
cy.contains("کد تخفیف با موفقیت ایجاد شد").should("be.visible");
|
||
});
|
||
|
||
it("should create discount with user restrictions", () => {
|
||
cy.createDiscountCode(discountTemplates.loyalUsers);
|
||
cy.wait("@createDiscount");
|
||
cy.contains("کد تخفیف با موفقیت ایجاد شد").should("be.visible");
|
||
});
|
||
|
||
it("should create time-based discount with all features", () => {
|
||
cy.createDiscountCode(discountTemplates.timeBasedDiscount);
|
||
cy.wait("@createDiscount");
|
||
cy.contains("کد تخفیف با موفقیت ایجاد شد").should("be.visible");
|
||
});
|
||
});
|
||
|
||
describe("Error Handling", () => {
|
||
it("should handle validation errors from API", () => {
|
||
cy.intercept("POST", "**/discount/**", apiMocks.validationError).as(
|
||
"validationError"
|
||
);
|
||
|
||
cy.navigateToCreateDiscount();
|
||
cy.fillBasicDiscountInfo(discountTemplates.basicPercentage);
|
||
cy.fillDiscountSettings(discountTemplates.basicPercentage);
|
||
cy.submitDiscountForm();
|
||
|
||
cy.wait("@validationError");
|
||
cy.contains("کد تخفیف تکراری است").should("be.visible");
|
||
});
|
||
|
||
it("should handle server errors", () => {
|
||
cy.intercept("POST", "**/discount/**", apiMocks.serverError).as(
|
||
"serverError"
|
||
);
|
||
|
||
cy.navigateToCreateDiscount();
|
||
cy.fillBasicDiscountInfo(discountTemplates.basicPercentage);
|
||
cy.fillDiscountSettings(discountTemplates.basicPercentage);
|
||
cy.submitDiscountForm();
|
||
|
||
cy.wait("@serverError");
|
||
cy.contains("خطا در ایجاد کد تخفیف").should("be.visible");
|
||
});
|
||
|
||
it("should handle loading states", () => {
|
||
cy.intercept("POST", "**/discount/**", {
|
||
delay: 2000,
|
||
...apiMocks.successfulCreation(discountTemplates.basicPercentage),
|
||
}).as("slowCreate");
|
||
|
||
cy.navigateToCreateDiscount();
|
||
cy.fillBasicDiscountInfo(discountTemplates.basicPercentage);
|
||
cy.fillDiscountSettings(discountTemplates.basicPercentage);
|
||
cy.submitDiscountForm();
|
||
|
||
// Check loading state
|
||
cy.getByTestId("submit-discount-button").should("be.disabled");
|
||
cy.get(".animate-spin").should("be.visible");
|
||
|
||
cy.wait("@slowCreate");
|
||
});
|
||
});
|
||
|
||
describe("List Page Features", () => {
|
||
beforeEach(() => {
|
||
cy.intercept("GET", "**/discount/**", apiMocks.discountsList).as(
|
||
"getDiscounts"
|
||
);
|
||
cy.visit("/discount-codes");
|
||
cy.wait("@getDiscounts");
|
||
});
|
||
|
||
it("should search discount codes", () => {
|
||
cy.searchDiscountCode("SAVE20");
|
||
cy.contains("SAVE20").should("be.visible");
|
||
|
||
cy.searchDiscountCode("NONEXISTENT");
|
||
cy.contains("هیچ کد تخفیفی یافت نشد").should("be.visible");
|
||
});
|
||
|
||
it("should clear filters", () => {
|
||
cy.searchDiscountCode("TEST");
|
||
cy.clearDiscountFilters();
|
||
cy.get('input[placeholder*="جستجو"]').should("have.value", "");
|
||
});
|
||
|
||
it("should display discount codes with correct formatting", () => {
|
||
cy.contains("SAVE20").should("be.visible");
|
||
cy.contains("20%").should("be.visible");
|
||
cy.get(".bg-green-100").should("contain", "فعال");
|
||
});
|
||
});
|
||
|
||
describe("Edit Functionality", () => {
|
||
beforeEach(() => {
|
||
cy.intercept("GET", "**/discount/**", apiMocks.discountsList).as(
|
||
"getDiscounts"
|
||
);
|
||
cy.intercept("GET", "**/discount/1", {
|
||
statusCode: 200,
|
||
body: {
|
||
id: 1,
|
||
code: "SAVE20",
|
||
name: "20% Off Discount",
|
||
description: "Get 20% off on your purchase",
|
||
type: "percentage",
|
||
value: 20,
|
||
status: "active",
|
||
application_level: "invoice",
|
||
},
|
||
}).as("getDiscount");
|
||
cy.intercept("PUT", "**/discount/1", {
|
||
statusCode: 200,
|
||
body: { message: "updated successfully" },
|
||
}).as("updateDiscount");
|
||
});
|
||
|
||
it("should edit existing discount code", () => {
|
||
cy.visit("/discount-codes");
|
||
cy.wait("@getDiscounts");
|
||
|
||
cy.contains("SAVE20")
|
||
.parent()
|
||
.parent()
|
||
.within(() => {
|
||
cy.get('[title="ویرایش"]').click();
|
||
});
|
||
|
||
cy.wait("@getDiscount");
|
||
cy.url().should("include", "/edit");
|
||
|
||
cy.getByTestId("discount-name-input")
|
||
.clear()
|
||
.type("Updated Discount Name");
|
||
cy.submitDiscountForm();
|
||
|
||
cy.wait("@updateDiscount");
|
||
cy.contains("کد تخفیف با موفقیت بهروزرسانی شد").should("be.visible");
|
||
});
|
||
});
|
||
|
||
describe("Delete Functionality", () => {
|
||
beforeEach(() => {
|
||
cy.intercept("GET", "**/discount/**", apiMocks.discountsList).as(
|
||
"getDiscounts"
|
||
);
|
||
cy.intercept("DELETE", "**/discount/**", {
|
||
statusCode: 200,
|
||
body: { message: "deleted successfully" },
|
||
}).as("deleteDiscount");
|
||
});
|
||
|
||
it("should delete discount code", () => {
|
||
cy.visit("/discount-codes");
|
||
cy.wait("@getDiscounts");
|
||
|
||
cy.contains("SAVE20")
|
||
.parent()
|
||
.parent()
|
||
.within(() => {
|
||
cy.get('[title="حذف"]').click();
|
||
});
|
||
|
||
cy.contains("آیا از حذف این کد تخفیف اطمینان دارید؟").should(
|
||
"be.visible"
|
||
);
|
||
cy.contains("button", "حذف").click();
|
||
|
||
cy.wait("@deleteDiscount");
|
||
cy.contains("کد تخفیف با موفقیت حذف شد").should("be.visible");
|
||
});
|
||
});
|
||
|
||
describe("Responsive Design", () => {
|
||
it("should work on mobile devices", () => {
|
||
cy.viewport("iphone-6");
|
||
cy.navigateToCreateDiscount();
|
||
|
||
cy.fillBasicDiscountInfo({
|
||
code: "MOBILE123",
|
||
name: "Mobile Test",
|
||
});
|
||
|
||
cy.fillDiscountSettings({
|
||
type: "percentage",
|
||
value: "10",
|
||
status: "active",
|
||
applicationLevel: "invoice",
|
||
});
|
||
|
||
cy.getByTestId("submit-discount-button").should("be.visible");
|
||
});
|
||
|
||
it("should work on tablets", () => {
|
||
cy.viewport("ipad-2");
|
||
cy.visit("/discount-codes");
|
||
cy.waitForLoading();
|
||
|
||
cy.get("table").should("be.visible");
|
||
cy.get('[title="کد تخفیف جدید"]').should("be.visible");
|
||
});
|
||
});
|
||
|
||
describe("Accessibility", () => {
|
||
it("should be keyboard navigable", () => {
|
||
cy.navigateToCreateDiscount();
|
||
|
||
cy.getByTestId("discount-code-input").focus();
|
||
cy.focused().should("have.attr", "data-testid", "discount-code-input");
|
||
|
||
cy.focused().tab();
|
||
cy.focused().should("have.attr", "data-testid", "discount-name-input");
|
||
});
|
||
|
||
it("should have proper ARIA labels", () => {
|
||
cy.navigateToCreateDiscount();
|
||
|
||
cy.get("label").should("have.length.greaterThan", 5);
|
||
cy.get("input[required]").should("have.length.greaterThan", 3);
|
||
});
|
||
|
||
it("should announce errors to screen readers", () => {
|
||
cy.navigateToCreateDiscount();
|
||
|
||
cy.getByTestId("discount-code-input").type("AB");
|
||
cy.get(".text-red-600").should("have.attr", "role", "alert");
|
||
});
|
||
});
|
||
|
||
describe("Performance", () => {
|
||
it("should load create page quickly", () => {
|
||
const startTime = Date.now();
|
||
cy.navigateToCreateDiscount();
|
||
cy.getByTestId("discount-code-input")
|
||
.should("be.visible")
|
||
.then(() => {
|
||
const loadTime = Date.now() - startTime;
|
||
expect(loadTime).to.be.lessThan(3000); // Should load within 3 seconds
|
||
});
|
||
});
|
||
|
||
it("should handle large forms efficiently", () => {
|
||
cy.navigateToCreateDiscount();
|
||
|
||
// Fill form quickly without delays
|
||
cy.getByTestId("discount-code-input").type("PERF123");
|
||
cy.getByTestId("discount-name-input").type("Performance Test");
|
||
cy.getByTestId("discount-description-textarea").type("A".repeat(400));
|
||
cy.getByTestId("discount-type-select").select("percentage");
|
||
cy.getByTestId("discount-value-input").type("25");
|
||
|
||
// Form should remain responsive
|
||
cy.getByTestId("submit-discount-button").should("not.be.disabled");
|
||
});
|
||
});
|
||
});
|