diff --git a/package.json b/package.json
index a0113308b8..cca08069c4 100644
--- a/package.json
+++ b/package.json
@@ -76,16 +76,16 @@
"phaser": "~3.90.0",
"query-string": "^9.0.0",
"re-resizable": "^6.9.9",
- "react": "^18.3.1",
+ "react": "^19.1.0",
"react-ace": "^14.0.0",
"react-copy-to-clipboard": "^5.1.0",
"react-debounce-render": "^8.0.2",
- "react-dom": "^18.3.1",
+ "react-dom": "^19.1.0",
"react-drag-drop-files": "^3.0.0",
"react-draggable": "^4.4.5",
"react-dropzone": "^14.2.3",
"react-i18next": "^15.0.0",
- "react-konva": "^18.2.10",
+ "react-konva": "^19.0.7",
"react-latex-next": "^3.0.0",
"react-mde": "^11.5.0",
"react-papaparse": "^4.0.2",
@@ -139,12 +139,11 @@
"@types/js-cookie": "^3.0.6",
"@types/js-yaml": "^4.0.5",
"@types/lodash": "^4.14.195",
- "@types/react": "^18.3.3",
+ "@types/react": "^19.1.8",
"@types/react-copy-to-clipboard": "^5.0.4",
- "@types/react-dom": "^18.3.0",
+ "@types/react-dom": "^19.1.6",
"@types/react-redux": "^7.1.24",
"@types/react-syntax-highlighter": "^15.5.7",
- "@types/react-test-renderer": "^18.0.0",
"@types/redux-mock-store": "^1.0.3",
"@types/showdown": "^2.0.1",
"@types/xml2js": "^0.4.11",
@@ -173,10 +172,10 @@
"prettier": "^3.3.3",
"process": "^0.11.10",
"react-error-overlay": "^6.0.11",
- "react-test-renderer": "^18.2.0",
"redux-saga-test-plan": "^4.0.6",
"resize-observer-polyfill": "^1.5.1",
"sass": "^1.63.6",
+ "shallow-react-snapshot": "^0.2.2",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"timers-browserify": "^2.0.12",
diff --git a/src/commons/ContentDisplay.tsx b/src/commons/ContentDisplay.tsx
index 30f77584f7..35e442646a 100644
--- a/src/commons/ContentDisplay.tsx
+++ b/src/commons/ContentDisplay.tsx
@@ -1,5 +1,5 @@
import { Card, Elevation } from '@blueprintjs/core';
-import React, { useEffect } from 'react';
+import React, { type JSX, useEffect } from 'react';
export type ContentDisplayProps = {
fullWidth?: boolean;
diff --git a/src/commons/__tests__/__snapshots__/ContentDisplay.test.tsx.snap b/src/commons/__tests__/__snapshots__/ContentDisplay.test.tsx.snap
index 7e524c0b5f..df045c8aa0 100644
--- a/src/commons/__tests__/__snapshots__/ContentDisplay.test.tsx.snap
+++ b/src/commons/__tests__/__snapshots__/ContentDisplay.test.tsx.snap
@@ -1,19 +1,21 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ContentDisplay page renders correctly 1`] = `
-
+
+
`;
diff --git a/src/commons/__tests__/__snapshots__/Markdown.test.tsx.snap b/src/commons/__tests__/__snapshots__/Markdown.test.tsx.snap
index 924eff7c36..cff2144717 100644
--- a/src/commons/__tests__/__snapshots__/Markdown.test.tsx.snap
+++ b/src/commons/__tests__/__snapshots__/Markdown.test.tsx.snap
@@ -1,16 +1,75 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Markdown page renders correctly 1`] = `
-
Welcome to the Source Academy playground!
-
The book Structure and Interpretation of Computer Programs, JavaScript Edition
-uses JavaScript sublanguages that we call Source . You have chosen the sublanguage Source §1 .
-
In the editor on the left, you can use the Ace keyboard shortcuts
-and also the Source Academy keyboard shortcuts .
",
- }
- }
-/>
+
+
+
+ Welcome to the Source Academy playground!
+
+
+
+
+ The book
+
+
+ Structure and Interpretation of Computer Programs, JavaScript Edition
+
+
+
+uses JavaScript sublanguages that we call
+
+
+ Source
+
+
+ . You have chosen the sublanguage
+
+
+ Source §1
+
+
+ .
+
+
+
+
+ In the editor on the left, you can use the
+
+
+ Ace keyboard shortcuts
+
+
+
+and also the
+
+
+ Source Academy keyboard shortcuts
+
+
+ .
+
+
+
`;
diff --git a/src/commons/achievement/control/AchievementEditor.tsx b/src/commons/achievement/control/AchievementEditor.tsx
index 9388ff6972..83bc712616 100644
--- a/src/commons/achievement/control/AchievementEditor.tsx
+++ b/src/commons/achievement/control/AchievementEditor.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useState } from 'react';
+import React, { type JSX, useContext, useState } from 'react';
import { AchievementContext } from 'src/features/achievement/AchievementConstants';
import AchievementAdder from './achievementEditor/AchievementAdder';
diff --git a/src/commons/achievement/control/GoalEditor.tsx b/src/commons/achievement/control/GoalEditor.tsx
index 9d0a40ef25..9ba8d3b73e 100644
--- a/src/commons/achievement/control/GoalEditor.tsx
+++ b/src/commons/achievement/control/GoalEditor.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useState } from 'react';
+import React, { type JSX, useContext, useState } from 'react';
import { AchievementContext } from 'src/features/achievement/AchievementConstants';
import EditableGoal from './goalEditor/EditableGoal';
diff --git a/src/commons/assessment/Assessment.tsx b/src/commons/assessment/Assessment.tsx
index 158ac7cacf..35f976e80e 100644
--- a/src/commons/assessment/Assessment.tsx
+++ b/src/commons/assessment/Assessment.tsx
@@ -13,7 +13,7 @@ import {
} from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import { sortBy } from 'lodash';
-import React, { useEffect, useMemo, useState } from 'react';
+import React, { type JSX, useEffect, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';
import { Navigate, useLoaderData, useParams } from 'react-router';
import { numberRegExp } from 'src/features/academy/AcademyTypes';
diff --git a/src/commons/assessmentWorkspace/__tests__/__snapshots__/AssessmentWorkspace.test.tsx.snap b/src/commons/assessmentWorkspace/__tests__/__snapshots__/AssessmentWorkspace.test.tsx.snap
index fdbedb13ae..fc7ba41f38 100644
--- a/src/commons/assessmentWorkspace/__tests__/__snapshots__/AssessmentWorkspace.test.tsx.snap
+++ b/src/commons/assessmentWorkspace/__tests__/__snapshots__/AssessmentWorkspace.test.tsx.snap
@@ -1,57 +1,54 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AssessmentWorkspace > AssessmentWorkspace page "loading" content renders correctly 1`] = `
-
-
-
- Getting mission ready...
+
+
+ Getting mission ready...
+
-
+
`;
exports[`AssessmentWorkspace > AssessmentWorkspace page with ContestVoting question renders correctly 1`] = `
@@ -398,7 +395,6 @@ exports[`AssessmentWorkspace > AssessmentWorkspace page with ContestVoting quest
AssessmentWorkspace page with ContestVoting quest
AssessmentWorkspace page with ContestVoting quest
AssessmentWorkspace page with MCQ question render
AssessmentWorkspace page with MCQ question render
AssessmentWorkspace page with MCQ question render
AssessmentWorkspace page with overdue assessment
AssessmentWorkspace page with overdue assessment
AssessmentWorkspace page with overdue assessment
AssessmentWorkspace page with programming questio
AssessmentWorkspace page with programming questio
AssessmentWorkspace page with programming questio
AssessmentWorkspace renders Grading tab correctly
AssessmentWorkspace renders Grading tab correctly
AssessmentWorkspace renders Grading tab correctly
AssessmentWorkspace renders Grading tab correctly
;
diff --git a/src/commons/controlBar/ControlBarShareButton.tsx b/src/commons/controlBar/ControlBarShareButton.tsx
index 7c3464895a..15945e579f 100644
--- a/src/commons/controlBar/ControlBarShareButton.tsx
+++ b/src/commons/controlBar/ControlBarShareButton.tsx
@@ -35,7 +35,7 @@ type State = {
};
export class ControlBarShareButton extends React.PureComponent
{
- private shareInputElem: React.RefObject;
+ private shareInputElem: React.RefObject;
constructor(props: ControlBarShareButtonProps) {
super(props);
diff --git a/src/commons/delay/Delay.tsx b/src/commons/delay/Delay.tsx
index 5c190739cb..5304d29687 100644
--- a/src/commons/delay/Delay.tsx
+++ b/src/commons/delay/Delay.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
type Props = {
children: JSX.Element;
diff --git a/src/commons/dropdown/DropdownCourses.tsx b/src/commons/dropdown/DropdownCourses.tsx
index 6bc10e5f6c..e47042912c 100644
--- a/src/commons/dropdown/DropdownCourses.tsx
+++ b/src/commons/dropdown/DropdownCourses.tsx
@@ -13,7 +13,7 @@ type Props = {
courseId?: number;
};
-const DropdownCourses: React.FC = ({ isOpen, onClose, courses, courseId }) => {
+const DropdownCourses = (({ isOpen, onClose, courses, courseId }) => {
const navigate = useNavigate();
const options = courses.map(course => ({
@@ -47,6 +47,6 @@ const DropdownCourses: React.FC = ({ isOpen, onClose, courses, courseId }
);
-};
+}) satisfies React.FC;
export default DropdownCourses;
diff --git a/src/commons/dropdown/DropdownCreateCourse.tsx b/src/commons/dropdown/DropdownCreateCourse.tsx
index 2d37ce7eb9..54c2bfe3a2 100644
--- a/src/commons/dropdown/DropdownCreateCourse.tsx
+++ b/src/commons/dropdown/DropdownCreateCourse.tsx
@@ -29,7 +29,7 @@ type Props = {
onClose: () => void;
};
-const DropdownCreateCourse: React.FC = props => {
+const DropdownCreateCourse = (props => {
const dispatch = useDispatch();
const [courseConfig, setCourseConfig] = React.useState({
@@ -280,6 +280,6 @@ const DropdownCreateCourse: React.FC = props => {
);
-};
+}) satisfies React.FC;
export default DropdownCreateCourse;
diff --git a/src/commons/dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap b/src/commons/dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap
index 1a6c827952..8f6034a8a5 100644
--- a/src/commons/dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap
+++ b/src/commons/dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap
@@ -1,69 +1,61 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Dropdown correctly mounts Profile, DropdownCourses, and DropdownCreateCourses components when a user is logged in 1`] = `
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
`;
exports[`Dropdown does not mount Profile, DropdownCourses and DropdownCreateCourses components when a user is not logged in 1`] = `
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
`;
diff --git a/src/commons/editor/__tests__/Editor.test.tsx b/src/commons/editor/__tests__/Editor.test.tsx
index a3c04a84f0..d241aeff3a 100644
--- a/src/commons/editor/__tests__/Editor.test.tsx
+++ b/src/commons/editor/__tests__/Editor.test.tsx
@@ -1,9 +1,11 @@
-import { shallowRender } from 'src/commons/utils/TestUtils';
+import { Provider } from 'react-redux';
+import { renderTree } from 'src/commons/utils/TestUtils';
+import { createStore } from 'src/pages/createStore';
import Editor, { EditorProps } from '../Editor';
import { Position } from '../EditorTypes';
-test('Editor renders correctly', () => {
+test('Editor renders correctly', async () => {
const props: EditorProps = {
editorTabIndex: 0,
breakpoints: [],
@@ -20,7 +22,11 @@ test('Editor renders correctly', () => {
handleUpdateHasUnsavedChanges: hasUnsavedChanges => {},
handlePromptAutocomplete: (row: number, col: number, callback: any) => {}
};
- const Element: React.FC = () => ;
- const tree = shallowRender( );
+ const Element: React.FC = () => (
+
+
+
+ );
+ const tree = await renderTree( );
expect(tree).toMatchSnapshot();
});
diff --git a/src/commons/editor/__tests__/__snapshots__/Editor.test.tsx.snap b/src/commons/editor/__tests__/__snapshots__/Editor.test.tsx.snap
index d99b0bc4b9..182c90137a 100644
--- a/src/commons/editor/__tests__/__snapshots__/Editor.test.tsx.snap
+++ b/src/commons/editor/__tests__/__snapshots__/Editor.test.tsx.snap
@@ -1,20 +1,120 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Editor renders correctly 1`] = `
-
+
+
+
+
+
+
+
+
+
+
+
+
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+
+
+
+
+
+
+
`;
diff --git a/src/commons/fileSystemView/FileSystemViewContextMenu.tsx b/src/commons/fileSystemView/FileSystemViewContextMenu.tsx
index a107d6bf87..0f29876587 100644
--- a/src/commons/fileSystemView/FileSystemViewContextMenu.tsx
+++ b/src/commons/fileSystemView/FileSystemViewContextMenu.tsx
@@ -1,7 +1,7 @@
import { Classes } from '@blueprintjs/core';
import { ControlledMenu, MenuItem, useMenuState } from '@szhsin/react-menu';
import classNames from 'classnames';
-import React from 'react';
+import React, { type JSX } from 'react';
import classes from 'src/styles/ContextMenu.module.scss';
type Props = {
diff --git a/src/commons/mobileWorkspace/mobileSideContent/MobileSideContent.tsx b/src/commons/mobileWorkspace/mobileSideContent/MobileSideContent.tsx
index 08646a28c5..0dd3ad44cc 100644
--- a/src/commons/mobileWorkspace/mobileSideContent/MobileSideContent.tsx
+++ b/src/commons/mobileWorkspace/mobileSideContent/MobileSideContent.tsx
@@ -1,6 +1,6 @@
import { Classes, Icon, Tab, Tabs, Tooltip } from '@blueprintjs/core';
import classNames from 'classnames';
-import React from 'react';
+import React, { type JSX } from 'react';
import { SideContentProps } from 'src/commons/sideContent/SideContent';
import { generateIconId } from 'src/commons/sideContent/SideContentHelper';
import SideContentProvider from 'src/commons/sideContent/SideContentProvider';
diff --git a/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx b/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx
index 443cae23ad..b22b7ca19c 100644
--- a/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx
+++ b/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx
@@ -20,9 +20,9 @@ const assessmentPaths = assessmentTypes.map(e => e.toLowerCase()).map(createCour
const staffPaths = staffRoutes.map(createCoursePath);
const adminPaths = adminRoutes.map(createCoursePath);
-const createMatchFn = (to: string) => (e: React.ReactElement) =>
+const createMatchFn = (to: string) => (e: React.ReactElement) =>
e.props.to === to && !e.props.disabled;
-const getChildren = (e: React.ReactElement) => e.props.children;
+const getChildren = (e: React.ReactElement) => e.props.children;
const validateAssessmentPaths = (tree: React.ReactElement, exist: boolean = true) =>
assessmentPaths.forEach(path => {
diff --git a/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/NavigationBarLangSelectButton.test.tsx.snap b/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/NavigationBarLangSelectButton.test.tsx.snap
index 892cff62df..5a6628923b 100644
--- a/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/NavigationBarLangSelectButton.test.tsx.snap
+++ b/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/NavigationBarLangSelectButton.test.tsx.snap
@@ -1,45 +1,40 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`NavigationBarLangSelectButton > should render correctly 1`] = `
-
-
+
-
- JavaScript
-
-
-
+ JavaScript
+
+
-
-
-
-
-
+
+
+
+
+
+
+
`;
diff --git a/src/commons/profile/Profile.tsx b/src/commons/profile/Profile.tsx
index da0368b21c..a443658d3b 100644
--- a/src/commons/profile/Profile.tsx
+++ b/src/commons/profile/Profile.tsx
@@ -1,6 +1,6 @@
import { Drawer, DrawerSize, NonIdealState, Spinner } from '@blueprintjs/core';
import { IconName, IconNames } from '@blueprintjs/icons';
-import React, { useEffect, useState } from 'react';
+import React, { type JSX, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import SessionActions from '../application/actions/SessionActions';
@@ -16,7 +16,7 @@ type OwnProps = {
onClose: () => void;
};
-const Profile: React.FC = props => {
+const Profile = (props => {
// FIXME: `xp` is actually of type number | undefined here!
// Fix the session type, then remove the typecast below
const {
@@ -188,6 +188,6 @@ const Profile: React.FC = props => {
{content}
);
-};
+}) satisfies React.FC;
export default Profile;
diff --git a/src/commons/repl/Repl.tsx b/src/commons/repl/Repl.tsx
index 2a8416c6b5..600a2b24ef 100644
--- a/src/commons/repl/Repl.tsx
+++ b/src/commons/repl/Repl.tsx
@@ -4,7 +4,7 @@ import classNames from 'classnames';
import { parseError } from 'js-slang';
import { Chapter, Variant } from 'js-slang/dist/types';
import { stringify } from 'js-slang/dist/utils/stringify';
-import React from 'react';
+import React, { type JSX } from 'react';
import type { InterpreterOutput, ResultOutput } from '../application/ApplicationTypes';
import { ExternalLibraryName } from '../application/types/ExternalTypes';
diff --git a/src/commons/repl/ReplInput.tsx b/src/commons/repl/ReplInput.tsx
index dc2a4e4bbc..1ed7664a2c 100644
--- a/src/commons/repl/ReplInput.tsx
+++ b/src/commons/repl/ReplInput.tsx
@@ -2,7 +2,7 @@ import { Classes } from '@blueprintjs/core';
import { Ace } from 'ace-builds';
import classNames from 'classnames';
import { Chapter, Variant } from 'js-slang/dist/types';
-import React from 'react';
+import React, { type JSX } from 'react';
import AceEditor from 'react-ace';
import ReactAce from 'react-ace/lib/ace';
diff --git a/src/commons/repl/__tests__/Repl.test.tsx b/src/commons/repl/__tests__/Repl.test.tsx
index da77d4c895..298e79c38b 100644
--- a/src/commons/repl/__tests__/Repl.test.tsx
+++ b/src/commons/repl/__tests__/Repl.test.tsx
@@ -1,6 +1,5 @@
import { Chapter, Variant } from 'js-slang/dist/types';
import { ExternalLibraryName } from 'src/commons/application/types/ExternalTypes';
-import { shallowRender } from 'src/commons/utils/TestUtils';
import {
CodeOutput,
@@ -34,7 +33,7 @@ const mockErrorOutput: ErrorOutput = {
consoleLogs: []
};
-test('Repl renders correctly', () => {
+test('Repl renders correctly', async () => {
const props = {
handleBrowseHistoryDown: () => {},
handleBrowseHistoryUp: () => {},
@@ -49,56 +48,48 @@ test('Repl renders correctly', () => {
replButtons: []
};
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Code output renders correctly', () => {
+test('Code output renders correctly', async () => {
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Running output renders correctly', () => {
+test('Running output renders correctly', async () => {
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Result output (no consoleLogs) renders correctly', () => {
+test('Result output (no consoleLogs) renders correctly', async () => {
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Result output (with consoleLogs) renders correctly', () => {
+test('Result output (with consoleLogs) renders correctly', async () => {
const props = {
...mockResultOutput,
consoleLogs: mockRunningOutput.consoleLogs
};
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Error output (no consoleLogs) renders correctly', () => {
+test('Error output (no consoleLogs) renders correctly', async () => {
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Error output (with consoleLogs) renders correctly', () => {
+test('Error output (with consoleLogs) renders correctly', async () => {
const props = {
...mockErrorOutput,
consoleLogs: mockRunningOutput.consoleLogs
};
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
-test('Empty output renders an empty card', () => {
+test('Empty output renders an empty card', async () => {
const app = ;
- const tree = shallowRender(app);
- expect(tree).toMatchSnapshot();
+ expect(app).toMatchSnapshot();
});
diff --git a/src/commons/repl/__tests__/__snapshots__/Repl.test.tsx.snap b/src/commons/repl/__tests__/__snapshots__/Repl.test.tsx.snap
index ddf57f9564..433a370b73 100644
--- a/src/commons/repl/__tests__/__snapshots__/Repl.test.tsx.snap
+++ b/src/commons/repl/__tests__/__snapshots__/Repl.test.tsx.snap
@@ -1,196 +1,152 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Code output renders correctly 1`] = `
-
-
- display('');
-
-
+
`;
exports[`Empty output renders an empty card 1`] = `
-
- ''
-
+
`;
exports[`Error output (no consoleLogs) renders correctly 1`] = `
-
-
- Expected , got .
-
-
+
`;
exports[`Error output (with consoleLogs) renders correctly 1`] = `
-
-
- a
-bb
-cccccccccccccccccccccccccccccccc
-d
-
-
-
- Expected , got .
-
-
-`;
-
-exports[`Repl renders correctly 1`] = `
-
-
-
-
-
+`;
+
+exports[`Repl renders correctly 1`] = `
+
-
-
-
-
-
-
+ "severity": "Error",
+ "side": "",
+ "type": "Runtime",
+ },
+ ],
+ "type": "errors",
+ },
+ {
+ "consoleLogs": [
+ "a",
+ "bb",
+ "cccccccccccccccccccccccccccccccc",
+ "d",
+ ],
+ "type": "running",
+ },
+ ]
+ }
+ replButtons={[]}
+ replValue=""
+ sourceChapter={1}
+ sourceVariant="default"
+/>
`;
exports[`Result output (no consoleLogs) renders correctly 1`] = `
-
-
- a
-bb
-cccccccccccccccccccccccccccccccc
-d
-
-
+
`;
diff --git a/src/commons/sideBar/SideBar.tsx b/src/commons/sideBar/SideBar.tsx
index 39c9813dae..27581bbe27 100644
--- a/src/commons/sideBar/SideBar.tsx
+++ b/src/commons/sideBar/SideBar.tsx
@@ -1,6 +1,6 @@
import { Card, Icon, IconName } from '@blueprintjs/core';
import classNames from 'classnames';
-import React from 'react';
+import React, { type JSX } from 'react';
import { SideContentType } from '../sideContent/SideContentTypes';
diff --git a/src/commons/sideContent/SideContent.tsx b/src/commons/sideContent/SideContent.tsx
index 75cffad579..57a1078233 100644
--- a/src/commons/sideContent/SideContent.tsx
+++ b/src/commons/sideContent/SideContent.tsx
@@ -1,4 +1,5 @@
import { Card, Icon, Tab, TabProps, Tabs, Tooltip } from '@blueprintjs/core';
+import type { JSX } from 'react';
import { assertType } from '../utils/TypeHelper';
import { generateTabAlert, getTabId } from './SideContentHelper';
diff --git a/src/commons/sideContent/SideContentProvider.tsx b/src/commons/sideContent/SideContentProvider.tsx
index d373f4084b..dcdbe4e976 100644
--- a/src/commons/sideContent/SideContentProvider.tsx
+++ b/src/commons/sideContent/SideContentProvider.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from 'react';
+import { type JSX, useCallback } from 'react';
import { useSideContent } from './SideContentHelper';
import type {
diff --git a/src/commons/sideContent/SideContentTypes.ts b/src/commons/sideContent/SideContentTypes.ts
index b45e457392..4bcee675f7 100644
--- a/src/commons/sideContent/SideContentTypes.ts
+++ b/src/commons/sideContent/SideContentTypes.ts
@@ -1,4 +1,5 @@
import { IconName } from '@blueprintjs/core';
+import type { JSX } from 'react';
import { DebuggerContext, WorkspaceLocation } from '../workspace/WorkspaceTypes';
diff --git a/src/commons/sideContent/__tests__/__snapshots__/SideContentContestVoting.test.tsx.snap b/src/commons/sideContent/__tests__/__snapshots__/SideContentContestVoting.test.tsx.snap
index cbdd854b4b..06c211fa79 100644
--- a/src/commons/sideContent/__tests__/__snapshots__/SideContentContestVoting.test.tsx.snap
+++ b/src/commons/sideContent/__tests__/__snapshots__/SideContentContestVoting.test.tsx.snap
@@ -1,272 +1,200 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`SideContentContestVotingContainer matches snapshot 1`] = `
-
-
+
-
-
-
-
-
-
-
- Contest Voting
+
+
+
+
+ Contest Voting
+
-
-
-
+
+
+
+
-
-
-
-
-
-
+ class="tier"
+ data-testid="tier"
+ id="tier-d"
+ >
+
+ D
+
+
+
-
-
-
@@ -274,5 +202,5 @@ exports[`SideContentContestVotingContainer matches snapshot 1`] = `
-
+
`;
diff --git a/src/commons/sideContent/__tests__/__snapshots__/SideContentCseMachine.test.tsx.snap b/src/commons/sideContent/__tests__/__snapshots__/SideContentCseMachine.test.tsx.snap
index 99e5c5d468..6e542cd1b1 100644
--- a/src/commons/sideContent/__tests__/__snapshots__/SideContentCseMachine.test.tsx.snap
+++ b/src/commons/sideContent/__tests__/__snapshots__/SideContentCseMachine.test.tsx.snap
@@ -1,559 +1,437 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`CSE Machine component renders correctly 1`] = `
-
+
-
+ class="bp6-slider-track"
+ >
+
+
+
+
-
-
- 0
+
+ 0
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
- The CSE machine generates control, stash and environment model diagrams following a notation introduced in
-
-
-
- Structure and Interpretation of Computer Programs, JavaScript Edition, Chapter 3, Section 2
-
-
-
- .
-
-
- On this tab, the REPL will be hidden from view, so do check that your code has no errors before running the stepper. You may use this tool by running your program and then dragging the slider above to see the state of the control, stash and environment at different stages in the evaluation of your program. Clicking on the fast-forward button (double chevron) will take you to the next breakpoint in your program
-
-
+
+
- Some useful keyboard shortcuts:
-
-
- a: Move to the first step
-
- e: Move to the last step
-
- f: Move to the next step
-
- b: Move to the previous step
-
-
- Note that these shortcuts are only active when the browser focus is on this tab.
-
-
-
-
-
+ The CSE machine generates control, stash and environment model diagrams following a notation introduced in
+
-
-
+
+ Structure and Interpretation of Computer Programs, JavaScript Edition, Chapter 3, Section 2
+
+
-
-
+
+ On this tab, the REPL will be hidden from view, so do check that your code has no errors before running the stepper. You may use this tool by running your program and then dragging the slider above to see the state of the control, stash and environment at different stages in the evaluation of your program. Clicking on the fast-forward button (double chevron) will take you to the next breakpoint in your program
+
+
+
+ Some useful keyboard shortcuts:
+
+
+ a: Move to the first step
+
+ e: Move to the last step
+
+ f: Move to the next step
+
+ b: Move to the previous step
+
+
+ Note that these shortcuts are only active when the browser focus is on this tab.
+
+
-
+
`;
diff --git a/src/commons/sideContent/__tests__/__snapshots__/SideContentHtmlDisplay.test.tsx.snap b/src/commons/sideContent/__tests__/__snapshots__/SideContentHtmlDisplay.test.tsx.snap
index a2c2cc1885..b36c852245 100644
--- a/src/commons/sideContent/__tests__/__snapshots__/SideContentHtmlDisplay.test.tsx.snap
+++ b/src/commons/sideContent/__tests__/__snapshots__/SideContentHtmlDisplay.test.tsx.snap
@@ -1,11 +1,13 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`HTML Display renders correctly 1`] = `
-
+
+
+
`;
diff --git a/src/commons/sideContent/content/SideContentContestVoting.tsx b/src/commons/sideContent/content/SideContentContestVoting.tsx
index 2af8989e25..2c15dae975 100644
--- a/src/commons/sideContent/content/SideContentContestVoting.tsx
+++ b/src/commons/sideContent/content/SideContentContestVoting.tsx
@@ -117,7 +117,9 @@ const SideContentContestVoting: React.FC = ({
onDragLeave={handleDragLeave}
onDragEnter={handleDragEnter}
onDrop={handleDrop}
- ref={item => (tierContainerRefs.current[index] = item)}
+ ref={item => {
+ tierContainerRefs.current[index] = item;
+ }}
/>
));
@@ -146,7 +148,9 @@ const SideContentContestVoting: React.FC = ({
id={`item-${index + 1}`}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd(contestEntry)}
- ref={item => (contestEntryRefs.current[index] = item)}
+ ref={item => {
+ contestEntryRefs.current[index] = item;
+ }}
data-testid="voting-item"
>
= ({ allowEdits, content, setContent }) => {
const [editorModeOn, setEditorModeOn] = React.useState(false);
- const node = React.useRef() as any;
+ const node = React.useRef(null);
useEffect(() => {
function handleClick(event: any) {
diff --git a/src/commons/sourceRecorder/SourceRecorderControlBar.tsx b/src/commons/sourceRecorder/SourceRecorderControlBar.tsx
index 842a6d9b1f..4606a87eca 100644
--- a/src/commons/sourceRecorder/SourceRecorderControlBar.tsx
+++ b/src/commons/sourceRecorder/SourceRecorderControlBar.tsx
@@ -53,7 +53,7 @@ type State = {
};
class SourceRecorderControlBar extends React.PureComponent {
- private audio: React.RefObject;
+ private audio: React.RefObject;
constructor(props: SourceRecorderControlBarProps) {
super(props);
diff --git a/src/commons/sourceRecorder/SourceRecorderEditor.tsx b/src/commons/sourceRecorder/SourceRecorderEditor.tsx
index 0f7b9af4d0..ebb1de4a72 100644
--- a/src/commons/sourceRecorder/SourceRecorderEditor.tsx
+++ b/src/commons/sourceRecorder/SourceRecorderEditor.tsx
@@ -60,7 +60,7 @@ type OwnProps = {
class SourcecastEditor extends React.PureComponent {
public ShareAce: any;
- public AceEditor: React.RefObject;
+ public AceEditor: React.RefObject;
private onChangeMethod: (newCode: string, delta: CodeDelta) => void;
private onCursorChange: (selecction: any) => void;
private onSelectionChange: (selection: any) => void;
diff --git a/src/commons/utils/Hooks.ts b/src/commons/utils/Hooks.ts
index 9aafc00d08..f54732ab95 100644
--- a/src/commons/utils/Hooks.ts
+++ b/src/commons/utils/Hooks.ts
@@ -79,7 +79,9 @@ export const useTypedSelector: TypedUseSelectorHook = useSelector;
* @param ref A reference to the underlying HTML element.
*/
-export const useDimensions = (ref: RefObject): [width: number, height: number] => {
+export const useDimensions = (
+ ref: RefObject
+): [width: number, height: number] => {
const [width, setWidth] = React.useState(0);
const [height, setHeight] = React.useState(0);
diff --git a/src/commons/utils/TestUtils.ts b/src/commons/utils/TestUtils.ts
index 30fce9e0bb..2dec8ca811 100644
--- a/src/commons/utils/TestUtils.ts
+++ b/src/commons/utils/TestUtils.ts
@@ -1,22 +1,22 @@
+import { render } from '@testing-library/react';
import React, { act } from 'react';
-import renderer from 'react-test-renderer';
-import { createRenderer } from 'react-test-renderer/shallow';
+import { shallow } from 'shallow-react-snapshot';
export const shallowRender = (element: React.ReactElement) => {
- const renderer = createRenderer();
- renderer.render(element);
- return renderer.getRenderOutput();
+ const app = render(element);
+ return shallow(app.container, element);
};
export const renderTree = async (element: React.ReactElement) => {
- const app = renderer.create(element);
+ const app = render(element);
await act(() => app);
- return app;
+ return app.asFragment();
};
+// TODO: Remove and replace with renderTree directly
export const renderTreeJson = async (element: React.ReactElement) => {
const app = await renderTree(element);
- return app.toJSON();
+ return app;
};
/**
@@ -27,7 +27,7 @@ export const renderTreeJson = async (element: React.ReactElement) => {
export function deepFilter(
nestedObject: T,
matchFn: (e: T) => boolean,
- getChildren: (e: T) => T[]
+ getChildren: (e: T) => T[] | undefined
) {
const matches: any[] = [];
diff --git a/src/commons/utils/notifications/NotificationsHelper.ts b/src/commons/utils/notifications/NotificationsHelper.ts
index 1f6f43226c..437b696220 100644
--- a/src/commons/utils/notifications/NotificationsHelper.ts
+++ b/src/commons/utils/notifications/NotificationsHelper.ts
@@ -1,4 +1,5 @@
import { Intent, ToastProps } from '@blueprintjs/core';
+import type { JSX } from 'react';
import { notification } from './createNotification';
diff --git a/src/features/cseMachine/components/Text.tsx b/src/features/cseMachine/components/Text.tsx
index d979391885..2629cb70de 100644
--- a/src/features/cseMachine/components/Text.tsx
+++ b/src/features/cseMachine/components/Text.tsx
@@ -49,7 +49,7 @@ export class Text extends Visible implements IHoverable {
readonly fullStr: string; // full string representation of data
readonly options: TextOptions = defaultOptions;
- readonly labelRef: React.RefObject = React.createRef();
+ readonly labelRef: React.RefObject = React.createRef();
constructor(
readonly data: Data,
diff --git a/src/features/cseMachine/components/values/ContValue.tsx b/src/features/cseMachine/components/values/ContValue.tsx
index 0e54531631..a8170884f3 100644
--- a/src/features/cseMachine/components/values/ContValue.tsx
+++ b/src/features/cseMachine/components/values/ContValue.tsx
@@ -37,7 +37,7 @@ import { Value } from './Value';
export class ContValue extends Value implements IHoverable {
readonly radius: number = Config.FnRadius;
readonly innerRadius: number = Config.FnInnerRadius;
- readonly labelRef: RefObject = React.createRef();
+ readonly labelRef: RefObject = React.createRef();
readonly tooltip: string = 'continuation';
readonly tooltipWidth: number = getTextWidth(this.tooltip);
diff --git a/src/features/cseMachine/components/values/FnValue.tsx b/src/features/cseMachine/components/values/FnValue.tsx
index 56c4a42ecc..734b332039 100644
--- a/src/features/cseMachine/components/values/FnValue.tsx
+++ b/src/features/cseMachine/components/values/FnValue.tsx
@@ -49,7 +49,7 @@ export class FnValue extends Value implements IHoverable {
/** width of the closure circles + label */
readonly totalWidth: number;
- readonly labelRef: RefObject = React.createRef();
+ readonly labelRef: RefObject = React.createRef();
centerX: number;
enclosingFrame?: Frame;
diff --git a/src/features/cseMachine/components/values/GlobalFnValue.tsx b/src/features/cseMachine/components/values/GlobalFnValue.tsx
index 1c906d07ce..6dc8c5e519 100644
--- a/src/features/cseMachine/components/values/GlobalFnValue.tsx
+++ b/src/features/cseMachine/components/values/GlobalFnValue.tsx
@@ -41,7 +41,7 @@ export class GlobalFnValue extends Value implements IHoverable {
readonly exportTooltip: string;
readonly exportTooltipWidth: number;
readonly totalWidth: number;
- readonly labelRef: RefObject = React.createRef();
+ readonly labelRef: RefObject = React.createRef();
centerX: number;
private _arrow: ArrowFromFn | undefined;
diff --git a/src/features/dataVisualizer/dataVisualizer.tsx b/src/features/dataVisualizer/dataVisualizer.tsx
index c742c6aac3..f32c22a445 100644
--- a/src/features/dataVisualizer/dataVisualizer.tsx
+++ b/src/features/dataVisualizer/dataVisualizer.tsx
@@ -1,3 +1,4 @@
+import type { JSX } from 'react';
import { Stage } from 'react-konva';
import { Config } from './Config';
diff --git a/src/features/dataVisualizer/dataVisualizerTypes.ts b/src/features/dataVisualizer/dataVisualizerTypes.ts
index e592cf4aed..650bf31e04 100644
--- a/src/features/dataVisualizer/dataVisualizerTypes.ts
+++ b/src/features/dataVisualizer/dataVisualizerTypes.ts
@@ -1,3 +1,5 @@
+import type { JSX } from 'react';
+
// Source-related types
export type Data = any;
export type Pair = [Data, Data];
diff --git a/src/features/dataVisualizer/tree/ArrayTreeNode.tsx b/src/features/dataVisualizer/tree/ArrayTreeNode.tsx
index f33ed98601..44761375c1 100644
--- a/src/features/dataVisualizer/tree/ArrayTreeNode.tsx
+++ b/src/features/dataVisualizer/tree/ArrayTreeNode.tsx
@@ -1,3 +1,4 @@
+import type { JSX } from 'react';
import { Group } from 'react-konva';
import { Config } from '../Config';
diff --git a/src/features/dataVisualizer/tree/DrawableTreeNode.tsx b/src/features/dataVisualizer/tree/DrawableTreeNode.tsx
index 1d6bdaf01f..61ed91fe8f 100644
--- a/src/features/dataVisualizer/tree/DrawableTreeNode.tsx
+++ b/src/features/dataVisualizer/tree/DrawableTreeNode.tsx
@@ -1,3 +1,5 @@
+import type { JSX } from 'react';
+
import { TreeNode } from './BaseTreeNode';
/**
diff --git a/src/features/dataVisualizer/tree/FunctionTreeNode.tsx b/src/features/dataVisualizer/tree/FunctionTreeNode.tsx
index 95407b8907..6b2a1a1ad4 100644
--- a/src/features/dataVisualizer/tree/FunctionTreeNode.tsx
+++ b/src/features/dataVisualizer/tree/FunctionTreeNode.tsx
@@ -1,3 +1,4 @@
+import type { JSX } from 'react';
import { Group } from 'react-konva';
import { Config } from '../Config';
diff --git a/src/features/dataVisualizer/tree/Tree.tsx b/src/features/dataVisualizer/tree/Tree.tsx
index cfa0353647..0457d327f1 100644
--- a/src/features/dataVisualizer/tree/Tree.tsx
+++ b/src/features/dataVisualizer/tree/Tree.tsx
@@ -1,4 +1,5 @@
import Konva from 'konva';
+import type { JSX } from 'react';
import { Layer, Text } from 'react-konva';
import { Config } from '../Config';
diff --git a/src/features/sicp/errors/SicpErrors.tsx b/src/features/sicp/errors/SicpErrors.tsx
index 818c5b48f5..bbe24c8a1c 100644
--- a/src/features/sicp/errors/SicpErrors.tsx
+++ b/src/features/sicp/errors/SicpErrors.tsx
@@ -1,5 +1,6 @@
import { NonIdealState } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
+import type { JSX } from 'react';
export enum SicpErrorType {
UNEXPECTED_ERROR,
diff --git a/src/features/sicp/errors/__tests__/SicpErrors.test.tsx b/src/features/sicp/errors/__tests__/SicpErrors.test.tsx
index 4d2be1aa2f..f130364446 100644
--- a/src/features/sicp/errors/__tests__/SicpErrors.test.tsx
+++ b/src/features/sicp/errors/__tests__/SicpErrors.test.tsx
@@ -1,31 +1,24 @@
-import { render, screen } from '@testing-library/react';
-import { act } from 'react';
-import { shallowRender } from 'src/commons/utils/TestUtils';
+import { screen } from '@testing-library/react';
+import { renderTree } from 'src/commons/utils/TestUtils';
import getSicpError, { SicpErrorType } from '../SicpErrors';
describe('Sicp errors:', () => {
test('unexpected error renders correctly', async () => {
const element = getSicpError(SicpErrorType.UNEXPECTED_ERROR);
- expect(shallowRender(element)).toMatchSnapshot();
-
- await act(() => render(element));
+ expect(await renderTree(element)).toMatchSnapshot();
screen.getByTestId('sicp-unexpected-error');
});
test('page not found error renders correctly', async () => {
const element = getSicpError(SicpErrorType.PAGE_NOT_FOUND_ERROR);
- expect(shallowRender(element)).toMatchSnapshot();
-
- await act(() => render(element));
+ expect(await renderTree(element)).toMatchSnapshot();
screen.getByTestId('sicp-page-not-found-error');
});
test('unexpected error renders correctly', async () => {
const element = getSicpError(SicpErrorType.PARSING_ERROR);
- expect(shallowRender(element)).toMatchSnapshot();
-
- await act(() => render(element));
+ expect(await renderTree(element)).toMatchSnapshot();
screen.getByTestId('sicp-parsing-error');
});
});
diff --git a/src/features/sicp/errors/__tests__/__snapshots__/SicpErrors.test.tsx.snap b/src/features/sicp/errors/__tests__/__snapshots__/SicpErrors.test.tsx.snap
index 341029d910..eeed2a4676 100644
--- a/src/features/sicp/errors/__tests__/__snapshots__/SicpErrors.test.tsx.snap
+++ b/src/features/sicp/errors/__tests__/__snapshots__/SicpErrors.test.tsx.snap
@@ -1,131 +1,157 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp errors: > page not found error renders correctly 1`] = `
-
+
-
-
-
-
- Something went wrong :(
-
+
-
+
`;
exports[`Sicp errors: > unexpected error renders correctly 1`] = `
-
-
-
-
+
-
- Something went wrong :(
-
+
- Something unexpected went wrong trying to load this page. Please try refreshing the page. If the issue persists, kindly let us know by filing an issue at
-
-
- https://github.com/source-academy/frontend
-
- .
+ Something went wrong :(
+
+
-
+
`;
exports[`Sicp errors: > unexpected error renders correctly 2`] = `
-
-
-
-
+
-
- Something went wrong :(
-
+
-
+
`;
diff --git a/src/features/sicp/parser/ParseJson.tsx b/src/features/sicp/parser/ParseJson.tsx
index 8d3f669d3e..d8115434d7 100644
--- a/src/features/sicp/parser/ParseJson.tsx
+++ b/src/features/sicp/parser/ParseJson.tsx
@@ -1,6 +1,6 @@
import { Blockquote, Code, H1, H2, H4, Icon, OL, Pre, UL } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
-import React from 'react';
+import React, { type JSX } from 'react';
import { Link } from 'react-router';
import Constants from 'src/commons/utils/Constants';
import SicpExercise from 'src/pages/sicp/subcomponents/SicpExercise';
@@ -55,7 +55,9 @@ const AnchorLink: React.FC = ({ refs, id, children, top }) => {
(refs.current[id] = ref)}
+ ref={ref => {
+ refs.current[id] = ref;
+ }}
to={id}
>
@@ -71,7 +73,11 @@ const handleFootnote = (obj: JsonType, refs: RefType) => {
<>
{obj.count === 1 && }
-
(refs.current[obj.id!] = ref)} />
+
@@ -81,7 +87,12 @@ const handleFootnote = (obj: JsonType, refs: RefType) => {
const handleRef = (obj: JsonType, refs: RefType) => {
return (
-
(refs.current[obj.id!] = ref)} to={obj.href!}>
+
{
+ refs.current[obj.id!] = ref;
+ }}
+ to={obj.href!}
+ >
{obj.body}
);
@@ -227,7 +238,13 @@ export const processingFunctions: Record
(
- (refs.current[obj.id!] = ref)}>{handleRef(obj, refs)}
+ {
+ refs.current[obj.id!] = ref;
+ }}
+ >
+ {handleRef(obj, refs)}
+
),
JAVASCRIPTINLINE: (obj, _refs) => {obj.body},
diff --git a/src/features/sicp/parser/__tests__/__snapshots__/ParseJson.test.tsx.snap b/src/features/sicp/parser/__tests__/__snapshots__/ParseJson.test.tsx.snap
index 6d56169933..7a04dfb3cc 100644
--- a/src/features/sicp/parser/__tests__/__snapshots__/ParseJson.test.tsx.snap
+++ b/src/features/sicp/parser/__tests__/__snapshots__/ParseJson.test.tsx.snap
@@ -1,418 +1,382 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-exports[`Parse array > no child successful 1`] = `null`;
+exports[`Parse array > no child successful 1`] = ` `;
-exports[`Parse array > one child successful 1`] = `"Mock Text"`;
+exports[`Parse array > one child successful 1`] = `
+
+ Mock Text
+
+`;
exports[`Parse array > two child successful 1`] = `
-[
- "Mock Text",
- "Mock Text",
-]
+
+ Mock TextMock Text
+
`;
exports[`Parse epigraph > EPIGRAPH with all successful 1`] = `
-
- Mock Text
-
+
- -
- Author
-
- Title
-
- 2021
-
-
+ Mock Text
+
+ -Author
+
+ Title
+
+ 2021
+
+
+
`;
exports[`Parse epigraph > EPIGRAPH with author successful 1`] = `
-
- Mock Text
-
-
+ Mock Text
+
+ -Author
+
+
+
`;
exports[`Parse epigraph > EPIGRAPH with date successful 1`] = `
-
- Mock Text
-
-
+ Mock Text
+
+ -2021
+
+
+
`;
exports[`Parse epigraph > EPIGRAPH with none successful 1`] = `
-
- Mock Text
-
+
+
+ Mock Text
+
+
`;
exports[`Parse epigraph > EPIGRAPH with title successful 1`] = `
-
- Mock Text
-
-
+ Mock Text
+
+ -
+
+ Title
+
+
+
+
`;
exports[`Parse exercise > EXERCISE with solution successful 1`] = `
-
+
-
-
-
+
+
-
- Show Solution
-
-
-
-
+
+ Show Solution
+
+
+
+ class="bp6-collapse sicp-solution"
+ >
+
+
-
+
`;
exports[`Parse exercise > EXERCISE without solution successful 1`] = `
-
+
-
- Title
-
-
- Mock Text
-
-
+ Title
+
+
+ Mock Text
+
+
-
- Show Solution
-
-
-
-
+
+ Show Solution
+
+
+
+ class="bp6-collapse sicp-solution"
+ >
+
+
-
+
`;
exports[`Parse figures > FIGURE with image and scale successful 1`] = `
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+
`;
exports[`Parse figures > FIGURE with image successful 1`] = `
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+
`;
exports[`Parse figures > FIGURE with snippet successful 1`] = `
-
-
+
-
-
-
-
-
-
-
-
- Code Snippet
-
-
+
+
+
+
+
-
+
`;
exports[`Parse figures > FIGURE with table successful 1`] = `
-
+
`;
exports[`Parse footnote > DISPLAYFOOTNOTE count is 2 successful 1`] = `
-
+
`;
exports[`Parse heading > SUBHEADING successful 1`] = `
-
-
+
- Mock Text
-
-
+
+ Mock Text
+
+
+
`;
exports[`Parse heading > SUBSUBHEADING successful 1`] = `
-
-
+
-
- Mock Text
-
-
+
+
+ Mock Text
+
+
+
`;
exports[`Parse latex > LATEX block successful 1`] = `
-t e s t test t es t ",
- }
- }
-/>
+
+
+
+
+
+
+
+
+
+ t
+
+
+ e
+
+
+ s
+
+
+ t
+
+
+
+ test
+
+
+
+
+
+
+
+
+ t
+
+
+ es
+
+
+ t
+
+
+
+
+
+
+
`;
exports[`Parse latex > LATEX inline successful 1`] = `
-t e s t test t es t ",
- }
- }
-/>
+
+
+
+
+
+
+
+
+ t
+
+
+ e
+
+
+ s
+
+
+ t
+
+
+
+ test
+
+
+
+
+
+
+
+
+ t
+
+
+ es
+
+
+ t
+
+
+
+
+
+
`;
exports[`Parse links > FOOTNOTE_REF successful 1`] = `
-
+
+
+
+ link
+
+
+
+`;
+
+exports[`Parse links > LINK successful 1`] = `
+
link
-
-`;
-
-exports[`Parse links > LINK successful 1`] = `
-
- link
-
+
`;
exports[`Parse links > REF successful 1`] = `
-
- link
-
+
+
+ link
+
+
`;
exports[`Parse list > OL successful 1`] = `
-
-
- Mock Text
-
-
+
+
+
+ Mock Text
+
+
+
`;
exports[`Parse list > UL successful 1`] = `
-
+
+
+
`;
-exports[`Parse object > no tag 1`] = `"Mock Text"`;
+exports[`Parse object > no tag 1`] = `
+
+ Mock Text
+
+`;
-exports[`Parse object > successful 1`] = `"Mock Text"`;
+exports[`Parse object > successful 1`] = `
+
+ Mock Text
+
+`;
exports[`Parse reference > REFERENCE successful 1`] = `
-
- Mock Text
-
+
+
+ Mock Text
+
+
`;
exports[`Parse snippet > SNIPPET no eval successful 1`] = `
-
- const a = 1;
+
+
+ const a = 1;
a+1;
-
+
+
`;
exports[`Parse snippet > SNIPPET with latex successful 1`] = `
-
-
-
+
+
+
+ const a = 1;
+a+1;
+
+
+
`;
exports[`Parse snippet > SNIPPET with prepend successful 1`] = `
-
- Code Snippet
-
+
+
+ Code Snippet
+
+
`;
exports[`Parse snippet > SNIPPET without prepend successful 1`] = `
-
- Code Snippet
-
+
+
+ Code Snippet
+
+
`;
exports[`Parse snippet > SNIPPET without prepend with output successful 1`] = `
-
- Code Snippet
-
+
+
+ Code Snippet
+
+
`;
exports[`Parse styling > B successful 1`] = `
-
- Mock Text
-
+
+
+ Mock Text
+
+
`;
exports[`Parse styling > EM successful 1`] = `
-
- Mock Text
-
+
+
+ Mock Text
+
+
`;
exports[`Parse styling > JAVASCRIPTINLINE successful 1`] = `
-
+
+
+
`;
-exports[`Parse styling > META successful 1`] = `
`;
+exports[`Parse styling > META successful 1`] = `
+
+
+
+`;
exports[`Parse styling > TT successful 1`] = `
-
- Mock Text
-
+
+
+ Mock Text
+
+
`;
-exports[`Parse symbol > BR successful 1`] = `
`;
+exports[`Parse symbol > BR successful 1`] = `
+
+
+
+`;
exports[`Parse table > TABLE successful 1`] = `
-
-
-
-
- Mock Text
-
-
- Mock Text
-
-
-
-
- Mock Text
-
-
- Mock Text
-
-
-
-
+
+
+
+
+
+ Mock Text
+
+
+ Mock Text
+
+
+
+
+ Mock Text
+
+
+ Mock Text
+
+
+
+
+
`;
exports[`Parse title > TITLE successful 1`] = `
-
-
+
- Title
-
-
+
+ Title
+
+
+
`;
diff --git a/src/pages/academy/adminPanel/subcomponents/AddStoriesUserPanel.tsx b/src/pages/academy/adminPanel/subcomponents/AddStoriesUserPanel.tsx
index 8786abc55e..788a3056b9 100644
--- a/src/pages/academy/adminPanel/subcomponents/AddStoriesUserPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/AddStoriesUserPanel.tsx
@@ -15,7 +15,7 @@ import { IconNames } from '@blueprintjs/icons';
import { ColDef } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { uniqBy } from 'lodash';
-import React from 'react';
+import React, { type JSX } from 'react';
import { useCSVReader } from 'react-papaparse';
import { StoriesRole } from 'src/commons/application/ApplicationTypes';
diff --git a/src/pages/academy/adminPanel/subcomponents/AddUserPanel.tsx b/src/pages/academy/adminPanel/subcomponents/AddUserPanel.tsx
index 398f933131..e95eb68e6d 100644
--- a/src/pages/academy/adminPanel/subcomponents/AddUserPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/AddUserPanel.tsx
@@ -15,7 +15,7 @@ import { IconNames } from '@blueprintjs/icons';
import { ColDef } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { uniqBy } from 'lodash';
-import React from 'react';
+import React, { type JSX } from 'react';
import { useCSVReader } from 'react-papaparse';
import { Role } from 'src/commons/application/ApplicationTypes';
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index d00ef3cd92..144b78494e 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -61,7 +61,7 @@ const AssessmentConfigPanel: WithImperativeApi<
React.FC
> = forwardRef(
({ setHasChangesAssessmentConfig, initialConfigs }, imperativeRef) => {
- const gridApi = React.useRef>();
+ const gridApi = React.useRef>(null);
// Create a mutable copy of the initialConfigs to track changes
// to prevent UI flicker during state changes.
const tableState = useRef(cloneDeep(initialConfigs));
diff --git a/src/pages/academy/adminPanel/subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel.tsx
index ebb0ae2d10..9a9703c5e8 100644
--- a/src/pages/academy/adminPanel/subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel.tsx
@@ -30,7 +30,7 @@ const defaultColumnDefs: ColDef = {
* no admins left in a course)
*/
const StoriesUserConfigPanel: React.FC = props => {
- const gridApi = React.useRef();
+ const gridApi = React.useRef(null);
const storiesUsers = props.storiesUsers?.map(e =>
!e.name ? { ...e, name: '(user has yet to log in)' } : e
@@ -88,12 +88,10 @@ const StoriesUserConfigPanel: React.FC = props => {
text="Export as CSV"
className="export-csv-button"
onClick={() => {
- if (gridApi.current) {
- gridApi.current.exportDataAsCsv({
- fileName: `SA Stories Users (${new Date().toISOString()}).csv`,
- columnKeys: ['name', 'username', 'role']
- });
- }
+ gridApi.current?.exportDataAsCsv({
+ fileName: `SA Stories Users (${new Date().toISOString()}).csv`,
+ columnKeys: ['name', 'username', 'role']
+ });
}}
/>
diff --git a/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserConfigPanel.tsx
index 8cc45e44d8..54436a142d 100644
--- a/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserConfigPanel.tsx
@@ -30,7 +30,7 @@ const defaultColumnDefs: ColDef = {
* no admins left in a course)
*/
const UserConfigPanel: React.FC = props => {
- const gridApi = React.useRef();
+ const gridApi = React.useRef(null);
const userCourseRegistrations = props.userCourseRegistrations?.map(e =>
!e.name ? { ...e, name: '(user has yet to log in)' } : e
@@ -89,12 +89,10 @@ const UserConfigPanel: React.FC = props => {
text="Export as CSV"
className="export-csv-button"
onClick={() => {
- if (gridApi.current) {
- gridApi.current.exportDataAsCsv({
- fileName: `SA Users (${new Date().toISOString()}).csv`,
- columnKeys: ['name', 'username', 'group', 'role']
- });
- }
+ gridApi.current?.exportDataAsCsv({
+ fileName: `SA Users (${new Date().toISOString()}).csv`,
+ columnKeys: ['name', 'username', 'group', 'role']
+ });
}}
/>
diff --git a/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewer.tsx b/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewer.tsx
index 668fd3e9b9..bd3ef16af1 100644
--- a/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewer.tsx
+++ b/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewer.tsx
@@ -1,6 +1,6 @@
import { Icon, Tab, Tabs, Tooltip, Tree, TreeNodeInfo } from '@blueprintjs/core';
import { cloneDeep } from 'lodash';
-import React from 'react';
+import React, { type JSX } from 'react';
import { useRequest } from 'src/commons/utils/Hooks';
import { fetchAssetPaths, s3AssetFolders } from 'src/features/gameSimulator/GameSimulatorService';
import { deleteS3File } from 'src/features/gameSimulator/GameSimulatorService';
diff --git a/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewerUtils.tsx b/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewerUtils.tsx
index 762ef1b4e6..35c4087088 100644
--- a/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewerUtils.tsx
+++ b/src/pages/academy/gameSimulator/subcomponents/assetViewer/AssetViewerUtils.tsx
@@ -1,5 +1,6 @@
import { TreeNodeInfo } from '@blueprintjs/core';
import { set } from 'lodash';
+import type { JSX } from 'react';
type Tree = Record | string[] | any;
diff --git a/src/pages/githubCallback/__tests__/GitHubCallback.test.tsx b/src/pages/githubCallback/__tests__/GitHubCallback.test.tsx
index 5cd76d7597..eea24dc6b9 100644
--- a/src/pages/githubCallback/__tests__/GitHubCallback.test.tsx
+++ b/src/pages/githubCallback/__tests__/GitHubCallback.test.tsx
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
-import { act } from 'react';
+import { act, type JSX } from 'react';
import { Route, Routes, StaticRouter } from 'react-router';
import { Mock, vi } from 'vitest';
diff --git a/src/pages/playground/__tests__/__snapshots__/Playground.test.tsx.snap b/src/pages/playground/__tests__/__snapshots__/Playground.test.tsx.snap
index 849252fd2a..4dfaa770ca 100644
--- a/src/pages/playground/__tests__/__snapshots__/Playground.test.tsx.snap
+++ b/src/pages/playground/__tests__/__snapshots__/Playground.test.tsx.snap
@@ -573,7 +573,6 @@ exports[`Playground tests > Playground renders correctly 1`] = `
Playground renders correctly 1`] = `
Playground renders correctly 1`] = `
Playground renders correctly 1`] = `
Playground with link renders correctly 1`] = `
Playground with link renders correctly 1`] = `
Playground with link renders correctly 1`] = `
Playground with link renders correctly 1`] = `
{
) : (
- (refs.current['#begin'] = ref)} />
+ {
+ refs.current['#begin'] = ref;
+ }}
+ />
{data}
{navigationButtons}
- (refs.current['#end'] = ref)} />
+ {
+ refs.current['#end'] = ref;
+ }}
+ />
)}
diff --git a/src/pages/sicp/__tests__/Sicp.test.tsx b/src/pages/sicp/__tests__/Sicp.test.tsx
index c18201ae44..12e3f5e26b 100644
--- a/src/pages/sicp/__tests__/Sicp.test.tsx
+++ b/src/pages/sicp/__tests__/Sicp.test.tsx
@@ -2,7 +2,7 @@ import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import type { Location } from 'react-router';
import { mockInitialStore } from 'src/commons/mocks/StoreMocks';
-import { shallowRender } from 'src/commons/utils/TestUtils';
+import { renderTree } from 'src/commons/utils/TestUtils';
import { vi } from 'vitest';
import Sicp from '../Sicp';
@@ -14,13 +14,13 @@ vi.mock('react-router', () => ({
}));
describe('Sicp renders', () => {
- test('correctly', () => {
+ test('correctly', async () => {
const sicp = (
);
- const tree = shallowRender(sicp);
+ const tree = await renderTree(sicp);
expect(tree).toMatchSnapshot();
});
diff --git a/src/pages/sicp/__tests__/__snapshots__/Sicp.test.tsx.snap b/src/pages/sicp/__tests__/__snapshots__/Sicp.test.tsx.snap
index d7e248cd9b..91ada124e5 100644
--- a/src/pages/sicp/__tests__/__snapshots__/Sicp.test.tsx.snap
+++ b/src/pages/sicp/__tests__/__snapshots__/Sicp.test.tsx.snap
@@ -1,32 +1,571 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp renders > correctly 1`] = `
-
-
-
+
+
+
+
+
+
+
+
+ Structure and Interpretation of Computer Programs
+
+
+ — JavaScript Edition
+
+
+
+
+ Harold Abelson and Gerald Jay Sussman
+
+
+ with Julie Sussman
+
+ — original authors
+
+
+
+ Martin Henz and Tobias Wrigstad
+
+
+ with Julie Sussman
+
+ — adapters to JavaScript
+
+
+
+ Samuel Fang
+
+
+
+ — designer and developer of this Interactive SICP JS edition
+
+
+
+
+
+
+
+ Content
+
+
+
+
+
+
+
+
+ Foreword
+
+
+
+
+
+
+
+
+ Foreword to Structure and Interpretation of Computer Programs, 1984
+
+
+
+
+
+
+
+
+ Preface
+
+
+
+
+
+
+
+
+ Prefaces to Structure and Interpretation of Computer Programs, 1996 & 1984
+
+
+
+
+
+
+
+
+ Acknowledgments
+
+
+
+
+
+
+
+
+
+ Expand group
+
+
+
+
+
+ 1 Building Abstractions with Functions
+
+
+
+
+
+
+
+
+
+ Expand group
+
+
+
+
+
+ 2 Building Abstractions with Data
+
+
+
+
+
+
+
+
+
+ Expand group
+
+
+
+
+
+ 3 Modularity, Objects, and State
+
+
+
+
+
+
+
+
+
+ Expand group
+
+
+
+
+
+ 4 Metalinguistic Abstraction
+
+
+
+
+
+
+
+
+
+ Expand group
+
+
+
+
+
+ 5 Computing with Register Machines
+
+
+
+
+
+
+
+
+ References
+
+
+
+
+
+
+
+
+ About the SICP JS Project
+
+
+
+
+
+
+
+
+
+ Licenses
+
+
+
+
+
`;
diff --git a/src/pages/sicp/subcomponents/SicpExercise.tsx b/src/pages/sicp/subcomponents/SicpExercise.tsx
index 885a9aac8b..9e59c30bb8 100644
--- a/src/pages/sicp/subcomponents/SicpExercise.tsx
+++ b/src/pages/sicp/subcomponents/SicpExercise.tsx
@@ -1,5 +1,5 @@
import { Button, Card, Collapse, Elevation } from '@blueprintjs/core';
-import React from 'react';
+import React, { type JSX } from 'react';
export const noSolutionPlaceholder = (
diff --git a/src/pages/sicp/subcomponents/__tests__/SicpLatex.test.tsx b/src/pages/sicp/subcomponents/__tests__/SicpLatex.test.tsx
index da78044a31..e296a8de17 100644
--- a/src/pages/sicp/subcomponents/__tests__/SicpLatex.test.tsx
+++ b/src/pages/sicp/subcomponents/__tests__/SicpLatex.test.tsx
@@ -1,25 +1,25 @@
-import { shallowRender } from 'src/commons/utils/TestUtils';
+import { renderTree } from 'src/commons/utils/TestUtils';
import SicpLatex from '../SicpLatex';
describe('Sicp latex renders', () => {
- test('correctly block', () => {
+ test('correctly block', async () => {
const props = {
math: '1+1',
inline: false
};
- const tree = shallowRender( );
+ const tree = await renderTree( );
expect(tree).toMatchSnapshot();
});
- test('correctly inline', () => {
+ test('correctly inline', async () => {
const props = {
math: '1+1',
inline: true
};
- const tree = shallowRender( );
+ const tree = await renderTree( );
expect(tree).toMatchSnapshot();
});
});
diff --git a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpExercise.test.tsx.snap b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpExercise.test.tsx.snap
index c9e88e8fa1..f01542c852 100644
--- a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpExercise.test.tsx.snap
+++ b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpExercise.test.tsx.snap
@@ -1,56 +1,41 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp exercise renders > correctly 1`] = `
-
-
- Title
-
-
+
-
+ Title
+
+
+
-
- Show Solution
-
-
-
-
+
+ Show Solution
+
+
+
+ class="bp6-collapse sicp-solution"
+ >
+
+
-
+
`;
diff --git a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpIndexPage.test.tsx.snap b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpIndexPage.test.tsx.snap
index 0ad1b8fbb4..07b0328010 100644
--- a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpIndexPage.test.tsx.snap
+++ b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpIndexPage.test.tsx.snap
@@ -1,798 +1,567 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp index page 1`] = `
-
+
-
-
-
- Structure and Interpretation of Computer Programs
-
-
- — JavaScript Edition
-
-
+
-
- Harold Abelson and Gerald Jay Sussman
-
-
- with Julie Sussman
-
- — original authors
-
-
-
- Martin Henz and Tobias Wrigstad
-
-
- with Julie Sussman
-
- — adapters to JavaScript
-
-
-
+
+ Structure and Interpretation of Computer Programs
+
+
+ — JavaScript Edition
+
+
+
- Samuel Fang
-
-
-
- — designer and developer of this Interactive SICP JS edition
-
-
+
+ Harold Abelson and Gerald Jay Sussman
+
+
+ with Julie Sussman
+
+ — original authors
+
+
+
+ Martin Henz and Tobias Wrigstad
+
+
+ with Julie Sussman
+
+ — adapters to JavaScript
+
+
+
+ Samuel Fang
+
+
+
+ — designer and developer of this Interactive SICP JS edition
+
+
+
-
-
-
- Content
-
-
+
+
+ Content
+
-
-
-
-
-
- Foreword
-
-
-
+
+
+ Foreword
+
+
-
-
-
-
-
-
- Foreword to Structure and Interpretation of Computer Programs, 1984
-
-
-
+
+
+
-
-
-
-
-
-
- Preface
-
-
-
+
+
+ Foreword to Structure and Interpretation of Computer Programs, 1984
+
+
-
-
-
-
-
-
- Prefaces to Structure and Interpretation of Computer Programs, 1996 & 1984
-
-
-
+
+
+
-
-
-
-
-
-
- Acknowledgments
-
-
-
+
+
+ Preface
+
+
-
-
-
-
+
+
-
-
+
-
- Expand group
-
-
-
-
-
+
+
- 1 Building Abstractions with Functions
-
-
-
+
+
+
-
-
-
-
-
-
+
-
- Expand group
-
-
-
-
-
+
+
- 2 Building Abstractions with Data
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+ Expand group
+
+
+
+
+
-
- Expand group
-
-
-
-
-
+
+
- 3 Modularity, Objects, and State
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+ Expand group
+
+
+
+
+
-
- Expand group
-
-
-
-
-
+
+
- 4 Metalinguistic Abstraction
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+ Expand group
+
+
+
+
+
-
- Expand group
-
-
-
-
-
+
+
- 5 Computing with Register Machines
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+ Expand group
+
+
+
+
+
+ 4 Metalinguistic Abstraction
+
+
+
- References
-
-
-
+
+
+
-
-
-
-
+
+
+
+ Expand group
+
+
+
+
+
+ 5 Computing with Register Machines
+
+
+
+
+
-
-
+
+
+ References
+
+
+
- About the SICP JS Project
-
-
-
+
+
+
-
-
-
-
-
-
-
- Licenses
-
-
-
-
-
-
+ class="bp6-tree-node-content bp6-tree-node-content-0"
+ >
+
+
+ About the SICP JS Project
+
+
+
+
+
+
-
-
- This work is licensed under a
-
+
+
+ Licenses
+
+
+
-
-
-
-
- All JavaScript programs in this work are licensed under the
-
+
+
+
+
-
-
-
+
+
+
+
+
-
-
+
`;
diff --git a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpLatex.test.tsx.snap b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpLatex.test.tsx.snap
index a0e550fdda..9792b0631e 100644
--- a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpLatex.test.tsx.snap
+++ b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpLatex.test.tsx.snap
@@ -1,13 +1,21 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp latex renders > correctly block 1`] = `
-
- 1+1
-
+
+
+ 1+1
+
+
`;
exports[`Sicp latex renders > correctly inline 1`] = `
-
- 1+1
-
+
+
+ 1+1
+
+
`;
diff --git a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpToc.test.tsx.snap b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpToc.test.tsx.snap
index 7588cee636..a20a62db29 100644
--- a/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpToc.test.tsx.snap
+++ b/src/pages/sicp/subcomponents/__tests__/__snapshots__/SicpToc.test.tsx.snap
@@ -1,635 +1,408 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sicp toc renders correctly 1`] = `
-
+
-
-
-
-
-
- Foreword
-
-
-
+
+
+ Foreword
+
+
-
-
-
-
-
-
- Foreword to Structure and Interpretation of Computer Programs, 1984
-
-
-
+
+
+
-
-
-
-
-
-
- Preface
-
-
-
+
+
+ Foreword to Structure and Interpretation of Computer Programs, 1984
+
+
-
-
-
-
-
-
- Prefaces to Structure and Interpretation of Computer Programs, 1996 & 1984
-
-
-
+
+
+
-
-
-
-
-
-
- Acknowledgments
-
-
-
+
+
+ Preface
+
+
-
-
-
-
+
+
-
-
+
-
- Expand group
-
-
-
-
-
+
+
- 1 Building Abstractions with Functions
-
-
-
+
+
+
-
-
-
-
-
-
+
-
- Expand group
-
-
-
-
-
+
+
- 2 Building Abstractions with Data
-
-
-
+
+
+
-
-
-
-
-
-
-
- Expand group
-
-
-
-
-
+
+ Expand group
+
+
+
+
+
+ 1 Building Abstractions with Functions
+
+
+
- 3 Modularity, Objects, and State
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+ Expand group
+
+
+
+
+
-
- Expand group
-
-
-
-
-
+
+
- 4 Metalinguistic Abstraction
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+ Expand group
+
+
+
+
+
-
- Expand group
-
-
-
-
-
+
+
- 5 Computing with Register Machines
-
-
-
+
+
+
-
-
-
-
-
-
- References
-
-
-
+
+
+ Expand group
+
+
+
+
+
+ 4 Metalinguistic Abstraction
+
+
+
+
+
-
-
-
-
+
+
+
+ Expand group
+
+
+
+
+
+ 5 Computing with Register Machines
+
+
+
+
+
-
-
- About the SICP JS Project
-
-
-
+
+ References
+
+
+
+
+
-
-
-
+ class="bp6-tree-node-content bp6-tree-node-content-0"
+ >
+
+
+ About the SICP JS Project
+
+
+
+
+
+
-
+
`;
diff --git a/src/pages/sicp/subcomponents/chatbot/ChatBox.tsx b/src/pages/sicp/subcomponents/chatbot/ChatBox.tsx
index 9fc43e66b0..3feda720ea 100644
--- a/src/pages/sicp/subcomponents/chatbot/ChatBox.tsx
+++ b/src/pages/sicp/subcomponents/chatbot/ChatBox.tsx
@@ -22,7 +22,7 @@ const BOT_ERROR_MESSAGE: Readonly = {
role: 'assistant'
};
-const scrollToBottom = (ref: React.RefObject) => {
+const scrollToBottom = (ref: React.RefObject) => {
ref.current?.scrollTo({ top: ref.current?.scrollHeight });
};
diff --git a/yarn.lock b/yarn.lock
index 25641adc70..ebae072a4d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4056,13 +4056,6 @@ __metadata:
languageName: node
linkType: hard
-"@types/prop-types@npm:*":
- version: 15.7.11
- resolution: "@types/prop-types@npm:15.7.11"
- checksum: 10c0/e53423cf9d510515ef8b47ff42f4f1b65a7b7b37c8704e2dbfcb9a60defe0c0e1f3cb1acfdeb466bad44ca938d7c79bffdd51b48ffb659df2432169d0b27a132
- languageName: node
- linkType: hard
-
"@types/react-copy-to-clipboard@npm:^5.0.4":
version: 5.0.7
resolution: "@types/react-copy-to-clipboard@npm:5.0.7"
@@ -4072,21 +4065,30 @@ __metadata:
languageName: node
linkType: hard
-"@types/react-dom@npm:^18.3.0":
- version: 18.3.7
- resolution: "@types/react-dom@npm:18.3.7"
+"@types/react-dom@npm:^19.1.6":
+ version: 19.1.7
+ resolution: "@types/react-dom@npm:19.1.7"
peerDependencies:
- "@types/react": ^18.0.0
- checksum: 10c0/8bd309e2c3d1604a28a736a24f96cbadf6c05d5288cfef8883b74f4054c961b6b3a5e997fd5686e492be903c8f3380dba5ec017eff3906b1256529cd2d39603e
+ "@types/react": ^19.0.0
+ checksum: 10c0/8db5751c1567552fe4e1ece9f5823b682f2994ec8d30ed34ba0ef984e3c8ace1435f8be93d02f55c350147e78ac8c4dbcd8ed2c3b6a60f575bc5374f588c51c9
languageName: node
linkType: hard
-"@types/react-reconciler@npm:^0.28.0, @types/react-reconciler@npm:^0.28.2":
- version: 0.28.2
- resolution: "@types/react-reconciler@npm:0.28.2"
- dependencies:
- "@types/react": "npm:*"
- checksum: 10c0/8b8819b492972f08b9975efdf59dec668094f9e9483408b84698659ac02f4966c9c082ba79e80fef723c4f46279c5c3b15a7de7fa70af00a20741a8a15890b82
+"@types/react-reconciler@npm:^0.28.9":
+ version: 0.28.9
+ resolution: "@types/react-reconciler@npm:0.28.9"
+ peerDependencies:
+ "@types/react": "*"
+ checksum: 10c0/9fe71fa856aab2cd4742fe0416bdd4f5c82ecc05ef6451ee7fcb65a5efdf5fa588f5820fbe2a665b15371b0da3bfc4097f28bb6d450b9a834af2d0fc00f403bd
+ languageName: node
+ linkType: hard
+
+"@types/react-reconciler@npm:^0.32.0":
+ version: 0.32.0
+ resolution: "@types/react-reconciler@npm:0.32.0"
+ peerDependencies:
+ "@types/react": "*"
+ checksum: 10c0/43bfbb0471811dc3aeb6e46a4724663b2bb26137a0169977f415e31c253037d53e549ed1b71d0f9bec9fe9dda5c22e7be9e55dcba564bf3eaf01ed19e950874e
languageName: node
linkType: hard
@@ -4111,15 +4113,6 @@ __metadata:
languageName: node
linkType: hard
-"@types/react-test-renderer@npm:^18.0.0":
- version: 18.3.1
- resolution: "@types/react-test-renderer@npm:18.3.1"
- dependencies:
- "@types/react": "npm:^18"
- checksum: 10c0/9fc8467ff1a3f14be6cc3498a75fc788d2c92c0fffa7bf21269ed5d9d82db9195bf2178ddc42ea16a0836995c1b77601c6be8abb27bd1864668c418c6d0e5a3b
- languageName: node
- linkType: hard
-
"@types/react-transition-group@npm:^4.4.0":
version: 4.4.10
resolution: "@types/react-transition-group@npm:4.4.10"
@@ -4129,13 +4122,12 @@ __metadata:
languageName: node
linkType: hard
-"@types/react@npm:*, @types/react@npm:^18, @types/react@npm:^18.3.3":
- version: 18.3.23
- resolution: "@types/react@npm:18.3.23"
+"@types/react@npm:*, @types/react@npm:^19.1.8":
+ version: 19.1.9
+ resolution: "@types/react@npm:19.1.9"
dependencies:
- "@types/prop-types": "npm:*"
csstype: "npm:^3.0.2"
- checksum: 10c0/49331800b76572eb2992a5c44801dbf8c612a5f99c8f4e4200f06c7de6f3a6e9455c661784a6c5469df96fa45622cb4a9d0982c44e6a0d5719be5f2ef1f545ed
+ checksum: 10c0/b418da4aaf18fbc6df4f1b7096dda7ee152d697cac00d729ffd855b2b44a3a9cfb2ecb017ed20979ea3a7d98a5ce5fcf01ac1a3614d4a3e4d7069a0c45e49b0f
languageName: node
linkType: hard
@@ -7566,12 +7558,11 @@ __metadata:
"@types/js-cookie": "npm:^3.0.6"
"@types/js-yaml": "npm:^4.0.5"
"@types/lodash": "npm:^4.14.195"
- "@types/react": "npm:^18.3.3"
+ "@types/react": "npm:^19.1.8"
"@types/react-copy-to-clipboard": "npm:^5.0.4"
- "@types/react-dom": "npm:^18.3.0"
+ "@types/react-dom": "npm:^19.1.6"
"@types/react-redux": "npm:^7.1.24"
"@types/react-syntax-highlighter": "npm:^15.5.7"
- "@types/react-test-renderer": "npm:^18.0.0"
"@types/redux-mock-store": "npm:^1.0.3"
"@types/showdown": "npm:^2.0.1"
"@types/xml2js": "npm:^0.4.11"
@@ -7629,17 +7620,17 @@ __metadata:
process: "npm:^0.11.10"
query-string: "npm:^9.0.0"
re-resizable: "npm:^6.9.9"
- react: "npm:^18.3.1"
+ react: "npm:^19.1.0"
react-ace: "npm:^14.0.0"
react-copy-to-clipboard: "npm:^5.1.0"
react-debounce-render: "npm:^8.0.2"
- react-dom: "npm:^18.3.1"
+ react-dom: "npm:^19.1.0"
react-drag-drop-files: "npm:^3.0.0"
react-draggable: "npm:^4.4.5"
react-dropzone: "npm:^14.2.3"
react-error-overlay: "npm:^6.0.11"
react-i18next: "npm:^15.0.0"
- react-konva: "npm:^18.2.10"
+ react-konva: "npm:^19.0.7"
react-latex-next: "npm:^3.0.0"
react-mde: "npm:^11.5.0"
react-papaparse: "npm:^4.0.2"
@@ -7650,7 +7641,6 @@ __metadata:
react-simple-keyboard: "npm:^3.6.27"
react-sortable-hoc: "npm:^2.0.0"
react-syntax-highlighter: "npm:^15.5.0"
- react-test-renderer: "npm:^18.2.0"
react-textarea-autosize: "npm:^8.5.2"
redux-mock-store: "npm:^1.5.4"
redux-saga: "npm:^1.2.3"
@@ -7658,6 +7648,7 @@ __metadata:
rehype-react: "npm:^8.0.0"
resize-observer-polyfill: "npm:^1.5.1"
sass: "npm:^1.63.6"
+ shallow-react-snapshot: "npm:^0.2.2"
showdown: "npm:^2.1.0"
sourceror: "npm:^0.8.5"
stream-browserify: "npm:^3.0.0"
@@ -8915,14 +8906,14 @@ __metadata:
languageName: node
linkType: hard
-"its-fine@npm:^1.1.1":
- version: 1.1.1
- resolution: "its-fine@npm:1.1.1"
+"its-fine@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "its-fine@npm:2.0.0"
dependencies:
- "@types/react-reconciler": "npm:^0.28.0"
+ "@types/react-reconciler": "npm:^0.28.9"
peerDependencies:
- react: ">=18.0"
- checksum: 10c0/66059a859720de19563a8abdb10f06eb6117df1897d984a54b0a71ab9dc02da3dc366428b1f0c5e085740962abb7d6ccc0b8c3e00725b0a2120c846f352adffc
+ react: ^19.0.0
+ checksum: 10c0/1ff1ff3257c0c7eb115c9c26cf0506eb84162edc1a63d3136780d146f7c7833298b240d0fcb46888909773f1a7d16539e0c03f2482cff1a5a502d6436686fe21
languageName: node
linkType: hard
@@ -9452,7 +9443,7 @@ __metadata:
languageName: node
linkType: hard
-"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0":
+"loose-envify@npm:^1.0.0, loose-envify@npm:^1.4.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
dependencies:
@@ -11260,15 +11251,14 @@ __metadata:
languageName: node
linkType: hard
-"react-dom@npm:^18.3.1":
- version: 18.3.1
- resolution: "react-dom@npm:18.3.1"
+"react-dom@npm:^19.1.0":
+ version: 19.1.1
+ resolution: "react-dom@npm:19.1.1"
dependencies:
- loose-envify: "npm:^1.1.0"
- scheduler: "npm:^0.23.2"
+ scheduler: "npm:^0.26.0"
peerDependencies:
- react: ^18.3.1
- checksum: 10c0/a752496c1941f958f2e8ac56239172296fcddce1365ce45222d04a1947e0cc5547df3e8447f855a81d6d39f008d7c32eab43db3712077f09e3f67c4874973e85
+ react: ^19.1.1
+ checksum: 10c0/8c91198510521299c56e4e8d5e3a4508b2734fb5e52f29eeac33811de64e76fe586ad32c32182e2e84e070d98df67125da346c3360013357228172dbcd20bcdd
languageName: node
linkType: hard
@@ -11363,13 +11353,6 @@ __metadata:
languageName: node
linkType: hard
-"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.3.1":
- version: 18.3.1
- resolution: "react-is@npm:18.3.1"
- checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072
- languageName: node
- linkType: hard
-
"react-is@npm:^17.0.1":
version: 17.0.2
resolution: "react-is@npm:17.0.2"
@@ -11377,19 +11360,26 @@ __metadata:
languageName: node
linkType: hard
-"react-konva@npm:^18.2.10":
- version: 18.2.12
- resolution: "react-konva@npm:18.2.12"
+"react-is@npm:^18.0.0":
+ version: 18.3.1
+ resolution: "react-is@npm:18.3.1"
+ checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072
+ languageName: node
+ linkType: hard
+
+"react-konva@npm:^19.0.7":
+ version: 19.0.7
+ resolution: "react-konva@npm:19.0.7"
dependencies:
- "@types/react-reconciler": "npm:^0.28.2"
- its-fine: "npm:^1.1.1"
- react-reconciler: "npm:~0.29.0"
- scheduler: "npm:^0.23.0"
+ "@types/react-reconciler": "npm:^0.32.0"
+ its-fine: "npm:^2.0.0"
+ react-reconciler: "npm:0.32.0"
+ scheduler: "npm:0.26.0"
peerDependencies:
konva: ^8.0.1 || ^7.2.5 || ^9.0.0
- react: ">=18.0.0"
- react-dom: ">=18.0.0"
- checksum: 10c0/cc0d57496651c361addcb8acf3e92fec1d67555a44ecab52c3d1a8df4c4923b02059ad266869f3868b44e0faed5585fe31770a2978c312726a2634f9db3b9a73
+ react: ^18.3.1 || ^19.0.0
+ react-dom: ^18.3.1 || ^19.0.0
+ checksum: 10c0/035e127be48518a6fd3a9d1fc83f10df229323ae2d71fd1dd74b3e0b10f067e8bcd80bafa4af40390d7404f5defe62db50a33d20867fd86f42c691be8a130c60
languageName: node
linkType: hard
@@ -11460,15 +11450,14 @@ __metadata:
languageName: node
linkType: hard
-"react-reconciler@npm:~0.29.0":
- version: 0.29.0
- resolution: "react-reconciler@npm:0.29.0"
+"react-reconciler@npm:0.32.0":
+ version: 0.32.0
+ resolution: "react-reconciler@npm:0.32.0"
dependencies:
- loose-envify: "npm:^1.1.0"
- scheduler: "npm:^0.23.0"
+ scheduler: "npm:^0.26.0"
peerDependencies:
- react: ^18.2.0
- checksum: 10c0/637442f98ee816b8f86586f537712a0463b53e12c0f4dec716dfdde68dfa52cef1d10138acfad194d5571296cde8715c331aa3986e538087acdc1ef83187a9b0
+ react: ^19.1.0
+ checksum: 10c0/ace0562d2aa99685416ac62741354706dec6df334aa64acc7ad455bd8a6f6af0068b276ad2e5412c3875388022ab13807f0b7d688fda7b2835301c110247146b
languageName: node
linkType: hard
@@ -11559,18 +11548,6 @@ __metadata:
languageName: node
linkType: hard
-"react-shallow-renderer@npm:^16.15.0":
- version: 16.15.0
- resolution: "react-shallow-renderer@npm:16.15.0"
- dependencies:
- object-assign: "npm:^4.1.1"
- react-is: "npm:^16.12.0 || ^17.0.0 || ^18.0.0"
- peerDependencies:
- react: ^16.0.0 || ^17.0.0 || ^18.0.0
- checksum: 10c0/c194d741792e86043a4ae272f7353c1cb9412bc649945c4220c6a101a6ea5410cceb3d65d5a4d750f11a24f7426e8eec7977e8a4e3ad5d3ee235ca2b18166fa8
- languageName: node
- linkType: hard
-
"react-simple-keyboard@npm:^3.6.27":
version: 3.8.107
resolution: "react-simple-keyboard@npm:3.8.107"
@@ -11626,19 +11603,6 @@ __metadata:
languageName: node
linkType: hard
-"react-test-renderer@npm:^18.2.0":
- version: 18.3.1
- resolution: "react-test-renderer@npm:18.3.1"
- dependencies:
- react-is: "npm:^18.3.1"
- react-shallow-renderer: "npm:^16.15.0"
- scheduler: "npm:^0.23.2"
- peerDependencies:
- react: ^18.3.1
- checksum: 10c0/c633558ef9af33bc68f0c4dbb5163a004c4fb9eade7bd0a7cfc0355fb367f36bd9d96533c90b7e85a146be6c525113a15f58683d269e0177ad77e2b04d4fe51c
- languageName: node
- linkType: hard
-
"react-textarea-autosize@npm:^8.5.2":
version: 8.5.9
resolution: "react-textarea-autosize@npm:8.5.9"
@@ -11692,12 +11656,10 @@ __metadata:
languageName: node
linkType: hard
-"react@npm:^18.3.1":
- version: 18.3.1
- resolution: "react@npm:18.3.1"
- dependencies:
- loose-envify: "npm:^1.1.0"
- checksum: 10c0/283e8c5efcf37802c9d1ce767f302dd569dd97a70d9bb8c7be79a789b9902451e0d16334b05d73299b20f048cbc3c7d288bbbde10b701fa194e2089c237dbea3
+"react@npm:^19.1.0":
+ version: 19.1.1
+ resolution: "react@npm:19.1.1"
+ checksum: 10c0/8c9769a2dfd02e603af6445058325e6c8a24b47b185d0e461f66a6454765ddcaecb3f0a90184836c68bb509f3c38248359edbc42f0d07c23eb500a5c30c87b4e
languageName: node
linkType: hard
@@ -12529,12 +12491,10 @@ __metadata:
languageName: node
linkType: hard
-"scheduler@npm:^0.23.0, scheduler@npm:^0.23.2":
- version: 0.23.2
- resolution: "scheduler@npm:0.23.2"
- dependencies:
- loose-envify: "npm:^1.1.0"
- checksum: 10c0/26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78
+"scheduler@npm:0.26.0, scheduler@npm:^0.26.0":
+ version: 0.26.0
+ resolution: "scheduler@npm:0.26.0"
+ checksum: 10c0/5b8d5bfddaae3513410eda54f2268e98a376a429931921a81b5c3a2873aab7ca4d775a8caac5498f8cbc7d0daeab947cf923dbd8e215d61671f9f4e392d34356
languageName: node
linkType: hard
@@ -12662,6 +12622,13 @@ __metadata:
languageName: node
linkType: hard
+"shallow-react-snapshot@npm:^0.2.2":
+ version: 0.2.2
+ resolution: "shallow-react-snapshot@npm:0.2.2"
+ checksum: 10c0/16f4294df815ce0a3f0ea4befefad057fda52b312e3a98d28ea99a2eca4968a48d1ebcc268e89f20ccea1b1dc06b3989610b3d9110f09735af8a70e710ee8fef
+ languageName: node
+ linkType: hard
+
"shallowequal@npm:1.1.0":
version: 1.1.0
resolution: "shallowequal@npm:1.1.0"