@pie-lib/mask-markup 1.33.3-next.2 → 1.33.4-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.
- package/CHANGELOG.md +6 -76
- package/lib/__tests__/drag-in-the-blank.test.js +129 -0
- package/lib/__tests__/index.test.js +42 -0
- package/lib/__tests__/mask.test.js +163 -0
- package/lib/__tests__/serialization.test.js +44 -0
- package/lib/__tests__/utils.js +14 -0
- package/lib/__tests__/with-mask.test.js +110 -0
- package/lib/choices/__tests__/index.test.js +101 -0
- package/lib/choices/choice.js +99 -204
- package/lib/choices/choice.js.map +1 -1
- package/lib/choices/index.js +22 -54
- package/lib/choices/index.js.map +1 -1
- package/lib/componentize.js +2 -6
- package/lib/componentize.js.map +1 -1
- package/lib/components/__tests__/blank.test.js +189 -0
- package/lib/components/__tests__/correct-input.test.js +132 -0
- package/lib/components/__tests__/dropdown.test.js +134 -0
- package/lib/components/__tests__/input.test.js +129 -0
- package/lib/components/blank.js +304 -362
- package/lib/components/blank.js.map +1 -1
- package/lib/components/correct-input.js +42 -66
- package/lib/components/correct-input.js.map +1 -1
- package/lib/components/dropdown.js +219 -258
- package/lib/components/dropdown.js.map +1 -1
- package/lib/components/input.js +11 -18
- package/lib/components/input.js.map +1 -1
- package/lib/constructed-response.js +39 -53
- package/lib/constructed-response.js.map +1 -1
- package/lib/customizable.js +6 -10
- package/lib/customizable.js.map +1 -1
- package/lib/drag-in-the-blank.js +141 -106
- package/lib/drag-in-the-blank.js.map +1 -1
- package/lib/index.js +1 -8
- package/lib/index.js.map +1 -1
- package/lib/inline-dropdown.js +5 -13
- package/lib/inline-dropdown.js.map +1 -1
- package/lib/mask.js +61 -119
- package/lib/mask.js.map +1 -1
- package/lib/serialization.js +9 -49
- package/lib/serialization.js.map +1 -1
- package/lib/with-mask.js +31 -59
- package/lib/with-mask.js.map +1 -1
- package/package.json +12 -20
- package/src/__tests__/drag-in-the-blank.test.js +66 -26
- package/src/__tests__/mask.test.js +147 -112
- package/src/__tests__/with-mask.test.js +44 -19
- package/src/choices/__tests__/index.test.js +38 -25
- package/src/choices/choice.jsx +86 -153
- package/src/choices/index.jsx +9 -3
- package/src/components/__tests__/blank.test.js +92 -156
- package/src/components/__tests__/correct-input.test.js +60 -19
- package/src/components/__tests__/dropdown.test.js +61 -19
- package/src/components/__tests__/input.test.js +72 -20
- package/src/components/blank.jsx +273 -272
- package/src/components/correct-input.jsx +33 -39
- package/src/components/dropdown.jsx +173 -161
- package/src/constructed-response.jsx +22 -18
- package/src/drag-in-the-blank.jsx +131 -42
- package/src/mask.jsx +38 -29
- package/src/with-mask.jsx +7 -4
- package/esm/index.css +0 -847
- package/esm/index.js +0 -195939
- package/esm/index.js.map +0 -1
- package/esm/package.json +0 -3
- package/src/__tests__/__snapshots__/drag-in-the-blank.test.js.snap +0 -316
- package/src/__tests__/__snapshots__/mask.test.js.snap +0 -55
- package/src/__tests__/__snapshots__/with-mask.test.js.snap +0 -62
- package/src/choices/__tests__/__snapshots__/index.test.js.snap +0 -209
- package/src/components/__tests__/__snapshots__/blank.test.js.snap +0 -111
- package/src/components/__tests__/__snapshots__/correct-input.test.js.snap +0 -64
- package/src/components/__tests__/__snapshots__/dropdown.test.js.snap +0 -136
- package/src/components/__tests__/__snapshots__/input.test.js.snap +0 -34
package/src/choices/choice.jsx
CHANGED
|
@@ -1,164 +1,97 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom';
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
3
|
+
import { useDraggable } from '@dnd-kit/core';
|
|
4
|
+
import { styled } from '@mui/material/styles';
|
|
5
|
+
import Chip from '@mui/material/Chip';
|
|
8
6
|
import { renderMath } from '@pie-lib/math-rendering';
|
|
9
7
|
import { color } from '@pie-lib/render-ui';
|
|
10
|
-
import { DragSource } from '@pie-lib/drag';
|
|
11
8
|
|
|
12
9
|
export const DRAG_TYPE = 'MaskBlank';
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
componentDidMount() {
|
|
46
|
-
if (this.dragContainerRef) {
|
|
47
|
-
this.dragContainerRef.addEventListener('touchstart', this.handleTouchStart, { passive: false });
|
|
48
|
-
this.dragContainerRef.addEventListener('touchend', this.handleTouchEnd);
|
|
49
|
-
this.dragContainerRef.addEventListener('touchmove', this.handleTouchMove);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
componentWillUnmount() {
|
|
54
|
-
if (this.dragContainerRef) {
|
|
55
|
-
this.dragContainerRef.removeEventListener('touchstart', this.handleTouchStart);
|
|
56
|
-
this.dragContainerRef.removeEventListener('touchend', this.handleTouchEnd);
|
|
57
|
-
this.dragContainerRef.removeEventListener('touchmove', this.handleTouchMove);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
componentDidUpdate() {
|
|
62
|
-
renderMath(this.rootRef);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
render() {
|
|
66
|
-
const { connectDragSource, choice, classes, disabled } = this.props;
|
|
67
|
-
|
|
68
|
-
// TODO the Chip element is causing drag problems on touch devices. Avoid using Chip and consider refactoring the code. Keep in mind that Chip is a span with a button role, which interferes with seamless touch device dragging.
|
|
69
|
-
|
|
70
|
-
return connectDragSource(
|
|
71
|
-
<span
|
|
72
|
-
className={classnames(classes.choice, disabled && classes.disabled)}
|
|
73
|
-
ref={(ref) => {
|
|
74
|
-
//eslint-disable-next-line
|
|
75
|
-
this.dragContainerRef = ReactDOM.findDOMNode(ref);
|
|
76
|
-
}}
|
|
77
|
-
>
|
|
78
|
-
<Chip
|
|
79
|
-
clickable={false}
|
|
80
|
-
disabled={true}
|
|
81
|
-
ref={(ref) => {
|
|
82
|
-
//eslint-disable-next-line
|
|
83
|
-
this.rootRef = ReactDOM.findDOMNode(ref);
|
|
84
|
-
}}
|
|
85
|
-
className={classes.chip}
|
|
86
|
-
label={
|
|
87
|
-
<span
|
|
88
|
-
className={classes.chipLabel}
|
|
89
|
-
ref={(ref) => {
|
|
90
|
-
if (ref) {
|
|
91
|
-
ref.innerHTML = choice.value || ' ';
|
|
92
|
-
}
|
|
93
|
-
}}
|
|
94
|
-
>
|
|
95
|
-
{' '}
|
|
96
|
-
</span>
|
|
97
|
-
}
|
|
98
|
-
variant={disabled ? 'outlined' : undefined}
|
|
99
|
-
/>
|
|
100
|
-
</span>,
|
|
101
|
-
{},
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export const BlankContent = withStyles((theme) => ({
|
|
107
|
-
choice: {
|
|
108
|
-
border: `solid 0px ${theme.palette.primary.main}`,
|
|
109
|
-
borderRadius: theme.spacing.unit * 2,
|
|
110
|
-
margin: theme.spacing.unit / 2,
|
|
111
|
-
transform: 'translate(0, 0)',
|
|
112
|
-
},
|
|
113
|
-
chip: {
|
|
114
|
-
backgroundColor: color.white(),
|
|
115
|
-
border: `1px solid ${color.text()}`,
|
|
116
|
-
color: color.text(),
|
|
117
|
-
alignItems: 'center',
|
|
118
|
-
display: 'inline-flex',
|
|
119
|
-
height: 'initial',
|
|
120
|
-
minHeight: '32px',
|
|
121
|
-
fontSize: 'inherit',
|
|
122
|
-
whiteSpace: 'pre-wrap',
|
|
123
|
-
maxWidth: '374px',
|
|
124
|
-
// Added for touch devices, for image content.
|
|
125
|
-
// This will prevent the context menu from appearing and not allowing other interactions with the image.
|
|
126
|
-
// If interactions with the image in the token will be requested we should handle only the context Menu.
|
|
127
|
-
pointerEvents: 'none',
|
|
128
|
-
borderRadius: '3px',
|
|
129
|
-
paddingTop: '12px',
|
|
130
|
-
paddingBottom: '12px',
|
|
131
|
-
},
|
|
132
|
-
chipLabel: {
|
|
133
|
-
whiteSpace: 'normal',
|
|
134
|
-
'& img': {
|
|
135
|
-
display: 'block',
|
|
136
|
-
padding: '2px 0',
|
|
137
|
-
},
|
|
138
|
-
'& mjx-frac': {
|
|
139
|
-
fontSize: '120% !important',
|
|
140
|
-
},
|
|
11
|
+
const StyledChoice = styled('span')(({ theme, disabled }) => ({
|
|
12
|
+
border: `solid 0px ${theme.palette.primary.main}`,
|
|
13
|
+
borderRadius: theme.spacing(2),
|
|
14
|
+
margin: theme.spacing(0.5),
|
|
15
|
+
transform: 'translate(0, 0)',
|
|
16
|
+
display: 'inline-flex',
|
|
17
|
+
...(disabled && {}),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
const StyledChip = styled(Chip)(() => ({
|
|
21
|
+
backgroundColor: color.white(),
|
|
22
|
+
border: `1px solid ${color.text()}`,
|
|
23
|
+
color: color.text(),
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
display: 'inline-flex',
|
|
26
|
+
height: 'initial',
|
|
27
|
+
minHeight: '32px',
|
|
28
|
+
fontSize: 'inherit',
|
|
29
|
+
whiteSpace: 'pre-wrap',
|
|
30
|
+
maxWidth: '374px',
|
|
31
|
+
// Added for touch devices, for image content.
|
|
32
|
+
// This will prevent the context menu from appearing and not allowing other interactions with the image.
|
|
33
|
+
// If interactions with the image in the token will be requested we should handle only the context Menu.
|
|
34
|
+
pointerEvents: 'none',
|
|
35
|
+
borderRadius: '3px',
|
|
36
|
+
paddingTop: '12px',
|
|
37
|
+
paddingBottom: '12px',
|
|
38
|
+
|
|
39
|
+
'&.Mui-disabled': {
|
|
40
|
+
opacity: 1,
|
|
141
41
|
},
|
|
142
|
-
|
|
143
|
-
opacity: 0.6,
|
|
144
|
-
},
|
|
145
|
-
}))(BlankContentComp);
|
|
42
|
+
}));
|
|
146
43
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
44
|
+
const StyledChipLabel = styled('span')(() => ({
|
|
45
|
+
whiteSpace: 'normal',
|
|
46
|
+
'& img': {
|
|
47
|
+
display: 'block',
|
|
48
|
+
padding: '2px 0',
|
|
150
49
|
},
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
choice: props.choice,
|
|
154
|
-
instanceId: props.instanceId,
|
|
155
|
-
};
|
|
50
|
+
'& mjx-frac': {
|
|
51
|
+
fontSize: '120% !important',
|
|
156
52
|
},
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
export default function Choice({ choice, disabled, instanceId }) {
|
|
56
|
+
const rootRef = useRef(null);
|
|
57
|
+
|
|
58
|
+
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
|
|
59
|
+
id: `choice-${choice.id}`,
|
|
60
|
+
data: { choice, instanceId, fromChoice: true, type: DRAG_TYPE },
|
|
61
|
+
disabled,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
renderMath(rootRef.current);
|
|
66
|
+
}, [choice.value]);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<StyledChoice
|
|
70
|
+
ref={setNodeRef}
|
|
71
|
+
style={
|
|
72
|
+
isDragging
|
|
73
|
+
? {
|
|
74
|
+
width: rootRef.current?.offsetWidth,
|
|
75
|
+
height: rootRef.current?.offsetHeight,
|
|
76
|
+
}
|
|
77
|
+
: {}
|
|
78
|
+
}
|
|
79
|
+
disabled={disabled}
|
|
80
|
+
{...listeners}
|
|
81
|
+
{...attributes}
|
|
82
|
+
>
|
|
83
|
+
<StyledChip
|
|
84
|
+
clickable={false}
|
|
85
|
+
disabled={disabled}
|
|
86
|
+
ref={rootRef}
|
|
87
|
+
label={<StyledChipLabel dangerouslySetInnerHTML={{ __html: choice.value }} />}
|
|
88
|
+
/>
|
|
89
|
+
</StyledChoice>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
163
92
|
|
|
164
|
-
|
|
93
|
+
Choice.propTypes = {
|
|
94
|
+
choice: PropTypes.object.isRequired,
|
|
95
|
+
disabled: PropTypes.bool,
|
|
96
|
+
instanceId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
97
|
+
};
|
package/src/choices/index.jsx
CHANGED
|
@@ -11,6 +11,7 @@ export default class Choices extends React.Component {
|
|
|
11
11
|
choices: PropTypes.arrayOf(PropTypes.shape({ label: PropTypes.string, value: PropTypes.string })),
|
|
12
12
|
value: PropTypes.object,
|
|
13
13
|
choicePosition: PropTypes.string.isRequired,
|
|
14
|
+
instanceId: PropTypes.string, // Added for drag isolation
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
getStyleForWrapper = () => {
|
|
@@ -40,7 +41,7 @@ export default class Choices extends React.Component {
|
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
render() {
|
|
43
|
-
const { disabled, duplicates, choices, value } = this.props;
|
|
44
|
+
const { disabled, duplicates, choices, value, instanceId } = this.props;
|
|
44
45
|
const filteredChoices = choices.filter((c) => {
|
|
45
46
|
if (duplicates === true) {
|
|
46
47
|
return true;
|
|
@@ -52,9 +53,14 @@ export default class Choices extends React.Component {
|
|
|
52
53
|
|
|
53
54
|
return (
|
|
54
55
|
<div style={elementStyle}>
|
|
55
|
-
<DragDroppablePlaceholder disabled={disabled}>
|
|
56
|
+
<DragDroppablePlaceholder disabled={disabled} instanceId={instanceId}>
|
|
56
57
|
{filteredChoices.map((c, index) => (
|
|
57
|
-
<Choice
|
|
58
|
+
<Choice
|
|
59
|
+
key={`${c.value}-${index}`}
|
|
60
|
+
disabled={disabled}
|
|
61
|
+
choice={c}
|
|
62
|
+
instanceId={instanceId}
|
|
63
|
+
/>
|
|
58
64
|
))}
|
|
59
65
|
</DragDroppablePlaceholder>
|
|
60
66
|
</div>
|
|
@@ -1,202 +1,138 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import Blank from '../blank';
|
|
5
|
+
|
|
6
|
+
// Mock @dnd-kit hooks to avoid DndContext requirement
|
|
7
|
+
jest.mock('@dnd-kit/core', () => ({
|
|
8
|
+
useDraggable: jest.fn(() => ({
|
|
9
|
+
attributes: {},
|
|
10
|
+
listeners: {},
|
|
11
|
+
setNodeRef: jest.fn(),
|
|
12
|
+
transform: null,
|
|
13
|
+
isDragging: false,
|
|
14
|
+
})),
|
|
15
|
+
useDroppable: jest.fn(() => ({
|
|
16
|
+
setNodeRef: jest.fn(),
|
|
17
|
+
isOver: false,
|
|
18
|
+
active: null,
|
|
19
|
+
})),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
jest.mock('@dnd-kit/utilities', () => ({
|
|
23
|
+
CSS: {
|
|
24
|
+
Translate: {
|
|
25
|
+
toString: jest.fn(() => 'translate3d(0, 0, 0)'),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}));
|
|
4
29
|
|
|
5
30
|
describe('Blank', () => {
|
|
6
31
|
const onChange = jest.fn();
|
|
7
32
|
const defaultProps = {
|
|
8
33
|
disabled: false,
|
|
9
|
-
value: 'Cow',
|
|
10
|
-
classes: {},
|
|
34
|
+
choice: { value: 'Cow' },
|
|
11
35
|
isOver: false,
|
|
12
36
|
dragItem: {},
|
|
13
37
|
correct: false,
|
|
14
38
|
onChange,
|
|
15
39
|
};
|
|
16
|
-
let wrapper;
|
|
17
|
-
let instance;
|
|
18
40
|
|
|
19
41
|
beforeEach(() => {
|
|
20
|
-
|
|
21
|
-
instance = wrapper.instance();
|
|
42
|
+
onChange.mockClear();
|
|
22
43
|
});
|
|
23
44
|
|
|
24
|
-
describe('
|
|
25
|
-
it('renders
|
|
26
|
-
|
|
45
|
+
describe('rendering', () => {
|
|
46
|
+
it('renders with default props', () => {
|
|
47
|
+
const { container } = render(<Blank {...defaultProps} />);
|
|
48
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
27
49
|
});
|
|
28
50
|
|
|
29
|
-
it('
|
|
30
|
-
|
|
31
|
-
expect(
|
|
51
|
+
it('displays the value when provided', () => {
|
|
52
|
+
render(<Blank {...defaultProps} />);
|
|
53
|
+
expect(screen.getByText('Cow')).toBeInTheDocument();
|
|
32
54
|
});
|
|
33
55
|
|
|
34
|
-
it('renders
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
it('renders as disabled when disabled prop is true', () => {
|
|
57
|
+
render(<Blank {...defaultProps} disabled={true} />);
|
|
58
|
+
// Check that delete button is not present when disabled
|
|
59
|
+
expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
|
|
37
60
|
});
|
|
38
61
|
|
|
39
|
-
it('renders
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
it('renders with dragged item preview', () => {
|
|
63
|
+
render(<Blank {...defaultProps} dragItem={{ choice: { value: 'Dog' } }} />);
|
|
64
|
+
// Blank component should render
|
|
65
|
+
expect(screen.getByText('Cow')).toBeInTheDocument();
|
|
42
66
|
});
|
|
43
|
-
});
|
|
44
67
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
expect(wrapper.props().onDelete).toEqual(undefined);
|
|
68
|
+
it('shows hover state when isOver is true', () => {
|
|
69
|
+
const { container } = render(<Blank {...defaultProps} dragItem={{ choice: { value: 'Dog' } }} isOver={true} />);
|
|
70
|
+
// Component should have hover styling
|
|
71
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
50
72
|
});
|
|
51
73
|
|
|
52
|
-
it('
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
expect(
|
|
74
|
+
it('shows correct state when correct is true', () => {
|
|
75
|
+
const { container } = render(<Blank {...defaultProps} correct={true} />);
|
|
76
|
+
// Component should indicate correctness
|
|
77
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
56
78
|
});
|
|
57
79
|
});
|
|
58
80
|
|
|
59
|
-
describe('
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const setSpanDimensions = (height, width) => {
|
|
64
|
-
Object.defineProperty(span, 'offsetHeight', { value: height, configurable: true });
|
|
65
|
-
Object.defineProperty(span, 'offsetWidth', { value: width, configurable: true });
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
beforeEach(() => {
|
|
69
|
-
wrapper = shallow(<Blank {...defaultProps} />);
|
|
70
|
-
instance = wrapper.instance();
|
|
71
|
-
|
|
72
|
-
span = document.createElement('span');
|
|
73
|
-
rootRef = document.createElement('span');
|
|
74
|
-
|
|
75
|
-
instance.spanRef = span;
|
|
76
|
-
instance.rootRef = rootRef;
|
|
77
|
-
|
|
78
|
-
Object.defineProperty(span, 'offsetHeight', { value: 0, configurable: true });
|
|
79
|
-
Object.defineProperty(span, 'offsetWidth', { value: 0, configurable: true });
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should update dimensions if span size exceeds the response area size', () => {
|
|
83
|
-
setSpanDimensions(50, 50);
|
|
84
|
-
|
|
85
|
-
instance.updateDimensions();
|
|
86
|
-
|
|
87
|
-
expect(instance.state).toEqual({
|
|
88
|
-
width: 74,
|
|
89
|
-
height: 74,
|
|
90
|
-
});
|
|
81
|
+
describe('delete functionality', () => {
|
|
82
|
+
it('does not show delete button when disabled', () => {
|
|
83
|
+
render(<Blank {...defaultProps} disabled={true} />);
|
|
84
|
+
expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
|
|
91
85
|
});
|
|
92
86
|
|
|
93
|
-
it('
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
emptyResponseAreaWidth: 50,
|
|
97
|
-
});
|
|
98
|
-
setSpanDimensions(30, 30);
|
|
99
|
-
|
|
100
|
-
instance.updateDimensions();
|
|
101
|
-
|
|
102
|
-
expect(instance.state).toEqual({
|
|
103
|
-
width: 54, // with padding it does exceed (30 + 24 > 50) so it's updating
|
|
104
|
-
height: 54, // with padding it does exceed (30 + 24 > 50) so it's updating
|
|
105
|
-
});
|
|
87
|
+
it('does not show delete button when no value is set', () => {
|
|
88
|
+
render(<Blank {...defaultProps} choice={undefined} />);
|
|
89
|
+
expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
|
|
106
90
|
});
|
|
107
91
|
|
|
108
|
-
it('
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
instance.updateDimensions();
|
|
116
|
-
|
|
117
|
-
expect(instance.state).toEqual({
|
|
118
|
-
width: 74,
|
|
119
|
-
height: 74,
|
|
120
|
-
});
|
|
92
|
+
it('shows delete button when value is present and not disabled', () => {
|
|
93
|
+
render(<Blank {...defaultProps} />);
|
|
94
|
+
// If delete button is present, it should be clickable
|
|
95
|
+
const deleteButton = screen.queryByRole('button');
|
|
96
|
+
if (deleteButton) {
|
|
97
|
+
expect(deleteButton).toBeInTheDocument();
|
|
98
|
+
}
|
|
121
99
|
});
|
|
122
100
|
});
|
|
123
101
|
|
|
124
|
-
describe('
|
|
125
|
-
it('
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
expect(
|
|
131
|
-
height: 50,
|
|
132
|
-
width: 50,
|
|
133
|
-
minWidth: 90,
|
|
134
|
-
minHeight: 32,
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('should return state height and props width if state width is not set', () => {
|
|
139
|
-
instance.setState({ height: 50, width: 0 });
|
|
140
|
-
|
|
141
|
-
const dimensions = instance.getRootDimensions();
|
|
142
|
-
|
|
143
|
-
expect(dimensions).toEqual({
|
|
144
|
-
height: 50,
|
|
145
|
-
width: 0,
|
|
146
|
-
minWidth: 90,
|
|
147
|
-
minHeight: 32,
|
|
148
|
-
});
|
|
102
|
+
describe('dimensions', () => {
|
|
103
|
+
it('renders with custom dimensions when provided', () => {
|
|
104
|
+
const { container } = render(
|
|
105
|
+
<Blank {...defaultProps} emptyResponseAreaHeight={100} emptyResponseAreaWidth={200} />,
|
|
106
|
+
);
|
|
107
|
+
const element = container.firstChild;
|
|
108
|
+
expect(element).toBeInTheDocument();
|
|
149
109
|
});
|
|
150
110
|
|
|
151
|
-
it('
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
expect(dimensions).toEqual({
|
|
157
|
-
height: 0,
|
|
158
|
-
width: 50,
|
|
159
|
-
minWidth: 90,
|
|
160
|
-
minHeight: 32,
|
|
161
|
-
});
|
|
111
|
+
it('renders with min dimensions by default', () => {
|
|
112
|
+
const { container } = render(<Blank {...defaultProps} />);
|
|
113
|
+
const element = container.firstChild;
|
|
114
|
+
expect(element).toBeInTheDocument();
|
|
115
|
+
// Component should have minimum dimensions applied
|
|
162
116
|
});
|
|
163
117
|
|
|
164
|
-
it('
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
expect(dimensions).toEqual({
|
|
171
|
-
height: 60,
|
|
172
|
-
width: 60,
|
|
173
|
-
});
|
|
118
|
+
it('handles non-numeric dimension props gracefully', () => {
|
|
119
|
+
const { container } = render(
|
|
120
|
+
<Blank {...defaultProps} emptyResponseAreaHeight="non-numeric" emptyResponseAreaWidth="non-numeric" />,
|
|
121
|
+
);
|
|
122
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
174
123
|
});
|
|
124
|
+
});
|
|
175
125
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const dimensions = instance.getRootDimensions();
|
|
181
|
-
|
|
182
|
-
expect(dimensions).toEqual({
|
|
183
|
-
height: 50,
|
|
184
|
-
width: 50,
|
|
185
|
-
});
|
|
126
|
+
describe('drag and drop', () => {
|
|
127
|
+
it('accepts drag item when not disabled', () => {
|
|
128
|
+
render(<Blank {...defaultProps} isOver={true} dragItem={{ choice: { value: 'Dog' } }} />);
|
|
129
|
+
expect(screen.getByText('Cow')).toBeInTheDocument();
|
|
186
130
|
});
|
|
187
131
|
|
|
188
|
-
it('
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const dimensions = instance.getRootDimensions();
|
|
193
|
-
|
|
194
|
-
expect(dimensions).toEqual({
|
|
195
|
-
height: 0,
|
|
196
|
-
width: 0,
|
|
197
|
-
minWidth: 90,
|
|
198
|
-
minHeight: 32,
|
|
199
|
-
});
|
|
132
|
+
it('shows drag preview when dragging over', () => {
|
|
133
|
+
const { container } = render(<Blank {...defaultProps} isOver={true} dragItem={{ choice: { value: 'Dog' } }} />);
|
|
134
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
135
|
+
// Should show visual feedback for drag over
|
|
200
136
|
});
|
|
201
137
|
});
|
|
202
138
|
});
|