diff --git a/frontend/app/generated/api.ts b/frontend/app/generated/api.ts index eaa9d0a..07092ab 100644 --- a/frontend/app/generated/api.ts +++ b/frontend/app/generated/api.ts @@ -332,7 +332,7 @@ export interface paths { * * The response includes: * - market_price: The raw price from the exchange - * - agreed_price: The price with admin premium applied + * - premium_percentage: The premium to apply to trades * - is_stale: Whether the price is older than 5 minutes * - config: Trading configuration (min/max EUR, increment) */ @@ -541,6 +541,29 @@ export interface paths { patch?: never; trace?: never; }; + "/api/admin/users/search": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Search Users + * @description Search users by email for autocomplete. + * + * Returns users whose email contains the search query (case-insensitive). + * Limited to 10 results for autocomplete purposes. + */ + get: operations["search_users_api_admin_users_search_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; } export type webhooks = Record; export interface components { @@ -884,13 +907,14 @@ export interface components { }; /** * PriceResponse - * @description Current BTC/EUR price with premium applied. + * @description Current BTC/EUR price for trading. + * + * Note: The actual agreed price depends on trade direction (buy/sell) + * and is calculated by the frontend using market_price and premium_percentage. */ PriceResponse: { /** Market Price */ market_price: number; - /** Agreed Price */ - agreed_price: number; /** Premium Percentage */ premium_percentage: number; /** @@ -1023,6 +1047,16 @@ export interface components { /** Permissions */ permissions: string[]; }; + /** + * UserSearchResult + * @description Result item for user search. + */ + UserSearchResult: { + /** Id */ + id: number; + /** Email */ + email: string; + }; /** ValidationError */ ValidationError: { /** Location */ @@ -1815,4 +1849,36 @@ export interface operations { }; }; }; + search_users_api_admin_users_search_get: { + parameters: { + query: { + /** @description Search query for user email */ + q: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UserSearchResult"][]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; } diff --git a/frontend/e2e/exchange.spec.ts b/frontend/e2e/exchange.spec.ts index c0a23c8..4efc648 100644 --- a/frontend/e2e/exchange.spec.ts +++ b/frontend/e2e/exchange.spec.ts @@ -92,9 +92,13 @@ test.describe("Exchange Page - Regular User Access", () => { await expect(page.getByText(/You buy €\d/)).toBeVisible(); }); - test("exchange page shows date selection", async ({ page }) => { + test("exchange page shows date selection after continue", async ({ page }) => { await page.goto("/exchange"); + // Step 1: Click "Continue to Booking" to proceed to step 2 + await page.getByRole("button", { name: "Continue to Booking" }).click(); + + // Step 2: Now date selection should be visible await expect(page.getByRole("heading", { name: "Select a Date" })).toBeVisible(); // Should see multiple date buttons const dateButtons = page @@ -118,7 +122,10 @@ test.describe("Exchange Page - With Availability", () => { test("shows available slots when availability is set", async ({ page }) => { await page.goto("/exchange"); - // Use data-testid for reliable date selection + // Step 1: Click "Continue to Booking" to proceed to step 2 + await page.getByRole("button", { name: "Continue to Booking" }).click(); + + // Step 2: Use data-testid for reliable date selection const tomorrowStr = getTomorrowDateStr(); const dateButton = page.getByTestId(`date-${tomorrowStr}`); await expect(dateButton).toBeEnabled({ timeout: 15000 }); @@ -138,7 +145,10 @@ test.describe("Exchange Page - With Availability", () => { test("clicking slot shows confirmation form", async ({ page }) => { await page.goto("/exchange"); - // Use data-testid for reliable date selection + // Step 1: Click "Continue to Booking" to proceed to step 2 + await page.getByRole("button", { name: "Continue to Booking" }).click(); + + // Step 2: Use data-testid for reliable date selection const tomorrowStr = getTomorrowDateStr(); const dateButton = page.getByTestId(`date-${tomorrowStr}`); await expect(dateButton).toBeEnabled({ timeout: 15000 }); @@ -160,7 +170,10 @@ test.describe("Exchange Page - With Availability", () => { test("confirmation shows trade details", async ({ page }) => { await page.goto("/exchange"); - // Use data-testid for reliable date selection + // Step 1: Click "Continue to Booking" to proceed to step 2 + await page.getByRole("button", { name: "Continue to Booking" }).click(); + + // Step 2: Use data-testid for reliable date selection const tomorrowStr = getTomorrowDateStr(); const dateButton = page.getByTestId(`date-${tomorrowStr}`); await expect(dateButton).toBeEnabled({ timeout: 15000 });