Skip to content

Commit dbbc452

Browse files
committed
Merge branch 'master' of https://github.com/source-academy/frontend into HEAD
2 parents 5c91790 + b9bb1cd commit dbbc452

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2805
-2109
lines changed

.github/workflows/build-development.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ on:
33
push:
44
branches:
55
- master
6+
workflow_dispatch:
7+
inputs:
8+
ref:
9+
description: Branch/Tag/SHA to checkout
10+
required: true
11+
default: master
612

713
jobs:
814
deploy:
@@ -11,6 +17,8 @@ jobs:
1117
steps:
1218
- name: Checkout repository
1319
uses: actions/checkout@v4
20+
with:
21+
ref: ${{ github.event.inputs.ref }}
1422
# Has to be run before actions/setup-node.
1523
# See: https://github.com/actions/setup-node/issues/480
1624
- name: Enable corepack for Yarn

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"i18next-browser-languagedetector": "^8.0.0",
6161
"java-slang": "^1.0.13",
6262
"js-cookie": "^3.0.5",
63-
"js-slang": "^1.0.82",
63+
"js-slang": "^1.0.84",
6464
"js-yaml": "^4.1.0",
6565
"konva": "^9.2.0",
6666
"language-directory": "https://github.com/source-academy/language-directory.git",

src/commons/__tests__/Markdown.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ test('Markdown page renders correct Source information', () => {
3131
const source3Default = <Markdown {...mockProps(Chapter.SOURCE_3, Variant.DEFAULT)} />;
3232
expect(source3Default.props.content).toContain('Source \xa73');
3333

34-
const source3Concurrent = <Markdown {...mockProps(Chapter.SOURCE_3, Variant.CONCURRENT)} />;
35-
expect(source3Concurrent.props.content).toContain('Source \xa73 Concurrent');
36-
3734
const source4Default = <Markdown {...mockProps(Chapter.SOURCE_4, Variant.DEFAULT)} />;
3835
expect(source4Default.props.content).toContain('Source \xa74');
3936
});

src/commons/application/ApplicationTypes.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import { Chapter, Language, SourceError, Variant } from 'js-slang/dist/types';
1+
import { Chapter, Language, type SourceError, type Value, Variant } from 'js-slang/dist/types';
22

