[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 9.5s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 11ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1351ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 173ms

Running 1 test using 1 worker

URL did not change to main, current: https://dnymer.ourvend.com/#/institutionList
--- MACHINE LIST ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (49.1s)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 45000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      24 |   await page.click('text=Machine Management').catch(() => {});
      25 |
    > 26 |   await page.waitForTimeout(3000); // Wait for table to load
         |              ^
      27 |
      28 |   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
      29 |   console.log(machines);
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:26:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


Read image file [image/png]


edit

  // Wait for login form
  await page.waitForSelector('input[placeholder="Username/email"]', { timeout: 10000 });

  await page.fill('input[placeholder="Username/email"]', 'cc');
  await page.fill('input[placeholder*="Password"]', 'ys123456');

  // Click login button
  await page.click('button:has-text("Login")');

  // Wait for dashboard or redirection
  await page.waitForURL(/.*main.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to main, current:', page.url()));

  // Wait for login form
  await page.waitForSelector('input[placeholder="Username/email"]', { timeout: 10000 });

  await page.fill('input[placeholder="Username/email"]', 'cc');
  await page.fill('input[placeholder*="Password"]', 'ys123456');

  // Click login button
  await page.click('button:has-text("Login")');

  // 1b. Handle Institution Selection
  await page.waitForSelector('text=cc一级机构', { timeout: 15000 });
  await page.click('text=cc一级机构');

  // Wait for dashboard or redirection
  await page.waitForURL(/.*main.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to main, current:', page.url()));


Successfully replaced 1 block(s) in /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts.

    ...
 12
 13   // Click login button
 14   await page.click('button:has-text("Login")');
 15
+16   // 1b. Handle Institution Selection
+17   await page.waitForSelector('text=cc一级机构', { timeout: 15000 });
+18   await page.click('text=cc一级机构');
+19
 16   // Wait for dashboard or redirection
 17   await page.waitForURL(/.*main.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to main, current:', page.url()));
 18
 19   // 2. Map Machine List
    ...


bash

cd /mnt/rpi/repos/ballbox && npx playwright test tests/e2e/inspect-ourvend.spec.ts --project=chromium


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 9.3s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 12ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1164ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 178ms

Running 1 test using 1 worker

URL did not change to main, current: https://dnymer.ourvend.com/#/home
--- MACHINE LIST ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (48.7s)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 45000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      28 |   await page.click('text=Machine Management').catch(() => {});
      29 |
    > 30 |   await page.waitForTimeout(3000); // Wait for table to load
         |              ^
      31 |
      32 |   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
      33 |   console.log(machines);
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:30:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


edit

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  await page.click('text=Device Management').catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log(machines);
  await page.screenshot({ path: 'machines.png' });

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.click('text=Track Management').catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.click('text=Payment settings').catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'payment_params.png' });

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  // Navigate to Machine Management if needed, though usually dashboard has some info
  // Based on docs: [Vending Machine Management] -> [Machine Management]
  await page.click('text=Vending Machine Management').catch(() => {});
  await page.click('text=Machine Management').catch(() => {});

  await page.waitForTimeout(3000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log(machines);
  await page.screenshot({ path: 'machines.png' });

  // 3. Check Commodity / Track
  console.log('--- COMMODITY MANAGEMENT ---');
  await page.click('text=Commodity Management').catch(() => {});
  await page.click('text=Commodity Information').catch(() => {});
  await page.waitForTimeout(2000);
  await page.screenshot({ path: 'commodities.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Setting of Payment Parameters').catch(() => {});
  await page.waitForTimeout(2000);
  await page.screenshot({ path: 'payment_params.png' });


    ...
 21   await page.waitForURL(/.*main.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to main, current:', page.url()));
 22
 23   // 2. Map Machine List
 24   console.log('--- MACHINE LIST ---');
-25   // Navigate to Machine Management if needed, though usually dashboard has some info
-26   // Based on docs: [Vending Machine Management] -> [Machine Management]
-27   await page.click('text=Vending Machine Management').catch(() => {});
-28   await page.click('text=Machine Management').catch(() => {});
+25   await page.click('text=Machine').catch(() => {});
+26   await page.click('text=Device Management').catch(() => {});
 29
-30   await page.waitForTimeout(3000); // Wait for table to load
+28   await page.waitForTimeout(5000); // Wait for table to load
 31
 32   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
 33   console.log(machines);
 34   await page.screenshot({ path: 'machines.png' });
 35
 36   // 3. Check Commodity / Track
-37   console.log('--- COMMODITY MANAGEMENT ---');
-38   await page.click('text=Commodity Management').catch(() => {});
-39   await page.click('text=Commodity Information').catch(() => {});
-40   await page.waitForTimeout(2000);
-41   await page.screenshot({ path: 'commodities.png' });
+35   console.log('--- PRODUCTS MANAGEMENT ---');
+36   await page.click('text=Products').catch(() => {});
+37   await page.click('text=Track Management').catch(() => {});
+38   await page.waitForTimeout(3000);
+39   await page.screenshot({ path: 'tracks.png' });
 42
 43   // 4. Look for Payment Settings
 44   console.log('--- PAYMENT SETTINGS ---');
-45   await page.click('text=Setting of Payment Parameters').catch(() => {});
-46   await page.waitForTimeout(2000);
+43   await page.click('text=Payment').catch(() => {});
+44   await page.click('text=Payment settings').catch(() => {});
+45   await page.waitForTimeout(3000);
 47   await page.screenshot({ path: 'payment_params.png' });
 48
 49   // Search for external/third-party
 50   const bodyText = await page.innerText('body');
    ...


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 9.6s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 11ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1447ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 176ms

Running 1 test using 1 worker

URL did not change to main, current: https://dnymer.ourvend.com/#/home
--- MACHINE LIST ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (47.7s)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 45000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      26 |   await page.click('text=Device Management').catch(() => {});
      27 |
    > 28 |   await page.waitForTimeout(5000); // Wait for table to load
         |              ^
      29 |
      30 |   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
      31 |   console.log(machines);
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:28:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


Cloud Code Assist API error (429): No capacity available for model gemini-3-flash-preview on the server


  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  // Use more specific selector from screenshot
  await page.locator('li').filter({ hasText: /^Machine$/ }).click().catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log(machines);
  await page.screenshot({ path: 'machines.png' });

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('li').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('li').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'payment_params.png' });

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  await page.click('text=Device Management').catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log(machines);
  await page.screenshot({ path: 'machines.png' });

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.click('text=Track Management').catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.click('text=Payment settings').catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'payment_params.png' });


    ...
 22
 23   // 2. Map Machine List
 24   console.log('--- MACHINE LIST ---');
 25   await page.click('text=Machine').catch(() => {});
-26   await page.click('text=Device Management').catch(() => {});
+26   // Use more specific selector from screenshot
+27   await page.locator('li').filter({ hasText: /^Machine$/ }).click().catch(() => {});
 27
 28   await page.waitForTimeout(5000); // Wait for table to load
 29
 30   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
    ...
 33
 34   // 3. Check Commodity / Track
 35   console.log('--- PRODUCTS MANAGEMENT ---');
 36   await page.click('text=Products').catch(() => {});
-37   await page.click('text=Track Management').catch(() => {});
+38   await page.locator('li').filter({ hasText: 'Track Management' }).click().catch(() => {});
 38   await page.waitForTimeout(3000);
 39   await page.screenshot({ path: 'tracks.png' });
 40
 41   // 4. Look for Payment Settings
 42   console.log('--- PAYMENT SETTINGS ---');
 43   await page.click('text=Payment').catch(() => {});
-44   await page.click('text=Payment settings').catch(() => {});
+45   await page.locator('li').filter({ hasText: 'Payment settings' }).click().catch(() => {});
 45   await page.waitForTimeout(3000);
 46   await page.screenshot({ path: 'payment_params.png' });
 47
 48   // Search for external/third-party
    ...


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 10.0s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 10ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1370ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 185ms

Running 1 test using 1 worker

URL did not change to main, current: https://dnymer.ourvend.com/#/home
--- MACHINE LIST ---
[
  'Machine Number\tMachine Name\tInstitution Name\tMachine Model\tMachine Type\tMachine Address\tNetwork Status\tOnline Status\tSoftware Activation Status\tSW Activation Time\tSoftware Expiration Time\tSale Status\tOperation',
  ' \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n ',
  'P00002604030001\tP00002604030001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：898604251024C0009302\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:42:42\n' +
    '\t\n' +
    '2027-04-03 16:42:42\n' +
    '\tOn sale\t',
  'P20602604030001\tP20602604030001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:00:51\n' +
    '\t\n' +
    '2027-04-03 16:00:51\n' +
    '\tOn sale\t',
  'P02562604020001\tP02562604020001\tcc一级机构\tTCN-CSC-8C(V49)(AB04)（安装加高款制冷）英文版\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860412102580005631\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-08 17:46:11\n' +
    '\t\n' +
    '2027-04-08 17:46:11\n' +
    '\tOn sale\t',
  'P00002604010001\tP00002604010001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-01 09:25:58\n' +
    '\t\n' +
    '2027-04-01 09:25:58\n' +
    '\tOn sale\t',
  'P02562603280002\tP02562603280002\tcc一级机构\tAF-CSC-60C(V22)-GS(AB04)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：Excellent signal\n' +
    'ICCID：89860412102580005512\n' +
    '\t\n' +
    'Online\n' +
    '\tActivated\t\n' +
    '2026-04-08 16:04:07\n' +
    '\t\n' +
    '2027-04-08 16:04:07\n' +
    '\tOn sale\t',
  'P00002603170001\tP00002603170001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860812192370160088\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-17 20:13:51\n' +
    '\t\n' +
    '2027-03-17 20:13:51\n' +
    '\tOn sale\t',
  'P00002603090001\tP00002603090001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-09 21:21:25\n' +
    '\t\n' +
    '2027-03-09 21:21:25\n' +
    '\tOn sale\t',
  'P02562511280002\tP02562511280002\tcc一级机构\tTCN-CSC-10N(V10)(AC02)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：Ethernet\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-07 14:25:48\n' +
    '\t\n' +
    '2027-04-07 14:25:48\n' +
    '\tOn sale\t',
  'P00002511240004\tP00002511240004\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2025-11-25 20:26:37\n' +
    '\t\n' +
    '2026-11-25 20:26:37\n' +
    '\tOn sale\t'
]
--- PRODUCTS MANAGEMENT ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (47.6s)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 45000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      37 |   await page.click('text=Products').catch(() => {});
      38 |   await page.locator('li').filter({ hasText: 'Track Management' }).click().catch(() => {});
    > 39 |   await page.waitForTimeout(3000);
         |              ^
      40 |   await page.screenshot({ path: 'tracks.png' });
      41 |
      42 |   // 4. Look for Payment Settings
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:39:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  // Use locator for sub-menu
  await page.locator('span').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('span').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'payment_params.png' });

  // 5. Look for Remote Toggle (Inside Machine list, look at one machine's settings)
  console.log('--- MACHINE SETTINGS ---');
  await page.click('text=Machine').catch(() => {});
  await page.locator('span').filter({ hasText: /^Machine$/ }).click().catch(() => {});
  await page.waitForTimeout(3000);
  // Click the gear icon (settings) for the first machine
  await page.locator('.anticon-setting').first().click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'machine_settings.png' });

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  // Use locator for sub-menu
  await page.locator('li').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('li').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'payment_params.png' });


