@pie-lib/render-ui 6.1.0 → 6.1.1-next.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.
Files changed (105) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/assets/enableAudioAutoplayImage.d.ts +10 -0
  3. package/dist/assets/enableAudioAutoplayImage.js +4 -0
  4. package/dist/collapsible/index.d.ts +31 -0
  5. package/dist/collapsible/index.js +53 -0
  6. package/dist/color.d.ts +116 -0
  7. package/dist/color.js +120 -0
  8. package/dist/feedback.d.ts +20 -0
  9. package/dist/feedback.js +65 -0
  10. package/dist/has-media.d.ts +9 -0
  11. package/dist/has-media.js +10 -0
  12. package/dist/has-text.d.ts +9 -0
  13. package/dist/has-text.js +10 -0
  14. package/dist/html-and-math.d.ts +22 -0
  15. package/dist/html-and-math.js +25 -0
  16. package/dist/index.d.ts +26 -0
  17. package/dist/index.js +18 -0
  18. package/dist/inline-menu.d.ts +33 -0
  19. package/dist/inline-menu.js +29 -0
  20. package/dist/input-container.d.ts +23 -0
  21. package/dist/input-container.js +39 -0
  22. package/dist/preview-layout.d.ts +24 -0
  23. package/dist/preview-layout.js +37 -0
  24. package/dist/preview-prompt.d.ts +38 -0
  25. package/dist/preview-prompt.js +154 -0
  26. package/dist/purpose.d.ts +18 -0
  27. package/dist/purpose.js +11 -0
  28. package/dist/readable.d.ts +18 -0
  29. package/dist/readable.js +11 -0
  30. package/dist/response-indicators.d.ts +121 -0
  31. package/dist/response-indicators.js +62 -0
  32. package/{src/transform-headings.js → dist/transform-headings.d.ts} +9 -30
  33. package/dist/transform-headings.js +15 -0
  34. package/dist/ui-layout.d.ts +31 -0
  35. package/dist/ui-layout.js +55 -0
  36. package/dist/withUndoReset.d.ts +47 -0
  37. package/dist/withUndoReset.js +84 -0
  38. package/package.json +30 -20
  39. package/CHANGELOG.json +0 -1
  40. package/CHANGELOG.md +0 -1144
  41. package/LICENSE.md +0 -5
  42. package/lib/assets/enableAudioAutoplayImage.js +0 -8
  43. package/lib/assets/enableAudioAutoplayImage.js.map +0 -1
  44. package/lib/collapsible/index.js +0 -105
  45. package/lib/collapsible/index.js.map +0 -1
  46. package/lib/color.js +0 -231
  47. package/lib/color.js.map +0 -1
  48. package/lib/feedback.js +0 -112
  49. package/lib/feedback.js.map +0 -1
  50. package/lib/has-media.js +0 -22
  51. package/lib/has-media.js.map +0 -1
  52. package/lib/has-text.js +0 -22
  53. package/lib/has-text.js.map +0 -1
  54. package/lib/html-and-math.js +0 -54
  55. package/lib/html-and-math.js.map +0 -1
  56. package/lib/index.js +0 -113
  57. package/lib/index.js.map +0 -1
  58. package/lib/input-container.js +0 -59
  59. package/lib/input-container.js.map +0 -1
  60. package/lib/preview-layout.js +0 -65
  61. package/lib/preview-layout.js.map +0 -1
  62. package/lib/preview-prompt.js +0 -299
  63. package/lib/preview-prompt.js.map +0 -1
  64. package/lib/purpose.js +0 -22
  65. package/lib/purpose.js.map +0 -1
  66. package/lib/readable.js +0 -22
  67. package/lib/readable.js.map +0 -1
  68. package/lib/response-indicators.js +0 -102
  69. package/lib/response-indicators.js.map +0 -1
  70. package/lib/transform-headings.js +0 -53
  71. package/lib/transform-headings.js.map +0 -1
  72. package/lib/ui-layout.js +0 -125
  73. package/lib/ui-layout.js.map +0 -1
  74. package/lib/withUndoReset.js +0 -135
  75. package/lib/withUndoReset.js.map +0 -1
  76. package/src/__tests__/color.test.js +0 -259
  77. package/src/__tests__/feedback.test.jsx +0 -279
  78. package/src/__tests__/has-media.test.js +0 -19
  79. package/src/__tests__/has-text.test.js +0 -20
  80. package/src/__tests__/html-and-math.test.js +0 -36
  81. package/src/__tests__/input-container.test.jsx +0 -328
  82. package/src/__tests__/preview-layout.test.jsx +0 -349
  83. package/src/__tests__/preview-prompt.test.jsx +0 -379
  84. package/src/__tests__/purpose.test.jsx +0 -51
  85. package/src/__tests__/readable.test.jsx +0 -69
  86. package/src/__tests__/response-indicators.test.jsx +0 -111
  87. package/src/__tests__/ui-layout.test.jsx +0 -52
  88. package/src/__tests__/withUndoReset.test.jsx +0 -176
  89. package/src/assets/enableAudioAutoplayImage.js +0 -1
  90. package/src/collapsible/__tests__/index.test.jsx +0 -39
  91. package/src/collapsible/index.jsx +0 -64
  92. package/src/color.js +0 -137
  93. package/src/feedback.jsx +0 -84
  94. package/src/has-media.js +0 -16
  95. package/src/has-text.js +0 -18
  96. package/src/html-and-math.js +0 -21
  97. package/src/index.js +0 -35
  98. package/src/input-container.jsx +0 -47
  99. package/src/preview-layout.jsx +0 -41
  100. package/src/preview-prompt.jsx +0 -280
  101. package/src/purpose.jsx +0 -17
  102. package/src/readable.jsx +0 -19
  103. package/src/response-indicators.jsx +0 -82
  104. package/src/ui-layout.jsx +0 -96
  105. package/src/withUndoReset.jsx +0 -114