3-
import { AchievementState } from '../../features/achievement/AchievementTypes';
4-
import { DashboardState } from '../../features/dashboard/DashboardTypes';
5-
import { PlaygroundState } from '../../features/playground/PlaygroundTypes';
3+
import type { AchievementState } from '../../features/achievement/AchievementTypes';
4+
import type { DashboardState } from '../../features/dashboard/DashboardTypes';
5+
import type { PlaygroundState } from '../../features/playground/PlaygroundTypes';
66
import { PlaybackStatus, RecordingStatus } from '../../features/sourceRecorder/SourceRecorderTypes';
7-
import { StoriesEnvState, StoriesState } from '../../features/stories/StoriesTypes';
7+
import type { StoriesEnvState, StoriesState } from '../../features/stories/StoriesTypes';
88
import { freshSortState } from '../../pages/academy/grading/subcomponents/GradingSubmissionsTable';
99
import { WORKSPACE_BASE_PATHS } from '../../pages/fileSystem/createInBrowserFileSystem';
1010
import { defaultFeatureFlags, FeatureFlagsState } from '../featureFlags';
11-
import { FileSystemState } from '../fileSystem/FileSystemTypes';
12-
import { SideContentManagerState, SideContentState } from '../sideContent/SideContentTypes';
11+
import type { FileSystemState } from '../fileSystem/FileSystemTypes';
12+
import type { SideContentManagerState, SideContentState } from '../sideContent/SideContentTypes';
1313
import Constants from '../utils/Constants';
1414
import { createContext } from '../utils/JsSlangHelper';
15-
import {
15+
import type {
1616
DebuggerContext,
1717
WorkspaceLocation,
1818
WorkspaceManagerState,
1919
WorkspaceState
2020
} from '../workspace/WorkspaceTypes';
21-
import { RouterState } from './types/CommonsTypes';
21+
import type { RouterState } from './types/CommonsTypes';
2222
import { ExternalLibraryName } from './types/ExternalTypes';
23-
import { SessionState } from './types/SessionTypes';
24-
import { VscodeState as VscodeState } from './types/VscodeTypes';
23+
import type { SessionState } from './types/SessionTypes';
24+
import type { VscodeState as VscodeState } from './types/VscodeTypes';
2525

2626
export type OverallState = {
2727
readonly router: RouterState;
@@ -74,7 +74,7 @@ export type CodeOutput = {
7474
*/
7575
export type ResultOutput = {
7676
type: 'result';
77-
value: any;
77+
value: Value;
7878
consoleLogs: string[];
7979
runtime?: number;
8080
isProgram?: boolean;
@@ -160,7 +160,6 @@ type LanguageFeatures = Partial<{
160160
const variantDisplay: Map<Variant, string> = new Map([
161161
[Variant.TYPED, 'Typed'],
162162
[Variant.WASM, 'WebAssembly'],
163-
[Variant.CONCURRENT, 'Concurrent'],
164163
[Variant.NATIVE, 'Native'],
165164
[Variant.EXPLICIT_CONTROL, 'Explicit-Control']
166165
]);
@@ -266,7 +265,6 @@ const sourceSubLanguages: Array<Pick<SALanguage, 'chapter' | 'variant'>> = [
266265

267266
{ chapter: Chapter.SOURCE_3, variant: Variant.DEFAULT },
268267
{ chapter: Chapter.SOURCE_3, variant: Variant.TYPED },
269-
{ chapter: Chapter.SOURCE_3, variant: Variant.CONCURRENT },
270268
{ chapter: Chapter.SOURCE_3, variant: Variant.NATIVE },
271269

272270
{ chapter: Chapter.SOURCE_4, variant: Variant.DEFAULT },
@@ -288,13 +286,13 @@ export const sourceLanguages: SALanguage[] = sourceSubLanguages.map(sublang => {
288286
(variant === Variant.DEFAULT || variant === Variant.NATIVE || variant === Variant.TYPED);
289287

290288
// Enable CSE Machine for Source Chapter 3 and above
291-
supportedFeatures.cseMachine = chapter >= Chapter.SOURCE_3 && variant !== Variant.CONCURRENT;
289+
supportedFeatures.cseMachine = chapter >= Chapter.SOURCE_3;
292290

293291
// Local imports/exports require Source 2+ as Source 1 does not have lists.
294292
supportedFeatures.multiFile = chapter >= Chapter.SOURCE_2;
295293

296294
// Disable REPL for concurrent variants
297-
supportedFeatures.repl = variant !== Variant.CONCURRENT;
295+
supportedFeatures.repl = true;
298296

299297
return {
300298
...sublang,

src/commons/application/__tests__/ApplicationTypes.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ describe('available Source language configurations', () => {
5555
variant: Variant.TYPED,
5656
supports: { dataVisualizer: true, cseMachine: true }
5757
},
58-
{
59-
chapter: Chapter.SOURCE_3,
60-
variant: Variant.CONCURRENT,
61-
supports: { dataVisualizer: true }
62-
},
6358
{
6459
chapter: Chapter.SOURCE_3,
6560
variant: Variant.NATIVE,

src/commons/application/__tests__/__snapshots__/ApplicationTypes.ts.snap

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,6 @@ exports[`available Source language configurations matches snapshot 1`] = `
188188
},
189189
"variant": "typed",
190190
},
191-
{
192-
"chapter": 3,
193-
"displayName": "Source §3 Concurrent",
194-
"mainLanguage": "JavaScript",
195-
"supports": {
196-
"cseMachine": false,
197-
"dataVisualizer": true,
198-
"multiFile": true,
199-
"repl": false,
200-
"substVisualizer": false,
201-
},
202-
"variant": "concurrent",
203-
},
204191
{
205192
"chapter": 3,
206193
"displayName": "Source §3 Native",

src/commons/application/actions/SessionActions.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ import {
44
unpublishedToBackendParams
55
} from 'src/features/grading/GradingUtils';
66
import { freshSortState } from 'src/pages/academy/grading/subcomponents/GradingSubmissionsTable';
7-
import { OptionType } from 'src/pages/academy/teamFormation/subcomponents/TeamFormationForm';
7+
import type { OptionType } from 'src/pages/academy/teamFormation/subcomponents/TeamFormationForm';
88

9-
import {
9+
import type {
1010
AllColsSortStates,
1111
GradingOverviews,
1212
GradingQuery
1313
} from '../../../features/grading/GradingTypes';
14-
import { TeamFormationOverview } from '../../../features/teamFormation/TeamFormationTypes';
15-
import {
14+
import type { TeamFormationOverview } from '../../../features/teamFormation/TeamFormationTypes';
15+
import type {
1616
Assessment,
1717
AssessmentConfiguration,
1818
AssessmentOverview,
1919
ContestEntry
2020
} from '../../assessment/AssessmentTypes';
21-
import {
21+
import type {
2222
Notification,
2323
NotificationFilterFunction
2424
} from '../../notificationBadge/NotificationBadgeTypes';
2525
import { generateOctokitInstance } from '../../utils/GitHubPersistenceHelper';
2626
import { Role, StoriesRole } from '../ApplicationTypes';
27-
import {
27+
import type {
2828
AdminPanelCourseRegistration,
2929
CourseRegistration,
3030
Tokens,
@@ -153,6 +153,4 @@ const SessionActions = createActions('session', {
153153
});
154154

155155
// For compatibility with existing code (actions helper)
156-
export default {
157-
...SessionActions
158-
};
156+
export default SessionActions;

src/commons/mocks/ContextMocks.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { parse } from 'acorn';
2-
import { FunctionExpression, Node } from 'estree';
2+
import type { Node } from 'estree';
33
import { ACORN_PARSE_OPTIONS } from 'js-slang/dist/constants';
44
import createContext, { EnvTree } from 'js-slang/dist/createContext';
5-
import Closure from 'js-slang/dist/interpreter/closure';
6-
import { Context, Environment } from 'js-slang/dist/types';
5+
import type { Context } from 'js-slang/dist/types';
76
import { TypeError } from 'js-slang/dist/utils/rttc';
87

98
export function mockContext(chapter = 1): Context {
@@ -44,10 +43,6 @@ export function mockRuntimeContext(): Context {
4443
return context;
4544
}
4645

47-
export function mockClosure(): Closure {
48-
return new Closure({} as FunctionExpression, {} as Environment, {} as Context);
49-
}
50-
5146
export function mockTypeError(): TypeError {
5247
// Typecast to Node to fix estree-acorn compatability.
5348
return new TypeError(parse('', ACORN_PARSE_OPTIONS) as Node, '', '', '');

src/commons/redux/__tests__/utils.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { testSaga } from 'redux-saga-test-plan';
2+
import WorkspaceActions from 'src/commons/workspace/WorkspaceActions';
3+
4+
import { combineSagaHandlers, createActions } from '../utils';
5+
6+
// Would have used spyOn, but for some reason that doesn't work properly
7+
jest.mock('src/commons/sagas/SafeEffects', () => ({
8+
...jest.requireActual('src/commons/sagas/SafeEffects'),
9+
// Mock wrap saga to just be a passthrough so that the identity
10+
// checking that testSaga uses will pass
11+
wrapSaga: (x: any) => x
12+
}));
13+
14+
test('test combineSagaHandlers', () => {
15+
const mockTakeEveryHandler = jest.fn();
16+
const mockTakeLatestHandler = jest.fn();
17+
const mockTakeLeadingHandler = jest.fn();
18+
19+
const saga = combineSagaHandlers({
20+
[WorkspaceActions.toggleUsingUpload.type]: mockTakeEveryHandler,
21+
[WorkspaceActions.toggleFolderMode.type]: {
22+
takeEvery: mockTakeEveryHandler
23+
},
24+
[WorkspaceActions.toggleUsingCse.type]: {
25+
takeLatest: mockTakeLatestHandler
26+
},
27+
[WorkspaceActions.toggleUsingSubst.type]: {
28+
takeLeading: mockTakeLeadingHandler
29+
},
30+
[WorkspaceActions.toggleEditorAutorun.type]: {
31+
takeEvery: mockTakeEveryHandler,
32+
takeLeading: mockTakeLeadingHandler
33+
}
34+
});
35+
36+
testSaga(saga)
37+
.next()
38+
.takeEvery(WorkspaceActions.toggleUsingUpload.type, mockTakeEveryHandler)
39+
.next()
40+
.takeEvery(WorkspaceActions.toggleFolderMode.type, mockTakeEveryHandler)
41+
.next()
42+
.takeLatest(WorkspaceActions.toggleUsingCse.type, mockTakeLatestHandler)
43+
.next()
44+
.takeLeading(WorkspaceActions.toggleUsingSubst.type, mockTakeLeadingHandler)
45+
.next()
46+
.takeEvery(WorkspaceActions.toggleEditorAutorun.type, mockTakeEveryHandler)
47+
.next()
48+
.takeLeading(WorkspaceActions.toggleEditorAutorun.type, mockTakeLeadingHandler)
49+
.next()
50+
.isDone();
51+
});
52+
53+
test('createActions', () => {
54+
const actions = createActions('workspace', {
55+
act0: false,
56+
act1: (value: string) => ({ value }),
57+
act2: 525600
58+
});
59+
60+
const act0 = actions.act0();
61+
expect(act0.type).toEqual('workspace/act0');
62+
63+
const act1 = actions.act1('test');
64+
expect(act1.type).toEqual('workspace/act1');
65+
expect(act1.payload).toMatchObject({ value: 'test' });
66+
67+
const act2 = actions.act2();
68+
expect(act2.type).toEqual('workspace/act2');
69+
});

0 commit comments

Comments
 (0)