Could not find the exact text in /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts. The old text must match exactly including all whitespace and newlines.


import { test, expect } from '@playwright/test';

test('inspect ourvend panel', async ({ page }) => {
  // 1. Login
  await page.goto('https://dnymer.ourvend.com/');

  // Wait for login form
  await page.waitForSelector('input[placeholder="Username/email"]', { timeout: 10000 });

  await page.fill('input[placeholder="Username/email"]', 'cc');
  await page.fill('input[placeholder*="Password"]', 'ys123456');

  // Click login button
  await page.click('button:has-text("Login")');

  // 1b. Handle Institution Selection
  await page.waitForSelector('text=cc一级机构', { timeout: 15000 });
  await page.click('text=cc一级机构');

  // Wait for dashboard or redirection
  await page.waitForURL(/.*main.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to main, current:', page.url()));

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  // Use more specific selector from screenshot
  await page.locator('li').filter({ hasText: /^Machine$/ }).click().catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log(machines);
  await page.screenshot({ path: 'machines.png' });

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('li').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'tracks.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('li').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'payment_params.png' });

  // Search for external/third-party
  const bodyText = await page.innerText('body');
  if (bodyText.includes('Third-party') || bodyText.includes('External') || bodyText.includes('Callback') || bodyText.includes('API')) {
    console.log('FOUND PAYMENT INTEGRATION KEYWORDS');
  }

  // 5. Look for Remote Toggle
  console.log('--- REMOTE TOGGLE ---');
  // Usually inside Machine Management -> Edit or similar
  await page.screenshot({ path: 'final_state.png' });
});


write

import { test, expect } from '@playwright/test';

test('inspect ourvend panel', async ({ page }) => {
  test.setTimeout(90000); // Higher timeout for deep navigation

  // 1. Login
  await page.goto('https://dnymer.ourvend.com/');

  // Wait for login form
  await page.waitForSelector('input[placeholder="Username/email"]', { timeout: 10000 });

  await page.fill('input[placeholder="Username/email"]', 'cc');
  await page.fill('input[placeholder*="Password"]', 'ys123456');

  // Click login button
  await page.click('button:has-text("Login")');

  // 1b. Handle Institution Selection
  await page.waitForSelector('text=cc一级机构', { timeout: 15000 });
  await page.click('text=cc一级机构');

  // Wait for dashboard or redirection
  await page.waitForURL(/.*home.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to home, current:', page.url()));

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  await page.locator('span').filter({ hasText: /^Machine$/ }).click().catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log('MACHINES:', machines);
  await page.screenshot({ path: 'machines_list.png' });

  // 2b. Machine Settings (Check for Remote toggle)
  console.log('--- MACHINE SETTINGS ---');
  // Click the gear icon (settings) for the first machine (the TCN-CSC-8C)
  await page.locator('.anticon-setting').nth(2).click().catch(() => {}); // nth(2) is the 3rd machine (TCN-CSC-8C)
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'machine_settings_popup.png' });
  const settingsText = await page.innerText('body');
  if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
    console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
  }
  await page.keyboard.press('Escape'); // Close popup

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('span').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'tracks_list.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('span').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'payment_params_list.png' });

  // Search for external/third-party
  const bodyText = await page.innerText('body');
  if (bodyText.includes('Third-party') || bodyText.includes('External') || bodyText.includes('Callback') || bodyText.includes('API')) {
    console.log('FOUND PAYMENT INTEGRATION KEYWORDS');
  }

  // 5. Final state
  await page.screenshot({ path: 'final_state.png' });
});


