CI: feature/forms-submissions #24
+48
-3
@@ -48,10 +48,55 @@ jobs:
|
||||
run: |
|
||||
npm test
|
||||
|
||||
e2e:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_USER: app
|
||||
POSTGRES_PASSWORD: app_password
|
||||
POSTGRES_DB: page_builder
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd="pg_isready -U app -d page_builder"
|
||||
--health-interval=5s
|
||||
--health-timeout=3s
|
||||
--health-retries=20
|
||||
|
||||
env:
|
||||
DATABASE_URL: postgresql://app:app_password@postgres:5432/page_builder?schema=public
|
||||
AUTH_JWT_SECRET: ${{ secrets.AUTH_JWT_SECRET }}
|
||||
AUTH_ENCRYPTION_KEY: ${{ secrets.AUTH_ENCRYPTION_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run Prisma migrations
|
||||
run: npx prisma migrate deploy
|
||||
|
||||
- name: Build Next.js app
|
||||
run: npm run build
|
||||
|
||||
- name: Run Playwright E2E tests
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
run: |
|
||||
npx playwright test
|
||||
run: npm run e2e
|
||||
|
||||
pr_and_merge:
|
||||
needs: test
|
||||
|
||||
@@ -17,7 +17,21 @@ test("프리뷰 폼 제출 후 제출 내역 페이지에서 데이터가 보여
|
||||
data: { email, password },
|
||||
});
|
||||
|
||||
expect(signupRes.status()).toBe(201);
|
||||
// 디버깅용: CI 등에서 500 이 떨어질 때 응답 바디를 함께 로그로 출력해 원인을 파악할 수 있게 한다.
|
||||
const signupStatus = signupRes.status();
|
||||
if (signupStatus !== 201) {
|
||||
// text() 는 한 번만 읽을 수 있으므로, status 체크 이후에만 호출한다.
|
||||
// CI 로그에서 이 메시지를 보고 실제 에러 원인(AUTH_JWT_SECRET, DATABASE_URL, Prisma 오류 등)을 추적한다.
|
||||
console.log("[form-submission-flow] signup error status=", signupStatus);
|
||||
try {
|
||||
const bodyText = await signupRes.text();
|
||||
console.log("[form-submission-flow] signup error body=", bodyText);
|
||||
} catch (e) {
|
||||
console.log("[form-submission-flow] signup error: body read failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
expect(signupStatus).toBe(201);
|
||||
|
||||
const setCookieHeader = signupRes.headers()["set-cookie"];
|
||||
expect(setCookieHeader).toBeTruthy();
|
||||
|
||||
@@ -1074,7 +1074,7 @@ test("폼 체크박스 옵션 간격 px 입력이 프리뷰에서도 em 스케
|
||||
expect(gapStyles.inlineRowGap.endsWith("em")).toBeTruthy();
|
||||
});
|
||||
|
||||
test("FormBlock 은 프리뷰에서 별도 폼 컨트롤러 DOM 을 렌더하지 않아야 한다 (고정 너비 설정 시)", async ({ page }) => {
|
||||
test("FormBlock 은 프리뷰에서 폼 컨트롤러 DOM 을 렌더해야 한다 (고정 너비 설정 시)", async ({ page }) => {
|
||||
await page.goto("/editor");
|
||||
|
||||
await page.getByRole("button", { name: "폼 컨트롤러" }).click();
|
||||
@@ -1093,10 +1093,10 @@ test("FormBlock 은 프리뷰에서 별도 폼 컨트롤러 DOM 을 렌더하지
|
||||
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
|
||||
|
||||
const formLocator = page.getByTestId("preview-form-controller");
|
||||
await expect(formLocator).toHaveCount(0);
|
||||
await expect(formLocator).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("FormBlock 은 프리뷰에서 별도 폼 컨트롤러 DOM 을 렌더하지 않아야 한다 (상하 여백 설정 시)", async ({ page }) => {
|
||||
test("FormBlock 은 프리뷰에서 폼 컨트롤러 DOM 을 렌더해야 한다 (상하 여백 설정 시)", async ({ page }) => {
|
||||
await page.goto("/editor");
|
||||
|
||||
await page.getByRole("button", { name: "폼 컨트롤러" }).click();
|
||||
@@ -1115,7 +1115,7 @@ test("FormBlock 은 프리뷰에서 별도 폼 컨트롤러 DOM 을 렌더하지
|
||||
await expect(page.getByRole("heading", { name: "Page Preview" })).toBeVisible();
|
||||
|
||||
const formLocator = page.getByTestId("preview-form-controller");
|
||||
await expect(formLocator).toHaveCount(0);
|
||||
await expect(formLocator).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("폼 라디오 줄간격 px 입력이 프리뷰에서도 em 스케일로 반영되어야 한다", async ({ page }) => {
|
||||
@@ -1584,8 +1584,8 @@ test("폼 컨트롤러에 매핑한 폼 요소와 버튼이 프리뷰에서 함
|
||||
const input = page.getByRole("textbox").first();
|
||||
await expect(input).toBeVisible();
|
||||
|
||||
// 프리뷰 정책: FormBlock 컨트롤러는 프리뷰에서 실제 `<form>` DOM 을 렌더하지 않는다.
|
||||
await expect(page.getByTestId("preview-form-controller")).toHaveCount(0);
|
||||
const forms = page.getByTestId("preview-form-controller");
|
||||
await expect(forms).toHaveCount(1);
|
||||
await expect(page.getByText("성공적으로 전송되었습니다.")).toHaveCount(0);
|
||||
});
|
||||
|
||||
@@ -1647,9 +1647,8 @@ test("여러 폼 블록과 여러 버튼이 있을 때 각 폼이 독립적으
|
||||
const firstInput = textboxes.nth(0);
|
||||
const secondInput = textboxes.nth(1);
|
||||
|
||||
// 프리뷰 정책: 여러 FormBlock 이 있어도 preview-form-controller DOM 은 생성되지 않아야 한다.
|
||||
const controllers = page.getByTestId("preview-form-controller");
|
||||
await expect(controllers).toHaveCount(0);
|
||||
await expect(controllers).toHaveCount(2);
|
||||
|
||||
const successMessages = page.getByText("성공적으로 전송되었습니다.");
|
||||
await expect(successMessages).toHaveCount(0);
|
||||
|
||||
Reference in New Issue
Block a user