@axinom/mosaic-ui 0.32.0-rc.1 → 0.32.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/components/Actions/Action/Action.d.ts.map +1 -1
  2. package/dist/components/Actions/Actions.models.d.ts +4 -16
  3. package/dist/components/Actions/Actions.models.d.ts.map +1 -1
  4. package/dist/components/Buttons/Button/Button.d.ts +9 -10
  5. package/dist/components/Buttons/Button/Button.d.ts.map +1 -1
  6. package/dist/components/Buttons/Button/Button.model.d.ts +21 -0
  7. package/dist/components/Buttons/Button/Button.model.d.ts.map +1 -0
  8. package/dist/components/Buttons/Button/index.d.ts +3 -0
  9. package/dist/components/Buttons/Button/index.d.ts.map +1 -0
  10. package/dist/components/Buttons/Button.model.d.ts +69 -7
  11. package/dist/components/Buttons/Button.model.d.ts.map +1 -1
  12. package/dist/components/Buttons/CompositeButton/CompositeButton.d.ts +5 -14
  13. package/dist/components/Buttons/CompositeButton/CompositeButton.d.ts.map +1 -1
  14. package/dist/components/Buttons/CompositeButton/CompositeButton.model.d.ts +20 -0
  15. package/dist/components/Buttons/CompositeButton/CompositeButton.model.d.ts.map +1 -0
  16. package/dist/components/Buttons/CompositeButton/index.d.ts +3 -0
  17. package/dist/components/Buttons/CompositeButton/index.d.ts.map +1 -0
  18. package/dist/components/Buttons/TextButton/TextButton.d.ts +5 -9
  19. package/dist/components/Buttons/TextButton/TextButton.d.ts.map +1 -1
  20. package/dist/components/Buttons/TextButton/TextButton.model.d.ts +18 -0
  21. package/dist/components/Buttons/TextButton/TextButton.model.d.ts.map +1 -0
  22. package/dist/components/Buttons/TextButton/index.d.ts +3 -0
  23. package/dist/components/Buttons/TextButton/index.d.ts.map +1 -0
  24. package/dist/components/Buttons/index.d.ts +3 -3
  25. package/dist/components/Buttons/index.d.ts.map +1 -1
  26. package/dist/components/Explorer/Explorer.d.ts.map +1 -1
  27. package/dist/components/Explorer/Explorer.model.d.ts +2 -2
  28. package/dist/components/Explorer/Explorer.model.d.ts.map +1 -1
  29. package/dist/components/Explorer/NavigationExplorer/NavigationExplorer.d.ts +13 -3
  30. package/dist/components/Explorer/NavigationExplorer/NavigationExplorer.d.ts.map +1 -1
  31. package/dist/components/FormElements/ToggleButton/ToggleButton.d.ts +2 -2
  32. package/dist/components/FormElements/ToggleButton/ToggleButton.d.ts.map +1 -1
  33. package/dist/components/List/List.d.ts +1 -1
  34. package/dist/components/List/List.d.ts.map +1 -1
  35. package/dist/components/List/ListRow/ListRow.d.ts.map +1 -1
  36. package/dist/components/PageHeader/PageHeader.d.ts +1 -22
  37. package/dist/components/PageHeader/PageHeader.d.ts.map +1 -1
  38. package/dist/components/PageHeader/PageHeader.model.d.ts +23 -0
  39. package/dist/components/PageHeader/PageHeader.model.d.ts.map +1 -0
  40. package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.d.ts +20 -33
  41. package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.d.ts.map +1 -1
  42. package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.model.d.ts +47 -0
  43. package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.model.d.ts.map +1 -0
  44. package/dist/components/PageHeader/PageHeaderAction/index.d.ts +3 -0
  45. package/dist/components/PageHeader/PageHeaderAction/index.d.ts.map +1 -0
  46. package/dist/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.d.ts +2 -2
  47. package/dist/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.d.ts.map +1 -1
  48. package/dist/components/PageHeader/index.d.ts +3 -2
  49. package/dist/components/PageHeader/index.d.ts.map +1 -1
  50. package/dist/components/models.d.ts +22 -0
  51. package/dist/components/models.d.ts.map +1 -1
  52. package/dist/index.es.js +3 -3
  53. package/dist/index.es.js.map +1 -1
  54. package/dist/index.js +3 -3
  55. package/dist/index.js.map +1 -1
  56. package/package.json +3 -3
  57. package/src/components/Actions/Action/Action.spec.tsx +14 -0
  58. package/src/components/Actions/Action/Action.tsx +5 -2
  59. package/src/components/Actions/Actions.models.ts +4 -23
  60. package/src/components/Buttons/Button/Button.model.ts +30 -0
  61. package/src/components/Buttons/Button/Button.scss +3 -1
  62. package/src/components/Buttons/Button/Button.spec.tsx +254 -83
  63. package/src/components/Buttons/Button/Button.stories.tsx +20 -0
  64. package/src/components/Buttons/Button/Button.tsx +103 -32
  65. package/src/components/Buttons/Button/index.ts +2 -0
  66. package/src/components/Buttons/Button.model.ts +84 -9
  67. package/src/components/Buttons/CompositeButton/CompositeButton.model.ts +32 -0
  68. package/src/components/Buttons/CompositeButton/CompositeButton.scss +6 -1
  69. package/src/components/Buttons/CompositeButton/CompositeButton.spec.tsx +277 -89
  70. package/src/components/Buttons/CompositeButton/CompositeButton.stories.tsx +20 -0
  71. package/src/components/Buttons/CompositeButton/CompositeButton.tsx +94 -30
  72. package/src/components/Buttons/CompositeButton/index.ts +2 -0
  73. package/src/components/Buttons/TextButton/TextButton.model.ts +27 -0
  74. package/src/components/Buttons/TextButton/TextButton.scss +3 -1
  75. package/src/components/Buttons/TextButton/TextButton.spec.tsx +198 -87
  76. package/src/components/Buttons/TextButton/TextButton.stories.tsx +20 -0
  77. package/src/components/Buttons/TextButton/TextButton.tsx +74 -20
  78. package/src/components/Buttons/TextButton/index.ts +2 -0
  79. package/src/components/Buttons/index.ts +3 -6
  80. package/src/components/Explorer/Explorer.model.ts +2 -2
  81. package/src/components/Explorer/Explorer.tsx +21 -16
  82. package/src/components/Explorer/NavigationExplorer/NavigationExplorer.tsx +32 -11
  83. package/src/components/FormElements/CustomTags/CustomTags.spec.tsx +26 -16
  84. package/src/components/FormElements/ToggleButton/ToggleButton.tsx +2 -2
  85. package/src/components/List/List.spec.tsx +23 -0
  86. package/src/components/List/List.stories.tsx +8 -0
  87. package/src/components/List/List.tsx +15 -3
  88. package/src/components/List/ListRow/ListRow.tsx +18 -13
  89. package/src/components/PageHeader/PageHeader.model.ts +23 -0
  90. package/src/components/PageHeader/PageHeader.stories.tsx +2 -1
  91. package/src/components/PageHeader/PageHeader.tsx +2 -26
  92. package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.model.ts +60 -0
  93. package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.spec.tsx +549 -382
  94. package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.stories.tsx +12 -1
  95. package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.tsx +94 -44
  96. package/src/components/PageHeader/PageHeaderAction/index.ts +2 -0
  97. package/src/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.spec.tsx +2 -2
  98. package/src/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.tsx +56 -43
  99. package/src/components/PageHeader/index.ts +3 -2
  100. package/src/components/models.ts +30 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axinom/mosaic-ui",