Successfully wrote 2957 bytes to /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 9.2s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 16ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1366ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 180ms

Running 1 test using 1 worker

--- MACHINE LIST ---
MACHINES: [ 'Rank\tProduct Name\tSales Volume', ' \n\t\n \n\t\n ', 'No data' ]
--- MACHINE SETTINGS ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (1.6m)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 90000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      38 |   // Click the gear icon (settings) for the first machine (the TCN-CSC-8C)
      39 |   await page.locator('.anticon-setting').nth(2).click().catch(() => {}); // nth(2) is the 3rd machine (TCN-CSC-8C)
    > 40 |   await page.waitForTimeout(3000);
         |              ^
      41 |   await page.screenshot({ path: 'machine_settings_popup.png' });
      42 |   const settingsText = await page.innerText('body');
      43 |   if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:40:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


Read image file [image/png]


edit

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  // First, make sure the menu is expanded if needed (screenshot shows it is)
  await page.click('text=Machine').catch(() => {});
  // Use the specific sub-item from the sidebar
  await page.locator('.ant-menu-item').filter({ hasText: /^Machine$/ }).click().catch(() => {});

  await page.waitForTimeout(10000); // Wait longer for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log('MACHINES:', machines);
  await page.screenshot({ path: 'machines_list.png' });

  // 2. Map Machine List
  console.log('--- MACHINE LIST ---');
  await page.click('text=Machine').catch(() => {});
  await page.locator('span').filter({ hasText: /^Machine$/ }).click().catch(() => {});

  await page.waitForTimeout(5000); // Wait for table to load

  const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
  console.log('MACHINES:', machines);
  await page.screenshot({ path: 'machines_list.png' });


    ...
 23   await page.waitForURL(/.*home.*/, { timeout: 15000 }).catch(() => console.log('URL did not change to home, current:', page.url()));
 24
 25   // 2. Map Machine List
 26   console.log('--- MACHINE LIST ---');
