@pie-lib/render-ui 4.35.3-next.0 → 4.35.3-next.155

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +9 -81
  2. package/esm/package.json +3 -0
  3. package/lib/append-css-rules.js +10 -37
  4. package/lib/append-css-rules.js.map +1 -1
  5. package/lib/assets/enableAudioAutoplayImage.js +1 -2
  6. package/lib/assets/enableAudioAutoplayImage.js.map +1 -1
  7. package/lib/collapsible/index.js +35 -65
  8. package/lib/collapsible/index.js.map +1 -1
  9. package/lib/color.js +57 -201
  10. package/lib/color.js.map +1 -1
  11. package/lib/feedback.js +71 -108
  12. package/lib/feedback.js.map +1 -1
  13. package/lib/has-media.js +2 -7
  14. package/lib/has-media.js.map +1 -1
  15. package/lib/has-text.js +1 -7
  16. package/lib/has-text.js.map +1 -1
  17. package/lib/html-and-math.js +10 -30
  18. package/lib/html-and-math.js.map +1 -1
  19. package/lib/index.js +1 -24
  20. package/lib/index.js.map +1 -1
  21. package/lib/input-container.js +43 -44
  22. package/lib/input-container.js.map +1 -1
  23. package/lib/preview-layout.js +22 -58
  24. package/lib/preview-layout.js.map +1 -1
  25. package/lib/preview-prompt.js +104 -131
  26. package/lib/preview-prompt.js.map +1 -1
  27. package/lib/purpose.js +1 -7
  28. package/lib/purpose.js.map +1 -1
  29. package/lib/readable.js +1 -7
  30. package/lib/readable.js.map +1 -1
  31. package/lib/response-indicators.js +37 -86
  32. package/lib/response-indicators.js.map +1 -1
  33. package/lib/ui-layout.js +53 -70
  34. package/lib/ui-layout.js.map +1 -1
  35. package/lib/withUndoReset.js +51 -97
  36. package/lib/withUndoReset.js.map +1 -1
  37. package/package.json +23 -13
  38. package/src/__tests__/html-and-math.test.js +26 -14
  39. package/src/__tests__/preview-prompt.test.jsx +43 -40
  40. package/src/__tests__/purpose.test.jsx +27 -23
  41. package/src/__tests__/readable.test.jsx +34 -29
  42. package/src/__tests__/response-indicators.test.jsx +104 -9
  43. package/src/__tests__/ui-layout.test.jsx +28 -12
  44. package/src/__tests__/withUndoReset.test.jsx +110 -188
  45. package/src/collapsible/__tests__/index.test.jsx +33 -7
  46. package/src/collapsible/index.jsx +17 -17
  47. package/src/color.js +1 -5
  48. package/src/feedback.jsx +59 -63
  49. package/src/input-container.jsx +41 -32
  50. package/src/preview-layout.jsx +11 -23
  51. package/src/preview-prompt.jsx +76 -58
  52. package/src/response-indicators.jsx +22 -29
  53. package/src/ui-layout.jsx +41 -28
  54. package/src/withUndoReset.jsx +48 -50
  55. package/src/__tests__/__snapshots__/html-and-math.test.js.snap +0 -11
  56. package/src/__tests__/__snapshots__/preview-prompt.test.jsx.snap +0 -37
  57. package/src/__tests__/__snapshots__/purpose.test.jsx.snap +0 -42
  58. package/src/__tests__/__snapshots__/readable.test.jsx.snap +0 -64
  59. package/src/__tests__/__snapshots__/response-indicators.test.jsx.snap +0 -27
  60. package/src/collapsible/__tests__/__snapshots__/index.test.jsx.snap +0 -18
@@ -1,24 +1,23 @@
1
1
  import React from 'react';
2
- import { mount } from 'enzyme';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import Readable from '../readable';
4
4
 
5
5
  describe('Readable', () => {
6
- let wrapper;
7
-
8
- describe('renders fine', () => {
9
- it('renders child unaltered', () => {
10
- wrapper = mount(
6
+ describe('rendering', () => {
7
+ it('renders child with data-pie-readable attribute set to true', () => {
8
+ const { container } = render(
11
9
  <Readable>
12
10
  <div>text</div>
13
11
  </Readable>,
14
12
  );
15
- expect(wrapper.find('div')).toHaveLength(1);
16
- expect(wrapper.html().includes('data-pie-readable="true"')).toEqual(true);
17
- expect(wrapper.html().includes('text')).toEqual(true);
18
- expect(wrapper).toMatchSnapshot();
13
+
14
+ expect(screen.getByText('text')).toBeInTheDocument();
15
+ const div = container.querySelector('div');
16
+ expect(div).toHaveAttribute('data-pie-readable', 'true');
19
17
  });
20
- it('renders children unaltered', () => {
21
- wrapper = mount(
18
+
19
+ it('renders multiple children with data-pie-readable attribute', () => {
20
+ const { container } = render(
22
21
  <Readable>
23
22
  <div>
24
23
  <div>text1</div>
@@ -26,14 +25,17 @@ describe('Readable', () => {
26
25
  </div>
27
26
  </Readable>,
28
27
  );
29
- expect(wrapper.find('div')).toHaveLength(3);
30
- expect(wrapper.html().includes('data-pie-readable="true"')).toEqual(true);
31
- expect(wrapper.html().includes('text1')).toEqual(true);
32
- expect(wrapper.html().includes('text3')).toEqual(false);
33
- expect(wrapper).toMatchSnapshot();
28
+
29
+ expect(screen.getByText('text1')).toBeInTheDocument();
30
+ expect(screen.getByText('text2')).toBeInTheDocument();
31
+ expect(screen.queryByText('text3')).not.toBeInTheDocument();
32
+
33
+ const parentDiv = container.querySelector('div');
34
+ expect(parentDiv).toHaveAttribute('data-pie-readable', 'true');
34
35
  });
35
- it('renders with false tag', () => {
36
- wrapper = mount(
36
+
37
+ it('renders with data-pie-readable set to false when false prop is provided', () => {
38
+ const { container } = render(
37
39
  <Readable false>
38
40
  <div>
39
41
  <div>text1</div>
@@ -41,14 +43,17 @@ describe('Readable', () => {
41
43
  </div>
42
44
  </Readable>,
43
45
  );
44
- expect(wrapper.find('div')).toHaveLength(3);
45
- expect(wrapper.html().includes('data-pie-readable="false"')).toEqual(true);
46
- expect(wrapper.html().includes('text1')).toEqual(true);
47
- expect(wrapper.html().includes('text3')).toEqual(false);
48
- expect(wrapper).toMatchSnapshot();
46
+
47
+ expect(screen.getByText('text1')).toBeInTheDocument();
48
+ expect(screen.getByText('text2')).toBeInTheDocument();
49
+ expect(screen.queryByText('text3')).not.toBeInTheDocument();
50
+
51
+ const parentDiv = container.querySelector('div');
52
+ expect(parentDiv).toHaveAttribute('data-pie-readable', 'false');
49
53
  });
50
- it('renders even with specific true tag', () => {
51
- wrapper = mount(
54
+
55
+ it('renders with data-pie-readable set to false when false={true}', () => {
56
+ const { container } = render(
52
57
  <Readable false={true}>
53
58
  <div>
54
59
  <div>text1</div>
@@ -56,9 +61,9 @@ describe('Readable', () => {
56
61
  </div>
57
62
  </Readable>,
58
63
  );
59
- expect(wrapper.find('div')).toHaveLength(3);
60
- expect(wrapper.html().includes('data-pie-readable="false"')).toEqual(true);
61
- expect(wrapper).toMatchSnapshot();
64
+
65
+ const parentDiv = container.querySelector('div');
66
+ expect(parentDiv).toHaveAttribute('data-pie-readable', 'false');
62
67
  });
63
68
  });
64
69
  });
@@ -1,16 +1,111 @@
1
1
  import React from 'react';
2
- import debug from 'debug';
3
- import renderer from 'react-test-renderer';
4
- import { Correct } from '../response-indicators';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { Correct, Incorrect, PartiallyCorrect, NothingSubmitted } from '../response-indicators';
5
+
6
+ // Mock the icons
7
+ jest.mock('@pie-lib/icons', () => ({
8
+ Correct: () => <span data-testid="correct-icon">Correct Icon</span>,
9
+ Incorrect: () => <span data-testid="incorrect-icon">Incorrect Icon</span>,
10
+ PartiallyCorrect: () => <span data-testid="partially-correct-icon">Partially Correct Icon</span>,
11
+ NothingSubmitted: () => <span data-testid="nothing-submitted-icon">Nothing Submitted Icon</span>,
12
+ }));
13
+
14
+ // Mock the Feedback component
15
+ jest.mock('../feedback', () => {
16
+ return function Feedback({ feedback, correctness }) {
17
+ return (
18
+ <div data-testid="feedback-content">
19
+ <div>{feedback}</div>
20
+ <div>{correctness}</div>
21
+ </div>
22
+ );
23
+ };
24
+ });
5
25
 
6
26
  describe('response-indicators', () => {
7
- it('snapshot - no feedback ', () => {
8
- const tree = renderer.create(<Correct />).toJSON();
9
- expect(tree).toMatchSnapshot();
27
+ describe('Correct indicator', () => {
28
+ it('renders correct icon without feedback', () => {
29
+ render(<Correct />);
30
+ expect(screen.getByTestId('correct-icon')).toBeInTheDocument();
31
+ });
32
+
33
+ it('renders correct icon with feedback', () => {
34
+ render(<Correct feedback="Great job!" />);
35
+ expect(screen.getByTestId('correct-icon')).toBeInTheDocument();
36
+ });
37
+
38
+ it('shows feedback popover when icon is clicked', async () => {
39
+ const user = userEvent.setup();
40
+ render(<Correct feedback="Great job!" />);
41
+
42
+ const icon = screen.getByTestId('correct-icon');
43
+ await user.click(icon);
44
+
45
+ expect(screen.getByTestId('feedback-content')).toBeInTheDocument();
46
+ expect(screen.getByText('Great job!')).toBeInTheDocument();
47
+ expect(screen.getByText('correct')).toBeInTheDocument();
48
+ });
49
+
50
+ it('does not show popover when there is no feedback', async () => {
51
+ const user = userEvent.setup();
52
+ render(<Correct />);
53
+
54
+ const icon = screen.getByTestId('correct-icon');
55
+ await user.click(icon);
56
+
57
+ expect(screen.queryByTestId('feedback-content')).not.toBeInTheDocument();
58
+ });
10
59
  });
11
60
 
12
- it('snapshot - with feedback ', () => {
13
- const tree = renderer.create(<Correct feedback="hi" />).toJSON();
14
- expect(tree).toMatchSnapshot();
61
+ describe('Incorrect indicator', () => {
62
+ it('renders incorrect icon', () => {
63
+ render(<Incorrect />);
64
+ expect(screen.getByTestId('incorrect-icon')).toBeInTheDocument();
65
+ });
66
+
67
+ it('shows feedback with incorrect correctness', async () => {
68
+ const user = userEvent.setup();
69
+ render(<Incorrect feedback="Try again" />);
70
+
71
+ await user.click(screen.getByTestId('incorrect-icon'));
72
+
73
+ expect(screen.getByText('Try again')).toBeInTheDocument();
74
+ expect(screen.getByText('incorrect')).toBeInTheDocument();
75
+ });
76
+ });
77
+
78
+ describe('PartiallyCorrect indicator', () => {
79
+ it('renders partially correct icon', () => {
80
+ render(<PartiallyCorrect />);
81
+ expect(screen.getByTestId('partially-correct-icon')).toBeInTheDocument();
82
+ });
83
+
84
+ it('shows feedback with partially-correct correctness', async () => {
85
+ const user = userEvent.setup();
86
+ render(<PartiallyCorrect feedback="Almost there" />);
87
+
88
+ await user.click(screen.getByTestId('partially-correct-icon'));
89
+
90
+ expect(screen.getByText('Almost there')).toBeInTheDocument();
91
+ expect(screen.getByText('partially-correct')).toBeInTheDocument();
92
+ });
93
+ });
94
+
95
+ describe('NothingSubmitted indicator', () => {
96
+ it('renders nothing submitted icon', () => {
97
+ render(<NothingSubmitted />);
98
+ expect(screen.getByTestId('nothing-submitted-icon')).toBeInTheDocument();
99
+ });
100
+
101
+ it('shows feedback with nothing-submitted correctness', async () => {
102
+ const user = userEvent.setup();
103
+ render(<NothingSubmitted feedback="Please submit an answer" />);
104
+
105
+ await user.click(screen.getByTestId('nothing-submitted-icon'));
106
+
107
+ expect(screen.getByText('Please submit an answer')).toBeInTheDocument();
108
+ expect(screen.getByText('nothing-submitted')).toBeInTheDocument();
109
+ });
15
110
  });
16
111
  });
@@ -1,34 +1,50 @@
1
1
  import React from 'react';
2
- import { mount, shallow } from 'enzyme';
2
+ import { render } from '@testing-library/react';
3
3
  import { UiLayout } from '../index';
4
4
 
5
5
  describe('UiLayout', () => {
6
- let wrapper;
7
6
  const mockClasses = { extraCSSRules: 'extra-class' };
8
7
  const fontSizeFactor = 1.5;
9
8
 
10
9
  // Mock `getComputedStyle` to return a specific root font size.
11
- jest.spyOn(window, 'getComputedStyle').mockImplementation(() => ({
12
- fontSize: '16px', // Default font size for root
13
- }));
10
+ beforeAll(() => {
11
+ jest.spyOn(window, 'getComputedStyle').mockImplementation(() => ({
12
+ fontSize: '16px', // Default font size for root
13
+ }));
14
+ });
14
15
 
15
- wrapper = mount(<UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
16
+ afterAll(() => {
17
+ jest.restoreAllMocks();
18
+ });
16
19
 
17
20
  it('renders correctly', () => {
18
- expect(wrapper.exists()).toBe(true);
21
+ const { container } = render(<UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
22
+ expect(container.firstChild).toBeInTheDocument();
19
23
  });
20
24
 
21
25
  it('applies the correct classes', () => {
22
- const div = wrapper.find('.extra-class');
23
- expect(div.exists()).toBe(true);
26
+ const { container } = render(<UiLayout className="custom-class" classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
27
+ const div = container.querySelector('.custom-class');
28
+ expect(div).toBeInTheDocument();
24
29
  });
25
30
 
26
31
  it('computes style correctly based on fontSizeFactor', () => {
27
- const div = wrapper.find('.extra-class');
32
+ const { container } = render(<UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
33
+ const div = container.firstChild;
28
34
 
29
35
  // Get the style property of the rendered div
30
- const computedStyle = div.getDOMNode().style;
31
- // Assert the computed font size
36
+ const computedStyle = div.style;
37
+ // Assert the computed font size (16px * 1.5 = 24px)
32
38
  expect(computedStyle.fontSize).toBe('24px');
33
39
  });
40
+
41
+ it('renders children when provided', () => {
42
+ const { container } = render(
43
+ <UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor}>
44
+ <div className="test-child">Test Content</div>
45
+ </UiLayout>,
46
+ );
47
+
48
+ expect(container.querySelector('.test-child')).toBeInTheDocument();
49
+ });
34
50
  });
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
2
4
  import withUndoReset from '../withUndoReset';
3
- import { mount, shallow } from 'enzyme';
4
- import { shallowChild } from '@pie-lib/test-utils';
5
5
 
6
6
  describe('withUndoReset', () => {
7
- let wrapper;
8
7
  let defaultProps;
8
+ let onSessionChange;
9
+
9
10
  const WrappedClass = class WrappedComponent extends React.Component {
10
11
  onSessionChange = (session) => {
11
12
  this.props.onSessionChange(session);
@@ -20,7 +21,6 @@ describe('withUndoReset', () => {
20
21
 
21
22
  onRemoveLastItem = () => {
22
23
  const newItems = [...this.props.session.items];
23
-
24
24
  newItems.pop();
25
25
 
26
26
  this.onSessionChange({
@@ -31,13 +31,23 @@ describe('withUndoReset', () => {
31
31
 
32
32
  render() {
33
33
  const { session } = this.props;
34
- const items = session.items || {};
34
+ const items = session.items || [];
35
35
 
36
36
  return (
37
- <div>
38
- {items.map((item) => (
39
- <span key={item.id}>{item.id}</span>
40
- ))}
37
+ <div data-testid="wrapped-component">
38
+ <button data-testid="add-item" onClick={() => this.onAddItem({ id: Date.now() })}>
39
+ Add Item
40
+ </button>
41
+ <button data-testid="remove-item" onClick={() => this.onRemoveLastItem()}>
42
+ Remove Item
43
+ </button>
44
+ <div data-testid="items-container">
45
+ {items.map((item) => (
46
+ <span key={item.id} data-testid={`item-${item.id}`}>
47
+ {item.id}
48
+ </span>
49
+ ))}
50
+ </div>
41
51
  </div>
42
52
  );
43
53
  }
@@ -45,210 +55,122 @@ describe('withUndoReset', () => {
45
55
 
46
56
  const Component = withUndoReset(WrappedClass);
47
57
 
48
- describe('retains internal component functionality', () => {
49
- beforeEach(() => {
50
- defaultProps = {
51
- session: {
52
- items: [],
53
- },
54
- onSessionChange: jest.fn(),
55
- };
58
+ beforeEach(() => {
59
+ onSessionChange = jest.fn();
60
+ defaultProps = {
61
+ session: {
62
+ items: [],
63
+ },
64
+ onSessionChange,
65
+ };
66
+ });
67
+
68
+ describe('HOC functionality', () => {
69
+ it('renders the wrapped component', () => {
70
+ render(<Component {...defaultProps} />);
71
+ expect(screen.getByTestId('wrapped-component')).toBeInTheDocument();
56
72
  });
57
73
 
58
- it('moves past HoC and returns the rendered component using enzyme', () => {
59
- wrapper = mount(<Component {...defaultProps} />);
60
- expect(wrapper.find(WrappedClass).length).toEqual(1);
61
- expect(wrapper.find(WrappedClass).props()).toEqual(
62
- expect.objectContaining({
63
- session: { items: [] },
64
- }),
65
- );
74
+ it('renders undo and reset buttons', () => {
75
+ render(<Component {...defaultProps} />);
76
+ expect(screen.getByText(/Undo/i)).toBeInTheDocument();
77
+ expect(screen.getByText(/Start Over/i)).toBeInTheDocument();
66
78
  });
67
79
 
68
- it('contains the reset logic container', () => {
69
- wrapper = mount(<Component {...defaultProps} />);
70
- expect(wrapper.html().includes('Start Over')).toEqual(true);
71
- expect(wrapper.html().includes('Undo')).toEqual(true);
80
+ it('passes session props to wrapped component', () => {
81
+ render(<Component {...defaultProps} />);
82
+ const itemsContainer = screen.getByTestId('items-container');
83
+ expect(itemsContainer).toBeInTheDocument();
72
84
  });
85
+ });
73
86
 
74
- it('can interact with session', () => {
75
- wrapper = mount(<Component {...defaultProps} />);
76
-
77
- expect(wrapper.find('span').length).toEqual(2);
78
-
79
- wrapper
80
- .find(WrappedClass)
81
- .instance()
82
- .onAddItem({ id: 1 });
83
-
84
- expect(
85
- wrapper
86
- .find(WrappedClass)
87
- .html()
88
- .includes('span'),
89
- ).toEqual(true);
90
-
91
- wrapper
92
- .find(WrappedClass)
93
- .instance()
94
- .onRemoveLastItem();
95
-
96
- expect(
97
- wrapper
98
- .find(WrappedClass)
99
- .html()
100
- .includes('span'),
101
- ).toEqual(false);
87
+ describe('undo functionality', () => {
88
+ it('undo button is disabled when there are no changes', () => {
89
+ render(<Component {...defaultProps} />);
90
+ const undoButton = screen.getByText(/Undo/i).closest('button');
91
+ expect(undoButton).toBeDisabled();
102
92
  });
103
93
 
104
- it('can undo changes in the session', () => {
105
- wrapper = shallowChild(Component, defaultProps, 1)();
106
- const instance = wrapper.instance();
94
+ it('undo button is enabled after a change', async () => {
95
+ const user = userEvent.setup();
96
+ render(<Component {...defaultProps} />);
107
97
 
108
- instance.onSessionChange({
109
- items: [
110
- {
111
- id: 2,
112
- },
113
- ],
114
- });
98
+ const addButton = screen.getByTestId('add-item');
99
+ await user.click(addButton);
115
100
 
116
- instance.onSessionChange({
117
- items: [
118
- {
119
- id: 2,
120
- },
121
- {
122
- id: 3,
123
- },
124
- ],
125
- });
101
+ const undoButton = screen.getByText(/Undo/i).closest('button');
102
+ expect(undoButton).toBeEnabled();
103
+ });
126
104
 
127
- expect(wrapper.state().changes).toEqual([
128
- {
129
- items: [
130
- {
131
- id: 2,
132
- },
133
- ],
134
- },
135
- {
136
- items: [
137
- {
138
- id: 2,
139
- },
140
- {
141
- id: 3,
142
- },
143
- ],
144
- },
145
- ]);
146
-
147
- expect(wrapper.state().session).toEqual({
148
- items: [
149
- {
150
- id: 2,
151
- },
152
- {
153
- id: 3,
154
- },
155
- ],
156
- });
105
+ it('undoes changes when undo button is clicked', async () => {
106
+ const user = userEvent.setup();
107
+ const { rerender } = render(<Component {...defaultProps} />);
157
108
 
158
- instance.onUndo();
159
-
160
- expect(wrapper.state().changes).toEqual([
161
- {
162
- items: [
163
- {
164
- id: 2,
165
- },
166
- ],
167
- },
168
- ]);
169
-
170
- expect(wrapper.state().session).toEqual({
171
- items: [
172
- {
173
- id: 2,
174
- },
175
- ],
176
- });
109
+ // Add an item
110
+ const addButton = screen.getByTestId('add-item');
111
+ await user.click(addButton);
177
112
 
178
- instance.onUndo();
113
+ // Get the actual item ID from the onSessionChange call
114
+ const addedItem = onSessionChange.mock.calls[0][0].items[0];
179
115
 
180
- expect(wrapper.state().changes).toEqual([]);
116
+ // Update props to reflect the change
117
+ const updatedProps = {
118
+ ...defaultProps,
119
+ session: { items: [addedItem] },
120
+ };
121
+ rerender(<Component {...updatedProps} />);
181
122
 
182
- expect(wrapper.state().session).toEqual({
183
- items: [],
184
- });
123
+ expect(screen.getByTestId(`item-${addedItem.id}`)).toBeInTheDocument();
124
+
125
+ // Click undo
126
+ const undoButton = screen.getByText(/Undo/i).closest('button');
127
+ await user.click(undoButton);
185
128
 
186
- expect(wrapper.find(WrappedClass).html()).toEqual('<div></div>');
129
+ // Should call onSessionChange with previous session
130
+ expect(onSessionChange).toHaveBeenCalledWith({ items: [] });
187
131
  });
132
+ });
188
133
 
189
- it('can reset changes in the session', () => {
190
- wrapper = shallowChild(Component, defaultProps, 1)();
191
- const instance = wrapper.instance();
134
+ describe('reset functionality', () => {
135
+ it('reset button is disabled when there are no changes', () => {
136
+ render(<Component {...defaultProps} />);
137
+ const resetButton = screen.getByText(/Start Over/i).closest('button');
138
+ expect(resetButton).toBeDisabled();
139
+ });
192
140
 
193
- instance.onSessionChange({
194
- items: [
195
- {
196
- id: 2,
197
- },
198
- ],
199
- });
141
+ it('reset button is enabled after a change', async () => {
142
+ const user = userEvent.setup();
143
+ render(<Component {...defaultProps} />);
200
144
 
201
- instance.onSessionChange({
202
- items: [
203
- {
204
- id: 2,
205
- },
206
- {
207
- id: 3,
208
- },
209
- ],
210
- });
145
+ const addButton = screen.getByTestId('add-item');
146
+ await user.click(addButton);
211
147
 
212
- expect(wrapper.state().changes).toEqual([
213
- {
214
- items: [
215
- {
216
- id: 2,
217
- },
218
- ],
219
- },
220
- {
221
- items: [
222
- {
223
- id: 2,
224
- },
225
- {
226
- id: 3,
227
- },
228
- ],
229
- },
230
- ]);
231
-
232
- expect(wrapper.state().session).toEqual({
233
- items: [
234
- {
235
- id: 2,
236
- },
237
- {
238
- id: 3,
239
- },
240
- ],
241
- });
148
+ const resetButton = screen.getByText(/Start Over/i).closest('button');
149
+ expect(resetButton).toBeEnabled();
150
+ });
242
151
 
243
- instance.onReset();
152
+ it('resets all changes when reset button is clicked', async () => {
153
+ const user = userEvent.setup();
154
+ const { rerender } = render(<Component {...defaultProps} />);
244
155
 
245
- expect(wrapper.state().changes).toEqual([]);
156
+ // Make multiple changes
157
+ const addButton = screen.getByTestId('add-item');
158
+ await user.click(addButton);
159
+ await user.click(addButton);
246
160
 
247
- expect(wrapper.state().session).toEqual({
248
- items: [],
249
- });
161
+ // Update props to reflect the changes
162
+ const updatedProps = {
163
+ ...defaultProps,
164
+ session: { items: [{ id: 1 }, { id: 2 }] },
165
+ };
166
+ rerender(<Component {...updatedProps} />);
167
+
168
+ // Click reset
169
+ const resetButton = screen.getByText(/Start Over/i).closest('button');
170
+ await user.click(resetButton);
250
171
 
251
- expect(wrapper.find(WrappedClass).html()).toEqual('<div></div>');
172
+ // Should call onSessionChange with initial session
173
+ expect(onSessionChange).toHaveBeenCalledWith({ items: [] });
252
174
  });
253
175
  });
254
176
  });