From 42990d146d43dfd20d7af5edfce5de12f8bcbbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Wed, 7 Aug 2024 16:52:21 +0300 Subject: [PATCH 1/5] ci: allow manual runs for tests --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6becfa674..c00ef21ba 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,6 +5,7 @@ on: branches: - main pull_request: + workflow_dispatch: jobs: test: From 110d4cefbe001e812f9073ca4a149e29e80ae11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Wed, 7 Aug 2024 19:08:03 +0300 Subject: [PATCH 2/5] refactor: move `getFilesRefList` to its own file --- packages/astro/src/default/utils/content.ts | 35 ++----------------- .../src/default/utils/content/files-ref.ts | 25 +++++++++++++ .../create-tutorial.test.ts.snap | 1 + 3 files changed, 29 insertions(+), 32 deletions(-) create mode 100644 packages/astro/src/default/utils/content/files-ref.ts diff --git a/packages/astro/src/default/utils/content.ts b/packages/astro/src/default/utils/content.ts index f70743fb2..68d2cb55e 100644 --- a/packages/astro/src/default/utils/content.ts +++ b/packages/astro/src/default/utils/content.ts @@ -1,23 +1,12 @@ -import type { - ChapterSchema, - FilesRefList, - Lesson, - LessonSchema, - PartSchema, - Tutorial, - TutorialSchema, -} from '@tutorialkit/types'; -import { folderPathToFilesRef, interpolateString } from '@tutorialkit/types'; +import type { ChapterSchema, Lesson, LessonSchema, PartSchema, Tutorial, TutorialSchema } from '@tutorialkit/types'; +import { interpolateString } from '@tutorialkit/types'; import { getCollection } from 'astro:content'; -import glob from 'fast-glob'; import path from 'node:path'; -import { IGNORED_FILES } from './constants'; import { DEFAULT_LOCALIZATION } from './content/default-localization'; import { squash } from './content/squash.js'; import { logger } from './logger'; import { joinPaths } from './url'; - -const CONTENT_DIR = path.join(process.cwd(), 'src/content/tutorial'); +import { getFilesRefList } from './content/files-ref'; export async function getTutorial(): Promise { const collection = sortCollection(await getCollection('tutorial')); @@ -331,24 +320,6 @@ function getSlug(entry: CollectionEntryTutorial) { return slug; } -async function getFilesRefList(pathToFolder: string): Promise { - const root = path.join(CONTENT_DIR, pathToFolder); - - const filePaths = ( - await glob(`${glob.convertPathToPattern(root)}/**/*`, { - onlyFiles: true, - ignore: IGNORED_FILES, - dot: true, - }) - ).map((filePath) => `/${path.relative(root, filePath)}`); - - filePaths.sort(); - - const filesRef = folderPathToFilesRef(pathToFolder); - - return [filesRef, filePaths]; -} - interface CollectionEntryTutorial { id: string; slug: string; diff --git a/packages/astro/src/default/utils/content/files-ref.ts b/packages/astro/src/default/utils/content/files-ref.ts new file mode 100644 index 000000000..69e8ec67d --- /dev/null +++ b/packages/astro/src/default/utils/content/files-ref.ts @@ -0,0 +1,25 @@ +import type { FilesRefList } from '@tutorialkit/types'; +import { folderPathToFilesRef } from '@tutorialkit/types'; +import glob from 'fast-glob'; +import path from 'node:path'; +import { IGNORED_FILES } from '../constants'; + +const CONTENT_DIR = path.join(process.cwd(), 'src/content/tutorial'); + +export async function getFilesRefList(pathToFolder: string, base = CONTENT_DIR): Promise { + const root = path.join(base, pathToFolder); + + const filePaths = ( + await glob(`${glob.convertPathToPattern(root)}/**/*`, { + onlyFiles: true, + ignore: IGNORED_FILES, + dot: true, + }) + ).map((filePath) => `/${path.relative(root, filePath)}`); + + filePaths.sort(); + + const filesRef = folderPathToFilesRef(pathToFolder); + + return [filesRef, filePaths]; +} diff --git a/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap b/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap index ee67bba96..b9a014132 100644 --- a/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap +++ b/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap @@ -253,6 +253,7 @@ exports[`create and eject a project 1`] = ` "src/utils/content", "src/utils/content.ts", "src/utils/content/default-localization.ts", + "src/utils/content/files-ref.ts", "src/utils/content/squash.ts", "src/utils/logger.ts", "src/utils/nav.ts", From 4f6d6f6f2028af547d5f0475192f0d560384d953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Wed, 7 Aug 2024 19:08:56 +0300 Subject: [PATCH 3/5] test: add failing test case for #209 --- .../src/default/utils/content/files-ref.spec.ts | 17 +++++++++++++++++ packages/astro/test/fixtures/files/first.js | 1 + .../fixtures/files/nested/directory/second.ts | 1 + 3 files changed, 19 insertions(+) create mode 100644 packages/astro/src/default/utils/content/files-ref.spec.ts create mode 100644 packages/astro/test/fixtures/files/first.js create mode 100644 packages/astro/test/fixtures/files/nested/directory/second.ts diff --git a/packages/astro/src/default/utils/content/files-ref.spec.ts b/packages/astro/src/default/utils/content/files-ref.spec.ts new file mode 100644 index 000000000..5aa5c70c5 --- /dev/null +++ b/packages/astro/src/default/utils/content/files-ref.spec.ts @@ -0,0 +1,17 @@ +import { expect, test } from 'vitest'; + +import { getFilesRefList } from './files-ref'; + +test('getFilesRefList returns files', async () => { + const files = await getFilesRefList('test/fixtures/files', ''); + + expect(files).toMatchInlineSnapshot(` + [ + "test-fixtures-files.json", + [ + "/first.js", + "/nested/directory/second.ts", + ], + ] + `); +}); diff --git a/packages/astro/test/fixtures/files/first.js b/packages/astro/test/fixtures/files/first.js new file mode 100644 index 000000000..424f47511 --- /dev/null +++ b/packages/astro/test/fixtures/files/first.js @@ -0,0 +1 @@ +export default 'Example JS file'; diff --git a/packages/astro/test/fixtures/files/nested/directory/second.ts b/packages/astro/test/fixtures/files/nested/directory/second.ts new file mode 100644 index 000000000..c70e3c00c --- /dev/null +++ b/packages/astro/test/fixtures/files/nested/directory/second.ts @@ -0,0 +1 @@ +export default 'Example TS file'; From 7581c1559458440c1ca6c6ba664c71b34bbb363a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Wed, 7 Aug 2024 19:16:22 +0300 Subject: [PATCH 4/5] fix(astro): convert windows filepaths to webcontainer compatible --- packages/astro/src/default/utils/content/files-ref.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/default/utils/content/files-ref.ts b/packages/astro/src/default/utils/content/files-ref.ts index 69e8ec67d..553c3a127 100644 --- a/packages/astro/src/default/utils/content/files-ref.ts +++ b/packages/astro/src/default/utils/content/files-ref.ts @@ -15,7 +15,7 @@ export async function getFilesRefList(pathToFolder: string, base = CONTENT_DIR): ignore: IGNORED_FILES, dot: true, }) - ).map((filePath) => `/${path.relative(root, filePath)}`); + ).map((filePath) => `/${path.relative(root, filePath).replaceAll(path.sep, '/')}`); filePaths.sort(); From e44d4c897b805d20a01d66c8dcd225936254874a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Wed, 7 Aug 2024 19:23:14 +0300 Subject: [PATCH 5/5] test: add test case for file ref JSON contents --- .../create-tutorial.test.ts.snap | 52 +++++++++++++++++++ packages/cli/tests/create-tutorial.test.ts | 15 ++++++ 2 files changed, 67 insertions(+) diff --git a/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap b/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap index b9a014132..381191655 100644 --- a/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap +++ b/packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap @@ -94,6 +94,58 @@ exports[`create a project 1`] = ` ] `; +exports[`create and build a project > built project file references 1`] = ` +{ + "1-basics-1-introduction-1-welcome-files.json": [ + "/src/index.js", + "/src/test/bar.js", + ], + "1-basics-1-introduction-1-welcome-solution.json": [ + "/src/index.js", + ], + "1-basics-1-introduction-2-foo-files.json": [ + "/bar/styles.css", + "/src/index.html", + "/src/unicorn.js", + "/src/windows_xp.png", + ], + "1-basics-1-introduction-2-foo-solution.json": [ + "/src/index.html", + ], + "1-basics-1-introduction-3-bar-files.json": [ + "/src/index.html", + ], + "template-default.json": [ + "/package-lock.json", + "/package.json", + "/src/index.js", + ], + "template-vite-app-2.json": [ + "/.gitignore", + "/counter.js", + "/foo.txt", + "/index.html", + "/javascript.svg", + "/main.js", + "/package-lock.json", + "/package.json", + "/public/vite.svg", + "/style.css", + ], + "template-vite-app.json": [ + "/.gitignore", + "/counter.js", + "/index.html", + "/javascript.svg", + "/main.js", + "/package-lock.json", + "/package.json", + "/public/vite.svg", + "/style.css", + ], +} +`; + exports[`create and build a project 1`] = ` [ "1-basics", diff --git a/packages/cli/tests/create-tutorial.test.ts b/packages/cli/tests/create-tutorial.test.ts index 0809e4e8a..dce8f256a 100644 --- a/packages/cli/tests/create-tutorial.test.ts +++ b/packages/cli/tests/create-tutorial.test.ts @@ -1,5 +1,6 @@ import { execa } from 'execa'; import fs from 'node:fs/promises'; +import { readFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; import { afterAll, beforeAll, expect, test } from 'vitest'; @@ -67,6 +68,20 @@ test('create and build a project', async (context) => { const distFiles = await fs.readdir(path.join(dest, 'dist'), { recursive: true }); expect(distFiles.map(normaliseSlash).sort()).toMatchSnapshot(); + + // create snapshot of lesson, solution and template file reference JSONs + const lessonJsons = distFiles.filter((file) => file.endsWith('-files.json')); + const solutionJsons = distFiles.filter((file) => file.endsWith('-solution.json')); + const templateJsons = distFiles.filter((file) => file.startsWith('template-') && file.endsWith('.json')); + + const contents = [...lessonJsons, ...solutionJsons, ...templateJsons].reduce((jsons, current) => { + const fileJson = JSON.parse(readFileSync(path.join(dest, 'dist', current), 'utf8')); + const filenames = Object.keys(fileJson); + + return { ...jsons, [current]: filenames }; + }, {}); + + expect(contents).toMatchSnapshot('built project file references'); }); test('create and eject a project', async (context) => {