@eturnity/eturnity_reusable_components 7.45.1-EPDM-12459.1 → 7.45.2--EPDM-12129.3

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "7.45.1-EPDM-12459.1",
3
+ "version": "7.45.2--EPDM-12129.3",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <PageContainer :should-position="shouldPosition">
3
- <ButtonContainer :data-id="dataId">
3
+ <ButtonContainer :data-id="dataId" :data-qa-id="dataQaId">
4
4
  <PlusButtonSvg />
5
5
  </ButtonContainer>
6
6
  </PageContainer>
@@ -57,6 +57,10 @@
57
57
  type: String,
58
58
  default: '',
59
59
  },
60
+ dataQaId: {
61
+ type: String,
62
+ default: '',
63
+ },
60
64
  },
61
65
  }
62
66
  </script>
@@ -4,6 +4,7 @@
4
4
  :id="id"
5
5
  :custom-color="customColor"
6
6
  :data-id="dataId"
7
+ :data-qa-id="dataQaId"
7
8
  :font-color="fontColor"
8
9
  :is-disabled="isDisabled"
9
10
  :min-width="minWidth"
@@ -145,6 +146,10 @@
145
146
  type: String,
146
147
  default: '',
147
148
  },
149
+ dataQaId: {
150
+ type: String,
151
+ default: '',
152
+ },
148
153
  },
149
154
  }
150
155
  </script>