+27   // First, make sure the menu is expanded if needed (screenshot shows it is)
 27   await page.click('text=Machine').catch(() => {});
-28   await page.locator('span').filter({ hasText: /^Machine$/ }).click().catch(() => {});
+29   // Use the specific sub-item from the sidebar
+30   await page.locator('.ant-menu-item').filter({ hasText: /^Machine$/ }).click().catch(() => {});
 29
-30   await page.waitForTimeout(5000); // Wait for table to load
+32   await page.waitForTimeout(10000); // Wait longer for table to load
 31
 32   const machines = await page.$$eval('table tr', rows => rows.map(r => r.innerText));
 33   console.log('MACHINES:', machines);
 34   await page.screenshot({ path: 'machines_list.png' });
    ...


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 9.8s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 11ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1480ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 199ms

Running 1 test using 1 worker

--- MACHINE LIST ---
MACHINES: [
  'Machine Number\tMachine Name\tInstitution Name\tMachine Model\tMachine Type\tMachine Address\tNetwork Status\tOnline Status\tSoftware Activation Status\tSW Activation Time\tSoftware Expiration Time\tSale Status\tOperation',
  ' \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n ',
  'P00002604030001\tP00002604030001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：898604251024C0009302\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:42:42\n' +
    '\t\n' +
    '2027-04-03 16:42:42\n' +
    '\tOn sale\t',
  'P20602604030001\tP20602604030001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:00:51\n' +
    '\t\n' +
    '2027-04-03 16:00:51\n' +
    '\tOn sale\t',
  'P02562604020001\tP02562604020001\tcc一级机构\tTCN-CSC-8C(V49)(AB04)（安装加高款制冷）英文版\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860412102580005631\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-08 17:46:11\n' +
    '\t\n' +
    '2027-04-08 17:46:11\n' +
    '\tOn sale\t',
  'P00002604010001\tP00002604010001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-01 09:25:58\n' +
    '\t\n' +
    '2027-04-01 09:25:58\n' +
    '\tOn sale\t',
  'P02562603280002\tP02562603280002\tcc一级机构\tAF-CSC-60C(V22)-GS(AB04)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：Excellent signal\n' +
    'ICCID：89860412102580005512\n' +
    '\t\n' +
    'Online\n' +
    '\tActivated\t\n' +
    '2026-04-08 16:04:07\n' +
    '\t\n' +
    '2027-04-08 16:04:07\n' +
    '\tOn sale\t',
  'P00002603170001\tP00002603170001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860812192370160088\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-17 20:13:51\n' +
    '\t\n' +
    '2027-03-17 20:13:51\n' +
    '\tOn sale\t',
  'P00002603090001\tP00002603090001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-09 21:21:25\n' +
    '\t\n' +
    '2027-03-09 21:21:25\n' +
    '\tOn sale\t',
  'P02562511280002\tP02562511280002\tcc一级机构\tTCN-CSC-10N(V10)(AC02)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：Ethernet\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-07 14:25:48\n' +
    '\t\n' +
    '2027-04-07 14:25:48\n' +
    '\tOn sale\t',
  'P00002511240004\tP00002511240004\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2025-11-25 20:26:37\n' +
    '\t\n' +
    '2026-11-25 20:26:37\n' +
    '\tOn sale\t'
]
--- MACHINE SETTINGS ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (1.6m)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 90000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      40 |   // Click the gear icon (settings) for the first machine (the TCN-CSC-8C)
      41 |   await page.locator('.anticon-setting').nth(2).click().catch(() => {}); // nth(2) is the 3rd machine (TCN-CSC-8C)
    > 42 |   await page.waitForTimeout(3000);
         |              ^
      43 |   await page.screenshot({ path: 'machine_settings_popup.png' });
      44 |   const settingsText = await page.innerText('body');
      45 |   if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:42:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


  // 2b. Machine Settings (Check for Remote toggle)
  console.log('--- MACHINE SETTINGS ---');
  // From screenshot, the gear icon is .anticon-setting
  // The machines are in a table. Let's try to click the gear icon for the machine with model TCN-CSC-8C
  await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'machine_settings_popup.png' });
  const settingsText = await page.innerText('body');
  if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
    console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
  }
  await page.keyboard.press('Escape'); // Close popup
  await page.waitForTimeout(1000);

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'tracks_list.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'payment_params_list.png' });

  // 2b. Machine Settings (Check for Remote toggle)
  console.log('--- MACHINE SETTINGS ---');
  // Click the gear icon (settings) for the first machine (the TCN-CSC-8C)
  await page.locator('.anticon-setting').nth(2).click().catch(() => {}); // nth(2) is the 3rd machine (TCN-CSC-8C)
  await page.waitForTimeout(3000);
  await page.screenshot({ path: 'machine_settings_popup.png' });
  const settingsText = await page.innerText('body');
  if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
    console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
  }
  await page.keyboard.press('Escape'); // Close popup

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('span').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'tracks_list.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('span').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'payment_params_list.png' });


    ...
 36   await page.screenshot({ path: 'machines_list.png' });
 37
 38   // 2b. Machine Settings (Check for Remote toggle)
 39   console.log('--- MACHINE SETTINGS ---');
