fix(companies): align optional numeric fields with API validation
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
Make employee_count, annual_revenue, and founded_year truly optional in the create company form and payload. Add field validation docs and Cypress e2e coverage for dashboard and notifications. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const emptyHistoryResponse = {
|
||||
success: true,
|
||||
message: "ok",
|
||||
data: [],
|
||||
meta: {
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
page: 1,
|
||||
pages: 1,
|
||||
has_more: false,
|
||||
},
|
||||
};
|
||||
|
||||
const stubNotificationReads = () => {
|
||||
cy.intercept("GET", "**/api/proxy/notifications/my**", {
|
||||
statusCode: 200,
|
||||
body: emptyHistoryResponse,
|
||||
});
|
||||
cy.intercept("GET", /\/api\/proxy\/notifications(?:\?|$)/, {
|
||||
statusCode: 200,
|
||||
body: emptyHistoryResponse,
|
||||
}).as("notificationHistory");
|
||||
};
|
||||
|
||||
const chooseMultiSelectOption = (label: string, option: string) => {
|
||||
cy.contains("label", new RegExp(`^${label}`, "i"))
|
||||
.parent()
|
||||
.find('div[tabindex="0"]')
|
||||
.click();
|
||||
cy.contains(
|
||||
"div[class*='cursor-pointer']",
|
||||
new RegExp(`^${option}$`),
|
||||
).click();
|
||||
};
|
||||
|
||||
describe("create notification", () => {
|
||||
beforeEach(() => {
|
||||
cy.setAuthCookies();
|
||||
stubNotificationReads();
|
||||
});
|
||||
|
||||
it("renders breadcrumbs and validates required fields and an invalid link", () => {
|
||||
cy.visit("/notification-history/create");
|
||||
|
||||
cy.getByCy("breadcrumb-link-dashboard").should("be.visible");
|
||||
cy.getByCy("breadcrumb-link-notifications").should(
|
||||
"have.attr",
|
||||
"href",
|
||||
"/notification-history",
|
||||
);
|
||||
cy.getByCy("breadcrumb-current-create-notification")
|
||||
.should("be.visible")
|
||||
.and("contain.text", "Create Notification");
|
||||
|
||||
cy.get('textarea[name="description"]').type(
|
||||
"Description entered so custom validation can run.",
|
||||
);
|
||||
cy.getByCy("admin-form-submit-button").click();
|
||||
cy.get("p")
|
||||
.filter(
|
||||
(_index, element) =>
|
||||
element.textContent?.trim() === "This field is required",
|
||||
)
|
||||
.should("have.length", 4);
|
||||
|
||||
cy.get('input[name="link"]').type("not-a-valid-url");
|
||||
cy.get('input[name="title"]').type("Validation test");
|
||||
cy.get('select[name="target"]').select("all_users", { force: true });
|
||||
cy.get('select[name="priority"]').select("medium", { force: true });
|
||||
cy.get('select[name="type"]').select("info", { force: true });
|
||||
cy.get('textarea[name="description"]')
|
||||
.clear()
|
||||
.type("A valid notification message.");
|
||||
cy.getByCy("admin-form-submit-button").click();
|
||||
|
||||
cy.contains("This field does not match the required pattern").should(
|
||||
"be.visible",
|
||||
);
|
||||
});
|
||||
|
||||
it("loads role recipients and submits the expected notification payload", () => {
|
||||
cy.intercept("POST", "**/api/proxy/notifications", (req) => {
|
||||
expect(req.body).to.deep.equal({
|
||||
title: "Planned maintenance",
|
||||
target: "specific_role",
|
||||
recipient: ["admin"],
|
||||
channels: ["email", "push"],
|
||||
link: "https://example.com/maintenance",
|
||||
priority: "important",
|
||||
type: "warning",
|
||||
description: "The platform will be unavailable during maintenance.",
|
||||
schedule_at: 0,
|
||||
});
|
||||
req.reply({
|
||||
statusCode: 201,
|
||||
body: {
|
||||
success: true,
|
||||
message: "Notification created successfully",
|
||||
data: {},
|
||||
},
|
||||
});
|
||||
}).as("createNotification");
|
||||
|
||||
cy.visit("/notification-history");
|
||||
cy.wait("@notificationHistory");
|
||||
cy.getByCy("list-header-create-button").click();
|
||||
cy.location("pathname").should("eq", "/notification-history/create");
|
||||
|
||||
cy.get('input[name="title"]').type("Planned maintenance");
|
||||
cy.get('select[name="target"]').select("specific_role", { force: true });
|
||||
chooseMultiSelectOption("recipient", "Admin");
|
||||
chooseMultiSelectOption("channels", "Email");
|
||||
chooseMultiSelectOption("channels", "Push");
|
||||
cy.get('input[name="link"]').type("https://example.com/maintenance");
|
||||
cy.get('select[name="priority"]').select("important", { force: true });
|
||||
cy.get('select[name="type"]').select("warning", { force: true });
|
||||
cy.get('textarea[name="description"]').type(
|
||||
"The platform will be unavailable during maintenance.",
|
||||
);
|
||||
|
||||
cy.getByCy("admin-form-submit-button").click();
|
||||
cy.wait("@createNotification");
|
||||
|
||||
cy.location("pathname").should("eq", "/notification-history");
|
||||
cy.contains("Notification created successfully").should("be.visible");
|
||||
});
|
||||
|
||||
it("loads specific users from the API and clears recipients when target changes", () => {
|
||||
cy.intercept("GET", "**/api/proxy/users**", (req) => {
|
||||
expect(req.query.offset).to.eq("0");
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {
|
||||
success: true,
|
||||
message: "ok",
|
||||
data: {
|
||||
users: [
|
||||
{
|
||||
id: "admin-recipient-1",
|
||||
full_name: "Notification Admin",
|
||||
username: "notification-admin",
|
||||
},
|
||||
],
|
||||
},
|
||||
meta: { offset: 0, limit: 10, total: 1 },
|
||||
},
|
||||
});
|
||||
}).as("notificationRecipients");
|
||||
|
||||
cy.visit("/notification-history/create");
|
||||
cy.get('select[name="target"]').select("specific_users", { force: true });
|
||||
cy.wait("@notificationRecipients");
|
||||
|
||||
chooseMultiSelectOption("recipient", "Notification Admin");
|
||||
cy.contains("span", "Notification Admin").should("be.visible");
|
||||
|
||||
cy.get('select[name="target"]').select("all_users", { force: true });
|
||||
cy.contains("label", /^recipient/i)
|
||||
.parent()
|
||||
.find('[tabindex="-1"]')
|
||||
.should("exist");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user