@@ -0,0 +1,79 @@
1
+ import Card from './index.vue'
2
+
3
+ export default {
4
+ title: 'Card',
5
+ component: Card,
6
+ tags: ['autodocs'],
7
+ }
8
+
9
+ // To use:
10
+ // <RCCard
11
+ // :isLoading="true"
12
+ // minWidth="150px"
13
+ // popoverText="Sample popover text"
14
+ // :showPopover="true"
15
+ // title="Sample title"
16
+ // titleClass="sampleTitleClass"
17
+ // viewCardClass="sampleViewCardClass"
18
+ // width="200px"
19
+ // />
20
+
21
+ export const Default = {
22
+ args: {
23
+ title: 'Sample card title',
24
+ },
25
+ render: (args) => ({
26
+ components: { Card },
27
+ setup() {
28
+ return { args }
29
+ },
30
+ template: `
31
+ <Card v-bind="args">
32
+ Sample card content
33
+ </ActionBanner>
34
+ `,
35
+ }),
36
+ }
37
+
38
+ export const LoadingCard = {
39
+ args: {
40
+ isLoading: true,
41
+ },
42
+ }
43
+
44
+ export const CustomWidth = {
45
+ args: {
46
+ title: 'Sample card title',
47
+ width: '600px',
48
+ },
49
+ render: (args) => ({
50
+ components: { Card },
51
+ setup() {
52
+ return { args }
53
+ },
54
+ template: `
55
+ <Card v-bind="args">
56
+ Sample card content
57
+ </ActionBanner>
58
+ `,
59
+ }),
60
+ }
61
+
62
+ export const PopoverShown = {
63
+ args: {
64
+ title: 'Sample card title',
65
+ showPopover: true,
66
+ popoverText: 'Sample popover text',
67
+ },
68
+ render: (args) => ({
69
+ components: { Card },
70
+ setup() {
71
+ return { args }
72
+ },
73
+ template: `
74
+ <Card v-bind="args">
75
+ Sample card content
76
+ </ActionBanner>
77
+ `,
78
+ }),
79
+ }
@@ -0,0 +1,135 @@
1
+ /* eslint-disable */
2
+ import { mount, config } from '@vue/test-utils'
3
+ import Card from '@/components/card'
4
+ import theme from '@/assets/theme'
5
+
6
+ config.global.components = {
7
+ EtPopover: {
8
+ template: '<div>{{ text }}</div>',
9
+ props: ['text'],
10
+ },
11
+ }
12
+
13
+ config.global.mocks = {
14
+ $gettext: (msg) => msg,
15
+ }
16
+
17
+ describe('Card Component', () => {
18
+ it('card title is shown when a title props is passed', () => {
19
+ const title = 'Test Card Title'
20
+ const wrapper = mount(Card, {
21
+ props: {
22
+ title,
23
+ },
24
+ global: {
25
+ provide: {
26
+ theme,
27
+ },
28
+ },
29
+ })
30
+
31
+ expect(wrapper.text()).toContain(title)
32
+ })
33
+
34
+ it('card spinner is shown when user set isLoading props to true', async () => {
35
+ // Start with isLoading is false
36
+ const wrapper = mount(Card, {
37
+ props: {
38
+ title: 'Test Card Title',
39
+ isLoading: false,
40
+ },
41
+ global: {
42
+ provide: {
43
+ theme,
44
+ },
45
+ },
46
+ })
47
+
48
+ let cardSpinner = wrapper.find('[data-test-id="card_spinner"]')
49
+ expect(cardSpinner.exists()).toBe(false)
50
+ await wrapper.setProps({ isLoading: true })
51
+ await wrapper.vm.$nextTick()
52
+ cardSpinner = wrapper.find('[data-test-id="card_spinner"]')
53
+ expect(cardSpinner.exists()).toBe(true)
54
+ })
55
+
56
+ it('card wrapper has custom class when viewCardClass props is passed', async () => {
57
+ const viewCardClass = 'sampleClass'
58
+ const wrapper = mount(Card, {
59
+ props: {
60
+ title: 'Test Card Title',
61
+ viewCardClass,
62
+ },
63
+ global: {
64
+ provide: {
65
+ theme,
66
+ },
67
+ },
68
+ })
69
+
70
+ const cardMainWrapper = wrapper.find('[data-test-id="card_main_wrapper"]')
71
+ expect(cardMainWrapper.classes()).toContain(viewCardClass)
72
+ })
73
+
74
+ it('card title has custom class when titleClass props is passed', async () => {
75
+ const titleClass = 'sampleClass'
76
+ const wrapper = mount(Card, {
77
+ props: {
78
+ title: 'Test Card Title',
79
+ titleClass,
80
+ },
81
+ global: {
82
+ provide: {
83
+ theme,
84
+ },
85
+ },
86
+ })
87
+
88
+ const cardTitle = wrapper.find('[data-test-id="card_title"]')
89
+ expect(cardTitle.classes()).toContain(titleClass)
90
+ })
91
+
92
+ it('card popover is shown when user set showPopover props to true', async () => {
93
+ // Start with showPopover is false
94
+ const wrapper = mount(Card, {
95
+ props: {
96
+ title: 'Test Card Title',
97
+ showPopover: false,
98
+ popoverText: 'Sample popover text',
99
+ },
100
+ global: {
101
+ provide: {
102
+ theme,
103
+ },
104
+ },
105
+ })
106
+
107
+ let cardPopover = wrapper.find('[data-test-id="card_popover"]')
108
+ expect(cardPopover.exists()).toBe(false)
109
+ await wrapper.setProps({ showPopover: true })
110
+ await wrapper.vm.$nextTick()
111
+ cardPopover = wrapper.find('[data-test-id="card_popover"]')
112
+ expect(cardPopover.exists()).toBe(true)
113
+ expect(cardPopover.text()).toContain('Sample popover text')
114
+ })
115
+
116
+ it('card popover text is set when user passed a popoverText props value', async () => {
117
+ const popoverText = 'Sample popover text'
118
+ const wrapper = mount(Card, {
119
+ props: {
120
+ title: 'Test Card Title',
121
+ showPopover: true,
122
+ popoverText,
123
+ },
124
+ global: {
125
+ provide: {
126
+ theme,
127
+ },
128
+ },
129
+ })
130
+
131
+ let cardPopover = wrapper.find('[data-test-id="card_popover"]')
132
+ expect(cardPopover.exists()).toBe(true)
133
+ expect(cardPopover.text()).toContain('Sample popover text')
134
+ })
135
+ })
@@ -2,15 +2,22 @@
2
2
  <Wrapper