-40   // Click the gear icon (settings) for the first machine (the TCN-CSC-8C)
-41   await page.locator('.anticon-setting').nth(2).click().catch(() => {}); // nth(2) is the 3rd machine (TCN-CSC-8C)
-42   await page.waitForTimeout(3000);
+40   // From screenshot, the gear icon is .anticon-setting
+41   // The machines are in a table. Let's try to click the gear icon for the machine with model TCN-CSC-8C
+42   await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click().catch(() => {});
+43   await page.waitForTimeout(5000);
 43   await page.screenshot({ path: 'machine_settings_popup.png' });
 44   const settingsText = await page.innerText('body');
 45   if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
 46     console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
 47   }
 48   await page.keyboard.press('Escape'); // Close popup
+50   await page.waitForTimeout(1000);
 49
 50   // 3. Check Commodity / Track
 51   console.log('--- PRODUCTS MANAGEMENT ---');
 52   await page.click('text=Products').catch(() => {});
-53   await page.locator('span').filter({ hasText: 'Track Management' }).click().catch(() => {});
+55   await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click().catch(() => {});
 54   await page.waitForTimeout(5000);
 55   await page.screenshot({ path: 'tracks_list.png' });
 56
 57   // 4. Look for Payment Settings
 58   console.log('--- PAYMENT SETTINGS ---');
 59   await page.click('text=Payment').catch(() => {});
-60   await page.locator('span').filter({ hasText: 'Payment settings' }).click().catch(() => {});
+62   await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click().catch(() => {});
 61   await page.waitForTimeout(5000);
 62   await page.screenshot({ path: 'payment_params_list.png' });
 63
 64   // Search for external/third-party
    ...


