@khanacademy/perseus 12.3.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/es/index.css +3 -3
- package/dist/es/index.js +593 -223
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9698 -9446
- package/dist/index.js.map +1 -1
- package/dist/item-renderer.d.ts +3 -1
- package/dist/perseus-types.d.ts +4 -2
- package/dist/widgets/label-image/strings.d.ts +3 -0
- package/dist/widgets/plotter.d.ts +8 -22
- package/package.json +10 -8
- package/src/__tests__/item-renderer.test.tsx +41 -0
- package/src/__tests__/widget-container.test.tsx +126 -0
- package/src/error-boundary.tsx +1 -0
- package/src/index.ts +5 -1
- package/src/item-renderer.tsx +4 -2
- package/src/perseus-types.ts +11 -2
- package/src/styles/articles.less +3 -1
- package/src/styles/perseus-renderer.less +1 -1
- package/src/widget-container.tsx +2 -1
- package/src/widgets/__tests__/__snapshots__/graded-group-set.test.ts.snap +50 -19
- package/src/widgets/__tests__/plotter.test.tsx +11 -8
- package/src/widgets/graded-group-set.tsx +70 -25
- package/src/widgets/label-image/strings.ts +3 -0
- package/src/widgets/plotter.tsx +29 -50
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/item-renderer.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ KeypadProps & {
|
|
|
16
16
|
item: PerseusItem | any;
|
|
17
17
|
onShowCalculator?: () => unknown;
|
|
18
18
|
onShowChi2Table?: () => unknown;
|
|
19
|
-
onShowPeriodicTable?: (
|
|
19
|
+
onShowPeriodicTable?: (options?: {
|
|
20
|
+
showKey: boolean;
|
|
21
|
+
}) => unknown;
|
|
20
22
|
onShowTTable?: () => unknown;
|
|
21
23
|
onShowZTable?: () => unknown;
|
|
22
24
|
problemNum: number;
|
package/dist/perseus-types.d.ts
CHANGED
|
@@ -413,17 +413,19 @@ export type PerseusPassageRefWidgetOptions = {
|
|
|
413
413
|
referenceNumber: number;
|
|
414
414
|
summaryText: string;
|
|
415
415
|
};
|
|
416
|
+
export declare const plotterPlotTypes: readonly ["bar", "line", "pic", "histogram", "dotplot"];
|
|
417
|
+
export type PlotType = typeof plotterPlotTypes[number];
|
|
416
418
|
export type PerseusPlotterWidgetOptions = {
|
|
417
419
|
labels: ReadonlyArray<string>;
|
|
418
420
|
categories: ReadonlyArray<string>;
|
|
419
|
-
type:
|
|
421
|
+
type: PlotType;
|
|
420
422
|
maxY: number;
|
|
421
423
|
scaleY: number;
|
|
422
424
|
labelInterval: number | null | undefined;
|
|
423
425
|
snapsPerLine: number;
|
|
424
426
|
starting: ReadonlyArray<number>;
|
|
425
427
|
correct: ReadonlyArray<number>;
|
|
426
|
-
picUrl:
|
|
428
|
+
picUrl: string | null | undefined;
|
|
427
429
|
picSize: number | null | undefined;
|
|
428
430
|
picBoxHeight: number | null | undefined;
|
|
429
431
|
plotDimensions: ReadonlyArray<number>;
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
scaleY: number;
|
|
10
|
-
maxY: number;
|
|
11
|
-
snapsPerLine: number;
|
|
12
|
-
picSize: number;
|
|
13
|
-
picBoxHeight: number;
|
|
14
|
-
picUrl: string;
|
|
15
|
-
plotDimensions: ReadonlyArray<number>;
|
|
16
|
-
labelInterval: number;
|
|
17
|
-
starting: Array<number>;
|
|
18
|
-
static: boolean;
|
|
19
|
-
markings: any;
|
|
20
|
-
onChange: any;
|
|
21
|
-
trackInteraction: () => void;
|
|
22
|
-
apiOptions: APIOptions;
|
|
2
|
+
import type { PerseusPlotterWidgetOptions } from "../perseus-types";
|
|
3
|
+
import type { WidgetProps } from "../types";
|
|
4
|
+
type Rubric = PerseusPlotterWidgetOptions;
|
|
5
|
+
type RenderProps = PerseusPlotterWidgetOptions;
|
|
6
|
+
type Props = WidgetProps<RenderProps, Rubric> & {
|
|
7
|
+
labelInterval: NonNullable<PerseusPlotterWidgetOptions["labelInterval"]>;
|
|
8
|
+
picSize: NonNullable<PerseusPlotterWidgetOptions["picSize"]>;
|
|
23
9
|
};
|
|
24
10
|
type DefaultProps = {
|
|
25
11
|
type: Props["type"];
|
|
@@ -35,7 +21,7 @@ type DefaultProps = {
|
|
|
35
21
|
labelInterval: Props["labelInterval"];
|
|
36
22
|
};
|
|
37
23
|
type State = {
|
|
38
|
-
values:
|
|
24
|
+
values: ReadonlyArray<number>;
|
|
39
25
|
categoryHeights: Record<string, number>;
|
|
40
26
|
};
|
|
41
27
|
export declare class Plotter extends React.Component<Props, State> {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Core Perseus API (includes renderers and widgets)",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "13.0.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@khanacademy/kas": "^0.3.
|
|
26
|
-
"@khanacademy/kmath": "^0.1.
|
|
27
|
-
"@khanacademy/math-input": "^
|
|
28
|
-
"@khanacademy/perseus-core": "1.
|
|
29
|
-
"@khanacademy/perseus-linter": "^0.3.
|
|
30
|
-
"@khanacademy/pure-markdown": "^0.2.
|
|
31
|
-
"@khanacademy/simple-markdown": "^0.10.
|
|
25
|
+
"@khanacademy/kas": "^0.3.5",
|
|
26
|
+
"@khanacademy/kmath": "^0.1.6",
|
|
27
|
+
"@khanacademy/math-input": "^15.0.0",
|
|
28
|
+
"@khanacademy/perseus-core": "1.3.0",
|
|
29
|
+
"@khanacademy/perseus-linter": "^0.3.8",
|
|
30
|
+
"@khanacademy/pure-markdown": "^0.2.10",
|
|
31
|
+
"@khanacademy/simple-markdown": "^0.10.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@khanacademy/wonder-blocks-button": "^4.1.3",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"@khanacademy/wonder-blocks-tooltip": "^2.1.2",
|
|
49
49
|
"@khanacademy/wonder-blocks-typography": "^2.1.3",
|
|
50
50
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
51
|
+
"@phosphor-icons/core": "^2.0.2",
|
|
51
52
|
"aphrodite": "^1.2.5",
|
|
52
53
|
"classnames": "^1.1.4",
|
|
53
54
|
"create-react-class": "^15.6.3",
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"@khanacademy/wonder-blocks-tooltip": "^2.1.2",
|
|
83
84
|
"@khanacademy/wonder-blocks-typography": "^2.1.3",
|
|
84
85
|
"@khanacademy/wonder-stuff-core": "^1.5.1",
|
|
86
|
+
"@phosphor-icons/core": "^2.0.2",
|
|
85
87
|
"aphrodite": "^1.2.5",
|
|
86
88
|
"classnames": "^1.1.4",
|
|
87
89
|
"create-react-class": "^15.6.3",
|
|
@@ -805,6 +805,47 @@ describe("item renderer", () => {
|
|
|
805
805
|
expect(onShowTTable).toHaveBeenCalled();
|
|
806
806
|
expect(onShowChi2Table).toHaveBeenCalled();
|
|
807
807
|
});
|
|
808
|
+
|
|
809
|
+
it("should call onShowPeriodicTable with showKey option if selected", () => {
|
|
810
|
+
// Arrange
|
|
811
|
+
const item = {
|
|
812
|
+
...itemWithInput,
|
|
813
|
+
answerArea: {
|
|
814
|
+
zTable: false,
|
|
815
|
+
chi2Table: false,
|
|
816
|
+
tTable: false,
|
|
817
|
+
calculator: false,
|
|
818
|
+
periodicTable: true,
|
|
819
|
+
periodicTableWithKey: true,
|
|
820
|
+
},
|
|
821
|
+
} as const;
|
|
822
|
+
|
|
823
|
+
const onShowCalculator = jest.fn();
|
|
824
|
+
const onShowPeriodicTable = jest.fn();
|
|
825
|
+
const onShowZTable = jest.fn();
|
|
826
|
+
const onShowTTable = jest.fn();
|
|
827
|
+
const onShowChi2Table = jest.fn();
|
|
828
|
+
const localExtraProps = {
|
|
829
|
+
...extraProps,
|
|
830
|
+
onShowCalculator,
|
|
831
|
+
onShowPeriodicTable,
|
|
832
|
+
onShowZTable,
|
|
833
|
+
onShowTTable,
|
|
834
|
+
onShowChi2Table,
|
|
835
|
+
} as const;
|
|
836
|
+
|
|
837
|
+
// Act
|
|
838
|
+
renderQuestion(item, undefined, localExtraProps);
|
|
839
|
+
|
|
840
|
+
// Assert
|
|
841
|
+
expect(onShowCalculator).not.toHaveBeenCalled();
|
|
842
|
+
expect(onShowZTable).not.toHaveBeenCalled();
|
|
843
|
+
expect(onShowTTable).not.toHaveBeenCalled();
|
|
844
|
+
expect(onShowChi2Table).not.toHaveBeenCalled();
|
|
845
|
+
expect(onShowPeriodicTable).toHaveBeenCalledWith(
|
|
846
|
+
expect.objectContaining({showKey: true}),
|
|
847
|
+
);
|
|
848
|
+
});
|
|
808
849
|
});
|
|
809
850
|
|
|
810
851
|
describe("controlPeripherals is enabled", () => {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import "@testing-library/jest-dom"; // Joyous side-effects
|
|
2
|
+
import {render, screen} from "@testing-library/react";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import {testDependencies} from "../../../../testing/test-dependencies";
|
|
6
|
+
import * as Dependencies from "../dependencies";
|
|
7
|
+
import WidgetContainer from "../widget-container";
|
|
8
|
+
import {registerWidget} from "../widgets";
|
|
9
|
+
import PassageWidget from "../widgets/passage";
|
|
10
|
+
|
|
11
|
+
import type {WidgetExports} from "../types";
|
|
12
|
+
|
|
13
|
+
const MockWidgetComponent = ({
|
|
14
|
+
text,
|
|
15
|
+
fail = false,
|
|
16
|
+
}: {
|
|
17
|
+
text: string;
|
|
18
|
+
fail: boolean;
|
|
19
|
+
}) => {
|
|
20
|
+
if (fail) {
|
|
21
|
+
throw new Error("MockWidget failed to render");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return <div>{text}</div>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const MockWidget: WidgetExports<typeof MockWidgetComponent> = {
|
|
28
|
+
name: "mock-widget",
|
|
29
|
+
displayName: "Mock Widget",
|
|
30
|
+
widget: MockWidgetComponent,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe("widget-container", () => {
|
|
34
|
+
it("should render nothing when requested widget not registered", () => {
|
|
35
|
+
// Arrange
|
|
36
|
+
const warnMock = jest.spyOn(console, "warn").mockImplementation();
|
|
37
|
+
|
|
38
|
+
// Act
|
|
39
|
+
render(
|
|
40
|
+
<WidgetContainer
|
|
41
|
+
type="invalid-widget"
|
|
42
|
+
id="invalid-widget 1"
|
|
43
|
+
shouldHighlight={false}
|
|
44
|
+
initialProps={{apiOptions: {isMobile: false}}}
|
|
45
|
+
/>,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Assert
|
|
49
|
+
expect(warnMock).toHaveBeenCalledWith(
|
|
50
|
+
"Widget type 'invalid-widget' not found!",
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should render the requested widget", async () => {
|
|
55
|
+
// Arrange
|
|
56
|
+
jest.spyOn(Dependencies, "getDependencies").mockReturnValue(
|
|
57
|
+
testDependencies,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
registerWidget("passage", PassageWidget);
|
|
61
|
+
|
|
62
|
+
// Act
|
|
63
|
+
render(
|
|
64
|
+
<WidgetContainer
|
|
65
|
+
type="passage"
|
|
66
|
+
id="passage 1"
|
|
67
|
+
shouldHighlight={false}
|
|
68
|
+
initialProps={{
|
|
69
|
+
passageTitle: "Greeting",
|
|
70
|
+
passageText: "Hello world!",
|
|
71
|
+
footnotes: null,
|
|
72
|
+
showLineNumbers: true,
|
|
73
|
+
|
|
74
|
+
findWidgets: () => [],
|
|
75
|
+
|
|
76
|
+
apiOptions: {isMobile: false},
|
|
77
|
+
}}
|
|
78
|
+
/>,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Assert
|
|
82
|
+
expect(await screen.findByText("Greeting")).toBeInTheDocument();
|
|
83
|
+
expect(await screen.findByText("Hello world")).toBeInTheDocument();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should send analytics even when widget rendering errors", () => {
|
|
87
|
+
// Arrange
|
|
88
|
+
jest.spyOn(Dependencies, "getDependencies").mockReturnValue(
|
|
89
|
+
testDependencies,
|
|
90
|
+
);
|
|
91
|
+
jest.spyOn(console, "error").mockImplementation(() => {});
|
|
92
|
+
|
|
93
|
+
const onAnalyticsEventSpy = jest.fn();
|
|
94
|
+
const depsV2 = {analytics: {onAnalyticsEvent: onAnalyticsEventSpy}};
|
|
95
|
+
|
|
96
|
+
registerWidget("mock-widget", MockWidget);
|
|
97
|
+
|
|
98
|
+
// Act
|
|
99
|
+
render(
|
|
100
|
+
<Dependencies.DependenciesContext.Provider value={depsV2}>
|
|
101
|
+
<WidgetContainer
|
|
102
|
+
type="mock-widget"
|
|
103
|
+
id="mock-widget 1"
|
|
104
|
+
shouldHighlight={false}
|
|
105
|
+
initialProps={{
|
|
106
|
+
text: "Hello world!",
|
|
107
|
+
fail: true,
|
|
108
|
+
|
|
109
|
+
findWidgets: () => [],
|
|
110
|
+
|
|
111
|
+
apiOptions: {isMobile: false},
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
</Dependencies.DependenciesContext.Provider>,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Assert
|
|
118
|
+
expect(onAnalyticsEventSpy).toHaveBeenCalledWith({
|
|
119
|
+
type: "perseus:widget-rendering-error",
|
|
120
|
+
payload: {
|
|
121
|
+
widgetType: "mock-widget",
|
|
122
|
+
widgetId: "mock-widget 1",
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
package/src/error-boundary.tsx
CHANGED
|
@@ -21,6 +21,7 @@ class ErrorBoundary extends React.Component<Props, State> {
|
|
|
21
21
|
|
|
22
22
|
componentDidCatch(error: Error, info: any) {
|
|
23
23
|
this.setState({error: error.toString()});
|
|
24
|
+
this.props.onError?.(error, info);
|
|
24
25
|
Log.error("Perseus error boundary caught error", Errors.Internal, {
|
|
25
26
|
cause: error,
|
|
26
27
|
loggedMetadata: {
|
package/src/index.ts
CHANGED
|
@@ -62,7 +62,10 @@ export {default as KhanMath} from "./util/math";
|
|
|
62
62
|
export {default as LoadingContext} from "./loading-context";
|
|
63
63
|
export {default as mediaQueries} from "./styles/media-queries";
|
|
64
64
|
export {default as PerseusMarkdown} from "./perseus-markdown";
|
|
65
|
-
export {
|
|
65
|
+
export {
|
|
66
|
+
PerseusExpressionAnswerFormConsidered,
|
|
67
|
+
plotterPlotTypes,
|
|
68
|
+
} from "./perseus-types";
|
|
66
69
|
export {traverse} from "./traversal";
|
|
67
70
|
export {isItemRenderableByVersion} from "./renderability";
|
|
68
71
|
export {violatingWidgets} from "./a11y";
|
|
@@ -123,6 +126,7 @@ export type {
|
|
|
123
126
|
PerseusInteractiveGraphWidgetOptions,
|
|
124
127
|
PerseusRadioWidgetOptions,
|
|
125
128
|
PerseusExpressionWidgetOptions,
|
|
129
|
+
PerseusPlotterWidgetOptions,
|
|
126
130
|
PerseusRenderer,
|
|
127
131
|
} from "./perseus-types";
|
|
128
132
|
export type {Coord} from "./interactive2/types";
|
package/src/item-renderer.tsx
CHANGED
|
@@ -39,7 +39,7 @@ type Props = // These props are used by the ProvideKeypad mixin.
|
|
|
39
39
|
item: PerseusItem | any /* any for _multi items */;
|
|
40
40
|
onShowCalculator?: () => unknown;
|
|
41
41
|
onShowChi2Table?: () => unknown;
|
|
42
|
-
onShowPeriodicTable?: () => unknown;
|
|
42
|
+
onShowPeriodicTable?: (options?: {showKey: boolean}) => unknown;
|
|
43
43
|
onShowTTable?: () => unknown;
|
|
44
44
|
onShowZTable?: () => unknown;
|
|
45
45
|
problemNum: number;
|
|
@@ -254,7 +254,9 @@ class ItemRenderer extends React.Component<Props, State> {
|
|
|
254
254
|
}
|
|
255
255
|
if (answerArea.periodicTable) {
|
|
256
256
|
this.props.onShowPeriodicTable &&
|
|
257
|
-
this.props.onShowPeriodicTable(
|
|
257
|
+
this.props.onShowPeriodicTable({
|
|
258
|
+
showKey: answerArea.periodicTableWithKey,
|
|
259
|
+
});
|
|
258
260
|
}
|
|
259
261
|
if (answerArea.zTable) {
|
|
260
262
|
this.props.onShowZTable && this.props.onShowZTable();
|
package/src/perseus-types.ts
CHANGED
|
@@ -848,13 +848,22 @@ export type PerseusPassageRefWidgetOptions = {
|
|
|
848
848
|
summaryText: string;
|
|
849
849
|
};
|
|
850
850
|
|
|
851
|
+
export const plotterPlotTypes = [
|
|
852
|
+
"bar",
|
|
853
|
+
"line",
|
|
854
|
+
"pic",
|
|
855
|
+
"histogram",
|
|
856
|
+
"dotplot",
|
|
857
|
+
] as const;
|
|
858
|
+
export type PlotType = typeof plotterPlotTypes[number];
|
|
859
|
+
|
|
851
860
|
export type PerseusPlotterWidgetOptions = {
|
|
852
861
|
// Translatable Text; The Axis labels. e.g. ["X Label", "Y Label"]
|
|
853
862
|
labels: ReadonlyArray<string>;
|
|
854
863
|
// Translatable Text; Categories to display along the X access. e.g. [">0", ">6", ">12", ">18"]
|
|
855
864
|
categories: ReadonlyArray<string>;
|
|
856
865
|
// The type of the graph. options "bar", "line", "pic", "histogram", "dotplot"
|
|
857
|
-
type:
|
|
866
|
+
type: PlotType;
|
|
858
867
|
// The maximimum Y tick to display in the graph
|
|
859
868
|
maxY: number;
|
|
860
869
|
// The scale of the Y Axis
|
|
@@ -868,7 +877,7 @@ export type PerseusPlotterWidgetOptions = {
|
|
|
868
877
|
// The Y values that represent the correct answer expected
|
|
869
878
|
correct: ReadonlyArray<number>;
|
|
870
879
|
// A picture to represent items in a graph.
|
|
871
|
-
picUrl:
|
|
880
|
+
picUrl: string | null | undefined;
|
|
872
881
|
// deprecated
|
|
873
882
|
picSize: number | null | undefined;
|
|
874
883
|
// deprecated
|
package/src/styles/articles.less
CHANGED
|
@@ -498,7 +498,9 @@
|
|
|
498
498
|
margin-bottom: 2 * @baseUnit;
|
|
499
499
|
}
|
|
500
500
|
|
|
501
|
-
.perseus-renderer
|
|
501
|
+
.perseus-renderer
|
|
502
|
+
> .paragraph
|
|
503
|
+
ul:not(.perseus-widget-radio, .indicatorContainer) {
|
|
502
504
|
margin: 0 0 0 1em;
|
|
503
505
|
padding: 0;
|
|
504
506
|
|
package/src/widget-container.tsx
CHANGED
|
@@ -144,11 +144,12 @@ class WidgetContainer extends React.Component<Props, State> {
|
|
|
144
144
|
widget_type: type,
|
|
145
145
|
widget_id: this.props.id,
|
|
146
146
|
}}
|
|
147
|
-
onError={(
|
|
147
|
+
onError={() => {
|
|
148
148
|
analytics.onAnalyticsEvent({
|
|
149
149
|
type: "perseus:widget-rendering-error",
|
|
150
150
|
payload: {
|
|
151
151
|
widgetType: type,
|
|
152
|
+
widgetId: this.props.id,
|
|
152
153
|
},
|
|
153
154
|
});
|
|
154
155
|
}}
|
|
@@ -38,32 +38,63 @@ exports[`graded group widget should snapshot 1`] = `
|
|
|
38
38
|
class="spacer_bc4egv"
|
|
39
39
|
/>
|
|
40
40
|
<ul
|
|
41
|
-
class="
|
|
41
|
+
class="indicatorContainer_2pd7o4 indicatorContainer"
|
|
42
42
|
>
|
|
43
43
|
<li
|
|
44
|
-
|
|
45
|
-
class="indicator_qk5jgn-o_O-selectedIndicator_14jsc6v"
|
|
46
|
-
role="button"
|
|
47
|
-
tabindex="0"
|
|
44
|
+
class="indicator_7k5kza"
|
|
48
45
|
>
|
|
49
|
-
<
|
|
50
|
-
|
|
46
|
+
<button
|
|
47
|
+
aria-disabled="false"
|
|
48
|
+
aria-label="Skip to Problem 1a"
|
|
49
|
+
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-indicatorButton_8uaklu"
|
|
50
|
+
role="button"
|
|
51
|
+
type="button"
|
|
51
52
|
>
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
<div
|
|
54
|
+
class="default_xu2jcg-o_O-indicatorDot_yy8ygm"
|
|
55
|
+
>
|
|
56
|
+
<div
|
|
57
|
+
class="default_xu2jcg-o_O-indicatorDotActive_1pky1a"
|
|
58
|
+
>
|
|
59
|
+
<span
|
|
60
|
+
class="srOnly_19bpjuy"
|
|
61
|
+
>
|
|
62
|
+
Current
|
|
63
|
+
</span>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</button>
|
|
54
67
|
</li>
|
|
55
68
|
<li
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
class="indicator_7k5kza"
|
|
70
|
+
>
|
|
71
|
+
<button
|
|
72
|
+
aria-disabled="false"
|
|
73
|
+
aria-label="Skip to Problem 1b"
|
|
74
|
+
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-indicatorButton_8uaklu"
|
|
75
|
+
role="button"
|
|
76
|
+
type="button"
|
|
77
|
+
>
|
|
78
|
+
<div
|
|
79
|
+
class="default_xu2jcg-o_O-indicatorDot_yy8ygm"
|
|
80
|
+
/>
|
|
81
|
+
</button>
|
|
82
|
+
</li>
|
|
61
83
|
<li
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
84
|
+
class="indicator_7k5kza"
|
|
85
|
+
>
|
|
86
|
+
<button
|
|
87
|
+
aria-disabled="false"
|
|
88
|
+
aria-label="Skip to Problem 1c"
|
|
89
|
+
class="button_vr44p2-o_O-reset_152ygtm-o_O-link_13xlah4-o_O-indicatorButton_8uaklu"
|
|
90
|
+
role="button"
|
|
91
|
+
type="button"
|
|
92
|
+
>
|
|
93
|
+
<div
|
|
94
|
+
class="default_xu2jcg-o_O-indicatorDot_yy8ygm"
|
|
95
|
+
/>
|
|
96
|
+
</button>
|
|
97
|
+
</li>
|
|
67
98
|
</ul>
|
|
68
99
|
</div>
|
|
69
100
|
<div
|
|
@@ -4,13 +4,12 @@ import React from "react";
|
|
|
4
4
|
|
|
5
5
|
import {testDependencies} from "../../../../../testing/test-dependencies";
|
|
6
6
|
import {setDependencies} from "../../dependencies";
|
|
7
|
+
import {ApiOptions} from "../../perseus-api";
|
|
7
8
|
import {question1} from "../__testdata__/plotter.testdata";
|
|
8
9
|
import {Plotter} from "../plotter";
|
|
9
10
|
|
|
10
11
|
import {renderQuestion} from "./renderQuestion";
|
|
11
12
|
|
|
12
|
-
import type {APIOptions} from "../../types";
|
|
13
|
-
|
|
14
13
|
describe("plotter widget", () => {
|
|
15
14
|
beforeEach(() => {
|
|
16
15
|
setDependencies(testDependencies);
|
|
@@ -26,15 +25,17 @@ describe("plotter widget", () => {
|
|
|
26
25
|
|
|
27
26
|
it("should show drag text when not static", () => {
|
|
28
27
|
// Arrange and Act
|
|
29
|
-
const apiOptions: APIOptions = {isMobile: true};
|
|
30
28
|
render(
|
|
29
|
+
// @ts-expect-error - TS2769 - test works, but I can't figure out how to make the types happy
|
|
31
30
|
<Plotter
|
|
32
31
|
static={false}
|
|
33
32
|
trackInteraction={() => {}}
|
|
34
33
|
onChange={() => {}}
|
|
35
|
-
apiOptions={
|
|
34
|
+
apiOptions={{
|
|
35
|
+
...ApiOptions.defaults,
|
|
36
|
+
isMobile: true,
|
|
37
|
+
}}
|
|
36
38
|
starting={[0]}
|
|
37
|
-
markings={""}
|
|
38
39
|
/>,
|
|
39
40
|
);
|
|
40
41
|
|
|
@@ -46,15 +47,17 @@ describe("plotter widget", () => {
|
|
|
46
47
|
|
|
47
48
|
it("should not show drag text when static", () => {
|
|
48
49
|
// Arrange and Act
|
|
49
|
-
const apiOptions: APIOptions = {isMobile: true};
|
|
50
50
|
render(
|
|
51
|
+
// @ts-expect-error - TS2769 - test works, but I can't figure out how to make the types happy
|
|
51
52
|
<Plotter
|
|
52
53
|
static={true}
|
|
53
54
|
trackInteraction={() => {}}
|
|
54
55
|
onChange={() => {}}
|
|
55
|
-
apiOptions={
|
|
56
|
+
apiOptions={{
|
|
57
|
+
...ApiOptions.defaults,
|
|
58
|
+
isMobile: true,
|
|
59
|
+
}}
|
|
56
60
|
starting={[0]}
|
|
57
|
-
markings={""}
|
|
58
61
|
/>,
|
|
59
62
|
);
|
|
60
63
|
|