Skip to content

Commit 77df5fd

Browse files
authored
fix: update tests (#81)
* ambassador: add "Erica Hargreave" * ambassador: unpublish "Erica Hargreave" * ambassador: add "Erica Hargreave" * cohort: add "Ambassadors 2025" * cohort: delete "Ambassadors 2025" * cohort: add "Ambassadors 2025" * ambassador: add "Caroline Sinders" * cohort: delete "Ambassadors 2025" * cohort: add "Ambassadors 2024" * cohort: delete "Ambassadors 2024" * cohort: add "Ambassadors 2025" * page: add "test-ambassadors" (en) * page: unpublish "test-ambassadors" (en) * page: add "test-ambassadors" (en) * page: unpublish "test-ambassadors" (en) * page: add "test-ambassadors" (en) * page: unpublish "test-ambassadors" (en) * page: add "test-ambassadors" (en) * page: delete "test-ambassadors" (en) * wip: ambassador and associated content * cohort: add "alumni" * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * remove cohort * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: unpublish "ambassadors" (en) * page: add "ambassadors" (en) * page: add "test-ambs" (en) * page: delete "test-ambs" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * ambassador: unpublish "Erica Hargreave" * ambassador: add "Erica Hargreave" * ambassador: unpublish "Erica Hargreave" * ambassador: add "Erica Hargreave" * setup lifecycle and page to serialise and render ambassador * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * use ordering from strapi instead of sorting * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * fix page previews * fix linter error * lint and format * format & lint * ambassador: add "Jeremiah Lee" * ambassador: add "Kokayi Issa" * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: unpublish "test-page" (en) * page: add "test-page" (en) * page: delete "test-page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * update readme with preview setup * remove @astrojs/tailwind, fixes npm i * Component - blockquote (#11) Add BlockQuote as a component * ambassador: add "Caroline Sinders" * page: unpublish "test page" (en) * page: add "test page" (en) * ambassador: unpublish "Caroline Sinders" * ambassador: add "Caroline Sinders" * DRY the code * error handling in ambassador lifecycle * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * remove order from ambassador colection * make photo mandatory for ambassador * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * update readme, copy paths utils from main * ambassador: add "test ambassador" * ambassador: add "test ambassador 3" * ambassador: unpublish "test ambassador 3" * ambassador: add "test ambassador 3" * ambassador: delete "test ambassador 3" * ambassador: add "test mdx 4" * switch to mdx for ambassadors and add import functionality * ambassador: delete "Kokayi Issa" * remove test data * aria fixes * cleanup * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * page: unpublish "test page" (en) * page: add "test page" (en) * refactor * cleanup * ambassador: add "Stephanie Perrin" * page: unpublish "test page" (en) * page: add "test page" (en) * cleanup * ambassador: add "Stephanie Perrin2" * page: unpublish "test page" (en) * page: add "test page" (en) * make heading jsx prop for ambassador grid * page: add "About Us" (en) * page: add "Grant for web" (en) * page: add "Internet of Oppor­tunity" (en) * page: add "Interledger 2026" (en) * page: add "new page" (en) * page: add "policy-and-advocacy" (en) * update readme with future notes * Post-merge: add ambassador/blockquote serializers + update @/ imports - Create cms/src/serializers/blocks/ambassador.serializer.ts - Create cms/src/serializers/blocks/ambassadors-grid.serializer.ts - Create cms/src/serializers/blocks/blockquote.serializer.ts - Register all three in cms/src/serializers/blocks/index.ts - Update relative imports to @/ alias in ambassador/blockquote components and page-preview.astro (AmbassadorGrid, AmbassadorBlock, AmbassadorsGridBlock, BlockquoteBlock, Blockquote, page-preview) * paths and autogenerated types * lockfiles * fix: lint — prettier format + eslint no-console in DynamicZone * ambassador sync script with locale * --force flag to allow sync from non main branches * update readme, fix component inclusion in pages * fix blockquote output * format * ci: use Node 20 and frozen lockfile in lint workflow - Upgrade from EOL Node 18 to Node 20 to match local dev environment and avoid subtle runtime differences in Prettier's MDX formatting - Switch to --frozen-lockfile to prevent pnpm from re-resolving dependencies on Linux, which could hoist the transitive prettier@3.3.3 (from cms workspace) over the pinned root prettier@3.8.1 * fix: pin prettier@3.8.1 in cms workspace and fix pnpm override format The cms workspace's lockfile had prettier@3.3.3 as a transitive dependency (via prettier-plugin-packagejson). On Linux, pnpm can hoist this into root node_modules/.bin, overriding the root workspace's prettier@3.8.1 and causing the lint CI to fail with formatting errors on MDX files that pass locally. - Add pnpm.overrides.prettier = "3.8.1" to cms/package.json so the cms lockfile no longer resolves prettier@3.3.3 - Convert the pre-existing esbuild override from npm-style "overrides" to pnpm-style "pnpm.overrides" so it's actually applied by pnpm - Regenerate cms/pnpm-lock.yaml with prettier@3.8.1 throughout * fix: add root pnpm override to eliminate prettier@3.3.3 from lockfile The root pnpm-lock.yaml manages cms workspace deps including prettier-plugin-packagejson which pulls in prettier@3.3.3 as a transitive peer dep. With pnpm hoisting, this can put prettier@3.3.3 in root node_modules/.bin on Linux, shadowing the intended @3.8.1 and causing the lint CI to fail. Adding "pnpm.overrides.prettier = 3.8.1" in root package.json forces the root lockfile to resolve all prettier references to 3.8.1, eliminating the conflicting version entirely. The root devDependency alone does not prevent prettier@3.3.3 from appearing in the lockfile — the override is required for that. * remove bun lockfiles * ci: add debug step to show exact prettier diff on Linux * cleanup * fix locale lifecycle * format * refactor * format, remove compiled file * fix tsconfig * fix previews and quote rendering * format * format * review * fix(scripts/README): update content type mappings to current dirs * fix tests * format
1 parent 0d937dc commit 77df5fd

4 files changed

Lines changed: 240 additions & 85 deletions

File tree

cms/scripts/sync-mdx/mdxTransformer.test.ts

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ vi.mock('./siteSchemas', async () => {
3131
}
3232
})
3333

