chore: keep release checkouts free of build output and dev automation
Release packaging walked a working tree that still carried .NET build output, Playwright run artifacts, and one-off browser automation scripts. Those files are not source, could not be reproduced from the commit, and made a clean-tree release gate impossible. Build output and test run directories are now ignored and untracked, and developer-only automation/scratch material moved under a single ignored `scripts/local/` directory. A stale admin bundle that no HTML referenced was dropped from the API server web root.
This commit is contained in:
parent
aa5fc5b7d9
commit
65ecc7aabc
100 changed files with 37 additions and 3522 deletions
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"14d0f40653af2521dfdb-08f3aac9ed96398cb1fe"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
# 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
|
||||
|
||||
```ts
|
||||
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 |
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue