Skip to content

Commit 3dcc932

Browse files
docs-botCopilotheiskr
authored
feat: add timeCommitment field to journeyTracks frontmatter schema (#61211)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Kevin Heis <heiskr@users.noreply.github.com>
1 parent 7ac925c commit 3dcc932

4 files changed

Lines changed: 48 additions & 2 deletions

File tree

src/frame/lib/frontmatter.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ export const schema: Schema = {
220220
translatable: true,
221221
description: 'Optional description for the journey track',
222222
},
223+
timeCommitment: {
224+
type: 'string',
225+
translatable: true,
226+
description:
227+
'Optional time commitment displayed as metadata for the track (e.g. "2-4 hours")',
228+
},
223229
guides: {
224230
type: 'array',
225231
items: {

src/journeys/lib/journey-path-resolver.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface JourneyTrack {
3434
id: string
3535
title: string
3636
description?: string
37+
timeCommitment?: string
3738
guides: Array<{
3839
href: string
3940
title: string
@@ -50,6 +51,7 @@ type JourneyPage = {
5051
id: string
5152
title: string
5253
description?: string
54+
timeCommitment?: string
5355
guides: Array<{
5456
href: string
5557
alternativeNextStep?: string
@@ -329,6 +331,11 @@ export async function resolveJourneyTracks(
329331
? await renderContent(track.description, context, { textOnly: true })
330332
: track.description
331333

334+
const renderedTimeCommitment =
335+
track.timeCommitment && needsRendering(track.timeCommitment)
336+
? await renderContent(track.timeCommitment, context, { textOnly: true })
337+
: track.timeCommitment
338+
332339
const guides = (
333340
await Promise.all(
334341
track.guides.map(async (guide: { href: string; alternativeNextStep?: string }) => {
@@ -346,6 +353,7 @@ export async function resolveJourneyTracks(
346353
id: track.id,
347354
title: renderedTitle,
348355
description: renderedDescription,
356+
timeCommitment: renderedTimeCommitment,
349357
guides,
350358
}
351359
}),

src/journeys/tests/journey-path-resolver.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,15 @@ vi.mock('@/journeys/lib/get-link-data', () => ({
2222

2323
const mockGetLinkData = vi.mocked(getLinkData)
2424

25+
const mockRenderContent = vi.fn(async (content: string, _context?: unknown, _options?: unknown) => {
26+
void _context
27+
void _options
28+
return content
29+
})
30+
2531
vi.mock('@/content-render/index', () => ({
26-
renderContent: async (content: string) => content,
32+
renderContent: (content: string, context?: unknown, options?: unknown) =>
33+
mockRenderContent(content, context, options),
2734
}))
2835

2936
vi.mock('@/languages/lib/render-with-fallback', () => ({
@@ -204,6 +211,7 @@ describe('journey-path-resolver', () => {
204211
id: 'getting_started',
205212
title: 'Getting started with {% data variables.product.company_short %}',
206213
description: 'Learn the {% data variables.product.company_short %} basics',
214+
timeCommitment: '{% data variables.product.company_short %} 2-4 hours',
207215
guides: [
208216
{ href: '/enterprise-onboarding/setup' },
209217
{ href: '/enterprise-onboarding/config' },
@@ -213,6 +221,7 @@ describe('journey-path-resolver', () => {
213221
id: 'advanced',
214222
title: 'Advanced configuration',
215223
description: 'Advanced topics for experts',
224+
timeCommitment: '4-6 hours',
216225
guides: [{ href: '/enterprise-onboarding/advanced-setup' }],
217226
},
218227
]
@@ -237,6 +246,27 @@ describe('journey-path-resolver', () => {
237246
)
238247
})
239248

249+
test('propagates timeCommitment and renders Liquid with textOnly like title/description', async () => {
250+
mockRenderContent.mockClear()
251+
const result = await resolveJourneyTracks(mockJourneyTracks, mockContext)
252+
253+
// Liquid value passes through the (passthrough) renderer; plain string is unchanged
254+
expect(result[0].timeCommitment).toBe('{% data variables.product.company_short %} 2-4 hours')
255+
expect(result[1].timeCommitment).toBe('4-6 hours')
256+
257+
// The Liquid-bearing timeCommitment should be rendered with { textOnly: true },
258+
// matching how title/description are rendered.
259+
const timeCommitmentCall = mockRenderContent.mock.calls.find(
260+
([content]) => content === '{% data variables.product.company_short %} 2-4 hours',
261+
)
262+
expect(timeCommitmentCall).toBeDefined()
263+
expect(timeCommitmentCall?.[2]).toEqual({ textOnly: true })
264+
265+
// Plain (non-Liquid) timeCommitment should not be sent through renderContent
266+
const plainCall = mockRenderContent.mock.calls.find(([content]) => content === '4-6 hours')
267+
expect(plainCall).toBeUndefined()
268+
})
269+
240270
test('resolves guide links with proper versioning', async () => {
241271
const result = await resolveJourneyTracks(mockJourneyTracks, mockContext)
242272

@@ -275,6 +305,7 @@ describe('journey-path-resolver', () => {
275305
const result = await resolveJourneyTracks(trackWithoutDescription, mockContext)
276306

277307
expect(result[0].description).toBeUndefined()
308+
expect(result[0].timeCommitment).toBeUndefined()
278309
})
279310
})
280311

src/landings/components/journey/JourneyLearningTracks.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export const JourneyLearningTracks = ({ tracks, articlesHeading }: JourneyLearni
3131
<summary className={styles.trackSummary}>
3232
<div className={styles.trackHeader}>
3333
<h2 className="h4 text-bold">{track.title}</h2>
34-
<Token text={`${track.guides?.length || 0} articles`} />
34+
<Token text={t('articles').replace('{{ number }}', `${track.guides?.length || 0}`)} />
35+
{track.timeCommitment && <Token text={track.timeCommitment} />}
3536
</div>
3637
<div className={styles.trackDescription}>
3738
<p>{track.description}</p>

0 commit comments

Comments
 (0)