@khanacademy/perseus 0.2.8 → 0.3.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.
@@ -1,5 +1,5 @@
1
1
  // @flow
2
- import {screen, waitForElementToBeRemoved} from "@testing-library/react";
2
+ import {screen} from "@testing-library/react";
3
3
  import userEvent from "@testing-library/user-event";
4
4
 
5
5
  import "@testing-library/jest-dom"; // Imports custom matchers
@@ -49,28 +49,30 @@ describe("Definition widget", () => {
49
49
  expect(container).toMatchSnapshot("first render");
50
50
  });
51
51
 
52
- it("should have an open state snapshot", () => {
52
+ it("should have an open state snapshot", async () => {
53
53
  // Arrange
54
54
  const {container} = renderQuestion(question);
55
55
 
56
56
  // Act
57
57
  const definitionAnchor = screen.getByText("the Pequots");
58
- userEvent.hover(definitionAnchor);
58
+ userEvent.click(definitionAnchor);
59
59
 
60
60
  // Assert
61
+ const tooltip = await screen.findByRole("dialog");
62
+ expect(tooltip).toBeVisible();
61
63
  expect(container).toMatchSnapshot("open state");
62
64
  });
63
65
 
64
- it("should display the definition on hover", async () => {
66
+ it("should display the definition on click", async () => {
65
67
  // Arrange
66
68
  renderQuestion(question);
67
69
 
68
70
  // Act
69
71
  const definitionAnchor = screen.getByText("the Pequots");
70
- userEvent.hover(definitionAnchor);
72
+ userEvent.click(definitionAnchor);
71
73
 
72
74
  // Assert
73
- const tooltip = await screen.findByRole("tooltip");
75
+ const tooltip = await screen.findByRole("dialog");
74
76
  expect(tooltip).toBeVisible();
75
77
  expect(tooltip).toHaveTextContent("Definition text");
76
78
  });
@@ -82,41 +84,28 @@ describe("Definition widget", () => {
82
84
  // Act
83
85
  const definitionAnchor = screen.getByText("the Pequots");
84
86
  userEvent.click(definitionAnchor);
85
- const tooltip = await screen.findByRole("tooltip");
87
+ const tooltip = await screen.findByRole("dialog");
86
88
 
87
89
  // Assert
88
90
  expect(tooltip).toBeVisible();
89
91
  expect(tooltip).toHaveTextContent("Definition text");
90
92
  });
91
93
 
92
- it("should show via focus by the tab key", async () => {
94
+ it("should show via focus on space key", async () => {
93
95
  // Arrange
94
96
  renderQuestion(question);
95
97
 
96
98
  // Act - Tab in to set focus
97
- userEvent.tab();
99
+ const definitionAnchor = screen.getByText("the Pequots");
100
+ userEvent.type(definitionAnchor, "{space}");
98
101
 
99
102
  // Assert
100
- const tooltip = await screen.findByRole("tooltip");
103
+ const tooltip = await screen.findByRole("dialog");
101
104
  expect(tooltip).toBeVisible();
102
105
  expect(tooltip).toHaveTextContent("Definition text");
103
106
  });
104
107
 
105
- it("should hide and blur by the tab key", async () => {
106
- // Arrange
107
- renderQuestion(question);
108
-
109
- // Act - Tab in to set focus, tab out to blur
110
- userEvent.tab();
111
- await screen.findByRole("tooltip");
112
- userEvent.tab();
113
- await waitForElementToBeRemoved(() => screen.queryByRole("tooltip"));
114
-
115
- // Assert
116
- expect(screen.queryByRole("tooltip")).toBeNull();
117
- });
118
-
119
- it("should dimiss by a click when showing", async () => {
108
+ it("should dimiss by a click on the x when showing", async () => {
120
109
  renderQuestion(question);
121
110
 
122
111
  // Act
@@ -124,16 +113,12 @@ describe("Definition widget", () => {
124
113
  const definitionAnchor = screen.getByText("the Pequots");
125
114
  userEvent.click(definitionAnchor);
126
115
 
127
- // Move the mouse away and make sure text is still visible
128
- userEvent.unhover(definitionAnchor);
129
- await screen.findByRole("tooltip");
130
-
131
- // Click to elsewhere, tooltip is hidden
132
- userEvent.click((document.body: any));
133
- await waitForElementToBeRemoved(() => screen.queryByRole("tooltip"));
116
+ // Click close, tooltip is hidden
117
+ const close = screen.getByTestId("popover-close-btn");
118
+ userEvent.click(close);
134
119
 
135
120
  // Assert
136
- expect(screen.queryByRole("tooltip")).toBeNull();
121
+ expect(screen.queryByRole("dialog")).toBeNull();
137
122
  });
138
123
 
139
124
  it("should not affect answerable", () => {
@@ -1,7 +1,7 @@
1
1
  // @flow
2
2
 
3
3
  import renderQuestionWithCypress from "../../../../../testing/render-question-with-cypress.jsx";
4
- import {testDependencies} from "../../../../../testing/test-dependencies.js";
4
+ import {cypressTestDependencies} from "../../../../../testing/test-dependencies.js";
5
5
  import * as Perseus from "../../index.js";
6
6
  import {
7
7
  absoluteValueQuestion,
@@ -27,7 +27,7 @@ const LINES = "[data-interactive-kind-for-testing=movable-line] > svg > path";
27
27
  describe("Grapher widget", () => {
28
28
  beforeEach(() => {
29
29
  Perseus.init({skipMathJax: true});
30
- Perseus.Dependencies.setDependencies(testDependencies);
30
+ Perseus.Dependencies.setDependencies(cypressTestDependencies);
31
31
  });
32
32
 
33
33
  describe("absolute value graph", () => {
@@ -1,7 +1,7 @@
1
1
  // @flow
2
2
 
3
3
  import renderQuestion from "../../../../../testing/render-question-with-cypress.jsx";
4
- import {testDependencies} from "../../../../../testing/test-dependencies.js";
4
+ import {cypressTestDependencies} from "../../../../../testing/test-dependencies.js";
5
5
  import * as Dependencies from "../../dependencies.js";
6
6
  import * as Perseus from "../../index.js";
7
7
  import {
@@ -29,7 +29,7 @@ const CIRCLES = "svg > circle";
29
29
 
30
30
  describe("Interactive graph", () => {
31
31
  beforeEach(() => {
32
- Dependencies.setDependencies(testDependencies);
32
+ Dependencies.setDependencies(cypressTestDependencies);
33
33
  Perseus.init({skipMathJax: true});
34
34
  });
35
35
 
@@ -1,60 +1,20 @@
1
1
  // @flow
2
2
 
3
+ import Button from "@khanacademy/wonder-blocks-button";
3
4
  import Color from "@khanacademy/wonder-blocks-color";
4
- import {View} from "@khanacademy/wonder-blocks-core";
5
+ import {Popover, PopoverContentCore} from "@khanacademy/wonder-blocks-popover";
5
6
  import Spacing from "@khanacademy/wonder-blocks-spacing";
6
- import Tooltip from "@khanacademy/wonder-blocks-tooltip";
7
- import PropTypes from "prop-types";
8
7
  import * as React from "react";
9
- import _ from "underscore";
10
8
 
11
- import {ApiOptions} from "../perseus-api.jsx";
12
9
  import Renderer from "../renderer.jsx";
13
10
 
14
11
  import type {
15
12
  PerseusRenderer,
16
13
  PerseusDefinitionWidgetOptions,
17
14
  } from "../perseus-types.js";
18
- import type {
19
- APIOptionsWithDefaults,
20
- PerseusScore,
21
- WidgetExports,
22
- WidgetProps,
23
- } from "../types.js";
24
-
25
- type DefinitionContentProps = {|
26
- apiOptions: APIOptionsWithDefaults,
27
- content: string,
28
- trackInteraction: () => mixed,
29
- widgets: PerseusRenderer["widgets"],
30
- |};
31
-
32
- class DefinitionContent extends React.Component<DefinitionContentProps> {
33
- static propTypes = {
34
- apiOptions: ApiOptions.propTypes,
35
- content: PropTypes.string,
36
- trackInteraction: PropTypes.func.isRequired,
37
- widgets: PropTypes.objectOf(PropTypes.any),
38
- };
39
-
40
- componentDidMount() {
41
- this.props.trackInteraction();
42
- }
43
-
44
- render(): React.Node {
45
- return (
46
- <View style={styles.tooltipBody}>
47
- <Renderer
48
- apiOptions={this.props.apiOptions}
49
- content={this.props.content}
50
- widgets={this.props.widgets}
51
- />
52
- </View>
53
- );
54
- }
55
- }
15
+ import type {PerseusScore, WidgetExports, WidgetProps} from "../types.js";
56
16
 
57
- type RenderProps = PerseusDefinitionWidgetOptions; // transform = _.identity
17
+ type RenderProps = PerseusDefinitionWidgetOptions;
58
18
 
59
19
  type Rubric = PerseusDefinitionWidgetOptions;
60
20
 
@@ -89,25 +49,38 @@ class Definition extends React.Component<DefinitionProps> {
89
49
  };
90
50
 
91
51
  render(): React.Node {
92
- const content = (
93
- <DefinitionContent
94
- apiOptions={this.props.apiOptions}
95
- content={this.props.definition}
96
- key={this.props.definition}
97
- trackInteraction={this.props.trackInteraction}
98
- widgets={this.props.widgets}
99
- />
100
- );
101
-
102
52
  return (
103
- // $FlowFixMe[incompatible-type]: content prop
104
- <Tooltip content={content} placement="top">
105
- <span className="perseus-widget-definition">
106
- <View style={styles.definitionLink}>
107
- {this.props.togglePrompt}
108
- </View>
109
- </span>
110
- </Tooltip>
53
+ <Popover
54
+ content={
55
+ <PopoverContentCore
56
+ color="white"
57
+ style={styles.tooltipBody}
58
+ closeButtonVisible={true}
59
+ >
60
+ <Renderer
61
+ apiOptions={this.props.apiOptions}
62
+ content={this.props.definition}
63
+ widgets={this.props.widgets}
64
+ />
65
+ </PopoverContentCore>
66
+ }
67
+ placement="top"
68
+ >
69
+ {({open}) => (
70
+ <span className="perseus-widget-definition">
71
+ <Button
72
+ size="small"
73
+ kind="tertiary"
74
+ onClick={() => {
75
+ this.props.trackInteraction();
76
+ open();
77
+ }}
78
+ >
79
+ {this.props.togglePrompt}
80
+ </Button>
81
+ </span>
82
+ )}
83
+ </Popover>
111
84
  );
112
85
  }
113
86
  }
@@ -121,14 +94,6 @@ const styles = {
121
94
  lineHeight: "30px",
122
95
  margin: Spacing.xSmall_8,
123
96
  },
124
-
125
- definitionLink: {
126
- borderBottom: `dashed 1px ${Color.blue}`,
127
- color: Color.blue,
128
- cursor: "pointer",
129
- display: "inline-block",
130
- textDecoration: "none",
131
- },
132
97
  };
133
98
 
134
99
  export default ({
@@ -137,5 +102,5 @@ export default ({
137
102
  accessible: true,
138
103
  defaultAlignment: "inline",
139
104
  widget: Definition,
140
- transform: _.identity,
105
+ transform: (x: any) => x,
141
106
  }: WidgetExports<typeof Definition>);