feat: Sheets 템플릿 가이드 보강(TDD)

- Code.gs에 @tool/@version 헤더, 필드 매핑 TODO, try/catch 에러 처리 추가
- README.txt에 Web App 배포/필드 매핑 가이드 추가
- 테스트 추가: sheets.template.enhance.test.ts
- 전체 테스트 그린 유지
This commit is contained in:
2025-11-16 18:29:54 +09:00
parent 7928f9b6c5
commit c519055e90
3 changed files with 64 additions and 4 deletions
+15 -3
View File
@@ -68,13 +68,25 @@ export function buildExtrasForPage(page: Page, overrides?: ExtrasOverrides): Rec
const code = `/**
* Google Apps Script Web App for form submissions
* - Deploy as Web App and set URL as form action if needed.
* @tool: landing-builder
* @version: 1.0.0
*/
function doPost(e){
// TODO: handle submission to Google Sheets
return ContentService.createTextOutput('OK')
try {
// TODO: map incoming fields to sheet columns
// Example:
// const payload = JSON.parse(e.postData.contents || '{}');
// const row = [payload.name, payload.email, new Date()];
// SpreadsheetApp.openById('YOUR_SHEET_ID').getSheetByName('Sheet1').appendRow(row);
return ContentService.createTextOutput('OK')
} catch (e) {
return ContentService
.createTextOutput('ERROR: ' + (e && (e as any).message ? (e as any).message : 'unknown'))
.setMimeType(ContentService.MimeType.TEXT)
}
}
`
const readme = `Google Sheets Apps Script Template\n\n1) Apps Script에서 새 프로젝트를 만들고 아래 Code.gs를 붙여넣으세요.\n2) 배포 > 웹 앱으로 배포 후 URL을 복사해 사용하세요.`
const readme = `Google Sheets Apps Script Template\n\n1) Apps Script에서 새 프로젝트를 만들고 아래 Code.gs를 붙여넣으세요.\n2) Deploy as Web App로 배포 후 URL을 복사해 사용하세요.\n3) Map fields to columns: 제출 payload의 필드를 시트 컬럼에 매핑하세요.`
out['sheets/Code.gs'] = toBytes(code)
out['sheets/README.txt'] = toBytes(readme)
}
@@ -0,0 +1,46 @@
import { describe, it, expect } from 'vitest'
import { buildExtrasForPage } from '@/lib/exporter/extras'
import type { Page } from '@/lib/schema/page'
function td(b: Uint8Array){ return new TextDecoder().decode(b) }
const basePage: Page = {
title: 'Test',
seo: { title: 'T', description: 'D' },
theme: { primaryColor: '#0ea5e9', fontFamily: 'Inter' },
analytics: { ga4MeasurementId: '', metaPixelId: '', customHeadHtml: '' },
sections: [],
form: {
fields: [],
actionUrl: '',
spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 },
},
locale: 'en',
}
describe('Sheets template enhance', () => {
it('includes version/meta and mapping/error guide in Code.gs and README', () => {
const extras = buildExtrasForPage(basePage, { sheetsMode: 'include' })
const code = td(extras['sheets/Code.gs'])
const readme = td(extras['sheets/README.txt'])
// version/meta header
expect(code).toMatch(/@version:\s*\d+\.\d+\.\d+/)
expect(code).toMatch(/@tool:\s*landing-builder/i)
// field mapping and error handling guides
expect(code).toMatch(/TODO:\s*map incoming fields to sheet columns/i)
expect(code).toMatch(/try\s*\{/)
expect(code).toMatch(/catch\s*\(e\)/)
// README includes setup and mapping hint
expect(readme).toMatch(/Apps Script/i)
expect(readme).toMatch(/Deploy as Web App/i)
expect(readme).toMatch(/Map fields to columns/i)
})
it('respects exclude mode', () => {
const extras = buildExtrasForPage(basePage, { sheetsMode: 'exclude' })
expect(Object.keys(extras).some(k => k.startsWith('sheets/'))).toBe(false)
})
})