@@ -1,379 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import PreviewPrompt from '../preview-prompt';
5
-
6
- jest.mock('@pie-lib/math-rendering', () => ({
7
- renderMath: jest.fn(),
8
- }));
9
-
10
- const { renderMath } = require('@pie-lib/math-rendering');
11
-
12
- describe('Prompt without Custom tag', () => {
13
- const defaultProps = {
14
- classes: {},
15
- prompt:
16
- 'Which of these northern European countries are EU members? <math><mstack><msrow><mn>111</mn></msrow><msline/></mstack></math>',
17
- tagName: '',
18
- className: '',
19
- };
20
-
21
- describe('default rendering with markup', () => {
22
- it('renders the prompt text', () => {
23
- render(<PreviewPrompt {...defaultProps} />);
24
- expect(screen.getByText(/Which of these northern European countries are EU members/)).toBeInTheDocument();
25
- });
26
-
27
- it('does not have prompt class by default', () => {
28
- const { container } = render(<PreviewPrompt {...defaultProps} />);
29
- expect(container.firstChild).not.toHaveClass('prompt');
30
- });
31
-
32
- it('renders math markup', () => {
33
- const { container } = render(<PreviewPrompt {...defaultProps} />);
34
- // Math may be rendered but transformed by the math rendering library
35
- // Just check that the prompt text is rendered
36
- expect(screen.getByText(/Which of these northern European countries are EU members/)).toBeInTheDocument();
37
- });
38
- });
39
- });
40
-
41
- describe('Prompt with Custom tag', () => {
42
- const defaultProps = {
43
- classes: {},
44
- prompt:
45
- 'Which of these northern European countries are EU members? <math><mstack><msrow><mn>111</mn></msrow><msline/></mstack></math>',
46
- tagName: 'span',
47
- className: 'prompt',
48
- };
49
-
50
- describe('renders with custom tag "span" correctly', () => {
51
- it('renders with custom className', () => {
52
- const { container } = render(<PreviewPrompt {...defaultProps} />);
53
- expect(container.firstChild).toHaveClass('prompt');
54
- });
55
-
56
- it('renders as span element when tagName is specified', () => {
57
- const { container } = render(<PreviewPrompt {...defaultProps} />);
58
- expect(container.firstChild.tagName.toLowerCase()).toBe('span');
59
- });
60
-
61
- it('renders the prompt text', () => {
62
- render(<PreviewPrompt {...defaultProps} />);
63
- expect(screen.getByText(/Which of these northern European countries are EU members/)).toBeInTheDocument();
64
- });
65
- });
66
- });
67
-
68
- describe('PreviewPrompt - Extended Tests', () => {
69
- beforeEach(() => {
70
- jest.clearAllMocks();
71
- document.body.innerHTML = '';
72
- });
73
-
74
- describe('tagName variations', () => {
75
- it('should render as legend when tagName is "legend"', () => {
76
- const { container } = render(<PreviewPrompt prompt="Legend text" tagName="legend" />);
77
- expect(container.firstChild.tagName.toLowerCase()).toBe('legend');
78
- });
79
-
80
- it('should render as div by default when no tagName', () => {
81
- const { container } = render(<PreviewPrompt prompt="Default text" />);
82
- expect(container.firstChild.tagName.toLowerCase()).toBe('div');
83
- });
84
-
85
- it('should apply legend class when tagName is "legend"', () => {
86
- const { container } = render(<PreviewPrompt prompt="Legend text" tagName="legend" />);
87
- expect(container.firstChild).toHaveClass('legend');
88
- });
89
-
90
- it('should render as p tag when specified', () => {
91
- const { container } = render(<PreviewPrompt prompt="Paragraph text" tagName="p" />);
92
- expect(container.firstChild.tagName.toLowerCase()).toBe('p');
93
- });
94
- });
95
-
96
- describe('className handling', () => {
97
- it('should apply single className', () => {
98
- const { container } = render(<PreviewPrompt prompt="Test" className="custom-class" />);
99
- expect(container.firstChild).toHaveClass('custom-class');
100
- });
101
-
102
- it('should apply defaultClassName', () => {
103
- const { container } = render(<PreviewPrompt prompt="Test" defaultClassName="default-class" />);
104
- expect(container.firstChild).toHaveClass('default-class');
105
- });
106
-
107
- it('should combine className and defaultClassName', () => {
108
- const { container } = render(<PreviewPrompt prompt="Test" className="custom" defaultClassName="default" />);
109
- expect(container.firstChild).toHaveClass('custom');
110
- expect(container.firstChild).toHaveClass('default');
111
- });
112
-
113
- it('should add legend class when tagName is legend', () => {
114
- const { container } = render(<PreviewPrompt prompt="Test" tagName="legend" className="custom" />);
115
- expect(container.firstChild).toHaveClass('custom');
116
- expect(container.firstChild).toHaveClass('legend');
117
- });
118
- });
119
-
120
- describe('onClick handler', () => {
121
- it('should call onClick when clicked', async () => {
122
- const onClick = jest.fn();
123
- const user = userEvent.setup();
124
-
125
- render(<PreviewPrompt prompt="Clickable text" onClick={onClick} />);
126
-
127
- await user.click(screen.getByText('Clickable text'));
128
- expect(onClick).toHaveBeenCalledTimes(1);
129
- });
130
-
131
- it('should work without onClick handler', async () => {
132
- const user = userEvent.setup();
133
-
134
- render(<PreviewPrompt prompt="Text without handler" />);
135
-
136
- await user.click(screen.getByText('Text without handler'));
137
- });
138
-
139
- it('should call onClick multiple times', async () => {
140
- const onClick = jest.fn();
141
- const user = userEvent.setup();
142
-
143
- render(<PreviewPrompt prompt="Multi-click text" onClick={onClick} />);
144
-
145
- await user.click(screen.getByText('Multi-click text'));
146
- await user.click(screen.getByText('Multi-click text'));
147
- await user.click(screen.getByText('Multi-click text'));
148
-
149
- expect(onClick).toHaveBeenCalledTimes(3);
150
- });
151
- });
152
-
153
- describe('newline replacement', () => {
154
- it('should replace \\embed{newLine}[] with \\newline', () => {
155
- const promptWithNewline = 'Line 1\\embed{newLine}[]Line 2';
156
- const { container } = render(<PreviewPrompt prompt={promptWithNewline} />);
157
-
158
- expect(container.innerHTML).toContain('\\newline');
159
- expect(container.innerHTML).not.toContain('\\embed{newLine}[]');
160
- });
161
-
162
- it('should replace multiple newlines', () => {
163
- const promptWithNewlines = 'A\\embed{newLine}[]B\\embed{newLine}[]C';
164
- const { container } = render(<PreviewPrompt prompt={promptWithNewlines} />);
165
-
166
- const newlineCount = (container.innerHTML.match(/\\newline/g) || []).length;
167
- expect(newlineCount).toBe(2);
168
- });
169
-
170
- it('should handle prompt without newlines', () => {
171
- const normalPrompt = 'Normal text without newlines';
172
- render(<PreviewPrompt prompt={normalPrompt} />);
173
-
174
- expect(screen.getByText('Normal text without newlines')).toBeInTheDocument();
175
- });
176
- });
177
-
178
- describe('audio handling', () => {
179
- it('should parse audio tag and add source element', () => {
180
- const promptWithAudio = '<audio src="test.mp3"></audio>';
181
- render(<PreviewPrompt prompt={promptWithAudio} />);
182
-
183
- const audio = document.querySelector('audio');
184
- expect(audio).toBeInTheDocument();
185
- expect(audio).toHaveAttribute('id', 'pie-prompt-audio-player');
186
-
187
- const source = audio.querySelector('source');
188
- expect(source).toBeInTheDocument();
189
- expect(source).toHaveAttribute('src', 'test.mp3');
190
- expect(source).toHaveAttribute('type', 'audio/mp3');
191
- });
192
-
193
- it('should remove src attribute from audio tag after adding source', () => {
194
- const promptWithAudio = '<audio src="test.mp3"></audio>';
195
- render(<PreviewPrompt prompt={promptWithAudio} />);
196
-
197
- const audio = document.querySelector('audio');
198
- expect(audio).not.toHaveAttribute('src');
199
- });
200
-
201
- it('should handle custom audio button', () => {
202
- const customAudioButton = {
203
- playImage: 'play.png',
204
- pauseImage: 'pause.png',
205
- };
206
- const promptWithAudio = '<audio src="test.mp3"></audio>';
207
-
208
- render(<PreviewPrompt prompt={promptWithAudio} customAudioButton={customAudioButton} />);
209
-
210
- const audio = document.getElementById('pie-prompt-audio-player');
211
- expect(audio).toHaveStyle({ display: 'none' });
212
-
213
- const playButton = document.getElementById('play-audio-button');
214
- expect(playButton).toBeInTheDocument();
215
- });
216
-
217
- it('should not add custom button when customAudioButton is not provided', () => {
218
- const promptWithAudio = '<audio src="test.mp3"></audio>';
219
- render(<PreviewPrompt prompt={promptWithAudio} />);
220
-
221
- const playButton = document.getElementById('play-audio-button');
222
- expect(playButton).not.toBeInTheDocument();
223
- });
224
- });
225
-
226
- describe('image alignment', () => {
227
- it('should align images with alignment attribute', () => {
228
- const promptWithImage = '<img src="test.jpg" alignment="center" />';
229
- render(<PreviewPrompt prompt={promptWithImage} />);
230
-
231
- const images = document.querySelectorAll('img');
232
- expect(images.length).toBeGreaterThan(0);
233
- });
234
-
235
- it('should handle images without alignment attribute', () => {
236
- const promptWithImage = '<img src="test.jpg" />';
237
- render(<PreviewPrompt prompt={promptWithImage} />);
238
-
239
- const img = document.querySelector('img');
240
- expect(img).toBeInTheDocument();
241
- });
242
- });
243
-
244
- describe('edge cases', () => {
245
- it('should handle empty prompt', () => {
246
- const { container } = render(<PreviewPrompt prompt="" />);
247
- expect(container.firstChild).toBeInTheDocument();
248
- });
249
-
250
- it('should handle undefined prompt', () => {
251
- const { container } = render(<PreviewPrompt prompt={undefined} />);
252
- expect(container.firstChild).toBeInTheDocument();
253
- });
254
-
255
- it('should handle null prompt', () => {
256
- const { container } = render(<PreviewPrompt prompt={null} />);
257
- expect(container.firstChild).toBeInTheDocument();
258
- });
259
-
260
- it('should handle very long prompt', () => {
261
- const longPrompt = 'A'.repeat(10000);
262
- render(<PreviewPrompt prompt={longPrompt} />);
263
- expect(screen.getByText(longPrompt)).toBeInTheDocument();
264
- });
265
-
266
- it('should handle prompt with special HTML characters', () => {
267
- const specialPrompt = '<div>Test & "quotes" \' apostrophe</div>';
268
- render(<PreviewPrompt prompt={specialPrompt} />);
269
- expect(screen.getByText(/Test/)).toBeInTheDocument();
270
- });
271
-
272
- it('should handle prompt with script tags safely', () => {
273
- const scriptPrompt = '<script>alert("XSS")</script>Safe text';
274
- const { container } = render(<PreviewPrompt prompt={scriptPrompt} />);
275
- expect(container).toBeInTheDocument();
276
- });
277
- });
278
-
279
- describe('dangerouslySetInnerHTML', () => {
280
- it('should render HTML using dangerouslySetInnerHTML', () => {
281
- const htmlPrompt = '<strong>Bold</strong> and <em>italic</em>';
282
- render(<PreviewPrompt prompt={htmlPrompt} />);
283
-
284
- expect(screen.getByText('Bold')).toBeInTheDocument();
285
- expect(screen.getByText(/italic/)).toBeInTheDocument();
286
- });
287
-
288
- it('should render complex nested HTML', () => {
289
- const complexPrompt = `
290
- <div>
291
- <h3>Title</h3>
292
- <p>Paragraph 1</p>
293
- <ul>
294
- <li>Item 1</li>
295
- <li>Item 2</li>
296
- </ul>
297
- </div>
298
- `;
299
- render(<PreviewPrompt prompt={complexPrompt} />);
300
-
301
- expect(screen.getByText('Title')).toBeInTheDocument();
302
- expect(screen.getByText('Paragraph 1')).toBeInTheDocument();
303
- expect(screen.getByText('Item 1')).toBeInTheDocument();
304
- expect(screen.getByText('Item 2')).toBeInTheDocument();
305
- });
306
-
307
- it('should render tables', () => {
308
- const tablePrompt = `
309
- <table>
310
- <tbody>
311
- <tr><th>Header</th><td>Data</td></tr>
312
- </tbody>
313
- </table>
314
- `;
315
- render(<PreviewPrompt prompt={tablePrompt} />);
316
-
317
- expect(screen.getByText('Header')).toBeInTheDocument();
318
- expect(screen.getByText('Data')).toBeInTheDocument();
319
- });
320
- });
321
-
322
- describe('component lifecycle', () => {
323
- it('should cleanup on unmount', () => {
324
- const { unmount } = render(<PreviewPrompt prompt="Test" />);
325
- unmount();
326
- // Should not throw errors on unmount
327
- });
328
-
329
- it('should update when props change', () => {
330
- const { rerender } = render(<PreviewPrompt prompt="Initial" />);
331
- rerender(<PreviewPrompt prompt="Updated" />);
332
-
333
- expect(screen.getByText('Updated')).toBeInTheDocument();
334
- expect(screen.queryByText('Initial')).not.toBeInTheDocument();
335
- });
336
-
337
- it('should handle rapid prop changes', () => {
338
- const { rerender } = render(<PreviewPrompt prompt="V1" />);
339
- rerender(<PreviewPrompt prompt="V2" />);
340
- rerender(<PreviewPrompt prompt="V3" />);
341
- rerender(<PreviewPrompt prompt="V4" />);
342
-
343
- expect(screen.getByText('V4')).toBeInTheDocument();
344
- });
345
- });
346
-
347
- describe('accessibility', () => {
348
- it('should have preview-prompt id for accessibility', () => {
349
- render(<PreviewPrompt prompt="Accessible text" />);
350
- const element = document.getElementById('preview-prompt');
351
- expect(element).toBeInTheDocument();
352
- });
353
-
354
- it('should preserve semantic HTML', () => {
355
- const semanticPrompt = '<strong>Important:</strong> Read carefully';
356
- render(<PreviewPrompt prompt={semanticPrompt} />);
357
-
358
- const strong = document.querySelector('strong');
359
- expect(strong).toBeInTheDocument();
360
- expect(strong).toHaveTextContent('Important:');
361
- });
362
- });
363
-
364
- describe('multiple instances', () => {
365
- it('should handle multiple PreviewPrompt components', () => {
366
- const { container } = render(
367
- <div>
368
- <PreviewPrompt prompt="First prompt" />
369
- <PreviewPrompt prompt="Second prompt" />
370
- <PreviewPrompt prompt="Third prompt" />
371
- </div>,
372
- );
373
-
374
- expect(screen.getByText('First prompt')).toBeInTheDocument();
375
- expect(screen.getByText('Second prompt')).toBeInTheDocument();
376
- expect(screen.getByText('Third prompt')).toBeInTheDocument();
377
- });
378
- });
379
- });
@@ -1,51 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import Purpose from '../purpose';
4
-
5
- describe('Purpose', () => {
6
- describe('rendering', () => {
7
- it('renders child with data-pie-purpose attribute even when purpose prop is not provided', () => {
8
- const { container } = render(
9
- <Purpose>
10
- <div>text</div>
11
- </Purpose>,
12
- );
13
-
14
- expect(screen.getByText('text')).toBeInTheDocument();
15
- const div = container.querySelector('div');
16
- // When purpose is undefined, React sets the attribute as data-pie-purpose="undefined"
17
- // This is expected behavior - the component always adds the attribute
18
- expect(div).toBeInTheDocument();
19
- });
20
-
21
- it('renders child with data-pie-purpose="passage"', () => {
22
- const { container } = render(
23
- <Purpose purpose="passage">
24
- <div>text</div>
25
- </Purpose>,
26
- );
27
-
28
- expect(screen.getByText('text')).toBeInTheDocument();
29
- const div = container.querySelector('div');
30
- expect(div).toHaveAttribute('data-pie-purpose', 'passage');
31
- });
32
-
33
- it('renders multiple children with data-pie-purpose attribute', () => {
34
- const { container } = render(
35
- <Purpose purpose="something">
36
- <div>
37
- <div>text1</div>
38
- <div>text2</div>
39
- </div>
40
- </Purpose>,
41
- );
42
-
43
- expect(screen.getByText('text1')).toBeInTheDocument();
44
- expect(screen.getByText('text2')).toBeInTheDocument();
45
- expect(screen.queryByText('text3')).not.toBeInTheDocument();
46
-
47
- const parentDiv = container.querySelector('div');
48
- expect(parentDiv).toHaveAttribute('data-pie-purpose', 'something');
49
- });
50
- });
51
- });
@@ -1,69 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import Readable from '../readable';
4
-
5
- describe('Readable', () => {
6
- describe('rendering', () => {
7
- it('renders child with data-pie-readable attribute set to true', () => {
8
- const { container } = render(
9
- <Readable>
10
- <div>text</div>
11
- </Readable>,
12
- );
13
-
14
- expect(screen.getByText('text')).toBeInTheDocument();
15
- const div = container.querySelector('div');
16
- expect(div).toHaveAttribute('data-pie-readable', 'true');
17
- });
18
-
19
- it('renders multiple children with data-pie-readable attribute', () => {
20
- const { container } = render(
21
- <Readable>
22
- <div>
23
- <div>text1</div>
24
- <div>text2</div>
25
- </div>
26
- </Readable>,
27
- );
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');
35
- });
36
-
37
- it('renders with data-pie-readable set to false when false prop is provided', () => {
38
- const { container } = render(
39
- <Readable false>
40
- <div>
41
- <div>text1</div>
42
- <div>text2</div>
43
- </div>
44
- </Readable>,
45
- );
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');
53
- });
54
-
55
- it('renders with data-pie-readable set to false when false={true}', () => {
56
- const { container } = render(
57
- <Readable false={true}>
58
- <div>
59
- <div>text1</div>
60
- <div>text2</div>
61
- </div>
62
- </Readable>,
63
- );
64
-
65
- const parentDiv = container.querySelector('div');
66
- expect(parentDiv).toHaveAttribute('data-pie-readable', 'false');
67
- });
68
- });
69
- });
@@ -1,111 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import { Correct, Incorrect, NothingSubmitted, PartiallyCorrect } 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
- });
25
-
26
- describe('response-indicators', () => {
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
- });
59
- });
60
-
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
- });
110
- });
111
- });
@@ -1,52 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import { UiLayout } from '../index';
4
-
5
- describe('UiLayout', () => {
6
- const mockClasses = { extraCSSRules: 'extra-class' };
7
- const fontSizeFactor = 1.5;
8
-
9
- // Mock `getComputedStyle` to return a specific root font size.
10
- beforeAll(() => {
11
- jest.spyOn(window, 'getComputedStyle').mockImplementation(() => ({
12
- fontSize: '16px', // Default font size for root
13
- }));
14
- });
15
-
16
- afterAll(() => {
17
- jest.restoreAllMocks();
18
- });
19
-
20
- it('renders correctly', () => {
21
- const { container } = render(<UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
22
- expect(container.firstChild).toBeInTheDocument();
23
- });
24
-
25
- it('applies the correct classes', () => {
26
- const { container } = render(
27
- <UiLayout className="custom-class" classes={mockClasses} fontSizeFactor={fontSizeFactor} />,
28
- );
29
- const div = container.querySelector('.custom-class');
30
- expect(div).toBeInTheDocument();
31
- });
32
-
33
- it('computes style correctly based on fontSizeFactor', () => {
34
- const { container } = render(<UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor} />);
35
- const div = container.firstChild;
36
-
37
- // Get the style property of the rendered div
38
- const computedStyle = div.style;
39
- // Assert the computed font size (16px * 1.5 = 24px)
40
- expect(computedStyle.fontSize).toBe('24px');
41
- });
42
-
43
- it('renders children when provided', () => {
44
- const { container } = render(
45
- <UiLayout classes={mockClasses} fontSizeFactor={fontSizeFactor}>
46
- <div className="test-child">Test Content</div>
47
- </UiLayout>,
48
- );
49
-
50
- expect(container.querySelector('.test-child')).toBeInTheDocument();
51
- });
52
- });