[WebServer]
[WebServer] > my-v0-project@0.1.0 build:e2e /mnt/rpi/repos/ballbox
[WebServer] > pnpm build
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 build /mnt/rpi/repos/ballbox
[WebServer] > node scripts/next-build-safe.mjs
[WebServer]
[WebServer] [build] linux/arm64 detected: using webpack + SWC wasm fallback to avoid native next-swc crash
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Skipping creating a lockfile at /mnt/rpi/repos/ballbox/.next/lock because we're using WASM bindings
[WebServer] ▲ Next.js 16.2.1 (webpack)
[WebServer] - Environments: .env.local, .env.production
[WebServer]
[WebServer]   Creating an optimized production build ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ✓ Compiled successfully in 8.9s
[WebServer]   Skipping validation of types
[WebServer]   Finished TypeScript config validation in 10ms ...
[WebServer]   Collecting page data using 3 workers ...
[WebServer]   Generating static pages using 3 workers (0/52) ...
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer] ⚠ experimental.useWasmBinary is not an option for supported platform linux/arm64 and will be ignored.
[WebServer]   Generating static pages using 3 workers (13/52)
[WebServer]   Generating static pages using 3 workers (26/52)
[WebServer]   Generating static pages using 3 workers (39/52)
[WebServer] ✓ Generating static pages using 3 workers (52/52) in 1360ms
[WebServer]   Finalizing page optimization ...
[WebServer]   Collecting build traces ...
[WebServer]
[WebServer] Route (app)
[WebServer] ┌ ○ /
[WebServer] ├ ○ /_not-found
[WebServer] ├ ƒ /admin
[WebServer] ├ ƒ /admin/login
[WebServer] ├ ƒ /admin/network
[WebServer] ├ ƒ /admin/payments
[WebServer] ├ ƒ /admin/players
[WebServer] ├ ƒ /admin/screens
[WebServer] ├ ƒ /admin/sports
[WebServer] ├ ƒ /admin/tvs
[WebServer] ├ ƒ /api/account/session
[WebServer] ├ ƒ /api/admin/logout
[WebServer] ├ ƒ /api/admin/payments/operations
[WebServer] ├ ƒ /api/admin/payments/sessions
[WebServer] ├ ƒ /api/admin/payments/sessions/[sessionId]
[WebServer] ├ ƒ /api/admin/players
[WebServer] ├ ƒ /api/admin/players/[playerId]
[WebServer] ├ ƒ /api/admin/players/[playerId]/memberships
[WebServer] ├ ƒ /api/admin/players/memberships/[membershipId]
[WebServer] ├ ƒ /api/admin/session
[WebServer] ├ ƒ /api/admin/sports/classes
[WebServer] ├ ƒ /api/admin/sports/classes/[classId]
[WebServer] ├ ƒ /api/admin/sports/coaches
[WebServer] ├ ƒ /api/admin/sports/coaches/[coachId]
[WebServer] ├ ƒ /api/admin/sports/open-matches
[WebServer] ├ ƒ /api/admin/sports/open-matches/[matchId]
[WebServer] ├ ƒ /api/admin/sports/operations
[WebServer] ├ ƒ /api/admin/summary
[WebServer] ├ ƒ /api/admin/tvs/assignments/[assignmentId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/assignments
[WebServer] ├ ƒ /api/admin/tvs/campaigns/[campaignId]/creatives
[WebServer] ├ ƒ /api/admin/tvs/creatives/[creativeId]
[WebServer] ├ ƒ /api/admin/tvs/operations
[WebServer] ├ ƒ /api/admin/tvs/screens
[WebServer] ├ ƒ /api/admin/tvs/screens/[screenId]
[WebServer] ├ ƒ /api/admin/tvs/tv-devices
[WebServer] ├ ƒ /api/admin/tvs/tv-devices/[tvDeviceId]
[WebServer] ├ ƒ /api/atc-public/availability/sportclubs/[sportclubId]
[WebServer] ├ ƒ /api/classes/logout
[WebServer] ├ ƒ /api/classes/offers
[WebServer] ├ ƒ /api/classes/offers/[offerId]
[WebServer] ├ ƒ /api/classes/requests
[WebServer] ├ ƒ /api/classes/session
[WebServer] ├ ƒ /api/clubs/accounts
[WebServer] ├ ƒ /api/clubs/coaches
[WebServer] ├ ƒ /api/clubs/coaches/[coachId]
[WebServer] ├ ƒ /api/clubs/invites
[WebServer] ├ ƒ /api/clubs/logout
[WebServer] ├ ƒ /api/clubs/manual-classes
[WebServer] ├ ƒ /api/clubs/me
[WebServer] ├ ƒ /api/clubs/session
[WebServer] ├ ƒ /api/clubs/venues
[WebServer] ├ ƒ /api/clubs/venues/[venueId]
[WebServer] ├ ƒ /api/coaches/accounts
[WebServer] ├ ƒ /api/coaches/availability
[WebServer] ├ ƒ /api/coaches/clubs
[WebServer] ├ ƒ /api/coaches/invites/[token]
[WebServer] ├ ƒ /api/coaches/logout
[WebServer] ├ ƒ /api/coaches/me
[WebServer] ├ ƒ /api/coaches/session
[WebServer] ├ ƒ /api/coaches/students
[WebServer] ├ ƒ /api/coaches/students/[bookingId]
[WebServer] ├ ƒ /api/coaches/students/players/[playerId]
[WebServer] ├ ƒ /api/integrations/payments/approved
[WebServer] ├ ƒ /api/integrations/payments/health
[WebServer] ├ ƒ /api/integrations/payments/orders
[WebServer] ├ ƒ /api/integrations/payments/sessions
[WebServer] ├ ƒ /api/network
[WebServer] ├ ƒ /api/network/[clubId]
[WebServer] ├ ƒ /api/network/[clubId]/venues
[WebServer] ├ ƒ /api/network/[clubId]/venues/[venueId]
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines
[WebServer] ├ ƒ /api/network/venues/[venueId]/vending-machines/[vendingMachineId]
[WebServer] ├ ƒ /api/players
[WebServer] ├ ƒ /api/sports
[WebServer] ├ ƒ /api/tvs/health
[WebServer] ├ ƒ /api/tvs/heartbeat
[WebServer] ├ ƒ /api/tvs/impression
[WebServer] ├ ƒ /api/tvs/manifest/[screenId]
[WebServer] ├ ƒ /api/tvs/screens
[WebServer] ├ ƒ /classes
[WebServer] ├ ƒ /classes-by-date
[WebServer] ├ ƒ /classes/[offerId]
[WebServer] ├ ƒ /classes/login
[WebServer] ├ ƒ /classes/me
[WebServer] ├ ƒ /clubs
[WebServer] ├ ƒ /clubs/coaches
[WebServer] ├ ƒ /clubs/venues/[venueId]
[WebServer] ├ ○ /coaches
[WebServer] ├ ƒ /coaches/settings
[WebServer] ├ ƒ /notification/mercadopago
[WebServer] └ ƒ /player/[screenId]
[WebServer]
[WebServer]
[WebServer] ƒ Proxy (Middleware)
[WebServer]
[WebServer] ○  (Static)   prerendered as static content
[WebServer] ƒ  (Dynamic)  server-rendered on demand
[WebServer]
[WebServer]
[WebServer] > my-v0-project@0.1.0 start:e2e /mnt/rpi/repos/ballbox
[WebServer] > next start --port 3020
[WebServer]
[WebServer] ▲ Next.js 16.2.1
[WebServer] - Local:         http://localhost:3020
[WebServer] - Network:       http://192.168.1.33:3020
[WebServer] ✓ Ready in 178ms

Running 1 test using 1 worker

--- MACHINE LIST ---
MACHINES: [
  'Machine Number\tMachine Name\tInstitution Name\tMachine Model\tMachine Type\tMachine Address\tNetwork Status\tOnline Status\tSoftware Activation Status\tSW Activation Time\tSoftware Expiration Time\tSale Status\tOperation',
  ' \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n \n\t\n ',
  'P00002604030001\tP00002604030001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：898604251024C0009302\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:42:42\n' +
    '\t\n' +
    '2027-04-03 16:42:42\n' +
    '\tOn sale\t',
  'P20602604030001\tP20602604030001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-03 16:00:51\n' +
    '\t\n' +
    '2027-04-03 16:00:51\n' +
    '\tOn sale\t',
  'P02562604020001\tP02562604020001\tcc一级机构\tTCN-CSC-8C(V49)(AB04)（安装加高款制冷）英文版\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860412102580005631\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-08 17:46:11\n' +
    '\t\n' +
    '2027-04-08 17:46:11\n' +
    '\tOn sale\t',
  'P00002604010001\tP00002604010001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-01 09:25:58\n' +
    '\t\n' +
    '2027-04-01 09:25:58\n' +
    '\tOn sale\t',
  'P02562603280002\tP02562603280002\tcc一级机构\tAF-CSC-60C(V22)-GS(AB04)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：Excellent signal\n' +
    'ICCID：89860412102580005512\n' +
    '\t\n' +
    'Online\n' +
    '\tActivated\t\n' +
    '2026-04-08 16:04:07\n' +
    '\t\n' +
    '2027-04-08 16:04:07\n' +
    '\tOn sale\t',
  'P00002603170001\tP00002603170001\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：89860812192370160088\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-17 20:13:51\n' +
    '\t\n' +
    '2027-03-17 20:13:51\n' +
    '\tOn sale\t',
  'P00002603090001\tP00002603090001\tcc一级机构\t\t\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：4G\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-03-09 21:21:25\n' +
    '\t\n' +
    '2027-03-09 21:21:25\n' +
    '\tOn sale\t',
  'P02562511280002\tP02562511280002\tcc一级机构\tTCN-CSC-10N(V10)(AC02)\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：Ethernet\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2026-04-07 14:25:48\n' +
    '\t\n' +
    '2027-04-07 14:25:48\n' +
    '\tOn sale\t',
  'P00002511240004\tP00002511240004\tcc一级机构\t\tSpring machine\t\t\n' +
    'Telecom Operator：\n' +
    'Network type：WIFI\n' +
    'Signal strength：No signal\n' +
    'ICCID：\n' +
    '\t\n' +
    'Offline\n' +
    '\tActivated\t\n' +
    '2025-11-25 20:26:37\n' +
    '\t\n' +
    '2026-11-25 20:26:37\n' +
    '\tOn sale\t'
]
--- MACHINE SETTINGS ---
  ✘  1 [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel (1.6m)

  1) [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ────────────────────

    Test timeout of 90000ms exceeded.

    Error: page.waitForTimeout: Target page, context or browser has been closed

      41 |   // The machines are in a table. Let's try to click the gear icon for the machine with model TCN-CSC-8C
      42 |   await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click().catch(() => {});
    > 43 |   await page.waitForTimeout(5000);
         |              ^
      44 |   await page.screenshot({ path: 'machine_settings_popup.png' });
      45 |   const settingsText = await page.innerText('body');
      46 |   if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
        at /mnt/rpi/repos/ballbox/tests/e2e/inspect-ourvend.spec.ts:43:14

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/video.webm
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/inspect-ourvend-inspect-ourvend-panel-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/inspect-ourvend-inspect-ourvend-panel-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  1 failed
    [chromium] › tests/e2e/inspect-ourvend.spec.ts:3:5 › inspect ourvend panel ─────────────────────

Command exited with code 1


  // 2b. Machine Settings (Check for Remote toggle)
  console.log('--- MACHINE SETTINGS ---');
  // From screenshot, the gear icon is .anticon-setting
  // The machines are in a table. Let's try to click the gear icon for the machine with model TCN-CSC-8C
  await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'machine_settings_popup.png' });
  const settingsText = await page.innerText('body');
  if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
    console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
  }
  await page.keyboard.press('Escape'); // Close popup
  await page.waitForTimeout(1000);

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'tracks_list.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click().catch(() => {});
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'payment_params_list.png' });

  // 2b. Machine Settings (Check for Remote toggle)
  console.log('--- MACHINE SETTINGS ---');
  // Scroll into view if needed
  await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').scrollIntoViewIfNeeded();
  await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click();
  await page.waitForTimeout(5000);
  await page.screenshot({ path: 'machine_settings_popup.png' });
  const settingsText = await page.innerText('body');
  if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
    console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
  }
  await page.keyboard.press('Escape'); // Close popup
  await page.waitForTimeout(2000);

  // 3. Check Commodity / Track
  console.log('--- PRODUCTS MANAGEMENT ---');
  await page.click('text=Products').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click();
  await page.waitForTimeout(10000); // Wait longer
  await page.screenshot({ path: 'tracks_list.png' });

  // 4. Look for Payment Settings
  console.log('--- PAYMENT SETTINGS ---');
  await page.click('text=Payment').catch(() => {});
  await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click();
  await page.waitForTimeout(10000); // Wait longer
  await page.screenshot({ path: 'payment_params_list.png' });


    ...
 36   await page.screenshot({ path: 'machines_list.png' });
 37
 38   // 2b. Machine Settings (Check for Remote toggle)
 39   console.log('--- MACHINE SETTINGS ---');
-40   // From screenshot, the gear icon is .anticon-setting
-41   // The machines are in a table. Let's try to click the gear icon for the machine with model TCN-CSC-8C
-42   await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click().catch(() => {});
+40   // Scroll into view if needed
+41   await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').scrollIntoViewIfNeeded();
+42   await page.locator('tr').filter({ hasText: 'TCN-CSC-8C' }).locator('.anticon-setting').click();
 43   await page.waitForTimeout(5000);
 44   await page.screenshot({ path: 'machine_settings_popup.png' });
 45   const settingsText = await page.innerText('body');
 46   if (settingsText.includes('Remote') || settingsText.includes('Remote track')) {
 47     console.log('FOUND REMOTE TRACK CONFIG IN SETTINGS');
 48   }
 49   await page.keyboard.press('Escape'); // Close popup
-50   await page.waitForTimeout(1000);
+50   await page.waitForTimeout(2000);
 51
 52   // 3. Check Commodity / Track
 53   console.log('--- PRODUCTS MANAGEMENT ---');
 54   await page.click('text=Products').catch(() => {});
-55   await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click().catch(() => {});
-56   await page.waitForTimeout(5000);
+55   await page.locator('.ant-menu-item').filter({ hasText: 'Track Management' }).click();
+56   await page.waitForTimeout(10000); // Wait longer
 57   await page.screenshot({ path: 'tracks_list.png' });
 58
 59   // 4. Look for Payment Settings
 60   console.log('--- PAYMENT SETTINGS ---');
 61   await page.click('text=Payment').catch(() => {});
-62   await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click().catch(() => {});
-63   await page.waitForTimeout(5000);
+62   await page.locator('.ant-menu-item').filter({ hasText: 'Payment settings' }).click();
+63   await page.waitForTimeout(10000); // Wait longer
 64   await page.screenshot({ path: 'payment_params_list.png' });
 65
 66   // Search for external/third-party
 67   const bodyText = await page.innerText('body');
    ...