3
3
  v-show="!isLoading"
4
4
  :class="viewCardClass"
5
+ data-test-id="card_main_wrapper"
5
6
  :min-width="minWidth"
6
7
  :width="width"
7
8
  >
8
- <Spinner v-if="isLoading" :limited-to-modal="true" size="50px" />
9
+ <Spinner
10
+ v-if="isLoading"
11
+ data-test-id="card_spinner"
12
+ :limited-to-modal="true"
13
+ size="50px"
14
+ />
9
15
  <CardWrapper v-else>
10
- <CardTitle :class="titleClass">
16
+ <CardTitle :class="titleClass" data-test-id="card_title">
11
17
  {{ $gettext(title) }}
12
18
  <EtPopover
13
19
  v-if="showPopover && popoverText !== ''"
20
+ data-test-id="card_popover"
14
21
  :text="popoverText"
15
22
  />
16
23
  </CardTitle>
@@ -20,6 +27,19 @@
20
27
  </template>
21
28
 
22
29
  <script>
30
+ // To use:
31
+ // import RCCard from "@eturnity/eturnity_reusable_components/src/components/card"
32
+ // <RCCard
33
+ // :isLoading="true"
34
+ // minWidth="150px"
35
+ // popoverText="Sample popover text"
36
+ // :showPopover="true"
37
+ // title="Sample title"
38
+ // titleClass="sampleTitleClass"
39
+ // viewCardClass="sampleViewCardClass"
40
+ // width="200px"
41
+ // />
42
+
23
43
  import styled from 'vue3-styled-components'
24
44
  import Spinner from '../spinner'
25
45
 
@@ -4,6 +4,7 @@
4
4
  :border-radius="borderRadius"
5
5
  :color="iconColor"
6
6
  :data-id="dataId"
7
+ :data-qa-id="dataQaId"
7
8
  :disabled="disabled"
8
9
  :has-border="hasBorder"
9
10
  :hovered-background-color="hoveredBackgroundColor"
@@ -154,6 +155,10 @@
154
155
  type: String,
155
156
  default: '',
156
157
  },
158
+ dataQaId: {
159
+ type: String,
160
+ default: '',
161
+ },
157
162
  isHovered: {
158
163
  required: false,
159
164
  default: false,
@@ -13,6 +13,7 @@
13
13
  <InputCheckbox
14
14
  :checked="isChecked"
15
15
  :data-id="dataId"
16
+ :data-qa-id="dataQaId"
16
17
  type="checkbox"
17
18
  @change="onChangeHandler(!isChecked)"
18
19
  />
@@ -203,6 +204,10 @@
203
204
  type: String,
204
205
  default: '',
205
206
  },
207
+ dataQaId: {
208
+ type: String,
209
+ default: '',
210
+ },
206
211
  cursorType: {
207
212
  type: String,
208
213
  default: 'pointer',
@@ -13,7 +13,11 @@
13
13
  </LabelSlotWrapper>
14
14
 
15
15
  <LabelWrapper v-if="labelText">
16
- <LabelText :data-id="labelDataId" :label-font-color="labelFontColor">
16
+ <LabelText
17
+ :data-id="labelDataId"
18
+ :data-test-id="labelDataTestId"
19
+ :label-font-color="labelFontColor"
20
+ >
17
21
  {{ labelText }}
18
22
  </LabelText>
19
23
 
@@ -31,6 +35,7 @@
31
35
  :background-color="backgroundColor"
32
36
  :border-color="borderColor"
33
37
  :data-id="inputDataId"
38
+ :data-qa-id="dataQaId"
34
39
  :disabled="disabled"
35
40
  :font-color="fontColor"
36
41
  :font-size="fontSize"
@@ -496,6 +501,10 @@
496
501
  required: false,
497
502
  default: '',
498
503
  },
