goobs-frontend 0.8.27 → 0.8.28
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/package.json +8 -18
- package/src/components/Content/Structure/projectboard/useProjectBoard.tsx +1 -1
- package/src/components/MultiSelect/index.tsx +245 -0
- package/src/components/MultiSelect/multiselect.stories.tsx +129 -0
- package/src/components/ProjectBoard/board/desktop/index.tsx +348 -0
- package/src/components/ProjectBoard/board/index.tsx +43 -0
- package/src/components/ProjectBoard/board/mobile/index.tsx +364 -0
- package/src/components/ProjectBoard/board/tablet/index.tsx +355 -0
- package/src/components/ProjectBoard/{AddTask → forms/AddTask}/client.tsx +3 -3
- package/src/components/ProjectBoard/{ManageTask → forms/ManageTask}/client.tsx +4 -4
- package/src/components/ProjectBoard/forms/ShowTask/client.tsx +809 -0
- package/src/components/ProjectBoard/index.tsx +73 -152
- package/src/components/ProjectBoard/jotai/atom.ts +9 -0
- package/src/components/ProjectBoard/projectboard.stories.tsx +8 -3
- package/src/components/ProjectBoard/utils/useDragandDrop/columns.tsx +19 -13
- package/src/components/ProjectBoard/utils/useDragandDrop/tasks.tsx +53 -121
- package/src/components/SearchableDropdown/index.tsx +52 -20
- package/src/components/SearchableDropdown/searchabledropdown.stories.tsx +5 -0
- package/src/components/Searchbar/index.tsx +40 -15
- package/src/components/Toolbar/leftCenter/index.tsx +9 -3
- package/src/index.ts +8 -4
- package/src/components/ProjectBoard/Column/index.tsx +0 -595
- package/src/components/ProjectBoard/ShowTask/client.tsx +0 -434
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A comprehensive React-based UI library built on Material-UI, offering a wide range of customizable components including grids, typography, buttons, cards, forms, navigation, pricing tables, steppers, tooltips, accordions, and more. Designed for building responsive and consistent user interfaces with advanced features like form validation, theming, and code syntax highlighting.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
|
60
60
|
"@typescript-eslint/parser": "^8.21.0",
|
|
61
61
|
"chromatic": "^11.25.1",
|
|
62
|
-
"eslint": "^9.
|
|
62
|
+
"eslint": "^9.19.0",
|
|
63
63
|
"eslint-config-next": "^15.1.6",
|
|
64
64
|
"eslint-config-prettier": "^10.0.1",
|
|
65
65
|
"eslint-plugin-prettier": "^5.2.3",
|
|
@@ -92,26 +92,17 @@
|
|
|
92
92
|
"node.js",
|
|
93
93
|
"formData",
|
|
94
94
|
"form",
|
|
95
|
-
"form-validation",
|
|
96
|
-
"form-submission",
|
|
97
95
|
"button",
|
|
98
96
|
"grid",
|
|
99
97
|
"responsive",
|
|
100
|
-
"flexgrid",
|
|
101
98
|
"typography",
|
|
102
|
-
"
|
|
103
|
-
"styled-component",
|
|
104
|
-
"input-component",
|
|
105
|
-
"input-validation",
|
|
106
|
-
"button-validation",
|
|
107
|
-
"form-validation",
|
|
99
|
+
"button",
|
|
108
100
|
"searchbar",
|
|
109
101
|
"dropdown",
|
|
110
|
-
"
|
|
102
|
+
"complexeditor",
|
|
111
103
|
"textfield",
|
|
112
104
|
"phonenumber",
|
|
113
105
|
"password",
|
|
114
|
-
"email",
|
|
115
106
|
"number",
|
|
116
107
|
"card",
|
|
117
108
|
"pricing-table",
|
|
@@ -120,20 +111,19 @@
|
|
|
120
111
|
"tooltip",
|
|
121
112
|
"accordion",
|
|
122
113
|
"code-copy",
|
|
123
|
-
"syntax-highlighting",
|
|
124
|
-
"theming",
|
|
125
114
|
"customizable-components",
|
|
126
115
|
"react-components",
|
|
127
116
|
"ui-library",
|
|
128
|
-
"design-system",
|
|
129
117
|
"front-end",
|
|
130
|
-
"user-interface",
|
|
131
118
|
"responsive-design",
|
|
132
119
|
"typescript"
|
|
133
120
|
],
|
|
134
121
|
"resolutions": {
|
|
135
122
|
"string-width": "^4.2.3",
|
|
136
|
-
"strip-ansi": "^6.0.1"
|
|
123
|
+
"strip-ansi": "^6.0.1",
|
|
124
|
+
"webpack": "^5.0.0",
|
|
125
|
+
"glob": "^9.0.0",
|
|
126
|
+
"rimraf": "^4.0.0"
|
|
137
127
|
},
|
|
138
128
|
"eslintConfig": {
|
|
139
129
|
"extends": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import ProjectBoard from '../../../ProjectBoard'
|
|
3
|
+
import ProjectBoard from '../../../ProjectBoard/'
|
|
4
4
|
import { ProjectBoardProps } from '../../../ProjectBoard/types'
|
|
5
5
|
import { columnconfig, cellconfig } from '../../../Grid'
|
|
6
6
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Theme, useTheme, styled, SxProps, alpha } from '@mui/material/styles'
|
|
3
|
+
import Box from '@mui/material/Box'
|
|
4
|
+
import OutlinedInput from '@mui/material/OutlinedInput'
|
|
5
|
+
import InputLabel from '@mui/material/InputLabel'
|
|
6
|
+
import MenuItem from '@mui/material/MenuItem'
|
|
7
|
+
import FormControl, { FormControlProps } from '@mui/material/FormControl'
|
|
8
|
+
import Select, { SelectChangeEvent } from '@mui/material/Select'
|
|
9
|
+
import Chip from '@mui/material/Chip'
|
|
10
|
+
|
|
11
|
+
export interface MultiSelectChipProps
|
|
12
|
+
extends Omit<FormControlProps, 'onChange'> {
|
|
13
|
+
label?: React.ReactNode
|
|
14
|
+
options?: string[]
|
|
15
|
+
defaultSelected?: string[]
|
|
16
|
+
onChange?: (values: string[]) => void
|
|
17
|
+
|
|
18
|
+
backgroundcolor?: string
|
|
19
|
+
outlinecolor?: string
|
|
20
|
+
fontcolor?: string
|
|
21
|
+
inputfontcolor?: string
|
|
22
|
+
shrunkfontcolor?: string
|
|
23
|
+
unshrunkfontcolor?: string
|
|
24
|
+
placeholdercolor?: string
|
|
25
|
+
|
|
26
|
+
shrunklabelposition?: 'onNotch' | 'aboveNotch'
|
|
27
|
+
sx?: SxProps
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const ITEM_HEIGHT = 40
|
|
31
|
+
const ITEM_PADDING_TOP = 8
|
|
32
|
+
const MenuProps = {
|
|
33
|
+
PaperProps: {
|
|
34
|
+
style: {
|
|
35
|
+
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
|
|
36
|
+
width: 250,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getStyles(
|
|
42
|
+
name: string,
|
|
43
|
+
selectedArray: readonly string[],
|
|
44
|
+
theme: Theme
|
|
45
|
+
) {
|
|
46
|
+
return {
|
|
47
|
+
fontWeight: selectedArray.includes(name)
|
|
48
|
+
? theme.typography.fontWeightMedium
|
|
49
|
+
: theme.typography.fontWeightRegular,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const StyledFormControl = styled(FormControl, {
|
|
54
|
+
shouldForwardProp: prop =>
|
|
55
|
+
![
|
|
56
|
+
'backgroundcolor',
|
|
57
|
+
'outlinecolor',
|
|
58
|
+
'fontcolor',
|
|
59
|
+
'inputfontcolor',
|
|
60
|
+
'shrunkfontcolor',
|
|
61
|
+
'unshrunkfontcolor',
|
|
62
|
+
'placeholdercolor',
|
|
63
|
+
'shrunklabelposition',
|
|
64
|
+
].includes(prop as string),
|
|
65
|
+
})<
|
|
66
|
+
Pick<
|
|
67
|
+
MultiSelectChipProps,
|
|
68
|
+
| 'backgroundcolor'
|
|
69
|
+
| 'outlinecolor'
|
|
70
|
+
| 'fontcolor'
|
|
71
|
+
| 'inputfontcolor'
|
|
72
|
+
| 'shrunkfontcolor'
|
|
73
|
+
| 'unshrunkfontcolor'
|
|
74
|
+
| 'placeholdercolor'
|
|
75
|
+
| 'shrunklabelposition'
|
|
76
|
+
> & { hasvalue: string }
|
|
77
|
+
>(
|
|
78
|
+
({
|
|
79
|
+
backgroundcolor,
|
|
80
|
+
outlinecolor,
|
|
81
|
+
fontcolor,
|
|
82
|
+
inputfontcolor,
|
|
83
|
+
shrunkfontcolor,
|
|
84
|
+
unshrunkfontcolor,
|
|
85
|
+
placeholdercolor,
|
|
86
|
+
shrunklabelposition,
|
|
87
|
+
hasvalue,
|
|
88
|
+
}) => ({
|
|
89
|
+
'& .MuiOutlinedInput-root': {
|
|
90
|
+
minHeight: '40px',
|
|
91
|
+
backgroundColor: backgroundcolor || 'inherit',
|
|
92
|
+
color: fontcolor || 'inherit',
|
|
93
|
+
'& fieldset': {
|
|
94
|
+
borderColor:
|
|
95
|
+
outlinecolor || (hasvalue === 'true' ? 'black' : 'rgba(0,0,0,0.23)'),
|
|
96
|
+
},
|
|
97
|
+
'&:hover fieldset': {
|
|
98
|
+
borderColor:
|
|
99
|
+
outlinecolor || (hasvalue === 'true' ? 'black' : 'rgba(0,0,0,0.23)'),
|
|
100
|
+
},
|
|
101
|
+
'&.Mui-focused fieldset': {
|
|
102
|
+
borderColor:
|
|
103
|
+
outlinecolor || (hasvalue === 'true' ? 'black' : 'rgba(0,0,0,0.23)'),
|
|
104
|
+
},
|
|
105
|
+
'& input': {
|
|
106
|
+
color: inputfontcolor || fontcolor || 'inherit',
|
|
107
|
+
'&::placeholder': {
|
|
108
|
+
color: placeholdercolor || alpha('#000', 0.54),
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
'& .MuiSelect-icon': {
|
|
112
|
+
color: inputfontcolor || fontcolor || 'inherit',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
'& .MuiInputLabel-root': {
|
|
116
|
+
color: unshrunkfontcolor || fontcolor || 'inherit',
|
|
117
|
+
'&.Mui-focused': {
|
|
118
|
+
color: shrunkfontcolor || fontcolor || 'inherit',
|
|
119
|
+
},
|
|
120
|
+
'&.MuiInputLabel-shrink': {
|
|
121
|
+
color: shrunkfontcolor || fontcolor || 'inherit',
|
|
122
|
+
...(shrunklabelposition === 'aboveNotch' && {
|
|
123
|
+
transform: 'translate(0px, -17px) scale(0.75)',
|
|
124
|
+
}),
|
|
125
|
+
...(shrunklabelposition === 'onNotch' && {
|
|
126
|
+
transform: 'translate(13px, -4px) scale(0.75)',
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
export default function MultipleSelectChip(props: MultiSelectChipProps) {
|
|
134
|
+
const {
|
|
135
|
+
label = 'Chip',
|
|
136
|
+
options = [],
|
|
137
|
+
defaultSelected = [],
|
|
138
|
+
onChange,
|
|
139
|
+
|
|
140
|
+
backgroundcolor,
|
|
141
|
+
outlinecolor,
|
|
142
|
+
fontcolor,
|
|
143
|
+
inputfontcolor,
|
|
144
|
+
shrunkfontcolor,
|
|
145
|
+
unshrunkfontcolor,
|
|
146
|
+
placeholdercolor,
|
|
147
|
+
shrunklabelposition,
|
|
148
|
+
|
|
149
|
+
sx,
|
|
150
|
+
...rest
|
|
151
|
+
} = props
|
|
152
|
+
|
|
153
|
+
const theme = useTheme()
|
|
154
|
+
const [selectedValues, setSelectedValues] =
|
|
155
|
+
React.useState<string[]>(defaultSelected)
|
|
156
|
+
|
|
157
|
+
const hasValue = React.useMemo(
|
|
158
|
+
() => (selectedValues.length > 0).toString(),
|
|
159
|
+
[selectedValues]
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const handleSelectChange = (
|
|
163
|
+
event: SelectChangeEvent<typeof selectedValues>
|
|
164
|
+
) => {
|
|
165
|
+
const { value } = event.target
|
|
166
|
+
const newValue = typeof value === 'string' ? value.split(',') : value
|
|
167
|
+
setSelectedValues(newValue)
|
|
168
|
+
if (onChange) {
|
|
169
|
+
onChange(newValue)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>
|
|
175
|
+
<StyledFormControl
|
|
176
|
+
sx={{ width: 300, ...sx }}
|
|
177
|
+
variant="outlined"
|
|
178
|
+
hasvalue={hasValue}
|
|
179
|
+
backgroundcolor={backgroundcolor}
|
|
180
|
+
outlinecolor={outlinecolor}
|
|
181
|
+
fontcolor={fontcolor}
|
|
182
|
+
inputfontcolor={inputfontcolor}
|
|
183
|
+
shrunkfontcolor={shrunkfontcolor}
|
|
184
|
+
unshrunkfontcolor={unshrunkfontcolor}
|
|
185
|
+
placeholdercolor={placeholdercolor}
|
|
186
|
+
shrunklabelposition={shrunklabelposition}
|
|
187
|
+
{...rest}
|
|
188
|
+
>
|
|
189
|
+
<InputLabel id="multi-select-chip-label">{label}</InputLabel>
|
|
190
|
+
<Select
|
|
191
|
+
labelId="multi-select-chip-label"
|
|
192
|
+
id="multi-select-chip"
|
|
193
|
+
multiple
|
|
194
|
+
/**
|
|
195
|
+
* Remove any fixed height. Let the
|
|
196
|
+
* OutlinedInput's styles control minHeight.
|
|
197
|
+
*/
|
|
198
|
+
value={selectedValues}
|
|
199
|
+
onChange={handleSelectChange}
|
|
200
|
+
input={
|
|
201
|
+
<OutlinedInput
|
|
202
|
+
label={label}
|
|
203
|
+
/**
|
|
204
|
+
* Give the input an initial minHeight (e.g. 55px),
|
|
205
|
+
* and allow it to wrap chips, thus expanding the height
|
|
206
|
+
*/
|
|
207
|
+
sx={{
|
|
208
|
+
minHeight: 55,
|
|
209
|
+
display: 'flex',
|
|
210
|
+
flexWrap: 'wrap',
|
|
211
|
+
gap: 0.5,
|
|
212
|
+
alignItems: 'center',
|
|
213
|
+
}}
|
|
214
|
+
placeholder={placeholdercolor ? (label as string) : undefined}
|
|
215
|
+
/>
|
|
216
|
+
}
|
|
217
|
+
renderValue={selected => (
|
|
218
|
+
<Box
|
|
219
|
+
sx={{
|
|
220
|
+
display: 'flex',
|
|
221
|
+
flexWrap: 'wrap',
|
|
222
|
+
gap: 0.5,
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
{selected.map(val => (
|
|
226
|
+
<Chip key={val} label={val} />
|
|
227
|
+
))}
|
|
228
|
+
</Box>
|
|
229
|
+
)}
|
|
230
|
+
MenuProps={MenuProps}
|
|
231
|
+
>
|
|
232
|
+
{options.map(name => (
|
|
233
|
+
<MenuItem
|
|
234
|
+
key={name}
|
|
235
|
+
value={name}
|
|
236
|
+
style={getStyles(name, selectedValues, theme)}
|
|
237
|
+
>
|
|
238
|
+
{name}
|
|
239
|
+
</MenuItem>
|
|
240
|
+
))}
|
|
241
|
+
</Select>
|
|
242
|
+
</StyledFormControl>
|
|
243
|
+
</Box>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
// If using the official SB testing library + jest:
|
|
3
|
+
// import { within, userEvent } from '@storybook/testing-library';
|
|
4
|
+
// import { expect } from '@storybook/jest';
|
|
5
|
+
//
|
|
6
|
+
// If you're using the same approach from your example:
|
|
7
|
+
import { within, userEvent, expect } from '@storybook/test'
|
|
8
|
+
|
|
9
|
+
import MultipleSelectChip from './index'
|
|
10
|
+
|
|
11
|
+
const meta: Meta<typeof MultipleSelectChip> = {
|
|
12
|
+
title: 'Components/MultiSelectChip',
|
|
13
|
+
component: MultipleSelectChip,
|
|
14
|
+
parameters: {
|
|
15
|
+
a11y: { disable: false },
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
export default meta
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<typeof MultipleSelectChip>
|
|
21
|
+
|
|
22
|
+
// Example data array
|
|
23
|
+
const NAMES = [
|
|
24
|
+
'Oliver Hansen',
|
|
25
|
+
'Van Henry',
|
|
26
|
+
'April Tucker',
|
|
27
|
+
'Ralph Hubbard',
|
|
28
|
+
'Omar Alexander',
|
|
29
|
+
'Carlos Abbott',
|
|
30
|
+
'Miriam Wagner',
|
|
31
|
+
'Bradley Wilkerson',
|
|
32
|
+
'Virginia Andrews',
|
|
33
|
+
'Kelly Snyder',
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 1) Basic usage - No preselected items.
|
|
38
|
+
*/
|
|
39
|
+
export const Basic: Story = {
|
|
40
|
+
name: 'Basic (Default)',
|
|
41
|
+
args: {
|
|
42
|
+
label: 'Select a Name',
|
|
43
|
+
options: NAMES,
|
|
44
|
+
defaultSelected: [],
|
|
45
|
+
},
|
|
46
|
+
play: async ({ canvasElement }) => {
|
|
47
|
+
const canvas = within(canvasElement)
|
|
48
|
+
|
|
49
|
+
// 1. Verify label is visible
|
|
50
|
+
expect(canvas.getByLabelText('Select a Name')).toBeInTheDocument()
|
|
51
|
+
|
|
52
|
+
// 2. Click the Select to open the dropdown
|
|
53
|
+
await userEvent.click(canvas.getByLabelText('Select a Name'))
|
|
54
|
+
|
|
55
|
+
// 3. Choose "Van Henry" from the list
|
|
56
|
+
await userEvent.click(canvas.getByText('Van Henry'))
|
|
57
|
+
|
|
58
|
+
// 4. Now "Van Henry" should appear as a chip
|
|
59
|
+
expect(canvas.getByText('Van Henry')).toBeInTheDocument()
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 2) PreSelected
|
|
65
|
+
*/
|
|
66
|
+
export const PreSelected: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
label: 'PreSelected Names',
|
|
69
|
+
options: NAMES,
|
|
70
|
+
defaultSelected: ['April Tucker', 'Omar Alexander'],
|
|
71
|
+
},
|
|
72
|
+
play: ({ canvasElement }) => {
|
|
73
|
+
const canvas = within(canvasElement)
|
|
74
|
+
// Both pre-selected chips should be shown
|
|
75
|
+
expect(canvas.getByText('April Tucker')).toBeInTheDocument()
|
|
76
|
+
expect(canvas.getByText('Omar Alexander')).toBeInTheDocument()
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 3) Multiple Selections
|
|
82
|
+
*/
|
|
83
|
+
export const MultipleSelections: Story = {
|
|
84
|
+
args: {
|
|
85
|
+
label: 'Pick Multiple',
|
|
86
|
+
options: NAMES,
|
|
87
|
+
defaultSelected: [],
|
|
88
|
+
},
|
|
89
|
+
play: async ({ canvasElement }) => {
|
|
90
|
+
const canvas = within(canvasElement)
|
|
91
|
+
|
|
92
|
+
// Open the menu
|
|
93
|
+
await userEvent.click(canvas.getByLabelText('Pick Multiple'))
|
|
94
|
+
// Select "Van Henry"
|
|
95
|
+
await userEvent.click(canvas.getByText('Van Henry'))
|
|
96
|
+
expect(canvas.getByText('Van Henry')).toBeInTheDocument()
|
|
97
|
+
|
|
98
|
+
// Menu closes after selection, so open again
|
|
99
|
+
await userEvent.click(canvas.getByLabelText('Pick Multiple'))
|
|
100
|
+
await userEvent.click(canvas.getByText('April Tucker'))
|
|
101
|
+
expect(canvas.getByText('April Tucker')).toBeInTheDocument()
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 4) Custom Styles - Example usage of props like backgroundcolor, outlinecolor, etc.
|
|
107
|
+
*/
|
|
108
|
+
export const CustomStyles: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
label: 'Custom Colors',
|
|
111
|
+
options: NAMES,
|
|
112
|
+
defaultSelected: ['Kelly Snyder'],
|
|
113
|
+
backgroundcolor: '#f3e5f5', // Light purple
|
|
114
|
+
outlinecolor: '#6a1b9a', // Dark purple
|
|
115
|
+
fontcolor: '#283593', // Indigo for text
|
|
116
|
+
},
|
|
117
|
+
play: async ({ canvasElement }) => {
|
|
118
|
+
const canvas = within(canvasElement)
|
|
119
|
+
|
|
120
|
+
// Confirm that Kelly Snyder is initially selected
|
|
121
|
+
expect(canvas.getByText('Kelly Snyder')).toBeInTheDocument()
|
|
122
|
+
|
|
123
|
+
// Let's open the menu and deselect
|
|
124
|
+
await userEvent.click(canvas.getByLabelText('Custom Colors'))
|
|
125
|
+
await userEvent.click(canvas.getByText('Kelly Snyder'))
|
|
126
|
+
|
|
127
|
+
expect(canvas.queryByText('Kelly Snyder')).not.toBeInTheDocument()
|
|
128
|
+
},
|
|
129
|
+
}
|