Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/tutorialkit.dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@tutorialkit/react": "workspace:*",
"@webcontainer/api": "1.2.0",
"@webcontainer/api": "1.2.4",
"classnames": "^2.5.1",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
1 change: 1 addition & 0 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@tutorialkit/runtime": "workspace:*",
"@tutorialkit/theme": "workspace:*",
"@tutorialkit/types": "workspace:*",
"@types/react": "^18.3.3",
"@types/node": "^22.2.0",
"@unocss/reset": "^0.59.4",
"@unocss/transformer-directives": "^0.62.0",
Expand Down
27 changes: 27 additions & 0 deletions e2e/src/components/ButtonWriteToFile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import tutorialStore from 'tutorialkit:store';

interface Props {
filePath: string;
newContent: string;
testId?: string;
}

export function ButtonWriteToFile({ filePath, newContent, testId = 'write-to-file' }: Props) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I can imagine this utility component being useful in other future tests as well. It's good to have it accepting props like this. 🎉

async function writeFile() {
await new Promise<void>((resolve) => {
tutorialStore.lessonFullyLoaded.subscribe((value) => {
if (value) {
resolve();
}
});
});

tutorialStore.updateFile(filePath, newContent);
}

return (
<button data-testid={testId} onClick={writeFile}>
Write to File
</button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Index page
8 changes: 0 additions & 8 deletions e2e/src/content/tutorial/tests/preview/single/content.md

This file was deleted.

13 changes: 13 additions & 0 deletions e2e/src/content/tutorial/tests/preview/single/content.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
type: lesson
title: Single
template: file-server
previews:
- [8000, "Node Server"]
---

import { ButtonWriteToFile } from '@components/ButtonWriteToFile';

# Preview test - Single

<ButtonWriteToFile client:load filePath="/index.html" newContent="New content" />
16 changes: 16 additions & 0 deletions e2e/test/preview.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ test('user can see single preview tab', async ({ page }) => {
await expect(preview.getByText('Index page')).toBeVisible();
});

test('user can reload a preview tab', async ({ page }) => {
await page.goto(`${BASE_URL}/single`);

const preview = page.frameLocator('[title="Node Server"]');

await expect(preview.getByText('Index page')).toBeVisible();

await page.getByTestId('write-to-file').click();

await expect(preview.getByText('Index page')).toBeVisible();

await page.getByRole('button', { name: 'Reload Preview' }).click();

await expect(preview.getByText('New content')).toBeVisible();
});

test('user can see multiple preview tabs', async ({ page }) => {
await page.goto(`${BASE_URL}/multiple`);

Expand Down
13 changes: 13 additions & 0 deletions e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react-jsx",
"baseUrl": "./",
"jsxImportSource": "react",
"paths": {
"@*": ["src/*"]
}
},
"include": ["src", "./*.ts"],
"exclude": ["node_modules", "dist"]
}
2 changes: 1 addition & 1 deletion packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@tutorialkit/types": "workspace:*",
"@types/react": "^18.3.3",
"@unocss/reset": "^0.62.2",
"@webcontainer/api": "1.2.0",
"@webcontainer/api": "1.2.4",
"astro": "^4.15.0",
"astro-expressive-code": "^0.35.3",
"chokidar": "3.6.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const DEFAULT_LOCALIZATION = {
filesTitleText: 'Files',
prepareEnvironmentTitleText: 'Preparing Environment',
defaultPreviewTitleText: 'Preview',
reloadPreviewTitle: 'Reload Preview',
toggleTerminalButtonText: 'Toggle Terminal',
solveButtonText: 'Solve',
resetButtonText: 'Reset',
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"@replit/codemirror-lang-svelte": "^6.0.0",
"@tutorialkit/runtime": "workspace:*",
"@tutorialkit/theme": "workspace:*",
"@webcontainer/api": "1.2.0",
"@webcontainer/api": "1.2.4",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
Expand Down
15 changes: 14 additions & 1 deletion packages/react/src/Panels/PreviewPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useStore } from '@nanostores/react';
import type { PreviewInfo, TutorialStore } from '@tutorialkit/runtime';
import type { I18n } from '@tutorialkit/types';
import { reloadPreview } from '@webcontainer/api/utils';
import { createElement, forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import { BootScreen } from '../BootScreen.js';
Expand Down Expand Up @@ -161,6 +162,12 @@ function Preview({ preview, iframe, previewCount, first, last, toggleTerminal, i
}
}, [preview.url, iframe.ref]);

function reload() {
if (iframe.ref) {
reloadPreview(iframe.ref);
}
}

return (
<div className="panel-container">
<div
Expand All @@ -169,7 +176,13 @@ function Preview({ preview, iframe, previewCount, first, last, toggleTerminal, i
})}
>
<div className="panel-title">
<div className="panel-icon i-ph-globe-duotone"></div>
<button
onClick={reload}
title={i18n.reloadPreviewTitle}
className="panel-button rounded-full p-1.5 -my-1.5 -ml-2"
>
<div className="panel-icon i-ph-arrow-clockwise"></div>
</button>
<span className="text-sm truncate">{previewTitle(preview, previewCount, i18n)}</span>
</div>
{last && (
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"@tutorialkit/types": "workspace:*",
"@webcontainer/api": "1.2.0",
"@webcontainer/api": "1.2.4",
"nanostores": "^0.10.3"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"private": true,
"devDependencies": {
"@webcontainer/api": "1.2.0",
"@webcontainer/api": "1.2.4",
"typescript": "^5.4.5",
"vitest": "^1.6.0"
}
Expand Down
7 changes: 7 additions & 0 deletions packages/types/src/schemas/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export const i18nSchema = z.object({
*/
defaultPreviewTitleText: z.string().optional().describe('Text shown on top of the preview section.'),

/**
* Title attribute for the preview reload button.
*
* @default 'Reload Preview'
*/
reloadPreviewTitle: z.string().optional().describe('Title attribute for the preview reload button.'),

/**
* Text for the toggle terminal button.
*
Expand Down
27 changes: 15 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.