504
+ dataQaId: {
505
+ required: false,
506
+ default: '',
507
+ },
499
508
  showSelect: {
500
509
  type: Boolean,
501
510
  default: false,
@@ -28,6 +28,7 @@
28
28
  ref="inputElement"
29
29
  :background-color="backgroundColor"
30
30
  :data-id="inputDataId"
31
+ :data-qa-id="dataQaId"
31
32
  :disabled="disabled"
32
33
  :disabled-background-color="disabledBackgroundColor"
33
34
  :font-color="fontColor"
@@ -324,6 +325,10 @@
324
325
  required: false,
325
326
  default: '',
326
327
  },
328
+ dataQaId: {
329
+ required: false,
330
+ default: '',
331
+ },
327
332
  },
328
333
  data() {
329
334
  return {
@@ -15,6 +15,7 @@
15
15
  <Radio
16
16
  :checked="selectedOption === item.value"
17
17
  :data-id="`radio_button_${dataId}_option_${item.value}`"
18
+ :data-qa-id="dataQaId"
18
19
  :data-test-id="'radioInput_' + item.value"
19
20
  :disabled="item.disabled"
20
21
  :name="'radioButtons_' + radioName"
@@ -280,6 +281,10 @@
280
281
  required: false,
281
282
  type: String,
282
283
  },
284
+ dataQaId: {
285
+ type: String,
286
+ default: '',
287
+ },
283
288
  },
284
289
  emits: ['on-radio-change'],