3
- "version": "0.32.0-rc.1",
3
+ "version": "0.32.0-rc.10",
4
4
  "description": "UI components for building Axinom Mosaic applications",
5
5
  "author": "Axinom",
6
6
  "license": "PROPRIETARY",
@@ -32,7 +32,7 @@
32
32
  "build-storybook": "storybook build"
33
33
  },
34
34
  "dependencies": {
35
- "@axinom/mosaic-core": "^0.4.5-rc.1",
35
+ "@axinom/mosaic-core": "^0.4.5-rc.10",
36
36
  "@faker-js/faker": "^7.4.0",
37
37
  "@popperjs/core": "^2.9.2",
38
38
  "clsx": "^1.1.0",
@@ -102,5 +102,5 @@
102
102
  "publishConfig": {
103
103
  "access": "public"
104
104
  },
105
- "gitHead": "96545ea3a0b2388ae6aa19e9422b6089ba39560c"
105
+ "gitHead": "896d9e0951c9f8610938ec86dbf271d3aef9c5fc"
106
106
  }
@@ -62,6 +62,20 @@ describe('Action', () => {
62
62
  expect(container.hasClass('hasIcon')).toBe(true);
63
63
  });
64
64
 
65
+ it(`displays a 'External' as default icon when "openInNewTab: true"`, () => {
66
+ const wrapper = mount(
67
+ <Router>
68
+ <Action action={{ label: 'test', path: '/', openInNewTab: true }} />
69
+ </Router>,
70
+ );
71
+
72
+ const icon = wrapper.find(Icons);
73
+ const container = wrapper.find('.container').hostNodes();
74
+
75
+ expect(icon.prop('icon')).toBe(IconName.External);
76
+ expect(container.hasClass('hasIcon')).toBe(true);
77
+ });
78
+
65
79
  it(`disables link when property isDisabled is 'true'`, () => {
66
80
  const wrapper = mount(
67
81
  <Router>
@@ -183,10 +183,12 @@ const NavigationAction: React.FC<{ action: NavigationActionData }> = ({
183
183
  }) => {
184
184
  const {
185
185
  path,
186
+ openInNewTab = false,
186
187
  label,
187
- icon = IconName.ChevronRight,
188
+ icon,
188
189
  isDisabled = false,
189
190
  } = action;
191
+ const defaultIcon = openInNewTab ? IconName.External : IconName.ChevronRight;
190
192
  return (
191
193
  <Link
192
194
  to={path}
@@ -200,9 +202,10 @@ const NavigationAction: React.FC<{ action: NavigationActionData }> = ({
200
202
  'action-container',
201
203
  )}
202
204
  data-test-id="action"
205
+ target={openInNewTab ? '_blank' : undefined}
203
206
  >
204
207
  <span data-test-id="label">{label}</span>
205
- <Icons icon={icon} className={classes.icon} />
208
+ <Icons icon={icon ? icon : defaultIcon} className={classes.icon} />
206
209
  </Link>
207
210
  );
208
211
  };
@@ -1,7 +1,6 @@
1
1
  import { Not } from '../../types';
2
- import { ConfirmationConfig, ConfirmationMode } from '../ConfirmDialog';
3
2
  import { IconName } from '../Icons';
4
- import { ErrorType } from '../models';
3
+ import { ConfirmAction, DefaultHandler, LinkAction } from '../models';
5
4
 
6
5
  /**
7
6
  * @deprecated ActionData interface has been changed and no longer uses `actionType` property
@@ -11,7 +10,7 @@ export enum ActionType {
11
10
  Context,
12
11
  }
13
12
 
14
- export type ActionData<THandler = DefaultSelectionHandler> =
13
+ export type ActionData<THandler = DefaultHandler> =
15
14
  | ContextActionData<THandler>
16
15
  | NavigationActionData;
17
16
 
@@ -20,7 +19,7 @@ export type ActionData<THandler = DefaultSelectionHandler> =
20
19
  * to render an element with JS handler
21
20
  * and specified confirmation mode for click event
22
21
  */
23
- export interface ContextActionData<THandler = DefaultSelectionHandler>
22
+ export interface ContextActionData<THandler = DefaultHandler>
24
23
  extends ActionBaseData,
25
24
  ConfirmAction,
26
25
  HandledAction<THandler>,
@@ -36,29 +35,11 @@ export interface NavigationActionData
36
35
  Not<ConfirmAction>,
37
36
  Not<HandledAction<unknown>> {}
38
37
 
39
- export type DefaultSelectionHandler = () =>
40
- | Promise<ErrorType | undefined | void>
41
- | ErrorType
42
- | undefined
43
- | void;
44
-
45
- interface LinkAction {
46
- /** Path to navigate to when the action is clicked. */
47
- path: string;
48
- }
49
-
50
- interface HandledAction<THandler> {
38
+ export interface HandledAction<THandler> {
51
39
  /** Callback emitted when a user clicks on the Action. */
52
40
  onActionSelected: THandler;
53
41
  }
54
42
 
55
- interface ConfirmAction {
56
- /** If set to 'Simple', the action will require confirmation. If set to 'Advanced', action will require confirmation via a confirmation pop up. (default: 'None') */
57
- confirmationMode?: ConfirmationMode;
58
- /** Optional text overrides for the confirmation pop up. */
59
- confirmationConfig?: ConfirmationConfig;
60
- }
61
-
62
43
  interface ActionBaseData {
63
44
  /**
64
45
  * @deprecated this property is no longer used,
@@ -0,0 +1,30 @@
1
+ import { IconName } from '../../Icons';
2
+ import {
3
+ ButtonIconOptions,
4
+ CommonJsButtonOptions,
5
+ CommonNavigationButtonOptions,
6
+ } from '../Button.model';
7
+
8
+ export type ButtonProps =
9
+ | (NavigationButtonProps | ContextButtonProps) & {
10
+ /** Optional button's height (default: 50px) */
11
+ width?: string | number;
12
+ /** Optional button's height (default: 50px) */
13
+ height?: string | number;
14
+ /** Optional icon (default: IconName.ChevronRight) */
15
+ icon?: IconName;
16
+ };
17
+
18
+ /**
19
+ * Button options for icon buttons with navigation
20
+ */
21
+ export interface NavigationButtonProps
22
+ extends CommonNavigationButtonOptions,
23
+ Pick<ButtonIconOptions, 'icon'> {}
24
+
25
+ /**
26
+ * Button options for icon buttons with JS handlers
27
+ */
28
+ export interface ContextButtonProps
29
+ extends CommonJsButtonOptions,
30
+ Pick<ButtonIconOptions, 'icon'> {}
@@ -24,6 +24,7 @@
24
24
 
25
25
  &.navigation {
26
26
  background-color: $light-blue;
27
+ box-sizing: border-box;
27
28
 
28
29
  svg * {
29
30
  stroke: white;
@@ -41,8 +42,9 @@
41
42
  }
42
43
  }
43
44
 
44
- &:disabled {
45
+ &.disabled {
45
46
  background-color: $gray;
47
+ pointer-events: none;
46
48
 
47
49
  svg * {
48
50
  opacity: 0.5;
@@ -1,130 +1,301 @@
1
- import { mount, shallow } from 'enzyme';
1
+ import { mount } from 'enzyme';
2
2
  import React from 'react';
3
+ import { Link, BrowserRouter as Router } from 'react-router-dom';
3
4
  import { IconName, Icons } from '../../Icons';
4
5
  import { ButtonContext } from '../Button.model';
5
6
  import { Button } from './Button';
6
7
 
7
- describe('Button', () => {
8
- it('renders the component without crashing', () => {
9
- const wrapper = shallow(<Button />);
8
+ const navigationButtonProps = {
9
+ path: '/test',
10
+ };
10
11
 
11
- expect(wrapper).toBeTruthy();
12
- });
12
+ describe('Button (with icon)', () => {
13
+ describe('ContextButtonElement', () => {
14
+ it('renders the component without crashing', () => {
15
+ const wrapper = mount(<Button />);
13
16
 
14
- it('raises the onButtonClicked event', () => {
15
- const spy = jest.fn();
16
- const wrapper = shallow(<Button onButtonClicked={spy} />);
17
+ expect(wrapper).toBeTruthy();
18
+ });
17
19
 
18
- wrapper.simulate('click');
20
+ it('raises the onButtonClicked event', () => {
21
+ const spy = jest.fn();
22
+ const wrapper = mount(<Button onButtonClicked={spy} />);
19
23
 
20
- expect(spy).toHaveBeenCalledTimes(1);
21
- });
24
+ wrapper.simulate('click');
22
25
 
23
- it('creates a class based off of the className prop', () => {
24
- const mockClassName = 'test-class';
25
- const wrapper = shallow(<Button className={mockClassName} />);
26
+ expect(spy).toHaveBeenCalledTimes(1);
27
+ });
26
28
 
27
- const button = wrapper.find('button');
29
+ it('creates a class based off of the className prop', () => {
30
+ const mockClassName = 'test-class';
31
+ const wrapper = mount(<Button className={mockClassName} />);
28
32
 
29
- expect(button.hasClass(mockClassName)).toBe(true);
30
- });
33
+ const button = wrapper.find('button');
31
34
 
32
- it(`button 'type' must be 'button' by default`, () => {
33
- const wrapper = shallow(<Button />);
35
+ expect(button.hasClass(mockClassName)).toBe(true);
36
+ });
34
37
 
35
- const buttonType = wrapper.find('button').prop('type');
38
+ it(`button 'type' must be 'button' by default`, () => {
39
+ const wrapper = mount(<Button />);
36
40
 
37
- expect(buttonType).toBe('button');
38
- });
41
+ const buttonType = wrapper.find('button').prop('type');
39
42
 
40
- it('accepts type html attribute and width/height styles', () => {
41
- const mockType = 'submit';
42
- const mockHeight = '75px';
43
- const mockWidth = '80px';
43
+ expect(buttonType).toBe('button');
44
+ });
44
45
 
45
- const wrapper = shallow(<Button />);
46
+ it('accepts type html attribute and width/height styles', () => {
47
+ const mockType = 'submit';
48
+ const mockHeight = '75px';
49
+ const mockWidth = '80px';
46
50
 
47
- let buttonType = wrapper.find('button').prop('type');
48
- let buttonStyles = wrapper
49
- .find('button')
50
- .prop('style') as React.CSSProperties;
51
+ const wrapper = mount(<Button />);
51
52
 
52
- expect(buttonType).toBe('button');
53
- expect(buttonStyles.height).toBeUndefined();
54
- expect(buttonStyles.width).toBeUndefined();
53
+ let buttonType = wrapper.find('button').prop('type');
54
+ let buttonStyles = wrapper
55
+ .find('button')
56
+ .prop('style') as React.CSSProperties;
55
57
 
56
- wrapper.setProps({ type: mockType, height: mockHeight, width: mockWidth });
57
- wrapper.update();
58
+ expect(buttonType).toBe('button');
59
+ expect(buttonStyles.height).toBeUndefined();
60
+ expect(buttonStyles.width).toBeUndefined();
58
61
 
59
- buttonType = wrapper.find('button').prop('type');
60
- buttonStyles = wrapper.find('button').prop('style') as React.CSSProperties;
62
+ wrapper.setProps({
63
+ type: mockType,
64
+ height: mockHeight,
65
+ width: mockWidth,
66
+ });
67
+ wrapper.update();
61
68
 
62
- expect(buttonType).toBe(mockType);
63
- expect(buttonStyles.height).toBe(mockHeight);
64
- expect(buttonStyles.width).toBe(mockWidth);
65
- });
69
+ buttonType = wrapper.find('button').prop('type');
70
+ buttonStyles = wrapper
71
+ .find('button')
72
+ .prop('style') as React.CSSProperties;
66
73
 
67
- it('allows the button to be enabled by default', () => {
68
- const spy = jest.fn();
69
- const wrapper = mount(<Button onButtonClicked={spy} />);
74
+ expect(buttonType).toBe(mockType);
75
+ expect(buttonStyles.height).toBe(mockHeight);
76
+ expect(buttonStyles.width).toBe(mockWidth);
77
+ });
70
78
 
71
- const button = wrapper.find('button');
79
+ it('allows the button to be enabled by default', () => {
80
+ const spy = jest.fn();
81
+ const wrapper = mount(<Button onButtonClicked={spy} />);
72
82
 
73
- wrapper.simulate('click');
83
+ const button = wrapper.find('button');
74
84
 
75
- expect(button.prop('disabled')).toBe(false);
76
- expect(spy).toHaveBeenCalledTimes(1);
77
- });
85
+ wrapper.simulate('click');
78
86
 
79
- it('allows button to be disabled', () => {
80
- const spy = jest.fn();
81
- const wrapper = mount(<Button disabled={true} onButtonClicked={spy} />);
87
+ expect(button.prop('disabled')).toBe(false);
88
+ expect(spy).toHaveBeenCalledTimes(1);
89
+ });
82
90
 
83
- const button = wrapper.find('button');
91
+ it('allows button to be disabled', () => {
92
+ const spy = jest.fn();
93
+ const wrapper = mount(<Button disabled={true} onButtonClicked={spy} />);
84
94
 
85
- wrapper.simulate('click');
95
+ const button = wrapper.find('button');
86
96
 
87
- expect(button.prop('disabled')).toBe(true);
88
- expect(spy).not.toHaveBeenCalled();
89
- });
97
+ wrapper.simulate('click');
90
98
 
91
- it('default should have a navigation class', () => {
92
- const wrapper = shallow(<Button />);
99
+ expect(button.prop('disabled')).toBe(true);
100
+ expect(spy).not.toHaveBeenCalled();
101
+ });
93
102
 
94
- const button = wrapper.find('button');
103
+ it('default should have a active class', () => {
104
+ const wrapper = mount(<Button />);
95
105
 
96
- expect(button.hasClass('navigation')).toBe(true);
97
- });
106
+ const button = wrapper.find('button');
98
107
 
99
- it('context button type should have a context class', () => {
100
- const wrapper = shallow(<Button buttonContext={ButtonContext.Context} />);
108
+ expect(button.hasClass('active')).toBe(true);
109
+ });
101
110
 
102
- const button = wrapper.find('button');
111
+ it('context button type should have a context class', () => {
112
+ const wrapper = mount(<Button buttonContext={ButtonContext.Context} />);
103
113
 
104
- expect(button.hasClass('context')).toBe(true);
105
- });
114
+ const button = wrapper.find('button');
106
115
 
107
- it('context button type should have a icon class', () => {
108
- const wrapper = shallow(<Button buttonContext={ButtonContext.Icon} />);
116
+ expect(button.hasClass('context')).toBe(true);
117
+ });
109
118
 
110
- const button = wrapper.find('button');
119
+ it('context button type should have a icon class', () => {
120
+ const wrapper = mount(<Button buttonContext={ButtonContext.Icon} />);
111
121
 
112
- expect(button.hasClass('icon')).toBe(true);
113
- });
122
+ const button = wrapper.find('button');
114
123
 
115
- it('active button type should have a active class', () => {
116
- const wrapper = shallow(<Button buttonContext={ButtonContext.Active} />);
124
+ expect(button.hasClass('icon')).toBe(true);
125
+ });
117
126
 
118
- const button = wrapper.find('button');
127
+ it('active button type should have a active class', () => {
128
+ const wrapper = mount(<Button buttonContext={ButtonContext.Active} />);
119
129
 
120
- expect(button.hasClass('active')).toBe(true);
121
- });
130
+ const button = wrapper.find('button');
131
+
132
+ expect(button.hasClass('active')).toBe(true);
133
+ });
122
134
 
123
- it(`renders an icon as it's image from the Icons component`, () => {
124
- const wrapper = shallow(<Button icon={IconName.ChevronRight} />);
135
+ it(`renders an icon as it's image from the Icons component`, () => {
136
+ const wrapper = mount(<Button icon={IconName.ChevronRight} />);
137
+
138
+ const icon = wrapper.find(Icons);
139
+
140
+ expect(icon.exists()).toBe(true);
141
+ });
142
+ });
125
143
 
126
- const icon = wrapper.find(Icons);
144
+ describe('NavigationButtonElement', () => {
145
+ it('renders the component without crashing', () => {
146
+ const wrapper = mount(
147
+ <Router>
148
+ <Button {...navigationButtonProps} />
149
+ </Router>,
150
+ );
151
+
152
+ expect(wrapper).toBeTruthy();
153
+ });
154
+
155
+ it('creates a class based on the className prop', () => {
156
+ const mockClassName = 'test-class';
157
+ const wrapper = mount(
158
+ <Router>
159
+ <Button {...navigationButtonProps} className={mockClassName} />,
160
+ </Router>,
161
+ );
162
+
163
+ const link = wrapper.find('Link');
164
+
165
+ expect(link.hasClass(mockClassName)).toBe(true);
166
+ });
167
+
168
+ it('renders the correct path in the Link component', () => {
169
+ const mockPath = '/test';
170
+ const wrapper = mount(
171
+ <Router>
172
+ <Button path={mockPath} />
173
+ </Router>,
174
+ );
175
+
176
+ const link = wrapper.find('Link');
177
+
178
+ expect(link.prop('to')).toBe(mockPath);
179
+ });
180
+
181
+ it('accepts width/height styles', () => {
182
+ const mockHeight = '75px';
183
+ const mockWidth = '80px';
184
+
185
+ const wrapper = mount(
186
+ <Router>
187
+ <Button
188
+ {...navigationButtonProps}
189
+ height={mockHeight}
190
+ width={mockWidth}
191
+ />
192
+ </Router>,
193
+ );
194
+
195
+ const linkStyles = wrapper
196
+ .find('Link')
197
+ .prop('style') as React.CSSProperties;
198
+
199
+ expect(linkStyles.height).toBe(mockHeight);
200
+ expect(linkStyles.width).toBe(mockWidth);
201
+ });
202
+
203
+ it('allows the button to be enabled by default', () => {
204
+ const wrapper = mount(
205
+ <Router>
206
+ <Button {...navigationButtonProps} />
207
+ </Router>,
208
+ );
209
+
210
+ const link = wrapper.find('Link');
211
+
212
+ expect(link.hasClass('disabled')).toBe(false);
213
+ });
214
+
215
+ it('allows button to be disabled', () => {
216
+ const wrapper = mount(
217
+ <Router>
218
+ <Button {...navigationButtonProps} disabled={true} />
219
+ </Router>,
220
+ );
221
+
222
+ const link = wrapper.find('Link');
223
+
224
+ expect(link.hasClass('disabled')).toBe(true);
225
+ });
226
+
227
+ it('renders the correct data-test-id attribute', () => {
228
+ const mockTestId = 'test-button';
229
+ const wrapper = mount(
230
+ <Router>
231
+ <Button {...navigationButtonProps} dataTestId={mockTestId} />
232
+ </Router>,
233
+ );
234
+
235
+ const link = wrapper.find('Link');
236
+
237
+ expect(link.prop('data-test-id')).toBe(mockTestId);
238
+ });
239
+
240
+ it('renders the Icons component with the correct default icon', () => {
241
+ const wrapper = mount(
242
+ <Router>
243
+ <Button {...navigationButtonProps} />
244
+ </Router>,
245
+ );
246
+
247
+ const icons = wrapper.find(Icons);
248
+
249
+ expect(icons.prop('icon')).toBe(IconName.ChevronRight);
250
+ });
251
+
252
+ it('renders the Icons component with the correct default icon when `openInNewTab` is set to `true`', () => {
253
+ const wrapper = mount(
254
+ <Router>
255
+ <Button {...navigationButtonProps} openInNewTab={true} />
256
+ </Router>,
257
+ );
258
+
259
+ const icons = wrapper.find(Icons);
260
+
261
+ expect(icons.prop('icon')).toBe(IconName.External);
262
+ });
263
+
264
+ it('opens link in new tab when `openInNewTab` is set to `true`', () => {
265
+ const wrapper = mount(
266
+ <Router>
267
+ <Button {...navigationButtonProps} openInNewTab={true} />
268
+ </Router>,
269
+ );
270
+
271
+ const link = wrapper.find(Link);
272
+
273
+ expect(link.prop('target')).toBe('_blank');
274
+ });
275
+
276
+ it('does not open link in new tab by default', () => {
277
+ const wrapper = mount(
278
+ <Router>
279
+ <Button {...navigationButtonProps} />
280
+ </Router>,
281
+ );
282
+
283
+ const link = wrapper.find(Link);
284
+
285
+ expect(link.prop('target')).toBeUndefined();
286
+ });
287
+
288
+ it('renders the Icons component with the correct icon', () => {
289
+ const mockIcon = IconName.Copy;
290
+ const wrapper = mount(
291
+ <Router>
292
+ <Button {...navigationButtonProps} icon={mockIcon} />
293
+ </Router>,
294
+ );
295
+
296
+ const icons = wrapper.find(Icons);
127
297
 
128
- expect(icon.exists()).toBe(true);
298
+ expect(icons.prop('icon')).toBe(mockIcon);
299
+ });
129
300
  });
130
301
  });
@@ -1,4 +1,6 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
+ import React from 'react';
3
+ import { MemoryRouter } from 'react-router';
2
4
  import { enumToObj } from '../../../helpers/storybook';
3
5
  import { IconName } from '../../Icons';
4
6
  import { ButtonContext } from '../Button.model';
@@ -29,7 +31,25 @@ const meta: Meta<typeof Button> = {
29
31
  type: {
30
32
  control: false,
31
33
  },
34
+ width: {
35
+ control: {
36
+ type: 'number',
37
+ },
38
+ },
39
+ height: {
40
+ control: {
41
+ type: 'number',
42
+ },
43
+ },
32
44
  },
45
+ decorators: [
46
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
47
+ (Story) => (
48
+ <MemoryRouter>
49
+ <Story />
50
+ </MemoryRouter>
51
+ ),
52
+ ],
33
53
  };
34
54
 
35
55
  export default meta;