Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
6.7 KiB
6.7 KiB
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: launch_readiness.spec.ts >> Launch Readiness E2E & Visual Verification >> 01. Should render desktop app with Free Tier AdBanner and Support button
- Location: tests\e2e\launch_readiness.spec.ts:72:7
Error details
TimeoutError: electronApplication.firstWindow: Timeout 30000ms exceeded while waiting for event "window"
"afterAll" hook timeout of 60000ms exceeded.
Test source
1 | import * as fs from 'fs';
2 | import * as path from 'path';
3 | import { test, expect, _electron as electron } from '@playwright/test';
4 |
5 | const SCREENSHOT_DIR = 'C:/Users/encep/.gemini/antigravity-cli/brain/3ab7ae82-5634-41d5-93a7-3c12c22503e2/screenshots';
6 |
7 | test.describe('Launch Readiness E2E & Visual Verification', () => {
8 | test.describe.configure({ mode: 'serial' });
9 | let electronApp: any;
10 | let window: any;
11 |
12 | test.beforeAll(async () => {
13 | if (!fs.existsSync(SCREENSHOT_DIR)) {
14 | fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
15 | }
16 |
17 | electronApp = await electron.launch({
18 | args: [
19 | 'out/main/index.js',
20 | '--disable-gpu',
21 | '--no-sandbox',
22 | '--user-data-dir=C:/Users/encep/AppData/Local/Temp/playwright-d3ro-launch-test-' + Date.now(),
23 | ],
24 | env: {
25 | ...process.env,
26 | NODE_ENV: 'test',
27 | },
28 | });
29 |
30 | // Poll for main window (excluding popup windows)
31 | for (let i = 0; i < 40; i++) {
32 | for (const w of electronApp.windows()) {
33 | try {
34 | const url = w.url();
35 | if (url && url.includes('index.html') && !url.includes('popups/')) {
36 | window = w;
37 | break;
38 | }
39 | } catch {
40 | // ignore
41 | }
42 | }
43 | if (window) break;
44 | await new Promise((r) => setTimeout(r, 500));
45 | }
46 |
47 | if (!window) {
48 | window = electronApp.windows()[0] || await electronApp.firstWindow();
49 | }
50 | await window.waitForLoadState('domcontentloaded');
51 |
52 | // Bypass onboarding via IPC config set
53 | await window.evaluate(async () => {
54 | if (window.electronAPI && window.electronAPI.config) {
55 | await window.electronAPI.config.set({ key: 'onboardingCompleted', value: true });
56 | await window.electronAPI.config.set({ key: 'appUsageMode', value: 'online' });
57 | }
58 | });
59 |
60 | await window.waitForTimeout(500);
61 | await window.reload();
62 | await window.waitForLoadState('domcontentloaded');
63 | await window.waitForTimeout(1500);
64 | });
65 |
> 66 | test.afterAll(async () => {
| ^ "afterAll" hook timeout of 60000ms exceeded.
67 | if (electronApp) {
68 | await electronApp.close();
69 | }
70 | });
71 |
72 | test('01. Should render desktop app with Free Tier AdBanner and Support button', async () => {
73 | // Check if sidebar has Customer Support button
74 | const supportBtn = window.locator('text=/^(Customer Support|고객지원)$/').first();
75 | await expect(supportBtn).toBeVisible({ timeout: 10000 });
76 |
77 | // Check if Free Tier AdBanner is visible
78 | const adBanner = window.locator('text=/Cursor AI/').first();
79 | await expect(adBanner).toBeVisible({ timeout: 10000 });
80 |
81 | // Take screenshot of main window with AdBanner and sidebar
82 | await window.screenshot({ path: path.join(SCREENSHOT_DIR, '01_desktop_main_with_adbanner.png') });
83 | });
84 |
85 | test('02. Should open SupportModal and interact with AI Customer Assistant', async () => {
86 | // Click Customer Support in sidebar
87 | await window.locator('text=/^(Customer Support|고객지원)$/').first().click();
88 | await window.waitForTimeout(500);
89 |
90 | // Verify modal header is visible
91 | await expect(window.locator('text=/D3RO Voice Customer Assistance/').first()).toBeVisible();
92 |
93 | // Click quick prompt "🎤 마이크 인식 오류"
94 | const micPrompt = window.locator('text=/마이크 인식/').first();
95 | if (await micPrompt.isVisible()) {
96 | await micPrompt.click();
97 | await window.waitForTimeout(800);
98 | }
99 |
100 | // Capture screenshot of SupportModal with AI chat
101 | await window.screenshot({ path: path.join(SCREENSHOT_DIR, '02_support_modal_ai_chat.png') });
102 |
103 | // Switch to 7-Day Refund Tab (tab 3)
104 | const refundTab = window.locator('text=/7일 자동 환불/').first();
105 | await refundTab.click();
106 | await window.waitForTimeout(500);
107 |
108 | // Click "환불 자격 자동 조회하기"
109 | const checkRefundBtn = window.locator('button:has-text("환불 자격 자동 조회하기")').first();
110 | if (await checkRefundBtn.isVisible()) {
111 | await checkRefundBtn.click();
112 | await window.waitForTimeout(1000);
113 | }
114 |
115 | // Capture screenshot of refund eligibility result
116 | await window.screenshot({ path: path.join(SCREENSHOT_DIR, '03_support_modal_refund_check.png') });
117 |
118 | // Close Support Modal
119 | await window.keyboard.press('Escape');
120 | await window.waitForTimeout(500);
121 | });
122 |
123 | test('03. Should open CheckoutModal and display Toss Payments / Stripe options', async () => {
124 | // Trigger checkout via "Remove ads with Pro" link in AdBanner
125 | const removeAdsLink = window.locator('text=/Remove ads with Pro/').first();
126 | if (await removeAdsLink.isVisible()) {
127 | await removeAdsLink.click();
128 | await window.waitForTimeout(600);
129 |
130 | // Verify Checkout Modal is visible
131 | await expect(window.locator('text=/D3RO Voice Secure Checkout/').first()).toBeVisible();
132 |
133 | // Capture screenshot of CheckoutModal
134 | await window.screenshot({ path: path.join(SCREENSHOT_DIR, '04_checkout_modal_toss_stripe.png') });
135 |
136 | // Close modal
137 | await window.keyboard.press('Escape');
138 | await window.waitForTimeout(400);
139 | }
140 | });
141 | });
142 |