{"version":3,"names":["test","expect","describe","beforeEach","page","goto","fill","click","waitForTimeout","waitForLoadState","hasOrders","locator","isVisible","timeout","catch","skip","orderItem","first","ordersExist","uploadSection","uploadButton","hasUploadSection","hasUploadButton","toBeTruthy","fileInput","uploadVisible","setInputFiles","name","mimeType","buffer","Buffer","from","submitButton","submitVisible","errorToast","hasError","toBeFalsy","request","loginResponse","post","data","email","password","status","toBe","loginData","json","token","access_token","uploadResponse","headers","purchase_screenshot","not"],"sources":["purchase-screenshot-upload.spec.js"],"sourcesContent":["import { test, expect } from '@playwright/test'\n\n/**\n * E2E Test: Partner Purchase Screenshot Upload\n * \n * Tests the blocking bug: 合伙人上传采购截图功能提交失败\n * \n * Prerequisites:\n * - Test user must exist in database:\n *   - Email: e2e_test_partner@fetch.com\n *   - Password: e2etest123\n *   - Role: partner\n * - If user doesn't exist, tests will be SKIPPED\n * \n * To create test user, run:\n *   cd backend && python scripts/create_test_users.py\n */\n\ntest.describe('Partner Purchase Screenshot Upload', () => {\n\n  test.beforeEach(async ({ page }) => {\n    // Login as partner\n    await page.goto('/login')\n    await page.fill('input[type=\"email\"]', 'e2e_test_partner@fetch.com')\n    await page.fill('input[type=\"password\"]', 'e2etest123')\n    await page.click('button[type=\"submit\"]')\n    \n    // Wait for navigation (with longer timeout for login redirect)\n    await page.waitForTimeout(3000)\n  })\n\n  test('should display purchase screenshot upload option in order detail', async ({ page }) => {\n    await page.goto('/dashboard')\n    await page.waitForLoadState('networkidle')\n    await page.waitForTimeout(2000)\n\n    // Check for orders first\n    const hasOrders = await page.locator('text=/未找到订单|No orders|No order found/i')\n      .isVisible({ timeout: 3000 }).catch(() => false)\n    \n    if (hasOrders) {\n      // No orders available - skip this test\n      test.skip()\n      return\n    }\n\n    // Find first order and click to open detail\n    const orderItem = page.locator('.border.rounded-lg, [class*=\"order\"]').first()\n    const ordersExist = await orderItem.isVisible({ timeout: 3000 }).catch(() => false)\n\n    if (!ordersExist) {\n      test.skip()\n      return\n    }\n\n    await orderItem.click()\n    await page.waitForTimeout(1500)\n\n    // Look for purchase screenshot related elements\n    // These selectors should match the actual UI - adjust if needed\n    const uploadSection = page.locator('text=/purchase.*screenshot|采购.*截图|screenshot.*upload/i')\n    const uploadButton = page.locator('input[type=\"file\"], button:has-text(\"Upload\"), button:has-text(\"上传\")')\n\n    // Check if upload section is visible\n    const hasUploadSection = await uploadSection.isVisible({ timeout: 3000 }).catch(() => false)\n    const hasUploadButton = await uploadButton.first().isVisible({ timeout: 3000 }).catch(() => false)\n\n    // At least one should be present for orders that need purchase screenshots\n    expect(hasUploadSection || hasUploadButton).toBeTruthy()\n  })\n\n  test('should successfully upload and submit purchase screenshot', async ({ page }) => {\n    await page.goto('/dashboard')\n    await page.waitForLoadState('networkidle')\n    await page.waitForTimeout(2000)\n\n    // Find an order\n    const orderItem = page.locator('.border.rounded-lg, [class*=\"order\"]').first()\n    const ordersExist = await orderItem.isVisible({ timeout: 3000 }).catch(() => false)\n\n    if (!ordersExist) {\n      test.skip()\n      return\n    }\n\n    await orderItem.click()\n    await page.waitForTimeout(1500)\n\n    // Look for file upload input\n    const fileInput = page.locator('input[type=\"file\"]').first()\n    const uploadVisible = await fileInput.isVisible({ timeout: 3000 }).catch(() => false)\n\n    if (!uploadVisible) {\n      // No upload section available - skip\n      test.skip()\n      return\n    }\n\n    // Create a minimal valid PNG image (1x1 pixel)\n    // Playwright can upload via buffer\n    await fileInput.setInputFiles({\n      name: 'test-screenshot.png',\n      mimeType: 'image/png',\n      buffer: Buffer.from(\n        'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',\n        'base64'\n      )\n    })\n\n    // Wait for upload to process\n    await page.waitForTimeout(2000)\n\n    // Look for submit button and click\n    const submitButton = page.locator('button:has-text(\"Submit\"), button:has-text(\"提交\"), button:has-text(\"Save\")')\n    const submitVisible = await submitButton.first().isVisible({ timeout: 2000 }).catch(() => false)\n\n    if (submitVisible) {\n      await submitButton.first().click()\n      \n      // Wait for response\n      await page.waitForTimeout(2000)\n\n      // Check for error toast/message\n      const errorToast = page.locator('text=/error|failed|错误|失败/i')\n      const hasError = await errorToast.isVisible({ timeout: 2000 }).catch(() => false)\n\n      // If there's an error, it indicates the bug is present\n      // This test will FAIL if the bug exists, helping us catch it\n      expect(hasError).toBeFalsy()\n    }\n  })\n\n  test('API: should accept purchase screenshot upload via partner endpoint', async ({ request }) => {\n    // Login first to get token\n    const loginResponse = await request.post('/api/v1/auth/login', {\n      data: {\n        email: 'e2e_test_partner@fetch.com',\n        password: 'e2etest123'\n      }\n    })\n\n    expect(loginResponse.status()).toBe(200)\n    const loginData = await loginResponse.json()\n    const token = loginData.data?.access_token\n\n    if (!token) {\n      test.skip()\n      return\n    }\n\n    // Test the screenshot upload endpoint\n    // Note: This tests the API directly, not through UI\n    // The endpoint may vary - check backend for exact path\n    const uploadResponse = await request.post('/api/v1/partner/orders', {\n      headers: {\n        'Authorization': `Bearer ${token}`,\n        'Content-Type': 'application/json'\n      },\n      data: {\n        // Test with minimal data - field names must match backend expectations\n        purchase_screenshot: 'https://example.com/test.png'\n      }\n    })\n\n    // Should not return 422 (validation error) due to field name mismatch\n    // If we get 422, it might indicate the backend expects a different field name\n    expect(uploadResponse.status()).not.toBe(422)\n  })\n})\n"],"mappings":"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","ignoreList":[]}