34-
import { getEntryField, isPageType, mdxToStrapiPayload } from './mdxTransformer'
34+
import { getEntryField, buildPagePayload } from './mdxTransformer'
35+
import {
36+
foundationPageFrontmatterSchema,
37+
summitPageFrontmatterSchema
38+
} from './siteSchemas'
3539
import type { StrapiEntry } from './strapiClient'
3640
import { createMdxFile } from './test-utils'
3741

@@ -89,50 +93,18 @@ describe('getEntryField', () => {
8993
})
9094
})
9195

92-
// Determines if a content type should be treated as a "page" with hero sections
93-
// and content blocks. Other content types (like blog-posts) aren't supported yet.
94-
describe('isPageType', () => {
95-
it('returns true for foundation-pages', () => {
96-
expect(isPageType('foundation-pages')).toBe(true)
97-
})
98-
99-
it('returns true for summit-pages', () => {
100-
expect(isPageType('summit-pages')).toBe(true)
101-
})
102-
103-
it('returns false for blog-posts', () => {
104-
// @ts-expect-error - testing with invalid content type
105-
expect(isPageType('blog-posts')).toBe(false)
106-
})
107-
108-
it('returns false for unknown content types', () => {
109-
// @ts-expect-error - testing with invalid content type
110-
expect(isPageType('unknown-type')).toBe(false)
111-
})
112-
})
113-
11496
// Core transformation from MDX files to Strapi API payloads.
11597
// Handles validation, hero section logic, and content block creation.
116-
describe('mdxToStrapiPayload', () => {
98+
describe('buildPagePayload', () => {
11799
describe('error handling', () => {
118-
it('throws for unsupported content type', () => {
119-
const mdx = createMdxFile({
120-
slug: 'test',
121-
frontmatter: { title: 'Test' }
122-
})
123-
124-
// @ts-expect-error - testing with invalid content type
125-
expect(() => mdxToStrapiPayload('blog-posts', mdx)).toThrow(
126-
'Unsupported content type'
127-
)
128-
})
129-
130100
it('throws when frontmatter fails validation', () => {
131101
const mdx = createMdxFile({
132102
slug: 'test'
133103
})
134104

135-
expect(() => mdxToStrapiPayload('foundation-pages', mdx, null)).toThrow()
105+
expect(() =>
106+
buildPagePayload(foundationPageFrontmatterSchema, mdx, null)
107+
).toThrow()
136108
})
137109
})
138110

@@ -143,7 +115,11 @@ describe('mdxToStrapiPayload', () => {
143115
frontmatter: { title: 'About Us' }
144116
})
145117

146-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
118+
const payload = buildPagePayload(
119+
foundationPageFrontmatterSchema,
120+
mdx,
121+
null
122+
)
147123

148124
expect(payload.title).toBe('About Us')
149125
})
@@ -154,7 +130,11 @@ describe('mdxToStrapiPayload', () => {
154130
frontmatter: { title: 'About' }
155131
})
156132

157-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
133+
const payload = buildPagePayload(
134+
foundationPageFrontmatterSchema,
135+
mdx,
136+
null
137+
)
158138

159139
expect(payload.slug).toBe('about-page')
160140
})
@@ -165,7 +145,11 @@ describe('mdxToStrapiPayload', () => {
165145
frontmatter: { title: 'Test' }
166146
})
167147