285
290
  data() {
@@ -114,9 +114,7 @@ describe('RadioButton.vue', () => {
114
114
  const checkedWrapper = checkedWrapperArray[0]
115
115
  const checkedRadioInput = checkedWrapper.find('input[type="radio"]')
116
116
  const defaultValueFromProps = radioButtons.props('selectedOption')
117
- expect(checkedRadioInput.attributes('value')).toBe(
118
- defaultValueFromProps
119
- )
117
+ expect(checkedRadioInput.attributes('value')).toBe(defaultValueFromProps)
120
118
 
121
119
  // Log attributes to see what is rendered (commented out just for reference)
122
120
  // console.log('checkedRadioInput attributes', checkedRadioInput.attributes())
@@ -238,7 +236,9 @@ describe('RadioButton.vue', () => {
238
236
  const valueOfTestedRadioWrapper = testedRadioWrapper
239
237
  .attributes('data-test-id')
240
238
  .replace('radioWrapper_', '')
241
- const expectedText = defaultRadioButtonProps.options.find((el) => el.value === valueOfTestedRadioWrapper).infoText
239
+ const expectedText = defaultRadioButtonProps.options.find(
240
+ (el) => el.value === valueOfTestedRadioWrapper
241
+ ).infoText
242
242
  const iconForHover = testedRadioWrapper.find(
243
243
  '[data-test-id="infoText_trigger"]'
244
244
  )
@@ -5,6 +5,7 @@
5
5
  <InputContainer
6
6
  ref="inputElement"
7
7
  :data-id="dataId"
8
+ :data-qa-id="dataQaId"
8
9
  :disabled="disabled"
9
10
  :has-focus="hasFocus"
10
11
  :input-width="inputWidth"
@@ -120,6 +121,11 @@
120
121
  required: false,
121
122
  default: '',
122
123
  },
124
+ dataQaId: {
125
+ required: false,
126
+ default: '',
127
+ type: String,
128
+ },
123
129
  iconPosition: {
124
130
  type: String,
125
131
  default: 'right',
@@ -13,6 +13,7 @@
13
13
  <LabelWrapper
14
14
  v-if="label"
15
15
  :data-id="labelDataId"
16
+ :data-qa-id="dataQaId"
16
17
  :info-text-message="!!infoTextMessage || !!$slots.infoText"
17
18
  >
18
19
  <InputLabel
@@ -44,6 +45,7 @@
44
45
  "
45
46
  class="select-button"
46
47
  :data-id="dataId"
48
+ :data-qa-id="dataQaId"
47
49
  :disabled="disabled"
48
50
  :font-color="
49
51
  buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
@@ -120,11 +122,6 @@
120
122
  <SelectDropdown
121
123
  v-show="isSelectDropdownShown"
122
124
  ref="dropdown"
123
- :style="{
124
- transform: `translate(${dropdownPosition?.left}px, ${
125
- noRelative ? 'auto' : `${dropdownPosition?.top}px`
126
- })`,
127
- }"
128
125
  :bg-color="
129
126
  dropdownBgColor || colorMode == 'dark' ? 'black' : 'white'
130
127
  "
@@ -349,8 +346,9 @@
349
346
  box-sizing: border-box;
350
347
  z-index: ${(props) => (props.isActive ? '2' : '99999')};
351
348
  position: absolute;
352
- top: 0px;
353
- left: 0px;
349
+ top: ${(props) =>
350
+ props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
351
+ left: ${(props) => props.dropdownPosition?.left}px;
354
352
  border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
355
353
  border-radius: 4px;
356
354
  display: flex;
@@ -557,6 +555,10 @@
557
555
  type: String,
558
556
  default: '',
559
557
  },
558
+ dataQaId: {
559
+ type: String,
560
+ default: '',
561
+ },
560
562
  hasSelectButtonPadding: {
561
563
  required: false,
562
564
  type: Boolean,
@@ -610,10 +612,6 @@
610
612
  },
611
613
  dropdownWidth: null,
612
614
  hoveredValue: null,
613
- isDisplayedAtBottom: true,
614
- selectTopPosition: 0,
615
- selectAndDropdownDistance: 0,
616
- animationFrameId: null,
617
615
  }
618
616
  },
619
617
  computed: {
@@ -621,7 +619,7 @@
621
619
  if (this.isDropdownOpen) {
622
620
  return this.$refs.dropdown.$el.childElementCount > 1
623
621
  ? this.$refs.dropdown.$el.childElementCount
624
- : !!this.$refs.dropdown.$el.children[0]
622
+ : this.$refs.dropdown.$el.children[0]
625
623
  ? this.$refs.dropdown.$el.children[0].childElementCount
626
624
  : 0
627
625
  }
@@ -684,13 +682,8 @@
684
682
  }, 10)
685
683
  await this.$nextTick()
686
684
  this.handleSetDropdownOffet()
687
- this.calculateSelectTopPosition()
688
685
  } else {
689
686
  this.dropdownPosition.left = null
690
- if (this.animationFrameId) {
691
- cancelAnimationFrame(this.animationFrameId)
692
- this.animationFrameId = null
693
- }
694
687
  setTimeout(() => {
695
688
  this.isClickOutsideActive = false
696
689
  }, 10)
@@ -703,27 +696,11 @@
703
696
  })
704
697
  }
705
698
  },
706
- isSelectDropdownShown(isShown) {
707
- if (!isShown) return
708
-
709
- // Need to wait for 1ms to make sure the dropdown menu is shown in the DOM
710
- // before getting the distance between the select and the dropdown menu
711
- setTimeout(() => {
712
- this.getDistanceBetweenSelectAndDropdownMenu()
713
- }, 100)
714
- },
715
- selectTopPosition() {
716
- this.dropdownPosition.top =
717
- this.selectTopPosition +
718
- this.$refs.select.$el.clientHeight +
719
- this.selectAndDropdownDistance
720
- },
721
699
  },
722
700
  mounted() {
723
701
  this.observeDropdownHeight()
724
702
  this.observeSelectWidth()
725
703
  window.addEventListener('resize', this.handleSetDropdownOffet)
726
- document.body.addEventListener('scroll', this.calculateSelectTopPosition)
727
704
  },
