Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/destination-google-sheets/__tests__/examples.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ describe('buildExampleSections', () => {
expect(s.rows).toHaveLength(6) // last 6 months
// Formulas should reference customers.created (column C = index 2)
expect(s.rows[0][1]).toContain("'customers'!C2:C")
// Formula should use EDATE for Unix timestamp conversion
// Formula should use EDATE for month boundaries and DATEVALUE for ISO string parsing
expect(s.rows[0][1]).toContain('EDATE')
expect(s.rows[0][1]).toContain('DATE(1970,1,1)')
expect(s.rows[0][1]).toContain('DATEVALUE')
})

it('includes payment volume section when payment_intents has status and amount', () => {
Expand Down
47 changes: 47 additions & 0 deletions packages/destination-google-sheets/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
} from './index.js'
import {
applyBatch,
displayToField,
fieldToDisplay,
MAX_CELLS_PER_SPREADSHEET,
readEnumValidations,
readSheet,
Expand Down Expand Up @@ -2051,3 +2053,48 @@ describe('enum constraints on any column', () => {
).toBeUndefined()
})
})

describe('fieldToDisplay / displayToField', () => {
it('roundtrip — lowercase snake_case fields survive display conversion', () => {
const fields = ['id', 'created_at', 'customer_id', 'object', 'invoice_item_id']
for (const f of fields) {
expect(displayToField(fieldToDisplay(f))).toBe(f)
}
})

it('fieldToDisplay — single word gets sentence case', () => {
expect(fieldToDisplay('id')).toBe('Id')
expect(fieldToDisplay('object')).toBe('Object')
})

it('fieldToDisplay — multi-word snake_case becomes sentence case with spaces', () => {
expect(fieldToDisplay('created_at')).toBe('Created at')
expect(fieldToDisplay('customer_id')).toBe('Customer id')
})

it('fieldToDisplay — uppercase in input is normalised to lowercase (no case leakage)', () => {
expect(fieldToDisplay('API_version')).toBe('Api version')
expect(fieldToDisplay('UPPER_case')).toBe('Upper case')
})

it('fieldToDisplay — system fields (leading underscore) are returned as-is', () => {
expect(fieldToDisplay('_idx')).toBe('_idx')
expect(fieldToDisplay('_updated_at')).toBe('_updated_at')
})

it('displayToField — reverses sentence case label back to snake_case', () => {
expect(displayToField('Created at')).toBe('created_at')
expect(displayToField('Customer id')).toBe('customer_id')
expect(displayToField('Id')).toBe('id')
})

it('displayToField — system fields (leading underscore) are returned as-is', () => {
expect(displayToField('_idx')).toBe('_idx')
expect(displayToField('_updated_at')).toBe('_updated_at')
})

it('displayToField — idempotent on already-snake_case strings', () => {
expect(displayToField('customer_id')).toBe('customer_id')
expect(displayToField('id')).toBe('id')
})
})
12 changes: 7 additions & 5 deletions packages/destination-google-sheets/src/writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function colIndexToLetter(idx: number): string {
/** snake_case field name → "Sentence case" display label. System fields (_x) are returned as-is. */
export function fieldToDisplay(field: string): string {
if (field.startsWith('_')) return field
const words = field.split('_')
const words = field.split('_').map((w) => w.toLowerCase())
words[0] = words[0].charAt(0).toUpperCase() + words[0].slice(1)
return words.join(' ')
}
Expand Down Expand Up @@ -763,10 +763,12 @@ export function buildExampleSections(
for (let i = 5; i >= 0; i--) {
// EDATE shifts the first-of-month by N months; negative = past
const monthLabel = `=TEXT(EDATE(DATE(YEAR(TODAY()),MONTH(TODAY()),1),${-i}),"YYYY-MM")`
// Unix timestamp boundaries for each month
const startUnix = `(EDATE(DATE(YEAR(TODAY()),MONTH(TODAY()),1),${-i})-DATE(1970,1,1))*86400`
const endUnix = `(EDATE(DATE(YEAR(TODAY()),MONTH(TODAY()),1),${-(i - 1)})-DATE(1970,1,1))*86400`
rows.push([monthLabel, `=COUNTIFS(${createdRange},">="&${startUnix},${createdRange},"<"&${endUnix})`])
// COUNTIFS >=/< only works on numbers/dates, not text strings.
// DATEVALUE(LEFT(cell,10)) parses the "yyyy-mm-dd" prefix of the ISO string into a Sheets date serial.
const start = `EDATE(DATE(YEAR(TODAY()),MONTH(TODAY()),1),${-i})`
const end = `EDATE(DATE(YEAR(TODAY()),MONTH(TODAY()),1),${-(i - 1)})`
const parsed = `IFERROR(DATEVALUE(LEFT(${createdRange},10)),0)`
rows.push([monthLabel, `=SUMPRODUCT((${parsed}>=${start})*(${parsed}<${end}))`])
}
sections.push({
title: 'New Customers by Month',
Expand Down
Loading