Fix ConfirmationButton usage in pricing page and e2e tests
- Update pricing page to use ConfirmationButton API correctly (isConfirming, onConfirm, onCancel, onActionClick) - Fix e2e tests to set up response listeners before navigation - Fix validation error selector to use .first() for multiple matches - All 9 e2e tests now passing
This commit is contained in:
parent
1874c3a057
commit
1ef5ebe493
2 changed files with 64 additions and 38 deletions
|
|
@ -49,6 +49,7 @@ export default function AdminPricingPage() {
|
||||||
const [errors, setErrors] = useState<ValidationErrors>({});
|
const [errors, setErrors] = useState<ValidationErrors>({});
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [success, setSuccess] = useState(false);
|
const [success, setSuccess] = useState(false);
|
||||||
|
const [isConfirming, setIsConfirming] = useState(false);
|
||||||
|
|
||||||
const fetchConfig = useCallback(async () => {
|
const fetchConfig = useCallback(async () => {
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
@ -180,12 +181,16 @@ export default function AdminPricingPage() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleConfirmSave = () => {
|
||||||
if (!formData) return;
|
if (!formData) {
|
||||||
|
setIsConfirming(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const validationErrors = validateForm(formData);
|
const validationErrors = validateForm(formData);
|
||||||
if (Object.keys(validationErrors).length > 0) {
|
if (Object.keys(validationErrors).length > 0) {
|
||||||
setErrors(validationErrors);
|
setErrors(validationErrors);
|
||||||
|
setIsConfirming(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,6 +204,7 @@ export default function AdminPricingPage() {
|
||||||
eur_min_sell: formData.eur_min_sell,
|
eur_min_sell: formData.eur_min_sell,
|
||||||
eur_max_sell: formData.eur_max_sell,
|
eur_max_sell: formData.eur_max_sell,
|
||||||
});
|
});
|
||||||
|
setIsConfirming(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading || !formData) {
|
if (isLoading || !formData) {
|
||||||
|
|
@ -385,16 +391,19 @@ export default function AdminPricingPage() {
|
||||||
|
|
||||||
<div style={formStyles.actions}>
|
<div style={formStyles.actions}>
|
||||||
<ConfirmationButton
|
<ConfirmationButton
|
||||||
onClick={handleSave}
|
isConfirming={isConfirming}
|
||||||
disabled={hasErrors || isSaving}
|
onConfirm={handleConfirmSave}
|
||||||
confirmMessage={t("pricing.confirmSave")}
|
onCancel={() => setIsConfirming(false)}
|
||||||
style={{
|
onActionClick={() => setIsConfirming(true)}
|
||||||
|
actionLabel={isSaving ? tCommon("saving") : t("pricing.save")}
|
||||||
|
confirmLabel={tCommon("confirm")}
|
||||||
|
cancelLabel={tCommon("cancel")}
|
||||||
|
isLoading={isSaving}
|
||||||
|
actionButtonStyle={{
|
||||||
...buttonStyles.primary,
|
...buttonStyles.primary,
|
||||||
...(hasErrors || isSaving ? buttonStyles.disabled : {}),
|
...(hasErrors || isSaving ? buttonStyles.disabled : {}),
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
{isSaving ? tCommon("saving") : t("pricing.save")}
|
|
||||||
</ConfirmationButton>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,18 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
await expect(pricingLink).toBeVisible();
|
await expect(pricingLink).toBeVisible();
|
||||||
|
|
||||||
// Test page access and structure
|
// Test page access and structure
|
||||||
|
// Set up response listener before navigation
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
|
);
|
||||||
await page.goto("/admin/pricing");
|
await page.goto("/admin/pricing");
|
||||||
await expect(page).toHaveURL("/admin/pricing");
|
await expect(page).toHaveURL("/admin/pricing");
|
||||||
|
|
||||||
// Wait for API call to complete and form to render
|
// Wait for API call to complete and form to render
|
||||||
await page.waitForResponse(
|
await responsePromise;
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
// Wait for form inputs to be visible (indicates form has loaded)
|
||||||
);
|
await expect(page.locator('input[type="number"]').first()).toBeVisible({ timeout: 10000 });
|
||||||
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible();
|
||||||
timeout: 10000,
|
|
||||||
});
|
|
||||||
await expect(page.getByText("Configure premium pricing and trade amount limits")).toBeVisible();
|
await expect(page.getByText("Configure premium pricing and trade amount limits")).toBeVisible();
|
||||||
|
|
||||||
// Check all form fields are present (using text + input selector since labels aren't associated)
|
// Check all form fields are present (using text + input selector since labels aren't associated)
|
||||||
|
|
@ -52,12 +54,14 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can view current pricing configuration", async ({ page }) => {
|
test("can view current pricing configuration", async ({ page }) => {
|
||||||
|
// Set up response listener before navigation
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
|
);
|
||||||
await page.goto("/admin/pricing");
|
await page.goto("/admin/pricing");
|
||||||
|
|
||||||
// Wait for API call to complete and form to render
|
// Wait for API call to complete and form to render
|
||||||
await page.waitForResponse(
|
await responsePromise;
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
|
||||||
);
|
|
||||||
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
@ -77,12 +81,14 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can update pricing configuration", async ({ page }) => {
|
test("can update pricing configuration", async ({ page }) => {
|
||||||
|
// Set up response listener before navigation
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
|
);
|
||||||
await page.goto("/admin/pricing");
|
await page.goto("/admin/pricing");
|
||||||
|
|
||||||
// Wait for API call to complete and form to render
|
// Wait for API call to complete and form to render
|
||||||
await page.waitForResponse(
|
await responsePromise;
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
|
||||||
);
|
|
||||||
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
@ -98,6 +104,13 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
await premiumBuyInput.clear();
|
await premiumBuyInput.clear();
|
||||||
await premiumBuyInput.fill(newBuyValue);
|
await premiumBuyInput.fill(newBuyValue);
|
||||||
|
|
||||||
|
// Wait a bit for any validation to clear
|
||||||
|
await page.waitForTimeout(200);
|
||||||
|
|
||||||
|
// Verify save button is enabled before clicking
|
||||||
|
const saveButton = page.getByRole("button", { name: /Save Changes/i });
|
||||||
|
await expect(saveButton).toBeEnabled({ timeout: 5000 });
|
||||||
|
|
||||||
// Set up response listener before clicking save
|
// Set up response listener before clicking save
|
||||||
const putPromise = page.waitForResponse(
|
const putPromise = page.waitForResponse(
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "PUT"
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "PUT"
|
||||||
|
|
@ -106,12 +119,12 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Click save button (with confirmation)
|
// Click save button (enters confirmation mode)
|
||||||
await page.getByRole("button", { name: /Save Changes/i }).click();
|
await saveButton.click();
|
||||||
|
|
||||||
// Confirm the save action
|
// Confirm the save action (button text changes to "Confirm")
|
||||||
await expect(page.getByText(/Are you sure/i)).toBeVisible();
|
await expect(page.getByRole("button", { name: /Confirm/i })).toBeVisible({ timeout: 5000 });
|
||||||
await page.getByRole("button", { name: /confirm|yes|ok/i }).click();
|
await page.getByRole("button", { name: /Confirm/i }).click();
|
||||||
|
|
||||||
// Wait for API calls to complete
|
// Wait for API calls to complete
|
||||||
await putPromise;
|
await putPromise;
|
||||||
|
|
@ -127,12 +140,14 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("validation prevents invalid values", async ({ page }) => {
|
test("validation prevents invalid values", async ({ page }) => {
|
||||||
|
// Set up response listener before navigation
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
|
);
|
||||||
await page.goto("/admin/pricing");
|
await page.goto("/admin/pricing");
|
||||||
|
|
||||||
// Wait for API call to complete and form to render
|
// Wait for API call to complete and form to render
|
||||||
await page.waitForResponse(
|
await responsePromise;
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
|
||||||
);
|
|
||||||
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
@ -146,8 +161,8 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
|
|
||||||
// Try to save
|
// Try to save
|
||||||
await page.getByRole("button", { name: /Save Changes/i }).click();
|
await page.getByRole("button", { name: /Save Changes/i }).click();
|
||||||
await expect(page.getByText(/confirm|yes|ok/i)).toBeVisible();
|
await expect(page.getByRole("button", { name: /Confirm/i })).toBeVisible({ timeout: 2000 });
|
||||||
await page.getByRole("button", { name: /confirm|yes|ok/i }).click();
|
await page.getByRole("button", { name: /Confirm/i }).click();
|
||||||
|
|
||||||
// Should show validation error
|
// Should show validation error
|
||||||
await expect(page.getByText(/must be between.*-100.*100/i)).toBeVisible({ timeout: 2000 });
|
await expect(page.getByText(/must be between.*-100.*100/i)).toBeVisible({ timeout: 2000 });
|
||||||
|
|
@ -167,22 +182,24 @@ test.describe("Admin Pricing Page - Admin Access", () => {
|
||||||
|
|
||||||
// Try to save
|
// Try to save
|
||||||
await page.getByRole("button", { name: /Save Changes/i }).click();
|
await page.getByRole("button", { name: /Save Changes/i }).click();
|
||||||
await expect(page.getByText(/confirm|yes|ok/i)).toBeVisible();
|
await expect(page.getByRole("button", { name: /Confirm/i })).toBeVisible({ timeout: 2000 });
|
||||||
await page.getByRole("button", { name: /confirm|yes|ok/i }).click();
|
await page.getByRole("button", { name: /Confirm/i }).click();
|
||||||
|
|
||||||
// Should show validation error
|
// Should show validation error (there are two - one for min, one for max)
|
||||||
await expect(page.getByText(/minimum must be less than maximum/i)).toBeVisible({
|
await expect(page.getByText(/minimum must be less than maximum/i).first()).toBeVisible({
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("form fields update correctly when values change", async ({ page }) => {
|
test("form fields update correctly when values change", async ({ page }) => {
|
||||||
|
// Set up response listener before navigation
|
||||||
|
const responsePromise = page.waitForResponse(
|
||||||
|
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
||||||
|
);
|
||||||
await page.goto("/admin/pricing");
|
await page.goto("/admin/pricing");
|
||||||
|
|
||||||
// Wait for API call to complete and form to render
|
// Wait for API call to complete and form to render
|
||||||
await page.waitForResponse(
|
await responsePromise;
|
||||||
(resp) => resp.url().includes("/api/admin/pricing") && resp.request().method() === "GET"
|
|
||||||
);
|
|
||||||
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
await expect(page.getByRole("heading", { name: "Pricing Configuration" })).toBeVisible({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue