# Instructions

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

# Test info

- Name: cashier-full-flow.spec.ts >> 散客做单流程 >> 散客 - 返回不产生错误
- Location: tests/cashier-full-flow.spec.ts:164:7

# Error details

```
TimeoutError: locator.click: Timeout 15000ms exceeded.
Call log:
  - waiting for getByRole('button', { name: '返回' })
    - locator resolved to <button aria-label="返回" class="p-2 -ml-2 rounded-lg pc:hover:bg-rose-50 active:scale-95 transition">…</button>
  - attempting click action
    2 × waiting for element to be visible, enabled and stable
      - element is visible, enabled and stable
      - scrolling into view if needed
      - done scrolling
      - <div class="fixed inset-0 z-50 flex items-end pad:items-stretch justify-center bg-black/30">…</div> from <main class="flex-1 min-h-0">…</main> subtree intercepts pointer events
    - retrying click action
    - waiting 20ms
    2 × waiting for element to be visible, enabled and stable
      - element is visible, enabled and stable
      - scrolling into view if needed
      - done scrolling
      - <div class="fixed inset-0 z-50 flex items-end pad:items-stretch justify-center bg-black/30">…</div> from <main class="flex-1 min-h-0">…</main> subtree intercepts pointer events
    - retrying click action
      - waiting 100ms
    29 × waiting for element to be visible, enabled and stable
       - element is visible, enabled and stable
       - scrolling into view if needed
       - done scrolling
       - <div class="fixed inset-0 z-50 flex items-end pad:items-stretch justify-center bg-black/30">…</div> from <main class="flex-1 min-h-0">…</main> subtree intercepts pointer events
     - retrying click action
       - waiting 500ms

```

# Page snapshot

```yaml
- generic [ref=e2]:
  - main [ref=e4]:
    - generic [ref=e5]:
      - generic [ref=e6]:
        - button "返回" [ref=e7] [cursor=pointer]:
          - img [ref=e8]
        - navigation [ref=e10]:
          - generic [ref=e11]:
            - generic [ref=e12]: 1. 购物车
            - generic [ref=e13]: ›
          - generic [ref=e14]:
            - generic [ref=e15]: 2. 小费
            - generic [ref=e16]: ›
          - generic [ref=e18]: 3. 付款
      - main [ref=e19]:
        - generic [ref=e20]:
          - generic [ref=e21]:
            - navigation [ref=e22]:
              - button "推荐" [ref=e23] [cursor=pointer]
              - button "服务" [ref=e24] [cursor=pointer]
              - button "产品" [ref=e25] [cursor=pointer]
              - button "储值方案" [ref=e26] [cursor=pointer]
              - button "次卡" [ref=e27] [cursor=pointer]
              - button "套餐" [ref=e28] [cursor=pointer]
            - generic [ref=e29]:
              - generic [ref=e31]:
                - img [ref=e32]
                - textbox "搜索" [ref=e35]
              - generic [ref=e37]:
                - button "纯色美甲 60 min ¥88.00" [active] [ref=e38] [cursor=pointer]:
                  - paragraph [ref=e39]: 纯色美甲
                  - paragraph [ref=e40]: 60 min
                  - paragraph [ref=e41]: ¥88.00
                - button "渐变美甲 90 min ¥138.00" [ref=e42] [cursor=pointer]:
                  - paragraph [ref=e43]: 渐变美甲
                  - paragraph [ref=e44]: 90 min
                  - paragraph [ref=e45]: ¥138.00
                - button "日式手绘花艺 120 min ¥268.00" [ref=e46] [cursor=pointer]:
                  - paragraph [ref=e47]: 日式手绘花艺
                  - paragraph [ref=e48]: 120 min
                  - paragraph [ref=e49]: ¥268.00
                - button "日式极简线条 90 min ¥198.00" [ref=e50] [cursor=pointer]:
                  - paragraph [ref=e51]: 日式极简线条
                  - paragraph [ref=e52]: 90 min
                  - paragraph [ref=e53]: ¥198.00
                - button "韩式奶油肌 90 min ¥188.00" [ref=e54] [cursor=pointer]:
                  - paragraph [ref=e55]: 韩式奶油肌
                  - paragraph [ref=e56]: 90 min
                  - paragraph [ref=e57]: ¥188.00
                - button "韩式贝壳片 105 min ¥228.00" [ref=e58] [cursor=pointer]:
                  - paragraph [ref=e59]: 韩式贝壳片
                  - paragraph [ref=e60]: 105 min
                  - paragraph [ref=e61]: ¥228.00
                - button "经典法式美甲 75 min ¥128.00" [ref=e62] [cursor=pointer]:
                  - paragraph [ref=e63]: 经典法式美甲
                  - paragraph [ref=e64]: 75 min
                  - paragraph [ref=e65]: ¥128.00
                - button "彩色法式 90 min ¥168.00" [ref=e66] [cursor=pointer]:
                  - paragraph [ref=e67]: 彩色法式
                  - paragraph [ref=e68]: 90 min
                  - paragraph [ref=e69]: ¥168.00
                - button "新娘法式甲 120 min ¥328.00" [ref=e70] [cursor=pointer]:
                  - paragraph [ref=e71]: 新娘法式甲
                  - paragraph [ref=e72]: 120 min
                  - paragraph [ref=e73]: ¥328.00
                - button "自然嫁接美睫 90 min ¥198.00" [ref=e74] [cursor=pointer]:
                  - paragraph [ref=e75]: 自然嫁接美睫
                  - paragraph [ref=e76]: 90 min
                  - paragraph [ref=e77]: ¥198.00
                - button "轻盈自然款 75 min ¥168.00" [ref=e78] [cursor=pointer]:
                  - paragraph [ref=e79]: 轻盈自然款
                  - paragraph [ref=e80]: 75 min
                  - paragraph [ref=e81]: ¥168.00
                - button "浓密娃娃款 105 min ¥268.00" [ref=e82] [cursor=pointer]:
                  - paragraph [ref=e83]: 浓密娃娃款
                  - paragraph [ref=e84]: 105 min
                  - paragraph [ref=e85]: ¥268.00
                - button "浓密芭比款 120 min ¥298.00" [ref=e86] [cursor=pointer]:
                  - paragraph [ref=e87]: 浓密芭比款
                  - paragraph [ref=e88]: 120 min
                  - paragraph [ref=e89]: ¥298.00
                - button "山茶花美睫 120 min ¥328.00" [ref=e90] [cursor=pointer]:
                  - paragraph [ref=e91]: 山茶花美睫
                  - paragraph [ref=e92]: 120 min
                  - paragraph [ref=e93]: ¥328.00
                - button "山茶花仙子款 135 min ¥388.00" [ref=e94] [cursor=pointer]:
                  - paragraph [ref=e95]: 山茶花仙子款
                  - paragraph [ref=e96]: 135 min
                  - paragraph [ref=e97]: ¥388.00
                - button "基础手部护理 45 min ¥68.00" [ref=e98] [cursor=pointer]:
                  - paragraph [ref=e99]: 基础手部护理
                  - paragraph [ref=e100]: 45 min
                  - paragraph [ref=e101]: ¥68.00
                - button "深层滋养手膜 60 min ¥128.00" [ref=e102] [cursor=pointer]:
                  - paragraph [ref=e103]: 深层滋养手膜
                  - paragraph [ref=e104]: 60 min
                  - paragraph [ref=e105]: ¥128.00
                - button "手部SPA套餐 90 min ¥198.00" [ref=e106] [cursor=pointer]:
                  - paragraph [ref=e107]: 手部SPA套餐
                  - paragraph [ref=e108]: 90 min
                  - paragraph [ref=e109]: ¥198.00
                - button "基础足部护理 60 min ¥88.00" [ref=e110] [cursor=pointer]:
                  - paragraph [ref=e111]: 基础足部护理
                  - paragraph [ref=e112]: 60 min
                  - paragraph [ref=e113]: ¥88.00
                - button "足部SPA舒缓 90 min ¥168.00" [ref=e114] [cursor=pointer]:
                  - paragraph [ref=e115]: 足部SPA舒缓
                  - paragraph [ref=e116]: 90 min
                  - paragraph [ref=e117]: ¥168.00
                - button "足部深层修复 105 min ¥228.00" [ref=e118] [cursor=pointer]:
                  - paragraph [ref=e119]: 足部深层修复
                  - paragraph [ref=e120]: 105 min
                  - paragraph [ref=e121]: ¥228.00
                - button "基础修甲护理 30 min ¥38.00" [ref=e122] [cursor=pointer]:
                  - paragraph [ref=e123]: 基础修甲护理
                  - paragraph [ref=e124]: 30 min
                  - paragraph [ref=e125]: ¥38.00
                - button "精修甲型设计 45 min ¥58.00" [ref=e126] [cursor=pointer]:
                  - paragraph [ref=e127]: 精修甲型设计
                  - paragraph [ref=e128]: 45 min
                  - paragraph [ref=e129]: ¥58.00
                - button "甲片延长 120 min ¥268.00" [ref=e130] [cursor=pointer]:
                  - paragraph [ref=e131]: 甲片延长
                  - paragraph [ref=e132]: 120 min
                  - paragraph [ref=e133]: ¥268.00
                - button "甲油胶卸除 30 min ¥38.00" [ref=e134] [cursor=pointer]:
                  - paragraph [ref=e135]: 甲油胶卸除
                  - paragraph [ref=e136]: 30 min
                  - paragraph [ref=e137]: ¥38.00
                - button "光疗甲卸除 45 min ¥58.00" [ref=e138] [cursor=pointer]:
                  - paragraph [ref=e139]: 光疗甲卸除
                  - paragraph [ref=e140]: 45 min
                  - paragraph [ref=e141]: ¥58.00
                - button "美甲+手部护理套餐 120 min ¥148.00" [ref=e142] [cursor=pointer]:
                  - paragraph [ref=e143]: 美甲+手部护理套餐
                  - paragraph [ref=e144]: 120 min
                  - paragraph [ref=e145]: ¥148.00
                - button "日式美甲+美睫套餐 180 min ¥388.00" [ref=e146] [cursor=pointer]:
                  - paragraph [ref=e147]: 日式美甲+美睫套餐
                  - paragraph [ref=e148]: 180 min
                  - paragraph [ref=e149]: ¥388.00
                - button "新娘全套美甲美睫 240 min ¥588.00" [ref=e150] [cursor=pointer]:
                  - paragraph [ref=e151]: 新娘全套美甲美睫
                  - paragraph [ref=e152]: 240 min
                  - paragraph [ref=e153]: ¥588.00
                - button "足部护理+修甲套餐 105 min ¥118.00" [ref=e154] [cursor=pointer]:
                  - paragraph [ref=e155]: 足部护理+修甲套餐
                  - paragraph [ref=e156]: 105 min
                  - paragraph [ref=e157]: ¥118.00
          - complementary [ref=e158]:
            - generic [ref=e161]:
              - img [ref=e163]
              - textbox "搜索客户（名字/手机号）..." [ref=e166]
            - paragraph [ref=e168]: 添加项目开始结账
          - generic [ref=e171]:
            - generic [ref=e172]:
              - heading "纯色美甲" [level=3] [ref=e174]
              - generic [ref=e175]:
                - generic [ref=e176]: ¥88.00
                - button "close" [ref=e177] [cursor=pointer]: ✕
            - generic [ref=e178]:
              - generic [ref=e179]: 选择服务员工*
              - generic [ref=e180]:
                - button "a alice" [ref=e181] [cursor=pointer]:
                  - generic [ref=e182]: a
                  - generic [ref=e183]: alice
                - button "e echo" [ref=e184] [cursor=pointer]:
                  - generic [ref=e185]: e
                  - generic [ref=e186]: echo
                - button "刘 刘佳" [ref=e187] [cursor=pointer]:
                  - generic [ref=e188]: 刘
                  - generic [ref=e189]: 刘佳
                - button "周 周小雨" [ref=e190] [cursor=pointer]:
                  - generic [ref=e191]: 周
                  - generic [ref=e192]: 周小雨
                - button "孙 孙燕" [ref=e193] [cursor=pointer]:
                  - generic [ref=e194]: 孙
                  - generic [ref=e195]: 孙燕
                - button "张 张婷婷" [ref=e196] [cursor=pointer]:
                  - generic [ref=e197]: 张
                  - generic [ref=e198]: 张婷婷
                - button "李 李雪" [ref=e199] [cursor=pointer]:
                  - generic [ref=e200]: 李
                  - generic [ref=e201]: 李雪
                - button "王 王小丽" [ref=e202] [cursor=pointer]:
                  - generic [ref=e203]: 王
                  - generic [ref=e204]: 王小丽
                - button "赵 赵敏" [ref=e205] [cursor=pointer]:
                  - generic [ref=e206]: 赵
                  - generic [ref=e207]: 赵敏
                - button "陈 陈美美" [ref=e208] [cursor=pointer]:
                  - generic [ref=e209]: 陈
                  - generic [ref=e210]: 陈美美
                - button "黄 黄丽丽" [ref=e211] [cursor=pointer]:
                  - generic [ref=e212]: 黄
                  - generic [ref=e213]: 黄丽丽
            - generic [ref=e214]:
              - button "取消" [ref=e215] [cursor=pointer]
              - button "请选择服务员工" [disabled] [ref=e216]
  - region "Notifications (F8)":
    - list
```

# Test source

```ts
  72  | // ═══════════════════════════════════════════
  73  | test.describe('散客做单流程', () => {
  74  | 
  75  |   test('散客 - 单服务现金结账', async ({ page }) => {
  76  |     const monitor = setupApiMonitor(page);
  77  |     await loginAndEnterStore(page);
  78  |     await enterPOS(page);
  79  | 
  80  |     // 不选客户 = 散客
  81  |     await addServiceToCart(page, '纯色美甲');
  82  | 
  83  |     // 验证购物车
  84  |     const cart = page.getByRole('complementary');
  85  |     await expect(cart.getByText('¥88.00').first()).toBeVisible();
  86  | 
  87  |     // 走到付款
  88  |     await goToPayment(page);
  89  | 
  90  |     // 验证客户来源是散客
  91  |     await expect(page.getByText('散客')).toBeVisible();
  92  | 
  93  |     // 验证应收金额
  94  |     await expect(page.getByText('¥88.00').first()).toBeVisible();
  95  | 
  96  |     // 确认收款
  97  |     await confirmPayment(page);
  98  | 
  99  |     // 验证 API 无错误
  100 |     await monitor.expectNoApiErrors();
  101 |   });
  102 | 
  103 |   test('散客 - 多服务结账', async ({ page }) => {
  104 |     const monitor = setupApiMonitor(page);
  105 |     await loginAndEnterStore(page);
  106 |     await enterPOS(page);
  107 | 
  108 |     // 加两个服务
  109 |     await addServiceToCart(page, '纯色美甲');
  110 |     await addServiceToCart(page, '渐变美甲');
  111 | 
  112 |     // 验证合计 88 + 138 = 226
  113 |     const cart = page.getByRole('complementary');
  114 |     await expect(cart.getByText('¥226.00').first()).toBeVisible();
  115 | 
  116 |     // 走到付款
  117 |     await goToPayment(page);
  118 | 
  119 |     // 确认收款
  120 |     await confirmPayment(page);
  121 |     await monitor.expectNoApiErrors();
  122 |   });
  123 | 
  124 |   test('散客 - 带小费结账', async ({ page }) => {
  125 |     const monitor = setupApiMonitor(page);
  126 |     await loginAndEnterStore(page);
  127 |     await enterPOS(page);
  128 | 
  129 |     await addServiceToCart(page, '纯色美甲');
  130 | 
  131 |     // 购物车 → 小费
  132 |     await page.getByRole('button', { name: '继续付款 ›' }).click();
  133 |     await expect(page.getByRole('heading', { name: '小费' })).toBeVisible({ timeout: 5000 });
  134 | 
  135 |     // 选 10% 小费
  136 |     await page.getByRole('button', { name: '10%' }).click();
  137 |     await page.waitForTimeout(300);
  138 | 
  139 |     // 小费 → 付款
  140 |     await page.getByRole('button', { name: '继续付款 ›' }).click();
  141 |     await expect(page.getByText('支付方式')).toBeVisible({ timeout: 5000 });
  142 | 
  143 |     // 确认收款
  144 |     await confirmPayment(page);
  145 |     await monitor.expectNoApiErrors();
  146 |   });
  147 | 
  148 |   test('散客 - 购物车删除项目', async ({ page }) => {
  149 |     await loginAndEnterStore(page);
  150 |     await enterPOS(page);
  151 | 
  152 |     await addServiceToCart(page, '纯色美甲');
  153 |     await addServiceToCart(page, '渐变美甲');
  154 | 
  155 |     // 删除第一个
  156 |     const cart = page.getByRole('complementary');
  157 |     await cart.getByRole('button', { name: '删除' }).first().click();
  158 |     await page.waitForTimeout(500);
  159 | 
  160 |     // 合计应该只剩 138
  161 |     await expect(cart.getByText('¥138.00').first()).toBeVisible();
  162 |   });
  163 | 
  164 |   test('散客 - 返回不产生错误', async ({ page }) => {
  165 |     const monitor = setupApiMonitor(page);
  166 |     await loginAndEnterStore(page);
  167 |     await enterPOS(page);
  168 | 
  169 |     await addServiceToCart(page, '纯色美甲');
  170 | 
  171 |     // 返回
> 172 |     await page.getByRole('button', { name: '返回' }).click();
      |                                                    ^ TimeoutError: locator.click: Timeout 15000ms exceeded.
  173 |     await expect(page.getByRole('heading', { name: '收银' })).toBeVisible({ timeout: 5000 });
  174 | 
  175 |     await monitor.expectNoApiErrors();
  176 |   });
  177 | });
  178 | 
  179 | // ═══════════════════════════════════════════
  180 | // 会员做单子
  181 | // ═══════════════════════════════════════════
  182 | test.describe('会员做单流程', () => {
  183 | 
  184 |   test('会员 - 搜索并关联会员后结账', async ({ page }) => {
  185 |     const monitor = setupApiMonitor(page);
  186 |     await loginAndEnterStore(page);
  187 |     await enterPOS(page);
  188 | 
  189 |     // 搜索会员
  190 |     const customerSearch = page.getByPlaceholder('搜索客户（名字/手机号）...');
  191 |     await customerSearch.fill('Ada');
  192 |     await page.waitForTimeout(1000);
  193 | 
  194 |     // 选择会员 Ada
  195 |     await page.getByRole('button', { name: /Ada/ }).first().click();
  196 |     await page.waitForTimeout(500);
  197 | 
  198 |     // 验证会员已关联
  199 |     await expect(page.getByText('Ada')).toBeVisible();
  200 |     await expect(page.getByText('876542211111')).toBeVisible();
  201 | 
  202 |     // 加服务
  203 |     await addServiceToCart(page, '纯色美甲');
  204 | 
  205 |     // 走到付款
  206 |     await goToPayment(page);
  207 | 
  208 |     // 验证会员权益显示
  209 |     await expect(page.getByText('会员权益')).toBeVisible();
  210 | 
  211 |     // 确认收款
  212 |     await confirmPayment(page);
  213 |     await monitor.expectNoApiErrors();
  214 |   });
  215 | 
  216 |   test('会员 - 切换会员', async ({ page }) => {
  217 |     await loginAndEnterStore(page);
  218 |     await enterPOS(page);
  219 | 
  220 |     // 搜索并选择 Ada
  221 |     const customerSearch = page.getByPlaceholder('搜索客户（名字/手机号）...');
  222 |     await customerSearch.fill('Ada');
  223 |     await page.waitForTimeout(1000);
  224 |     await page.getByRole('button', { name: /Ada/ }).first().click();
  225 |     await page.waitForTimeout(500);
  226 | 
  227 |     // 验证 Ada 已选中
  228 |     await expect(page.getByText('Ada')).toBeVisible();
  229 | 
  230 |     // 点切换会员
  231 |     const switchBtn = page.getByRole('button', { name: '切换会员' });
  232 |     if (await switchBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
  233 |       await switchBtn.click();
  234 |       await page.waitForTimeout(500);
  235 |       // 应该回到搜索状态
  236 |       await expect(page.getByPlaceholder('搜索客户（名字/手机号）...')).toBeVisible();
  237 |     }
  238 |   });
  239 | 
  240 |   test('会员 - 新建会员', async ({ page }) => {
  241 |     const monitor = setupApiMonitor(page);
  242 |     await loginAndEnterStore(page);
  243 |     await enterPOS(page);
  244 | 
  245 |     // 搜索一个不存在的名字
  246 |     const customerSearch = page.getByPlaceholder('搜索客户（名字/手机号）...');
  247 |     await customerSearch.fill('E2E新会员测试');
  248 |     await page.waitForTimeout(1000);
  249 | 
  250 |     // 应该出现"新建会员"选项
  251 |     const createBtn = page.getByRole('button', { name: /新建会员/ });
  252 |     if (await createBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
  253 |       await createBtn.click();
  254 |       await page.waitForTimeout(1000);
  255 |       // 验证没有 API 错误
  256 |       await monitor.expectNoApiErrors();
  257 |     }
  258 |   });
  259 | 
  260 |   test('会员 - 多服务结账', async ({ page }) => {
  261 |     const monitor = setupApiMonitor(page);
  262 |     await loginAndEnterStore(page);
  263 |     await enterPOS(page);
  264 | 
  265 |     // 关联会员
  266 |     const customerSearch = page.getByPlaceholder('搜索客户（名字/手机号）...');
  267 |     await customerSearch.fill('Ada');
  268 |     await page.waitForTimeout(1000);
  269 |     await page.getByRole('button', { name: /Ada/ }).first().click();
  270 |     await page.waitForTimeout(500);
  271 | 
  272 |     // 加两个服务
```