728
705
  beforeMount() {
729
706
  this.selectedValue = this.value
@@ -732,10 +709,6 @@
732
709
  window.removeEventListener('resize', this.handleSetDropdownOffet)
733
710
  if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
734
711
  if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
735
- document.body.removeEventListener(
736
- 'scroll',
737
- this.calculateSelectTopPosition
738
- )
739
712
  },
740
713
  unmounted() {
741
714
  document.removeEventListener('click', this.clickOutside)
@@ -841,11 +814,11 @@
841
814
  return
842
815
  }
843
816
  await this.$nextTick()
844
- this.isDisplayedAtBottom = await this.generateDropdownPosition()
817
+ const isDisplayedAtBottom = await this.generateDropdownPosition()
845
818
  // If the dropdown menu is going to be displayed at the bottom,
846
819
  // we need reverify its position after a dom update (nextTick)
847
820
  await this.$nextTick()
848
- if (this.isDisplayedAtBottom) this.generateDropdownPosition()
821
+ if (isDisplayedAtBottom) this.generateDropdownPosition()
849
822
  },
850
823
  async generateDropdownPosition() {
851
824
  const isDropdownNotCompletelyVisible =
@@ -938,25 +911,6 @@
938
911
  }
939
912
  }
940
913
  },
941
- getDistanceBetweenSelectAndDropdownMenu() {
942
- const wholeSelectTopPosition =
943
- this.selectTopPosition + this.$refs.select.$el.clientHeight
944
- this.selectAndDropdownDistance =
945
- this.dropdownPosition.top - wholeSelectTopPosition
946
- },
947
- calculateSelectTopPosition() {
948
- const selectRef = this.$refs.select
949
- if (selectRef) {
950
- const currentTopPosition =
951
- selectRef.$el.getBoundingClientRect().top + window.scrollY
952
- if (this.selectTopPosition !== currentTopPosition) {
953
- this.selectTopPosition = currentTopPosition
954
- }
955
- }
956
- this.animationFrameId = requestAnimationFrame(
957
- this.calculateSelectTopPosition
958
- )
959
- },
960
914
  },
961
915
  }
962
916
  </script>
@@ -18,6 +18,7 @@
18
18
  >
19
19
  <textarea
20
20
  :data-id="inputDataId"
21
+ :data-qa-id="dataQaId"
21
22
  :disabled="isDisabled"
22
23
  :placeholder="placeholder"
23
24
  :resize="resize"
@@ -185,6 +186,11 @@
185
186
  required: false,
186
187
  default: '',
187
188
  },
189
+ dataQaId: {
190
+ required: false,
191
+ default: '',
192
+ type: String,
193
+ },
188
194
  },
189
195
  methods: {
190
196
  onChangeHandler($event) {
@@ -2,6 +2,7 @@
2
2
  <Container>
3
3
  <FlexWrapper
4
4
  :data-id="dataId"
5
+ :data-qa-id="dataQaId"
5
6
  data-test-id="page_wrapper"
6
7
  :disabled="disabled"
7
8
  :size="size"
@@ -304,6 +305,10 @@
304
305
  type: String,
305
306
  default: '',
306
307
  },
308
+ dataQaId: {
309
+ type: String,
310
+ default: '',
311
+ },
307
312
  },
308
313
  methods: {
309
314
  onToggleChange() {
@@ -2,6 +2,7 @@
2
2
  <div
3
3
  :class="className"
4
4
  :data-id="dataId"
5
+ :data-qa-id="dataQaId"
5
6
  :style="style"
6
7
  @mousedown="elementMouseDown"
7
8
  @touchstart="elementTouchDown"
@@ -64,6 +65,10 @@
64
65
  type: String,
65
66
  default: '',
66
67
  },
68
+ dataQaId: {
69
+ type: String,
70
+ default: '',
71
+ },
67
72
  className: {
68
73
  type: String,
69
74
  default: 'vdr',