| import { describe, expect, test } from 'vitest' | |
| import type { LearningTracks } from '@/types' | |
| import { loadPages, loadPageMap } from '@/frame/lib/page-data' | |
| import loadRedirects from '@/redirects/lib/precompile' | |
| import { getDeepDataByLanguage } from '@/data-directory/lib/get-data' | |
| import { checkURL } from '@/tests/helpers/check-url' | |
| const pageList = await loadPages(undefined, ['en']) | |
| const pages = await loadPageMap(pageList) | |
| const redirects = await loadRedirects(pageList) | |
| describe('learning tracks', () => { | |
| const allLearningTracks = getDeepDataByLanguage('learning-tracks', 'en') as LearningTracks | |
| const topLevels = Object.keys(allLearningTracks) | |
| test.each(topLevels)('learning-track in data/learning-tracks/%s.yml', (topLevel) => { | |
| const learningTracks = allLearningTracks[topLevel] | |
| const redirectsContext = { redirects, pages } | |
| for (const learningTrack of Object.values(learningTracks)) { | |
| const length = learningTrack.guides.length | |
| const size = new Set(learningTrack.guides).size | |
| let errorMessage = '' | |
| if (length !== size) { | |
| errorMessage = `In data/learning-tracks/${topLevel}.yml there are duplicate guides.` | |
| const counts = new Map() | |
| for (const guide of learningTrack.guides) { | |
| counts.set(guide, (counts.get(guide) || 0) + 1) | |
| } | |
| const dupes = [...counts.entries()].filter(([, count]) => count > 1).map(([entry]) => entry) | |
| errorMessage += `\nTo fix this, remove: ${dupes.join(' and ')}` | |
| } | |
| expect(length, errorMessage).toEqual(size) | |
| } | |
| type Trouble = { | |
| uri: string | |
| index: number | |
| redirects: string | undefined | |
| } | |
| type TroubleTuple = [string, Trouble[]] | |
| const troubles = Object.entries(learningTracks) | |
| .map(([learningTrackKey, learningTrack]) => { | |
| return [ | |
| learningTrackKey, | |
| learningTrack.guides | |
| .map((guide, i) => checkURL(guide, i, redirectsContext)) | |
| .filter(Boolean), | |
| ] | |
| }) | |
| .filter(([, trouble]) => trouble.length > 0) as TroubleTuple[] | |
| let errorMessage = `In data/learning-tracks/${topLevel}.yml there are ${troubles.length} guides that are not correct.\n` | |
| let fixables = 0 | |
| for (const [key, guides] of troubles) { | |
| errorMessage += `Under "${key}"...\n` | |
| for (const { uri, index, redirects: redirectTo } of guides) { | |
| if (redirectTo) { | |
| fixables += 1 | |
| errorMessage += ` guide: #${index + 1} ${uri} redirects to ${redirectTo}\n` | |
| } else { | |
| errorMessage += ` guide: #${index + 1} ${uri} is broken.\n` | |
| } | |
| } | |
| } | |
| if (fixables) { | |
| errorMessage += `\nNOTE! To automatically fix the redirects run this command:\n` | |
| errorMessage += `\n\t./src/links/scripts/update-internal-links.ts data/learning-tracks/${topLevel}.yml\n` | |
| } | |
| expect(troubles.length, errorMessage).toEqual(0) | |
| }) | |
| }) | |