Skip to content

Commit

Permalink
fix(astro): correct error message when chapter not found
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Oct 3, 2024
1 parent e335d17 commit cd4f77b
Show file tree
Hide file tree
Showing 4 changed files with 310 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"parts": {
"1-part": {
"id": "1-part",
"order": 0,
"data": {
"type": "part",
"title": "Basics"
},
"slug": "part-slug",
"chapters": {
"1-chapter": {
"id": "1-chapter",
"order": 0,
"data": {
"title": "The first chapter in part 1",
"type": "chapter"
},
"slug": "chapter-slug",
"lessons": {
"1-lesson": {
"data": {
"type": "lesson",
"title": "Welcome to TutorialKit",
"template": "default",
"i18n": {
"mocked": "default localization"
},
"openInStackBlitz": true
},
"id": "1-lesson",
"filepath": "1-part/1-chapter/1-lesson/content.md",
"order": 0,
"part": {
"id": "1-part",
"title": "Basics"
},
"chapter": {
"id": "1-chapter",
"title": "The first chapter in part 1"
},
"Markdown": "Markdown for tutorial",
"slug": "lesson-slug",
"files": [
"1-part-1-chapter-1-lesson-files.json",
[]
],
"solution": [
"1-part-1-chapter-1-lesson-solution.json",
[]
]
}
},
"firstLessonId": "1-lesson"
}
},
"firstChapterId": "1-chapter"
}
},
"firstPartId": "1-part"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"parts": {
"1-part": {
"id": "1-part",
"order": 0,
"data": {
"type": "part",
"title": "Basics"
},
"slug": "part-slug",
"chapters": {
"1-chapter": {
"id": "1-chapter",
"order": 0,
"data": {
"title": "The first chapter in part 1",
"type": "chapter"
},
"slug": "chapter-slug",
"lessons": {
"1-first": {
"data": {
"type": "lesson",
"title": "Welcome to TutorialKit",
"template": "default",
"i18n": {
"mocked": "default localization"
},
"openInStackBlitz": true
},
"id": "1-first",
"filepath": "1-part/1-chapter/1-first/content.md",
"order": 0,
"part": {
"id": "1-part",
"title": "Basics"
},
"chapter": {
"id": "1-chapter",
"title": "The first chapter in part 1"
},
"Markdown": "Markdown for tutorial",
"slug": "lesson-slug",
"files": [
"1-part-1-chapter-1-first-files.json",
[]
],
"solution": [
"1-part-1-chapter-1-first-solution.json",
[]
],
"next": {
"title": "Welcome to TutorialKit",
"href": "/part-slug/chapter-slug/lesson-slug"
}
},
"2-second": {
"data": {
"type": "lesson",
"title": "Welcome to TutorialKit",
"template": "default",
"i18n": {
"mocked": "default localization"
},
"openInStackBlitz": true
},
"id": "2-second",
"filepath": "1-part/1-chapter/2-second/content.md",
"order": 1,
"part": {
"id": "1-part",
"title": "Basics"
},
"chapter": {
"id": "1-chapter",
"title": "The first chapter in part 1"
},
"Markdown": "Markdown for tutorial",
"slug": "lesson-slug",
"files": [
"1-part-1-chapter-2-second-files.json",
[]
],
"solution": [
"1-part-1-chapter-2-second-solution.json",
[]
],
"prev": {
"title": "Welcome to TutorialKit",
"href": "/part-slug/chapter-slug/lesson-slug"
},
"next": {
"title": "Welcome to TutorialKit",
"href": "/part-slug/chapter-slug/lesson-slug"
}
},
"3-third": {
"data": {
"type": "lesson",
"title": "Welcome to TutorialKit",
"template": "default",
"i18n": {
"mocked": "default localization"
},
"openInStackBlitz": true
},
"id": "3-third",
"filepath": "1-part/1-chapter/3-third/content.md",
"order": 2,
"part": {
"id": "1-part",
"title": "Basics"
},
"chapter": {
"id": "1-chapter",
"title": "The first chapter in part 1"
},
"Markdown": "Markdown for tutorial",
"slug": "lesson-slug",
"files": [
"1-part-1-chapter-3-third-files.json",
[]
],
"solution": [
"1-part-1-chapter-3-third-solution.json",
[]
],
"prev": {
"title": "Welcome to TutorialKit",
"href": "/part-slug/chapter-slug/lesson-slug"
}
}
},
"firstLessonId": "1-first"
}
},
"firstChapterId": "1-chapter"
}
},
"firstPartId": "1-part"
}
106 changes: 106 additions & 0 deletions packages/astro/src/default/utils/content.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as content from 'astro:content';
import { expect, test, vi, type TaskContext } from 'vitest';
import { getTutorial, type CollectionEntryTutorial } from './content';

const getCollection = vi.mocked(content.getCollection);
vi.mock('astro:content', () => ({ getCollection: vi.fn() }));

// mock DEFAULT_LOCALIZATION so that we don't need to update test results everytime new keys are added there
vi.mock(import('@tutorialkit/types'), async (importOriginal) => ({
...(await importOriginal()),
DEFAULT_LOCALIZATION: { mocked: 'default localization' } as any,
}));

expect.addSnapshotSerializer({
serialize: (val) => JSON.stringify(val, null, 2),
test: (value) => !(value instanceof Error),
});

test('single part, chapter and lesson', async (ctx) => {
getCollection.mockReturnValueOnce([
{ id: 'meta.md', ...tutorial },
{ id: '1-part/meta.md', ...part },
{ id: '1-part/1-chapter/meta.md', ...chapter },
{ id: '1-part/1-chapter/1-lesson/content.md', ...lesson },
]);

const collection = await getTutorial();
await expect(collection).toMatchFileSnapshot(snapshotName(ctx));
});

test('single part, chapter and multiple lessons', async (ctx) => {
getCollection.mockReturnValueOnce([
{ id: 'meta.md', ...tutorial },
{ id: '1-part/meta.md', ...part },
{ id: '1-part/1-chapter/meta.md', ...chapter },

// 3 lessons
{ id: '1-part/1-chapter/1-first/content.md', ...lesson },
{ id: '1-part/1-chapter/2-second/content.md', ...lesson },
{ id: '1-part/1-chapter/3-third/content.md', ...lesson },
]);

const collection = await getTutorial();

const lessons = collection.parts['1-part'].chapters['1-chapter'].lessons;
expect(Object.keys(lessons)).toHaveLength(3);

await expect(collection).toMatchFileSnapshot(snapshotName(ctx));
});

test('throws when part not found', async () => {
getCollection.mockReturnValueOnce([
{ id: 'meta.md', ...tutorial },
{ id: '2-part/meta.md', ...part },
{ id: '1-part/1-chapter/meta.md', ...chapter },
{ id: '1-part/1-chapter/1-first/content.md', ...lesson },
]);

await expect(getTutorial).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Could not find part '1-part']`);
});

test('throws when chapter not found', async () => {
getCollection.mockReturnValueOnce([
{ id: 'meta.md', ...tutorial },
{ id: '1-part/meta.md', ...part },
{ id: '1-part/2-chapter/meta.md', ...chapter },
{ id: '1-part/1-chapter/1-first/content.md', ...lesson },
]);

await expect(getTutorial).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Could not find chapter '1-chapter']`);
});

const tutorial: Omit<CollectionEntryTutorial, 'render' | 'id'> = {
slug: 'tutorial-slug',
body: 'Hello world',
collection: 'tutorial',
data: { type: 'tutorial' },
};

const part: Omit<CollectionEntryTutorial, 'render' | 'id'> = {
slug: 'part-slug',
body: 'Hello world',
collection: 'tutorial',
data: { type: 'part', title: 'Basics' },
};

const chapter: Omit<CollectionEntryTutorial, 'render' | 'id'> = {
slug: 'chapter-slug',
body: 'body here',
collection: 'tutorial',
data: { title: 'The first chapter in part 1', type: 'chapter' },
};

const lesson: Omit<CollectionEntryTutorial, 'id'> = {
slug: 'lesson-slug',
body: 'body here',
collection: 'tutorial',
data: { type: 'lesson', title: 'Welcome to TutorialKit' },
render: () => ({ Content: 'Markdown for tutorial' }) as unknown as ReturnType<CollectionEntryTutorial['render']>,
};

function snapshotName(ctx: TaskContext) {
const testName = ctx.task.name.replaceAll(',', '').replaceAll(' ', '-');

return `__snapshots__/${testName}.json`;
}
4 changes: 2 additions & 2 deletions packages/astro/src/default/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export async function getTutorial(): Promise<Tutorial> {
}

if (!_tutorial.parts[partId].chapters[chapterId]) {
throw new Error(`Could not find chapter '${partId}'`);
throw new Error(`Could not find chapter '${chapterId}'`);
}

const { Content } = await entry.render();
Expand Down Expand Up @@ -321,7 +321,7 @@ function getSlug(entry: CollectionEntryTutorial) {
return slug;
}

interface CollectionEntryTutorial {
export interface CollectionEntryTutorial {
id: string;
slug: string;
body: string;
Expand Down

0 comments on commit cd4f77b

Please sign in to comment.