# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: src/manager/tests/e2e/unit/unit-navigate.spec.ts >> navigates from the list to the details page
- Location: src/manager/tests/e2e/unit/unit-navigate.spec.ts:8:5

# Error details

```
Error: Failed to sync billing catalog via http://billing-api-dev:8080/e2e/storeroom/import: 500 
```

# Test source

```ts
  1  | import { request as playwrightRequest } from '@playwright/test';
  2  | import { sleep } from '@/shared/utils/timeout-utils';
  3  | 
  4  | type BillingMode = 'modern' | 'classic';
  5  | 
  6  | const BILLING_STRIPE_SYNC_DELAY_MS = 5_000;
  7  | 
  8  | const DEFAULT_BILLING_API_URL = 'https://billing-api-test.kinnovis.com';
  9  | 
  10 | // `KINNOVIS_BILLING=1` runs the suite against the modern (Kinnovis) billing system; any other value
  11 | // (including `0` and unset) is classic. Mirrors the manager SPA's `isKinnovisBillingUser` switch: in
  12 | // modern mode booking writes and invoice mark-as-paid move from the manager API to the billing API.
  13 | function resolveBillingMode(): BillingMode {
  14 |   return process.env.KINNOVIS_BILLING === '1' ? 'modern' : 'classic';
  15 | }
  16 | 
  17 | export function isModernBillingMode(): boolean {
  18 |   return resolveBillingMode() === 'modern';
  19 | }
  20 | 
  21 | // Calls one of billing's unauthenticated e2e routes; `action` describes the intent in failure
  22 | // messages, e.g. `Failed to <action> via <url>: <status> <body>`.
  23 | async function callBillingE2eRoute(path: string, action: string): Promise<void> {
  24 |   const baseURL = process.env.BILLING_API_URL ?? DEFAULT_BILLING_API_URL;
  25 |   const ctx = await playwrightRequest.newContext({
  26 |     baseURL,
  27 |     extraHTTPHeaders: { Accept: 'application/json' },
  28 |   });
  29 | 
  30 |   try {
  31 |     const response = await ctx.get(path);
  32 | 
  33 |     if (!response.ok()) {
> 34 |       throw new Error(`Failed to ${action} via ${baseURL}${path}: ${response.status()} ${await response.text()}`);
     |             ^ Error: Failed to sync billing catalog via http://billing-api-dev:8080/e2e/storeroom/import: 500 
  35 |     }
  36 |   } finally {
  37 |     await ctx.dispose();
  38 |   }
  39 | }
  40 | 
  41 | // Pins the shared QA storeroom tenant to the resolved billing mode via billing's unauthenticated
  42 | // e2e reset route. Used by global setup so runs are deterministic regardless of the mode a
  43 | // previous run left the environment in.
  44 | export async function pinBillingMode(): Promise<void> {
  45 |   const mode = resolveBillingMode();
  46 |   await callBillingE2eRoute(`/e2e/storeroom/${mode}`, `pin billing mode to "${mode}"`);
  47 | }
  48 | 
  49 | // The modern billing system only learns about CLASSIC catalog changes through
  50 | // `kin:catalog:import`, which is scheduled every five minutes — far too slow for a test
  51 | // that creates a unit type (or discount, product, ...) and books it seconds later. This
  52 | // triggers the import synchronously via billing's e2e route; the route serializes
  53 | // concurrent callers server-side, so parallel workers can call it freely.
  54 | // No-op in classic mode, where the billing catalog is not involved.
  55 | export async function syncBillingCatalog(): Promise<void> {
  56 |   if (!isModernBillingMode()) {
  57 |     return;
  58 |   }
  59 | 
  60 |   await callBillingE2eRoute('/e2e/storeroom/import', 'sync billing catalog');
  61 | }
  62 | 
  63 | // The catalog import creates a product's price in billing right away but pushes it to Stripe
  64 | // asynchronously, so an invoice created straight after fails with Stripe's "No such price".
  65 | // Billing exposes no route to await that push, so give it a fixed head start instead.
  66 | // No-op in classic mode, where the billing catalog is not involved.
  67 | export async function waitForBillingStripeSync(): Promise<void> {
  68 |   if (!isModernBillingMode()) {
  69 |     return;
  70 |   }
  71 | 
  72 |   await sleep(BILLING_STRIPE_SYNC_DELAY_MS);
  73 | }
  74 | 
```