168-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
148+
const payload = buildPagePayload(
149+
foundationPageFrontmatterSchema,
150+
mdx,
151+
null
152+
)
169153

170154
expect(payload.publishedAt).toBeDefined()
171155
expect(typeof payload.publishedAt).toBe('string')
@@ -189,7 +173,11 @@ describe('mdxToStrapiPayload', () => {
189173
}
190174
})
191175

192-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
176+
const payload = buildPagePayload(
177+
foundationPageFrontmatterSchema,
178+
mdx,
179+
null
180+
)
193181

194182
expect(payload.title).toBe('About')
195183
expect(payload.slug).toBe('about')
@@ -209,7 +197,11 @@ describe('mdxToStrapiPayload', () => {
209197
}
210198
})
211199

212-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
200+
const payload = buildPagePayload(
201+
foundationPageFrontmatterSchema,
202+
mdx,
203+
null
204+
)
213205

214206
expect(payload.hero).toEqual({
215207
title: 'Welcome',
@@ -227,7 +219,11 @@ describe('mdxToStrapiPayload', () => {
227219
}
228220
})
229221

230-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
222+
const payload = buildPagePayload(
223+
foundationPageFrontmatterSchema,
224+
mdx,
225+
null
226+
)
231227

232228
expect(payload.hero).toEqual({
233229
title: 'About Page',
@@ -244,7 +240,11 @@ describe('mdxToStrapiPayload', () => {
244240
}
245241
})
246242

247-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
243+
const payload = buildPagePayload(
244+
foundationPageFrontmatterSchema,
245+
mdx,
246+
null
247+
)
248248

249249
expect(payload.hero).toEqual({
250250
title: 'Hero Only',
@@ -265,7 +265,11 @@ describe('mdxToStrapiPayload', () => {
265265
frontmatter: { title: 'About' }
266266
})
267267

268-
const payload = mdxToStrapiPayload('foundation-pages', mdx, existingEntry)
268+
const payload = buildPagePayload(
269+
foundationPageFrontmatterSchema,
270+
mdx,
271+
existingEntry
272+
)
269273

270274
expect(payload.hero).toEqual({
271275
title: 'Existing Hero',
@@ -280,7 +284,11 @@ describe('mdxToStrapiPayload', () => {
280284
frontmatter: { title: 'About' }
281285
})
282286

283-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
287+
const payload = buildPagePayload(
288+
foundationPageFrontmatterSchema,
289+
mdx,
290+
null
291+
)
284292

285293
expect(payload.hero).toBeUndefined()
286294
})
@@ -301,7 +309,11 @@ describe('mdxToStrapiPayload', () => {
301309
}
302310
})
303311

304-
const payload = mdxToStrapiPayload('foundation-pages', mdx, existingEntry)
312+
const payload = buildPagePayload(
313+
foundationPageFrontmatterSchema,
314+
mdx,
315+
existingEntry
316+
)
305317

306318
expect(payload.hero).toEqual({
307319
title: 'New Hero',
@@ -319,7 +331,11 @@ describe('mdxToStrapiPayload', () => {
319331
content: '## Heading\n\nParagraph text'
320332
})
321333

322-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
334+
const payload = buildPagePayload(
335+
foundationPageFrontmatterSchema,
336+
mdx,
337+
null
338+
)
323339

324340
expect(payload.content).toEqual([
325341
{
@@ -341,7 +357,11 @@ describe('mdxToStrapiPayload', () => {
341357
frontmatter: { title: 'About' }
342358
})
343359

344-
const payload = mdxToStrapiPayload('foundation-pages', mdx, existingEntry)
360+
const payload = buildPagePayload(
361+
foundationPageFrontmatterSchema,
362+
mdx,
363+
existingEntry
364+
)
345365

346366
expect(payload.content).toEqual([
347367
{ __component: 'blocks.paragraph', content: 'Existing' }
@@ -361,7 +381,11 @@ describe('mdxToStrapiPayload', () => {
361381
content: ' \n\n '
362382
})
363383

364-
const payload = mdxToStrapiPayload('foundation-pages', mdx, existingEntry)
384+
const payload = buildPagePayload(
385+
foundationPageFrontmatterSchema,
386+
mdx,
387+
existingEntry
388+
)
365389

366390
expect(payload.content).toEqual([
367391
{ __component: 'blocks.paragraph', content: 'Kept' }
@@ -374,7 +398,11 @@ describe('mdxToStrapiPayload', () => {
374398
frontmatter: { title: 'About' }
375399
})
376400

377-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
401+
const payload = buildPagePayload(
402+
foundationPageFrontmatterSchema,
403+
mdx,
404+
null
405+
)
378406

379407
expect(payload.content).toBeUndefined()
380408
})
@@ -391,7 +419,11 @@ describe('mdxToStrapiPayload', () => {
391419
content: 'New content'
392420
})
393421

394-
const payload = mdxToStrapiPayload('foundation-pages', mdx, existingEntry)
422+
const payload = buildPagePayload(
423+
foundationPageFrontmatterSchema,
424+
mdx,
425+
existingEntry
426+
)
395427

396428
expect(payload.content).toEqual([
397429
{ __component: 'blocks.paragraph', content: 'New content' }
@@ -405,7 +437,11 @@ describe('mdxToStrapiPayload', () => {
405437
content: undefined
406438
})
407439

408-
const payload = mdxToStrapiPayload('foundation-pages', mdx, null)
440+
const payload = buildPagePayload(
441+
foundationPageFrontmatterSchema,
442+
mdx,
443+
null
444+
)
409445

410446
expect(payload.content).toBeUndefined()
411447
})
@@ -419,7 +455,7 @@ describe('mdxToStrapiPayload', () => {
419455
content: 'Summit content'
420456
})
421457

422-
const payload = mdxToStrapiPayload('summit-pages', mdx, null)
458+
const payload = buildPagePayload(summitPageFrontmatterSchema, mdx, null)
423459

424460
expect(payload.title).toBe('Schedule')
425461
expect(payload.slug).toBe('schedule')

cms/scripts/sync-mdx/syncOperations.test.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import type { ContentTypes } from './config'
1010
import type { SyncContext, SyncResults } from './types'
1111
import { createMdxFile } from './test-utils'
1212

13-
vi.mock('./mdxTransformer', () => ({
14-
mdxToStrapiPayload: vi.fn(() => ({ title: 'Mocked Payload', slug: 'mocked' }))
15-
}))
16-
1713
vi.mock('./localeMatch', () => ({
1814
hasMdxFile: vi.fn(() => false)
1915
}))
@@ -22,11 +18,9 @@ vi.mock('./scan', () => ({
2218
getLocalesToCheck: vi.fn(() => ['en', 'es'])
2319
}))
2420

25-
import { mdxToStrapiPayload } from './mdxTransformer'
2621
import { hasMdxFile } from './localeMatch'
2722
import { getLocalesToCheck } from './scan'
2823

29-
const mockedMdxToStrapiPayload = vi.mocked(mdxToStrapiPayload)
3024
const mockedHasMdxFile = vi.mocked(hasMdxFile)
3125
const mockedGetLocalesToCheck = vi.mocked(getLocalesToCheck)
3226

@@ -41,6 +35,7 @@ function createMockStrapi() {
4135
request: vi.fn().mockResolvedValue({}),
4236
getAllEntries: vi.fn().mockResolvedValue([]),
4337
findBySlug: vi.fn().mockResolvedValue(undefined),
38+
findUploadByUrl: vi.fn().mockResolvedValue(null),
4439
createEntry: vi
4540
.fn()
4641
.mockResolvedValue({ data: { documentId: 'new-1', slug: 'test' } }),
@@ -54,15 +49,26 @@ function createMockStrapi() {
5449
}
5550
}
5651

57-
const baseConfig: ContentTypes['foundation-pages'] = {
52+
const buildPayloadMock = vi
53+
.fn()
54+
.mockResolvedValue({ title: 'Mocked Payload', slug: 'mocked' })
55+
56+
const baseConfig = {
5857
dir: '/content/foundation-pages',
59-
apiId: 'foundation-pages'
58+
apiId: 'foundation-pages',
59+
buildPayload: buildPayloadMock
6060
}
6161

62-
const contentTypes: ContentTypes = {
62+
const contentTypes = {
6363
'foundation-pages': baseConfig,
64-
'summit-pages': { dir: '/content/summit', apiId: 'summit-pages' }
65-
}
64+
'summit-pages': {
65+
dir: '/content/summit',
66+
apiId: 'summit-pages',
67+
buildPayload: vi
68+
.fn()
69+
.mockResolvedValue({ title: 'Mocked Payload', slug: 'mocked' })
70+
}
71+
} as unknown as ContentTypes
6672

6773
function createResults(): SyncResults {
6874
return { created: 0, updated: 0, deleted: 0, errors: 0 }
@@ -135,9 +141,9 @@ describe('syncEnglishEntry', () => {
135141
expect(results.updated).toBe(1)
136142
})
137143

138-
// Existing entry is passed to transformer so it can preserve hero/content
144+
// Existing entry is passed to buildPayload so it can preserve hero/content
139145
// that wasn't specified in the MDX file
140-
it('passes existing entry to mdxToStrapiPayload for hero fallback', async () => {
146+
it('passes existing entry to buildPayload for hero fallback', async () => {
141147
const existing: StrapiEntry = {
142148
documentId: 'doc-1',
143149
slug: 'about',
@@ -161,11 +167,7 @@ describe('syncEnglishEntry', () => {
161167
false
162168
)
163169

164-
expect(mockedMdxToStrapiPayload).toHaveBeenCalledWith(
165-
'foundation-pages',
166-
mdx,
167-
existing
168-
)
170+
expect(buildPayloadMock).toHaveBeenCalledWith(mdx, strapi, existing)
169171
})
170172

171173
// Dry run mode: count what would happen without actually calling Strapi

0 commit comments

Comments
 (0)