@griddo/ax 1.74.26 → 1.74.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 +2 -2
- package/src/__tests__/components/ActionMenu/ActionMenu.test.tsx +246 -0
- package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +48 -12
- package/src/__tests__/components/InformativeMenu/InformativeMenu.test.tsx +94 -0
- package/src/__tests__/components/ProgressBar/ProgressBar.test.tsx +27 -0
- package/src/__tests__/components/SideModal/SideModal.test.tsx +356 -0
- package/src/components/ActionMenu/index.tsx +3 -3
- package/src/components/ConfigPanel/index.tsx +0 -1
- package/src/components/Fields/ColorPicker/Picker/index.tsx +25 -31
- package/src/components/Fields/ColorPicker/helpers.tsx +36 -1
- package/src/components/Fields/ColorPicker/index.tsx +53 -31
- package/src/components/InformativeMenu/index.tsx +3 -3
- package/src/components/ProgressBar/index.tsx +2 -2
- package/src/components/SideModal/SideModalOption/index.tsx +1 -1
- package/src/components/SideModal/index.tsx +17 -10
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "1.74.
|
|
4
|
+
"version": "1.74.28",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -229,5 +229,5 @@
|
|
|
229
229
|
"publishConfig": {
|
|
230
230
|
"access": "public"
|
|
231
231
|
},
|
|
232
|
-
"gitHead": "
|
|
232
|
+
"gitHead": "47481a72f6d2927cfe008c79221793f0ea08e19c"
|
|
233
233
|
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { render, cleanup, screen, fireEvent } from "@testing-library/react";
|
|
4
|
+
import "@testing-library/jest-dom";
|
|
5
|
+
|
|
6
|
+
import { parseTheme } from "@ax/helpers";
|
|
7
|
+
import ActionMenu, { IActionMenuProps } from "@ax/components/ActionMenu";
|
|
8
|
+
import globalTheme from "@ax/themes/theme.json";
|
|
9
|
+
|
|
10
|
+
afterEach(cleanup);
|
|
11
|
+
|
|
12
|
+
describe("Action menu component rendering", () => {
|
|
13
|
+
it("should render the component with options hidden", () => {
|
|
14
|
+
const defaultProps: IActionMenuProps = {
|
|
15
|
+
icon: "more",
|
|
16
|
+
options: [
|
|
17
|
+
{
|
|
18
|
+
label: "Option 1",
|
|
19
|
+
icon: "modified",
|
|
20
|
+
action: jest.fn(),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
label: "Option 2",
|
|
24
|
+
icon: "active",
|
|
25
|
+
action: jest.fn(),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
render(
|
|
31
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
32
|
+
<ActionMenu {...defaultProps} />
|
|
33
|
+
</ThemeProvider>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
|
|
37
|
+
expect(actionMenuWrapper).toBeTruthy();
|
|
38
|
+
const menuItems = screen.queryAllByTestId("action-menu-item");
|
|
39
|
+
expect(menuItems.length).toBe(0);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("Action menu events", () => {
|
|
44
|
+
it("should show the component with 2 options on icon click", () => {
|
|
45
|
+
const defaultProps: IActionMenuProps = {
|
|
46
|
+
icon: "more",
|
|
47
|
+
options: [
|
|
48
|
+
{
|
|
49
|
+
label: "Option 1",
|
|
50
|
+
icon: "modified",
|
|
51
|
+
action: jest.fn(),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
label: "Option 2",
|
|
55
|
+
icon: "active",
|
|
56
|
+
action: jest.fn(),
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
render(
|
|
62
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
63
|
+
<ActionMenu {...defaultProps} />
|
|
64
|
+
</ThemeProvider>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
|
|
68
|
+
expect(actionMenuWrapper).toBeTruthy();
|
|
69
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
70
|
+
expect(iconAction).toBeTruthy();
|
|
71
|
+
fireEvent.click(iconAction);
|
|
72
|
+
|
|
73
|
+
const menuItems = screen.getAllByTestId("action-menu-item");
|
|
74
|
+
expect(menuItems.length).toBe(2);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should show the component with option with helptext", () => {
|
|
78
|
+
const helpText = "this is the helptext";
|
|
79
|
+
const defaultProps: IActionMenuProps = {
|
|
80
|
+
icon: "more",
|
|
81
|
+
options: [
|
|
82
|
+
{
|
|
83
|
+
label: "Option 1",
|
|
84
|
+
icon: "modified",
|
|
85
|
+
action: jest.fn(),
|
|
86
|
+
helpText,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
render(
|
|
92
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
93
|
+
<ActionMenu {...defaultProps} />
|
|
94
|
+
</ThemeProvider>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
|
|
98
|
+
expect(actionMenuWrapper).toBeTruthy();
|
|
99
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
100
|
+
expect(iconAction).toBeTruthy();
|
|
101
|
+
fireEvent.click(iconAction);
|
|
102
|
+
|
|
103
|
+
const helpTextComponent = screen.getByText(helpText);
|
|
104
|
+
expect(helpTextComponent).toBeTruthy();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should show the component with option with original class", () => {
|
|
108
|
+
const defaultProps: IActionMenuProps = {
|
|
109
|
+
icon: "more",
|
|
110
|
+
options: [
|
|
111
|
+
{
|
|
112
|
+
label: "Option 1",
|
|
113
|
+
icon: "modified",
|
|
114
|
+
action: jest.fn(),
|
|
115
|
+
color: true,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: "Option 2",
|
|
119
|
+
icon: "active",
|
|
120
|
+
action: jest.fn(),
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
render(
|
|
126
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
127
|
+
<ActionMenu {...defaultProps} />
|
|
128
|
+
</ThemeProvider>
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
|
|
132
|
+
expect(actionMenuWrapper).toBeTruthy();
|
|
133
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
134
|
+
expect(iconAction).toBeTruthy();
|
|
135
|
+
fireEvent.click(iconAction);
|
|
136
|
+
const menuItems = screen.getAllByTestId("action-menu-item");
|
|
137
|
+
|
|
138
|
+
expect(menuItems[0]).toHaveClass("original");
|
|
139
|
+
expect(menuItems[1]).not.toHaveClass("original");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should hide the component on second icon click", () => {
|
|
143
|
+
const defaultProps: IActionMenuProps = {
|
|
144
|
+
icon: "more",
|
|
145
|
+
options: [
|
|
146
|
+
{
|
|
147
|
+
label: "Option 1",
|
|
148
|
+
icon: "modified",
|
|
149
|
+
action: jest.fn(),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
label: "Option 2",
|
|
153
|
+
icon: "active",
|
|
154
|
+
action: jest.fn(),
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
render(
|
|
160
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
161
|
+
<ActionMenu {...defaultProps} />
|
|
162
|
+
</ThemeProvider>
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
|
|
166
|
+
expect(actionMenuWrapper).toBeTruthy();
|
|
167
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
168
|
+
expect(iconAction).toBeTruthy();
|
|
169
|
+
fireEvent.click(iconAction);
|
|
170
|
+
|
|
171
|
+
const menuItems = screen.getAllByTestId("action-menu-item");
|
|
172
|
+
expect(menuItems.length).toBe(2);
|
|
173
|
+
|
|
174
|
+
fireEvent.click(iconAction);
|
|
175
|
+
|
|
176
|
+
const menuItems2 = screen.queryAllByTestId("action-menu-item");
|
|
177
|
+
expect(menuItems2.length).toBe(0);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should call action on item click and hide component", () => {
|
|
181
|
+
const actionMock = jest.fn();
|
|
182
|
+
const defaultProps: IActionMenuProps = {
|
|
183
|
+
icon: "more",
|
|
184
|
+
options: [
|
|
185
|
+
{
|
|
186
|
+
label: "Option 1",
|
|
187
|
+
icon: "modified",
|
|
188
|
+
action: actionMock,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
render(
|
|
194
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
195
|
+
<ActionMenu {...defaultProps} />
|
|
196
|
+
</ThemeProvider>
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
200
|
+
fireEvent.click(iconAction);
|
|
201
|
+
|
|
202
|
+
const menuItems = screen.getAllByTestId("action-menu-item");
|
|
203
|
+
expect(menuItems.length).toBe(1);
|
|
204
|
+
fireEvent.click(menuItems[0]);
|
|
205
|
+
|
|
206
|
+
expect(actionMock).toBeCalledTimes(1);
|
|
207
|
+
|
|
208
|
+
const menuItems2 = screen.queryAllByTestId("action-menu-item");
|
|
209
|
+
expect(menuItems2.length).toBe(0);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("should show disabled item", () => {
|
|
213
|
+
const actionMock = jest.fn();
|
|
214
|
+
const defaultProps: IActionMenuProps = {
|
|
215
|
+
icon: "more",
|
|
216
|
+
options: [
|
|
217
|
+
{
|
|
218
|
+
label: "Option 1",
|
|
219
|
+
icon: "modified",
|
|
220
|
+
action: actionMock,
|
|
221
|
+
disabled: true,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
label: "Option 2",
|
|
225
|
+
icon: "active",
|
|
226
|
+
action: jest.fn(),
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
render(
|
|
232
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
233
|
+
<ActionMenu {...defaultProps} />
|
|
234
|
+
</ThemeProvider>
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
238
|
+
fireEvent.click(iconAction);
|
|
239
|
+
|
|
240
|
+
const menuItems = screen.getAllByTestId("action-menu-item");
|
|
241
|
+
expect(menuItems.length).toBe(2);
|
|
242
|
+
|
|
243
|
+
expect(menuItems[0]).toHaveAttribute("disabled");
|
|
244
|
+
expect(menuItems[1]).not.toHaveAttribute("disabled");
|
|
245
|
+
});
|
|
246
|
+
});
|
|
@@ -11,8 +11,8 @@ afterEach(cleanup);
|
|
|
11
11
|
|
|
12
12
|
const defaultProps = mock<IProps>();
|
|
13
13
|
|
|
14
|
-
describe("
|
|
15
|
-
test("should render the component
|
|
14
|
+
describe("ColorPicker component rendering", () => {
|
|
15
|
+
test("should render the component ColorPicker", () => {
|
|
16
16
|
defaultProps.value = "#000000";
|
|
17
17
|
defaultProps.theme = parseTheme(globalTheme);
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ describe("AsyncSelect component rendering", () => {
|
|
|
21
21
|
<ColorPicker {...defaultProps} />
|
|
22
22
|
</ThemeProvider>
|
|
23
23
|
);
|
|
24
|
-
expect(screen.getByTestId("
|
|
24
|
+
expect(screen.getByTestId("color-picker-wrapper")).toBeTruthy();
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
test("should render the Picker", () => {
|
|
@@ -36,14 +36,50 @@ describe("AsyncSelect component rendering", () => {
|
|
|
36
36
|
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
37
37
|
expect(inputActionComponent).toBeTruthy();
|
|
38
38
|
fireEvent.click(inputActionComponent);
|
|
39
|
-
expect(screen.findByTestId("
|
|
39
|
+
expect(screen.findByTestId("picker-wrapper")).toBeTruthy();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("should not render the text input field if onlyFixedColors is true", () => {
|
|
43
|
+
defaultProps.theme = "griddo-default";
|
|
44
|
+
defaultProps.error = true;
|
|
45
|
+
defaultProps.onlyFixedColors = true;
|
|
46
|
+
defaultProps.colors = [
|
|
47
|
+
{
|
|
48
|
+
theme: "griddo-default",
|
|
49
|
+
options: [
|
|
50
|
+
{ name: "chart1", hex: "#d9e3f0" },
|
|
51
|
+
{ name: "chart2", hex: "#697689" },
|
|
52
|
+
{ name: "chart2", hex: "#37d67a" },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
theme: "griddo-alternative",
|
|
57
|
+
options: [
|
|
58
|
+
{ name: "chart1", hex: "#fffff" },
|
|
59
|
+
{ name: "chart2", hex: "#ddddd" },
|
|
60
|
+
{ name: "chart2", hex: "#00000" },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
render(
|
|
66
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
67
|
+
<ColorPicker {...defaultProps} />
|
|
68
|
+
</ThemeProvider>
|
|
69
|
+
);
|
|
70
|
+
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
71
|
+
expect(inputActionComponent).toBeTruthy();
|
|
72
|
+
fireEvent.click(inputActionComponent);
|
|
73
|
+
expect(screen.queryByTestId("input-picker")).not.toBeTruthy();
|
|
40
74
|
});
|
|
41
75
|
});
|
|
42
76
|
|
|
43
|
-
describe("
|
|
77
|
+
describe("ColorPicker events", () => {
|
|
44
78
|
test("should trigger the onChange", () => {
|
|
45
79
|
defaultProps.value = "#000000";
|
|
46
80
|
defaultProps.theme = parseTheme(globalTheme);
|
|
81
|
+
defaultProps.colors = ["#000000", "#d9e3f0", "#f47373", "#697689"];
|
|
82
|
+
defaultProps.onlyFixedColors = false;
|
|
47
83
|
const onChangeMock = defaultProps.onChange as jest.MockedFunction<(newColor: string) => void>;
|
|
48
84
|
|
|
49
85
|
render(
|
|
@@ -51,7 +87,7 @@ describe("AsyncSelect events", () => {
|
|
|
51
87
|
<ColorPicker {...defaultProps} />
|
|
52
88
|
</ThemeProvider>
|
|
53
89
|
);
|
|
54
|
-
const inputComponent = screen.getByTestId("
|
|
90
|
+
const inputComponent = screen.getByTestId("input-picker-wrapper");
|
|
55
91
|
expect(inputComponent).toBeTruthy();
|
|
56
92
|
fireEvent.change(inputComponent, { target: { value: 555 } });
|
|
57
93
|
expect(onChangeMock).not.toBeCalled();
|
|
@@ -73,7 +109,7 @@ describe("AsyncSelect events", () => {
|
|
|
73
109
|
<ColorPicker {...defaultProps} />
|
|
74
110
|
</ThemeProvider>
|
|
75
111
|
);
|
|
76
|
-
const inputComponent = screen.getByTestId("
|
|
112
|
+
const inputComponent = screen.getByTestId("input-picker-wrapper");
|
|
77
113
|
expect(inputComponent).toBeTruthy();
|
|
78
114
|
fireEvent.change(inputComponent, { target: { value: "#fff" } });
|
|
79
115
|
expect(handleValidationMock).toBeCalled();
|
|
@@ -93,7 +129,7 @@ describe("AsyncSelect events", () => {
|
|
|
93
129
|
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
94
130
|
expect(inputActionComponent).toBeTruthy();
|
|
95
131
|
fireEvent.click(inputActionComponent);
|
|
96
|
-
const inputPicker = await screen.findByTestId("
|
|
132
|
+
const inputPicker = await screen.findByTestId("input-picker");
|
|
97
133
|
expect(inputPicker).toBeTruthy();
|
|
98
134
|
fireEvent.change(inputPicker, { target: { value: "#fff" } });
|
|
99
135
|
expect(onChangeMock).toBeCalled();
|
|
@@ -114,7 +150,7 @@ describe("AsyncSelect events", () => {
|
|
|
114
150
|
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
115
151
|
expect(inputActionComponent).toBeTruthy();
|
|
116
152
|
fireEvent.click(inputActionComponent);
|
|
117
|
-
const inputPicker = await screen.findByTestId("
|
|
153
|
+
const inputPicker = await screen.findByTestId("input-picker");
|
|
118
154
|
expect(inputPicker).toBeTruthy();
|
|
119
155
|
fireEvent.change(inputPicker, { target: { value: "#fff" } });
|
|
120
156
|
expect(onChangeMock).toBeCalled();
|
|
@@ -138,7 +174,7 @@ describe("AsyncSelect events", () => {
|
|
|
138
174
|
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
139
175
|
expect(inputActionComponent).toBeTruthy();
|
|
140
176
|
fireEvent.click(inputActionComponent);
|
|
141
|
-
const gridItem = await screen.findAllByTestId("
|
|
177
|
+
const gridItem = await screen.findAllByTestId("grid-item");
|
|
142
178
|
// is getting the default colors
|
|
143
179
|
expect(gridItem).toHaveLength(9);
|
|
144
180
|
});
|
|
@@ -161,7 +197,7 @@ describe("AsyncSelect events", () => {
|
|
|
161
197
|
const inputActionComponent = screen.getByTestId("icon-action-component");
|
|
162
198
|
expect(inputActionComponent).toBeTruthy();
|
|
163
199
|
fireEvent.click(inputActionComponent);
|
|
164
|
-
const gridItem = await screen.findAllByTestId("
|
|
200
|
+
const gridItem = await screen.findAllByTestId("grid-item");
|
|
165
201
|
// it's getting the color passed
|
|
166
202
|
expect(gridItem).toHaveLength(1);
|
|
167
203
|
});
|
|
@@ -178,7 +214,7 @@ describe("AsyncSelect events", () => {
|
|
|
178
214
|
<ColorPicker {...defaultProps} />
|
|
179
215
|
</ThemeProvider>
|
|
180
216
|
);
|
|
181
|
-
const inputComponent = screen.getByTestId("
|
|
217
|
+
const inputComponent = screen.getByTestId("input-picker-wrapper");
|
|
182
218
|
expect(inputComponent).toBeTruthy();
|
|
183
219
|
fireEvent.blur(inputComponent, { target: { value: "#fff" } });
|
|
184
220
|
expect(handleValidationMock).toBeCalled();
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { render, cleanup, screen, fireEvent } from "@testing-library/react";
|
|
4
|
+
import "@testing-library/jest-dom";
|
|
5
|
+
|
|
6
|
+
import { parseTheme } from "@ax/helpers";
|
|
7
|
+
import InformativeMenu, { IInformativeMenuProps } from "@ax/components/InformativeMenu";
|
|
8
|
+
import globalTheme from "@ax/themes/theme.json";
|
|
9
|
+
|
|
10
|
+
afterEach(cleanup);
|
|
11
|
+
|
|
12
|
+
describe("Informative Menu component rendering", () => {
|
|
13
|
+
it("should render the component hidden", () => {
|
|
14
|
+
const defaultProps: IInformativeMenuProps = {
|
|
15
|
+
message: "This is the message",
|
|
16
|
+
icon: "alert",
|
|
17
|
+
actionText: "Got it",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
render(
|
|
21
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
22
|
+
<InformativeMenu {...defaultProps} />
|
|
23
|
+
</ThemeProvider>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
expect(screen.queryByText(defaultProps.message)).toBeFalsy();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should render the component with message on mouse enter", () => {
|
|
30
|
+
const defaultProps: IInformativeMenuProps = {
|
|
31
|
+
message: "This is the message",
|
|
32
|
+
icon: "alert",
|
|
33
|
+
actionText: "Got it",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
render(
|
|
37
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
38
|
+
<InformativeMenu {...defaultProps} />
|
|
39
|
+
</ThemeProvider>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
43
|
+
expect(iconAction).toBeTruthy();
|
|
44
|
+
fireEvent.mouseEnter(iconAction);
|
|
45
|
+
const componentText = screen.getByText(defaultProps.message);
|
|
46
|
+
expect(componentText).toBeTruthy();
|
|
47
|
+
const button = screen.getByText(defaultProps.actionText).closest("button");
|
|
48
|
+
expect(button).toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should hide the component with message on mouse leave", () => {
|
|
52
|
+
const defaultProps: IInformativeMenuProps = {
|
|
53
|
+
message: "This is the message",
|
|
54
|
+
icon: "alert",
|
|
55
|
+
actionText: "Got it",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
render(
|
|
59
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
60
|
+
<InformativeMenu {...defaultProps} />
|
|
61
|
+
</ThemeProvider>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
65
|
+
expect(iconAction).toBeTruthy();
|
|
66
|
+
fireEvent.mouseEnter(iconAction);
|
|
67
|
+
expect(screen.getByText(defaultProps.message)).toBeTruthy();
|
|
68
|
+
fireEvent.mouseLeave(iconAction);
|
|
69
|
+
expect(screen.queryByText(defaultProps.message)).toBeFalsy();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should hide the component on button click", () => {
|
|
73
|
+
const defaultProps: IInformativeMenuProps = {
|
|
74
|
+
message: "This is the message",
|
|
75
|
+
icon: "alert",
|
|
76
|
+
actionText: "Got it",
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
render(
|
|
80
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
81
|
+
<InformativeMenu {...defaultProps} />
|
|
82
|
+
</ThemeProvider>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const iconAction = screen.getByTestId("icon-action-component");
|
|
86
|
+
expect(iconAction).toBeTruthy();
|
|
87
|
+
fireEvent.mouseEnter(iconAction);
|
|
88
|
+
expect(screen.getByText(defaultProps.message)).toBeTruthy();
|
|
89
|
+
const button = screen.getByText(defaultProps.actionText).closest("button");
|
|
90
|
+
expect(button).toBeTruthy();
|
|
91
|
+
button && fireEvent.click(button);
|
|
92
|
+
expect(screen.queryByText(defaultProps.message)).toBeFalsy();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { render, cleanup, screen } from "@testing-library/react";
|
|
4
|
+
import "@testing-library/jest-dom";
|
|
5
|
+
|
|
6
|
+
import { parseTheme } from "@ax/helpers";
|
|
7
|
+
import ProgressBar, { IProgressBarProps } from "@ax/components/ProgressBar";
|
|
8
|
+
import globalTheme from "@ax/themes/theme.json";
|
|
9
|
+
|
|
10
|
+
afterEach(cleanup);
|
|
11
|
+
|
|
12
|
+
describe("ProgressBar component rendering", () => {
|
|
13
|
+
it("should render the component", () => {
|
|
14
|
+
const defaultProps: IProgressBarProps = {
|
|
15
|
+
percentage: 0,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
render(
|
|
19
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
20
|
+
<ProgressBar {...defaultProps} />
|
|
21
|
+
</ThemeProvider>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const tracker = screen.getByTestId("progressbar-tracker");
|
|
25
|
+
expect(tracker).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { ThemeProvider } from "styled-components";
|
|
4
|
+
import { CalledWithMock, mock } from "jest-mock-extended";
|
|
5
|
+
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
|
|
6
|
+
import { parseTheme } from "@ax/helpers";
|
|
7
|
+
|
|
8
|
+
import SideModal, { ISideModalProps } from "@ax/components/SideModal";
|
|
9
|
+
import globalTheme from "@ax/themes/theme.json";
|
|
10
|
+
|
|
11
|
+
afterEach(cleanup);
|
|
12
|
+
|
|
13
|
+
const defaultProps = mock<ISideModalProps>();
|
|
14
|
+
|
|
15
|
+
describe("SideModal component rendering", () => {
|
|
16
|
+
it("should render the component", () => {
|
|
17
|
+
const handleClickMock = jest.fn();
|
|
18
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
19
|
+
defaultProps.categories = [
|
|
20
|
+
{ featured: true, label: "All", value: "all" },
|
|
21
|
+
{ label: "Articles And Events", value: "articlesAndEvents" },
|
|
22
|
+
];
|
|
23
|
+
defaultProps.isOpen = true;
|
|
24
|
+
defaultProps.theme = "default-theme";
|
|
25
|
+
defaultProps.whiteList = ["EventsDistributor", "ArticlesDistributor"];
|
|
26
|
+
defaultProps.handleClick = handleClickMock;
|
|
27
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
28
|
+
defaultProps.optionsType = "modules";
|
|
29
|
+
|
|
30
|
+
render(
|
|
31
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
32
|
+
<SideModal {...defaultProps} />
|
|
33
|
+
</ThemeProvider>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const sideModal = screen.getByTestId("side-modal");
|
|
37
|
+
expect(sideModal).toBeTruthy();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should not render the component if isOpen is false", () => {
|
|
41
|
+
const handleClickMock = jest.fn();
|
|
42
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
43
|
+
defaultProps.categories = [
|
|
44
|
+
{ featured: true, label: "All", value: "all" },
|
|
45
|
+
{ label: "Articles And Events", value: "articlesAndEvents" },
|
|
46
|
+
];
|
|
47
|
+
defaultProps.isOpen = false;
|
|
48
|
+
defaultProps.theme = "default-theme";
|
|
49
|
+
defaultProps.whiteList = ["EventsDistributor", "ArticlesDistributor"];
|
|
50
|
+
defaultProps.handleClick = handleClickMock;
|
|
51
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
52
|
+
defaultProps.optionsType = "modules";
|
|
53
|
+
|
|
54
|
+
render(
|
|
55
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
56
|
+
<SideModal {...defaultProps} />
|
|
57
|
+
</ThemeProvider>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const sideModal = screen.queryByTestId("side-modal");
|
|
61
|
+
expect(sideModal).not.toBeTruthy();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should render optiontype as title", () => {
|
|
65
|
+
defaultProps.isOpen = true;
|
|
66
|
+
render(
|
|
67
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
68
|
+
<SideModal {...defaultProps} />
|
|
69
|
+
</ThemeProvider>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const sideModalTitle = screen.getByTestId("side-modal-title");
|
|
73
|
+
expect(sideModalTitle).toBeTruthy();
|
|
74
|
+
expect(sideModalTitle.textContent).toEqual("modules");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should render close button", () => {
|
|
78
|
+
render(
|
|
79
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
80
|
+
<SideModal {...defaultProps} />
|
|
81
|
+
</ThemeProvider>
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const closeButton = screen.getByTestId("side-modal-close-button");
|
|
85
|
+
expect(closeButton).toBeTruthy();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should render default check if setDefault prop exists", () => {
|
|
89
|
+
defaultProps.setDefault = {
|
|
90
|
+
action: jest.fn(),
|
|
91
|
+
checked: false,
|
|
92
|
+
title: "Set the default header",
|
|
93
|
+
};
|
|
94
|
+
render(
|
|
95
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
96
|
+
<SideModal {...defaultProps} />
|
|
97
|
+
</ThemeProvider>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const checkfield = screen.getByTestId("check-field-wrapper");
|
|
101
|
+
expect(checkfield).toBeTruthy();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should render options", () => {
|
|
105
|
+
defaultProps.setDefault = undefined;
|
|
106
|
+
render(
|
|
107
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
108
|
+
<SideModal {...defaultProps} />
|
|
109
|
+
</ThemeProvider>
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
113
|
+
expect(options).toBeTruthy();
|
|
114
|
+
expect(options.length).toEqual(2);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("should render option thumbnails", () => {
|
|
118
|
+
render(
|
|
119
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
120
|
+
<SideModal {...defaultProps} />
|
|
121
|
+
</ThemeProvider>
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const thumbnails = screen.getAllByTestId("side-modal-option-img");
|
|
125
|
+
expect(thumbnails).toBeTruthy();
|
|
126
|
+
expect(thumbnails.length).toEqual(2);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("should render all options when All filter is selected", () => {
|
|
130
|
+
const handleClickMock = jest.fn();
|
|
131
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
132
|
+
defaultProps.categories = [
|
|
133
|
+
{ featured: true, label: "All", value: "all" },
|
|
134
|
+
{ label: "Content", value: "content" },
|
|
135
|
+
{ label: "Collections", value: "collections" },
|
|
136
|
+
];
|
|
137
|
+
defaultProps.isOpen = true;
|
|
138
|
+
defaultProps.theme = "default-theme";
|
|
139
|
+
defaultProps.whiteList = ["BasicContent", "CardCollection"];
|
|
140
|
+
defaultProps.handleClick = handleClickMock;
|
|
141
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
142
|
+
defaultProps.optionsType = "modules";
|
|
143
|
+
|
|
144
|
+
render(
|
|
145
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
146
|
+
<SideModal {...defaultProps} />
|
|
147
|
+
</ThemeProvider>
|
|
148
|
+
);
|
|
149
|
+
const filters = screen.getAllByTestId("side-modal-nav-link");
|
|
150
|
+
expect(filters).toBeTruthy();
|
|
151
|
+
expect(filters.length).toEqual(3);
|
|
152
|
+
const allFilter = filters[0];
|
|
153
|
+
expect(allFilter.textContent).toEqual("All");
|
|
154
|
+
const links = screen.getAllByTestId("side-modal-link");
|
|
155
|
+
const allOptionLink = links[0];
|
|
156
|
+
const selectedStyles = getComputedStyle(allOptionLink);
|
|
157
|
+
expect(selectedStyles.color).toEqual("rgb(32, 34, 76)");
|
|
158
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
159
|
+
expect(options).toBeTruthy();
|
|
160
|
+
expect(options.length).toEqual(2);
|
|
161
|
+
expect(options[0].textContent).toEqual("Basic Content");
|
|
162
|
+
expect(options[1].textContent).toEqual("Card Collection");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("should render components modal if option type is components", () => {
|
|
166
|
+
const handleClickMock = jest.fn();
|
|
167
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
168
|
+
defaultProps.componentOptions = {
|
|
169
|
+
image: { component: "LinkableImage", editorID: 11, parentEditorID: 6 },
|
|
170
|
+
video: { component: "Video", editorID: 12, parentEditorID: 6 },
|
|
171
|
+
};
|
|
172
|
+
defaultProps.isOpen = true;
|
|
173
|
+
defaultProps.theme = "default-theme";
|
|
174
|
+
defaultProps.whiteList = ["LinkableImage", "Video"];
|
|
175
|
+
defaultProps.handleClick = handleClickMock;
|
|
176
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
177
|
+
defaultProps.optionsType = "components";
|
|
178
|
+
|
|
179
|
+
render(
|
|
180
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
181
|
+
<SideModal {...defaultProps} />
|
|
182
|
+
</ThemeProvider>
|
|
183
|
+
);
|
|
184
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
185
|
+
expect(options).toBeTruthy();
|
|
186
|
+
expect(options.length).toEqual(2);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe("SideModal component events", () => {
|
|
191
|
+
it("should call handle click and toggle modal on click option", () => {
|
|
192
|
+
const handleClickMock = jest.fn();
|
|
193
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
194
|
+
defaultProps.categories = [
|
|
195
|
+
{ featured: true, label: "All", value: "all" },
|
|
196
|
+
{ label: "Articles And Events", value: "articlesAndEvents" },
|
|
197
|
+
];
|
|
198
|
+
defaultProps.componentOptions = undefined;
|
|
199
|
+
defaultProps.isOpen = true;
|
|
200
|
+
defaultProps.theme = "default-theme";
|
|
201
|
+
defaultProps.whiteList = ["Accordion", "AddressCollection"];
|
|
202
|
+
defaultProps.handleClick = handleClickMock;
|
|
203
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
204
|
+
defaultProps.optionsType = "modules";
|
|
205
|
+
|
|
206
|
+
render(
|
|
207
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
208
|
+
<SideModal {...defaultProps} />
|
|
209
|
+
</ThemeProvider>
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
213
|
+
expect(options).toBeTruthy();
|
|
214
|
+
expect(options.length).toEqual(2);
|
|
215
|
+
const option = options[0];
|
|
216
|
+
fireEvent.click(option);
|
|
217
|
+
expect(handleClickMock).toHaveBeenCalled();
|
|
218
|
+
expect(toggleModalMock).toHaveBeenCalled();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("should select filter on click", () => {
|
|
222
|
+
const handleClickMock = jest.fn();
|
|
223
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
224
|
+
defaultProps.categories = [
|
|
225
|
+
{ featured: true, label: "All", value: "all" },
|
|
226
|
+
{ label: "Content", value: "content" },
|
|
227
|
+
{ label: "Collections", value: "collections" },
|
|
228
|
+
];
|
|
229
|
+
defaultProps.isOpen = true;
|
|
230
|
+
defaultProps.theme = "default-theme";
|
|
231
|
+
defaultProps.whiteList = ["BasicContent", "CardCollection"];
|
|
232
|
+
defaultProps.handleClick = handleClickMock;
|
|
233
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
234
|
+
defaultProps.optionsType = "modules";
|
|
235
|
+
|
|
236
|
+
render(
|
|
237
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
238
|
+
<SideModal {...defaultProps} />
|
|
239
|
+
</ThemeProvider>
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const filters = screen.getAllByTestId("side-modal-nav-link");
|
|
243
|
+
expect(filters).toBeTruthy();
|
|
244
|
+
expect(filters.length).toEqual(3);
|
|
245
|
+
const allFilter = filters[0];
|
|
246
|
+
const contentFilter = filters[1];
|
|
247
|
+
expect(allFilter.textContent).toEqual("All");
|
|
248
|
+
expect(contentFilter.textContent).toEqual("Content");
|
|
249
|
+
const links = screen.getAllByTestId("side-modal-link");
|
|
250
|
+
expect(links).toBeTruthy();
|
|
251
|
+
expect(links.length).toEqual(3);
|
|
252
|
+
const contentOptionLink = links[1];
|
|
253
|
+
const notSelectedStyles = getComputedStyle(contentOptionLink);
|
|
254
|
+
expect(notSelectedStyles.color).toEqual("rgba(32, 34, 76, 0.6)");
|
|
255
|
+
fireEvent.click(contentFilter);
|
|
256
|
+
const selectedStyles = getComputedStyle(contentOptionLink);
|
|
257
|
+
expect(selectedStyles.color).toEqual("rgb(32, 34, 76)");
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it("should filter by category on click", () => {
|
|
261
|
+
const handleClickMock = jest.fn();
|
|
262
|
+
const toggleModalMock = jest.fn() as CalledWithMock<void, []> & (() => void);
|
|
263
|
+
defaultProps.categories = [
|
|
264
|
+
{ featured: true, label: "All", value: "all" },
|
|
265
|
+
{ label: "Content", value: "content" },
|
|
266
|
+
{ label: "Collections", value: "collections" },
|
|
267
|
+
];
|
|
268
|
+
defaultProps.isOpen = true;
|
|
269
|
+
defaultProps.theme = "default-theme";
|
|
270
|
+
defaultProps.whiteList = ["BasicContent", "CardCollection"];
|
|
271
|
+
defaultProps.handleClick = handleClickMock;
|
|
272
|
+
defaultProps.toggleModal = toggleModalMock;
|
|
273
|
+
defaultProps.optionsType = "modules";
|
|
274
|
+
|
|
275
|
+
render(
|
|
276
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
277
|
+
<SideModal {...defaultProps} />
|
|
278
|
+
</ThemeProvider>
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const filters = screen.getAllByTestId("side-modal-nav-link");
|
|
282
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
283
|
+
expect(options.length).toEqual(2);
|
|
284
|
+
expect(filters).toBeTruthy();
|
|
285
|
+
expect(filters.length).toEqual(3);
|
|
286
|
+
const contentFilter = filters[1];
|
|
287
|
+
expect(contentFilter.textContent).toEqual("Content");
|
|
288
|
+
fireEvent.click(contentFilter);
|
|
289
|
+
expect(options.length).toEqual(2);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("should filter by query", () => {
|
|
293
|
+
defaultProps.showSearch = true;
|
|
294
|
+
|
|
295
|
+
render(
|
|
296
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
297
|
+
<SideModal {...defaultProps} />
|
|
298
|
+
</ThemeProvider>
|
|
299
|
+
);
|
|
300
|
+
const filterButton = screen.getByTestId("icon-search-wrapper");
|
|
301
|
+
|
|
302
|
+
expect(filterButton).toBeTruthy();
|
|
303
|
+
fireEvent.click(filterButton);
|
|
304
|
+
const searchFieldWrapper = screen.getByTestId("search-field-wrapper");
|
|
305
|
+
expect(searchFieldWrapper).toBeTruthy();
|
|
306
|
+
const input = screen.getByTestId("search-input");
|
|
307
|
+
fireEvent.click(searchFieldWrapper);
|
|
308
|
+
fireEvent.change(input, { target: { value: "Basic content" } });
|
|
309
|
+
fireEvent.keyDown(input, { key: "Enter", code: "Enter", charCode: 13 });
|
|
310
|
+
const options = screen.getAllByTestId("side-modal-option");
|
|
311
|
+
expect(options.length).toEqual(1);
|
|
312
|
+
expect(options[0].textContent).toEqual("Basic Content");
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("should call toggle modal on click outside the modal", () => {
|
|
316
|
+
const map: any = {};
|
|
317
|
+
|
|
318
|
+
document.addEventListener = jest.fn((event, callback) => {
|
|
319
|
+
map[event] = callback;
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
render(
|
|
323
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
324
|
+
<SideModal {...defaultProps} />
|
|
325
|
+
</ThemeProvider>
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
map.mousedown({
|
|
329
|
+
target: document.body,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
expect(defaultProps.toggleModal).toHaveBeenCalled();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it("should not call toggle modal on click inside the modal", () => {
|
|
336
|
+
const map: any = {};
|
|
337
|
+
|
|
338
|
+
document.addEventListener = jest.fn((event, callback) => {
|
|
339
|
+
map[event] = callback;
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
render(
|
|
343
|
+
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
344
|
+
<SideModal {...defaultProps} />
|
|
345
|
+
</ThemeProvider>
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const title = screen.getByTestId("side-modal-title");
|
|
349
|
+
|
|
350
|
+
map.mousedown({
|
|
351
|
+
target: title,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(defaultProps.toggleModal).not.toHaveBeenCalled();
|
|
355
|
+
});
|
|
356
|
+
});
|
|
@@ -4,7 +4,7 @@ import { FloatingMenu, Icon, IconAction, Tooltip } from "@ax/components";
|
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const ActionMenu = (props:
|
|
7
|
+
const ActionMenu = (props: IActionMenuProps): JSX.Element => {
|
|
8
8
|
const { options, icon, className, tooltip } = props;
|
|
9
9
|
|
|
10
10
|
const MoreInfoButton = () => (
|
|
@@ -32,7 +32,7 @@ const ActionMenu = (props: IProps): JSX.Element => {
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<S.Wrapper className={className}>
|
|
35
|
+
<S.Wrapper className={className} data-testid="action-menu-wrapper">
|
|
36
36
|
<Tooltip content={tooltip} hideOnClick>
|
|
37
37
|
<FloatingMenu Button={MoreInfoButton}>
|
|
38
38
|
<S.ActionMenu>{options.map((item: IOption) => ActionMenuItem(item))}</S.ActionMenu>
|
|
@@ -51,7 +51,7 @@ interface IOption {
|
|
|
51
51
|
color?: boolean;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
interface
|
|
54
|
+
export interface IActionMenuProps {
|
|
55
55
|
options: IOption[];
|
|
56
56
|
icon: string;
|
|
57
57
|
className?: string;
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
-
import { hex3to6 } from "
|
|
2
|
+
import { hex3to6, defaultColors } from "./../helpers";
|
|
3
3
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const Picker = (props: IProps): JSX.Element => {
|
|
7
|
-
const { value, onChange, colors } = props;
|
|
8
|
-
|
|
7
|
+
const { value, onChange, colors, onlyFixedColors } = props;
|
|
9
8
|
const [color, setColor] = useState(value);
|
|
10
9
|
const [inputValue, setInputValue] = useState(value);
|
|
11
10
|
|
|
12
|
-
const defaultColors = [
|
|
13
|
-
"#d9e3f0",
|
|
14
|
-
"#f47373",
|
|
15
|
-
"#697689",
|
|
16
|
-
"#37d67a",
|
|
17
|
-
"#2ccce4",
|
|
18
|
-
"#555555",
|
|
19
|
-
"#dce775",
|
|
20
|
-
"#ff8a65",
|
|
21
|
-
"#ba68c8",
|
|
22
|
-
];
|
|
23
|
-
|
|
24
11
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
25
12
|
let newValue = e.target.value;
|
|
26
13
|
setInputValue(newValue);
|
|
@@ -38,9 +25,10 @@ const Picker = (props: IProps): JSX.Element => {
|
|
|
38
25
|
}
|
|
39
26
|
};
|
|
40
27
|
|
|
41
|
-
const handleClick = (newColor: string) => () => {
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
const handleClick = (newColor: string | any ) => () => {
|
|
29
|
+
const gridColor = typeof newColor !== "object" ? newColor : newColor.hex;
|
|
30
|
+
setInputValue(gridColor);
|
|
31
|
+
setColor(gridColor);
|
|
44
32
|
onChange(newColor);
|
|
45
33
|
};
|
|
46
34
|
|
|
@@ -57,24 +45,29 @@ const Picker = (props: IProps): JSX.Element => {
|
|
|
57
45
|
const gridColors = colors ? colors : defaultColors;
|
|
58
46
|
|
|
59
47
|
return (
|
|
60
|
-
<S.Wrapper data-testid="
|
|
48
|
+
<S.Wrapper data-testid="picker-wrapper">
|
|
61
49
|
<S.Cover background={color} light={isLight(color)}>
|
|
62
50
|
{color}
|
|
63
51
|
</S.Cover>
|
|
64
52
|
<S.Grid>
|
|
65
|
-
{gridColors.map((item:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
53
|
+
{gridColors.map((item: any) => {
|
|
54
|
+
const gridColor = typeof item === "object" ? item.hex : item;
|
|
55
|
+
return (
|
|
56
|
+
<S.GridItem
|
|
57
|
+
data-testid="grid-item"
|
|
58
|
+
key={gridColor}
|
|
59
|
+
background={gridColor}
|
|
60
|
+
onClick={handleClick(item)}
|
|
61
|
+
selected={gridColor === color}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
})}
|
|
74
65
|
</S.Grid>
|
|
75
|
-
|
|
76
|
-
<S.
|
|
77
|
-
|
|
66
|
+
{!onlyFixedColors ? (
|
|
67
|
+
<S.InputWrapper>
|
|
68
|
+
<S.Input data-testid="input-picker" type="text" value={inputValue} onChange={handleChange} />
|
|
69
|
+
</S.InputWrapper>
|
|
70
|
+
) : null}
|
|
78
71
|
</S.Wrapper>
|
|
79
72
|
);
|
|
80
73
|
};
|
|
@@ -83,6 +76,7 @@ export interface IProps {
|
|
|
83
76
|
value: string;
|
|
84
77
|
colors?: string[];
|
|
85
78
|
onChange: (newColor: string) => void;
|
|
79
|
+
onlyFixedColors?: boolean;
|
|
86
80
|
}
|
|
87
81
|
|
|
88
82
|
export default Picker;
|
|
@@ -3,4 +3,39 @@ const hex3to6 = (color: string) => {
|
|
|
3
3
|
return "#" + hexcolor.split('').map((hex: string) => hex + hex).join('');
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const defaultOptions = (vusOptions: Record<string, unknown>[]) => {
|
|
7
|
+
return !vusOptions.find((entry) => entry.theme);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const defaultColors = [
|
|
11
|
+
"#d9e3f0",
|
|
12
|
+
"#f47373",
|
|
13
|
+
"#697689",
|
|
14
|
+
"#37d67a",
|
|
15
|
+
"#2ccce4",
|
|
16
|
+
"#555555",
|
|
17
|
+
"#dce775",
|
|
18
|
+
"#ff8a65",
|
|
19
|
+
"#ba68c8",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const getOptions = (theme: string, onlyFixedColors: boolean | undefined, colorOptions: any[] | undefined) => {
|
|
23
|
+
if (!colorOptions) return defaultColors;
|
|
24
|
+
if (onlyFixedColors) return colorOptions;
|
|
25
|
+
|
|
26
|
+
const themes = colorOptions.filter((entry) => entry.theme).map((entry) => entry.theme);
|
|
27
|
+
const themeExists = themes.includes(theme);
|
|
28
|
+
const defaultsOptions = colorOptions.filter((entry) => typeof entry === "string");
|
|
29
|
+
|
|
30
|
+
// 1 - Si options solo tiene las defaults options (legacy) devuelve las defaults.
|
|
31
|
+
// 2 - Si options no tiene el theme, devuelve las defaults.
|
|
32
|
+
if (defaultOptions(colorOptions) || !themeExists) return defaultsOptions;
|
|
33
|
+
|
|
34
|
+
// Si options tiene el theme, devuelve las options de ese theme.
|
|
35
|
+
const optionsObj = colorOptions.find((entry) => entry.theme === theme);
|
|
36
|
+
|
|
37
|
+
return optionsObj && optionsObj.options;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export { hex3to6, getOptions, defaultColors };
|
|
@@ -2,18 +2,48 @@ import React, { useRef, useState, memo, useReducer, useCallback } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { useHandleClickOutside } from "@ax/hooks";
|
|
4
4
|
import { IconAction } from "@ax/components";
|
|
5
|
+
import { defaultColors, getOptions, hex3to6 } from "./helpers";
|
|
5
6
|
import Picker from "./Picker";
|
|
6
|
-
import { hex3to6 } from "./helpers";
|
|
7
7
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
10
10
|
const ColorPicker = (props: IProps): JSX.Element => {
|
|
11
|
-
const { value, onChange, error, colors, handleValidation, theme } = props;
|
|
11
|
+
const { value, onChange, error, colors = [], handleValidation, theme, onlyFixedColors } = props;
|
|
12
|
+
|
|
13
|
+
const getCurrentColors = () => {
|
|
14
|
+
if (onlyFixedColors) {
|
|
15
|
+
const currentOption = colors?.find((options: any) => options.theme === theme);
|
|
16
|
+
return currentOption ? currentOption?.options : defaultColors;
|
|
17
|
+
} else {
|
|
18
|
+
return colors.length ? colors : defaultColors;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
12
21
|
|
|
13
|
-
const
|
|
22
|
+
const currentColors = getCurrentColors();
|
|
23
|
+
|
|
24
|
+
const getInitialState = () => {
|
|
25
|
+
const defaultColor = currentColors[0];
|
|
26
|
+
if (onlyFixedColors) {
|
|
27
|
+
const currentValue = currentColors.find((color: any) => color.name === value);
|
|
28
|
+
const isObject = typeof defaultColor === "object";
|
|
29
|
+
|
|
30
|
+
let color;
|
|
31
|
+
if (currentValue) {
|
|
32
|
+
color = isObject ? currentValue.hex : currentValue;
|
|
33
|
+
} else {
|
|
34
|
+
color = isObject ? defaultColor.hex : defaultColor;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { color, inputValue: color };
|
|
38
|
+
} else {
|
|
39
|
+
const color = value ? value : defaultColor;
|
|
40
|
+
return { color, inputValue: color };
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const initialState = getInitialState();
|
|
14
45
|
const reducer = useCallback((state: any, payload: any) => ({ ...state, ...payload }), []);
|
|
15
46
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
16
|
-
|
|
17
47
|
const [isVisible, setIsVisible] = useState(false);
|
|
18
48
|
const wrapper = useRef<HTMLDivElement>(null);
|
|
19
49
|
|
|
@@ -44,9 +74,12 @@ const ColorPicker = (props: IProps): JSX.Element => {
|
|
|
44
74
|
error && handleValidation && handleValidation(inputValue, { colorHex: true });
|
|
45
75
|
};
|
|
46
76
|
|
|
47
|
-
const handlePickerChange = (
|
|
48
|
-
|
|
49
|
-
|
|
77
|
+
const handlePickerChange = (value: string | any) => {
|
|
78
|
+
const isObject = typeof value === "object";
|
|
79
|
+
const hex = !isObject ? value : value.hex;
|
|
80
|
+
const name = !isObject ? value : value.name;
|
|
81
|
+
dispatch({ color: hex, inputValue: hex });
|
|
82
|
+
onChange(name);
|
|
50
83
|
};
|
|
51
84
|
|
|
52
85
|
const handleOnBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
@@ -57,44 +90,32 @@ const ColorPicker = (props: IProps): JSX.Element => {
|
|
|
57
90
|
|
|
58
91
|
const icon = isVisible ? "close" : "colorPicker";
|
|
59
92
|
|
|
60
|
-
const defaultOptions = (vusOptions: Record<string, unknown>[]) => {
|
|
61
|
-
return !vusOptions.find((entry) => entry.theme);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const getOptions = (theme: string, colorOptions: any[] | undefined) => {
|
|
65
|
-
if (!colorOptions) return undefined;
|
|
66
|
-
|
|
67
|
-
const themes = colorOptions.filter((entry) => entry.theme).map((entry) => entry.theme);
|
|
68
|
-
const themeExists = themes.includes(theme);
|
|
69
|
-
const defaultsOptions = colorOptions.filter((entry) => typeof entry === "string");
|
|
70
|
-
|
|
71
|
-
// 1 - Si options solo tiene las defaults options (legacy) devuelve las defaults.
|
|
72
|
-
// 2 - Si options no tiene el theme, devuelve las defaults.
|
|
73
|
-
if (defaultOptions(colorOptions) || !themeExists) return defaultsOptions;
|
|
74
|
-
|
|
75
|
-
// Si options tiene el theme, devuelve las options de ese theme.
|
|
76
|
-
const optionsObj = colorOptions.find((entry) => entry.theme === theme);
|
|
77
|
-
return optionsObj && optionsObj.options;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
93
|
return (
|
|
81
|
-
<S.Wrapper ref={wrapper} data-testid="
|
|
94
|
+
<S.Wrapper ref={wrapper} data-testid="color-picker-wrapper">
|
|
82
95
|
<S.InputWrapper>
|
|
83
96
|
<S.ColorWrapper background={state.color} />
|
|
84
97
|
<S.Input
|
|
85
|
-
data-testid="
|
|
98
|
+
data-testid="input-picker-wrapper"
|
|
86
99
|
type="text"
|
|
87
100
|
value={state.inputValue}
|
|
88
101
|
onChange={handleInputChange}
|
|
89
102
|
error={error}
|
|
90
103
|
placeholder="#FFFFFF"
|
|
91
104
|
onBlur={handleOnBlur}
|
|
105
|
+
readOnly={onlyFixedColors}
|
|
92
106
|
/>
|
|
93
107
|
<S.IconWrapper>
|
|
94
108
|
<IconAction icon={icon} size="s" onClick={togglePicker} />
|
|
95
109
|
</S.IconWrapper>
|
|
96
110
|
</S.InputWrapper>
|
|
97
|
-
{isVisible &&
|
|
111
|
+
{isVisible && (
|
|
112
|
+
<Picker
|
|
113
|
+
value={state.color}
|
|
114
|
+
onChange={handlePickerChange}
|
|
115
|
+
colors={getOptions(theme, onlyFixedColors, currentColors)}
|
|
116
|
+
onlyFixedColors={onlyFixedColors}
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
98
119
|
</S.Wrapper>
|
|
99
120
|
);
|
|
100
121
|
};
|
|
@@ -102,10 +123,11 @@ const ColorPicker = (props: IProps): JSX.Element => {
|
|
|
102
123
|
export interface IProps {
|
|
103
124
|
value: string;
|
|
104
125
|
error?: boolean;
|
|
105
|
-
colors?: string[] | Record<string, unknown>[];
|
|
126
|
+
colors?: string[] | Record<string, unknown>[] | any[];
|
|
106
127
|
onChange: (newColor: string) => void;
|
|
107
128
|
handleValidation?: (value: string, validators: Record<string, unknown>) => void;
|
|
108
129
|
theme: string;
|
|
130
|
+
onlyFixedColors?: boolean;
|
|
109
131
|
}
|
|
110
132
|
|
|
111
133
|
export default memo(ColorPicker);
|
|
@@ -4,7 +4,7 @@ import { Button, FloatingMenu, IconAction } from "@ax/components";
|
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const InformativeMenu = (props:
|
|
7
|
+
const InformativeMenu = (props: IInformativeMenuProps): JSX.Element => {
|
|
8
8
|
const { icon, message, actionText, iconSize, position } = props;
|
|
9
9
|
|
|
10
10
|
const InfoButton = () => <IconAction icon={icon} size={iconSize} />;
|
|
@@ -25,11 +25,11 @@ const InformativeMenu = (props: IProps): JSX.Element => {
|
|
|
25
25
|
);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
interface
|
|
28
|
+
export interface IInformativeMenuProps {
|
|
29
29
|
icon: string;
|
|
30
30
|
message: string;
|
|
31
31
|
actionText: string;
|
|
32
|
-
iconSize?: "s" | "m"
|
|
32
|
+
iconSize?: "s" | "m";
|
|
33
33
|
position?: string;
|
|
34
34
|
}
|
|
35
35
|
export default InformativeMenu;
|
|
@@ -10,13 +10,13 @@ const ProgressBar = (props: IProgressBarProps): JSX.Element => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
return (
|
|
13
|
-
<S.Tracker>
|
|
13
|
+
<S.Tracker data-testid="progressbar-tracker">
|
|
14
14
|
<S.ProgressInTracker percentage={percentageLimits(0, percentage, 100)} />
|
|
15
15
|
</S.Tracker>
|
|
16
16
|
);
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
interface IProgressBarProps {
|
|
19
|
+
export interface IProgressBarProps {
|
|
20
20
|
percentage: number;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -28,7 +28,7 @@ const SideModalOption = (props: IProps) => {
|
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
30
|
<S.Item onClick={setOption} data-testid="side-modal-option">
|
|
31
|
-
<S.Thumbnail {...thumbnailProps} />
|
|
31
|
+
<S.Thumbnail data-testid="side-modal-option-img" {...thumbnailProps} />
|
|
32
32
|
{label}
|
|
33
33
|
</S.Item>
|
|
34
34
|
);
|
|
@@ -58,13 +58,19 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
58
58
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
59
59
|
}, [current, whiteList]);
|
|
60
60
|
|
|
61
|
+
const handleToggleModal = () => {
|
|
62
|
+
setSearchQuery("");
|
|
63
|
+
toggleModal();
|
|
64
|
+
};
|
|
65
|
+
|
|
61
66
|
const node = useRef<any>(null);
|
|
67
|
+
|
|
62
68
|
const handleClickOutside = (e: any) => {
|
|
63
69
|
if (node.current.contains(e.target)) {
|
|
64
70
|
return;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
|
|
73
|
+
handleToggleModal();
|
|
68
74
|
};
|
|
69
75
|
|
|
70
76
|
useHandleClickOutside(isOpen, handleClickOutside);
|
|
@@ -87,8 +93,10 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
87
93
|
|
|
88
94
|
return (
|
|
89
95
|
<MenuItem key={`${value}${i}`} active={isSelected}>
|
|
90
|
-
<S.NavLink onClick={filterOptions}>
|
|
91
|
-
<S.Link active={isSelected}>
|
|
96
|
+
<S.NavLink onClick={filterOptions} data-testid="side-modal-nav-link">
|
|
97
|
+
<S.Link data-testid="side-modal-link" active={isSelected}>
|
|
98
|
+
{label}
|
|
99
|
+
</S.Link>
|
|
92
100
|
</S.NavLink>
|
|
93
101
|
</MenuItem>
|
|
94
102
|
);
|
|
@@ -115,7 +123,6 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
115
123
|
const filteredOptions =
|
|
116
124
|
options.options &&
|
|
117
125
|
options.options.map((option: any, i: number) => {
|
|
118
|
-
if (typeof option !== "object" && typeof option !== "string") return null;
|
|
119
126
|
const displayName = getDisplayName(option.component ? option.component : option);
|
|
120
127
|
if (searchQuery.length > 0) {
|
|
121
128
|
const name = displayName.toLowerCase();
|
|
@@ -126,7 +133,7 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
126
133
|
<SideModalOption
|
|
127
134
|
option={option}
|
|
128
135
|
handleClick={handleClick}
|
|
129
|
-
toggleModal={
|
|
136
|
+
toggleModal={handleToggleModal}
|
|
130
137
|
key={`${option}${i}`}
|
|
131
138
|
theme={theme}
|
|
132
139
|
>
|
|
@@ -139,20 +146,20 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
139
146
|
? createPortal(
|
|
140
147
|
<S.Wrapper ref={node} optionsType={optionsType} data-testid="side-modal">
|
|
141
148
|
<S.Header>
|
|
142
|
-
<S.Title>{optionsType}</S.Title>
|
|
149
|
+
<S.Title data-testid="side-modal-title">{optionsType}</S.Title>
|
|
143
150
|
{showSearch && optionsType !== "components" && (
|
|
144
151
|
<S.SearchWrapper>
|
|
145
152
|
<SearchField onChange={setSearchQuery} closeOnInactive />
|
|
146
153
|
</S.SearchWrapper>
|
|
147
154
|
)}
|
|
148
155
|
{!showSearch && (
|
|
149
|
-
<S.ButtonWrapper>
|
|
150
|
-
<IconAction icon="close" onClick={
|
|
156
|
+
<S.ButtonWrapper data-testid="side-modal-close-button">
|
|
157
|
+
<IconAction icon="close" onClick={handleToggleModal} />
|
|
151
158
|
</S.ButtonWrapper>
|
|
152
159
|
)}
|
|
153
160
|
</S.Header>
|
|
154
161
|
{setDefault && !setDefault.checked && (
|
|
155
|
-
<S.CheckFieldWrapper>
|
|
162
|
+
<S.CheckFieldWrapper data-testid="check-field-wrapper">
|
|
156
163
|
<CheckField
|
|
157
164
|
name="setDefault"
|
|
158
165
|
value="setDefault"
|
|
@@ -177,7 +184,7 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
|
|
|
177
184
|
: null;
|
|
178
185
|
};
|
|
179
186
|
|
|
180
|
-
interface ISideModalProps {
|
|
187
|
+
export interface ISideModalProps {
|
|
181
188
|
isOpen: boolean;
|
|
182
189
|
whiteList: string[] | undefined;
|
|
183
190
|
categories?: ModuleCategoryInfo[];
|