@eturnity/eturnity_reusable_components 7.33.0 → 7.33.2-EPDM-9697.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js CHANGED
@@ -152,6 +152,8 @@ module.exports = {
152
152
  'no-multi-spaces': 'warn',
153
153
  'no-mixed-spaces-and-tabs': 'warn',
154
154
  'no-redeclare': 'warn',
155
+ 'vue/no-reserved-component-names': 'warn',
156
+ 'vue/no-deprecated-destroyed-lifecycle': 'warn',
155
157
  'no-prototype-builtins': 'warn',
156
158
  'no-unsafe-finally': 'warn',
157
159
  'max-len': [
package/babel.config.js CHANGED
@@ -1,5 +1,7 @@
1
1
  module.exports = {
2
- presets: [
3
- '@vue/cli-plugin-babel/preset'
4
- ]
2
+ presets: ['@vue/cli-plugin-babel/preset', '@babel/preset-env'],
3
+ plugins: [
4
+ '@babel/plugin-syntax-import-meta',
5
+ '@babel/plugin-transform-runtime',
6
+ ],
5
7
  }
package/jest.config.js ADDED
@@ -0,0 +1,19 @@
1
+ module.exports = {
2
+ transform: {
3
+ '^.+\\.vue$': 'vue-jest',
4
+ '^.+\\.js$': 'babel-jest',
5
+ },
6
+ moduleFileExtensions: ['js', 'json', 'vue'],
7
+ transformIgnorePatterns: ['<rootDir>/node_modules/'],
8
+ testMatch: ['**/src/**/*.spec.js'],
9
+ collectCoverageFrom: [
10
+ 'src/**/*.{js,vue}',
11
+ '!src/main.js',
12
+ '!src/router/index.js',
13
+ '!**/node_modules/**',
14
+ ],
15
+ moduleNameMapper: {
16
+ '^@/(.*)$': '<rootDir>/src/$1',
17
+ '^@/components/icon/iconCache$': '<rootDir>/tests/__mocks__/iconCache.js',
18
+ },
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "7.33.0",
3
+ "version": "7.33.2-EPDM-9697.0",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
@@ -8,7 +8,9 @@
8
8
  "lint": "vue-cli-service lint",
9
9
  "storybook": "start-storybook -p 6006",
10
10
  "build-storybook": "build-storybook",
11
- "prettier": "prettier --write 'src/**/*.{js,vue}'"
11
+ "prettier": "prettier --write 'src/**/*.{js,vue}'",
12
+ "test": "jest",
13
+ "prepublishOnly": "npm run test"
12
14
  },
13
15
  "dependencies": {
14
16
  "@storybook/vue3": "7.0.18",
@@ -19,19 +21,53 @@
19
21
  "html-loader": "0.5.5",
20
22
  "postcss": "8.4.25",
21
23
  "vue": "3.3.4",
24
+ "vue-router": "^4.4.2",
22
25
  "vue3-styled-components": "1.2.1",
23
26
  "vuedraggable": "4.1.0"
24
27
  },
25
28
  "devDependencies": {
26
- "babel-eslint": "10.1.0",
29
+ "@babel/core": "^7.25.2",
30
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
31
+ "@babel/preset-env": "^7.25.3",
32
+ "@types/node": "^22.1.0",
33
+ "@vue/cli-plugin-babel": "^5.0.8",
27
34
  "@vue/cli-plugin-eslint": "5.0.8",
28
- "@vue/cli-service": "5.0.8",
35
+ "@vue/cli-service": "^5.0.8",
29
36
  "@vue/compiler-sfc": "3.3.4",
37
+ "@vue/test-utils": "^2.4.6",
38
+ "babel-eslint": "10.1.0",
39
+ "babel-jest": "^26.6.3",
30
40
  "eslint": "8.0.1",
31
41
  "eslint-config-prettier": "8.8.0",
32
42
  "eslint-plugin-prettier": "4.2.1",
33
43
  "eslint-plugin-vue": "9.14.1",
34
- "prettier": "2.8.4"
44
+ "jest": "^26.6.3",
45
+ "prettier": "2.8.4",
46
+ "vue-jest": "^5.0.0-alpha.10"
47
+ },
48
+ "jest": {
49
+ "preset": "@vue/cli-plugin-unit-jest",
50
+ "transform": {
51
+ "^.+\\.vue$": "vue-jest",
52
+ "^.+\\.js$": "babel-jest"
53
+ },
54
+ "moduleFileExtensions": [
55
+ "js",
56
+ "json",
57
+ "vue"
58
+ ],
59
+ "transformIgnorePatterns": [
60
+ "<rootDir>/node_modules/"
61
+ ],
62
+ "testMatch": [
63
+ "**/tests/unit/**/*.spec.js"
64
+ ],
65
+ "collectCoverageFrom": [
66
+ "src/**/*.{js,vue}",
67
+ "!src/main.js",
68
+ "!src/router/index.js",
69
+ "!**/node_modules/**"
70
+ ]
35
71
  },
36
72
  "browserslist": [
37
73
  "> 1%",
package/src/App.vue CHANGED
@@ -1,99 +1,19 @@
1
1
  <template>
2
2
  <ThemeProvider :style="{ height: '100%' }" :theme="getTheme()">
3
- <PageContainer>
4
- <br />
5
- <InputNumber
6
- background-color="transparent"
7
- border-color="eturnityGrey"
8
- input-height="34px"
9
- input-width="420px"
10
- :interaction-step="1"
11
- :is-interactive="true"
12
- :min-number="0"
13
- :number-precision="0"
14
- text-align="left"
15
- unit-name="mm"
16
- :value="value"
17
- @input-blur="blurHandler"
18
- @input-change="changeHandler"
19
- @input-focus="focusHandler"
20
- @on-input="inputHandler"
21
- >
22
- <template #label>
23
- <div>Interactive Label 1</div>
24
- </template>
25
- </InputNumber>
26
-
27
- <hr />
28
-
29
- <InputNumber
30
- background-color="transparent"
31
- border-color="eturnityGrey"
32
- input-height="34px"
33
- input-width="420px"
34
- :interaction-step="1"
35
- :is-interactive="true"
36
- :min-number="0"
37
- :number-precision="0"
38
- text-align="left"
39
- unit-name="mm"
40
- :value="value"
41
- @input-blur="blurHandler"
42
- @input-change="changeHandler"
43
- @input-focus="focusHandler"
44
- @on-input="inputHandler"
45
- >
46
- <template #label>
47
- <div>Interactive Label 2</div>
48
- </template>
49
- </InputNumber>
50
-
51
- <hr />
52
- <button @click="value = 42">Click to set at 42</button>
53
- </PageContainer>
3
+ <RouterView />
54
4
  </ThemeProvider>
55
5
  </template>
56
6
 
57
7
  <script>
58
8
  import { ThemeProvider } from 'vue3-styled-components'
59
9
  import theme from './assets/theme'
60
- import styled from 'vue3-styled-components'
61
- import InputNumber from '@/components/inputs/inputNumber'
62
-
63
- const PageContainer = styled.div`
64
- padding: 40px;
65
- `
66
10
 
67
11
  export default {
68
12
  name: 'App',
69
13
  components: {
70
14
  ThemeProvider,
71
- PageContainer,
72
- InputNumber,
73
- },
74
- data() {
75
- return {
76
- value: 42,
77
- }
78
15
  },
79
- computed: {},
80
16
  methods: {
81
- blurHandler(e) {
82
- console.log('blur', e)
83
- },
84
- changeHandler(e) {
85
- console.log('change', e)
86
- },
87
- focusHandler(e) {
88
- console.log('focus', e)
89
- },
90
- inputHandler(e) {
91
- console.log('input', e)
92
- //this.value = e
93
- setTimeout(() => {
94
- this.value = e
95
- }, 1000)
96
- },
97
17
  getTheme() {
98
18
  return theme
99
19
  },
package/src/Test.vue ADDED
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <PageContainer>
3
+ <br />
4
+ <InputNumber
5
+ background-color="transparent"
6
+ border-color="eturnityGrey"
7
+ input-height="34px"
8
+ input-width="420px"
9
+ :interaction-step="1"
10
+ :is-interactive="true"
11
+ :min-number="0"
12
+ :number-precision="0"
13
+ text-align="left"
14
+ unit-name="mm"
15
+ :value="value"
16
+ @input-blur="blurHandler"
17
+ @input-change="changeHandler"
18
+ @input-focus="focusHandler"
19
+ @on-input="inputHandler"
20
+ >
21
+ <template #label>
22
+ <div>Interactive Label 1</div>
23
+ </template>
24
+ </InputNumber>
25
+
26
+ <hr />
27
+
28
+ <InputNumber
29
+ background-color="transparent"
30
+ border-color="eturnityGrey"
31
+ input-height="34px"
32
+ input-width="420px"
33
+ :interaction-step="1"
34
+ :is-interactive="true"
35
+ :min-number="0"
36
+ :number-precision="0"
37
+ text-align="left"
38
+ unit-name="mm"
39
+ :value="value"
40
+ @input-blur="blurHandler"
41
+ @input-change="changeHandler"
42
+ @input-focus="focusHandler"
43
+ @on-input="inputHandler"
44
+ >
45
+ <template #label>
46
+ <div>Interactive Label 2</div>
47
+ </template>
48
+ </InputNumber>
49
+
50
+ <hr />
51
+ <button @click="value = 42">Click to set at 42</button>
52
+ </PageContainer>
53
+ </template>
54
+
55
+ <script>
56
+ import styled from 'vue3-styled-components'
57
+ import InputNumber from '@/components/inputs/inputNumber'
58
+
59
+ const PageContainer = styled.div`
60
+ padding: 40px;
61
+ `
62
+
63
+ export default {
64
+ name: 'App',
65
+ components: {
66
+ PageContainer,
67
+ InputNumber,
68
+ },
69
+ data() {
70
+ return {
71
+ value: 42,
72
+ }
73
+ },
74
+ computed: {},
75
+ methods: {
76
+ blurHandler(e) {
77
+ console.log('blur', e)
78
+ },
79
+ changeHandler(e) {
80
+ console.log('change', e)
81
+ },
82
+ focusHandler(e) {
83
+ console.log('focus', e)
84
+ },
85
+ inputHandler(e) {
86
+ console.log('input', e)
87
+ //this.value = e
88
+ setTimeout(() => {
89
+ this.value = e
90
+ }, 1000)
91
+ },
92
+ },
93
+ }
94
+ </script>
95
+
96
+ <style>
97
+ html,
98
+ body {
99
+ height: 100%;
100
+ margin: 0;
101
+ }
102
+ </style>
@@ -0,0 +1 @@
1
+ export const fetchIcon = jest.fn(() => Promise.resolve('mocked-icon-url.svg'))
@@ -0,0 +1,12 @@
1
+ export function convertHexToRGB(hex) {
2
+ // Remove the '#' if it's included in the input
3
+ hex = hex.replace(/^#/, '')
4
+
5
+ // Parse the hex values into separate R, G, and B values
6
+ const red = parseInt(hex.substring(0, 2), 16)
7
+ const green = parseInt(hex.substring(2, 4), 16)
8
+ const blue = parseInt(hex.substring(4, 6), 16)
9
+
10
+ // Return the RGB values as a string
11
+ return `rgb(${red}, ${green}, ${blue})`
12
+ }
@@ -72,8 +72,7 @@
72
72
  </IconWrapper>
73
73
  <SelectWrapper v-if="showSelect">
74
74
  <Divider />
75
- <Select
76
- :disabled="isSelectDisabled"
75
+ <RCSelect
77
76
  :select-width="`${selectWidth}px`"
78
77
  :show-border="false"
79
78
  @input-change="$emit('select-change', $event)"
@@ -82,15 +81,15 @@
82
81
  <SelectText>{{ getSelectValue }}</SelectText>
83
82
  </template>
84
83
  <template #dropdown>
85
- <Option
84
+ <RCOption
86
85
  v-for="item in selectOptions"
87
86
  :key="item.value"
88
87
  :value="item.value"
89
88
  >
90
89
  {{ item.label }}
91
- </Option>
90
+ </RCOption>
92
91
  </template>
93
- </Select>
92
+ </RCSelect>
94
93
  </SelectWrapper>
95
94
  </InputWrapper>
96
95
  <ErrorMessage v-if="isError">{{ errorMessage }}</ErrorMessage>
@@ -133,8 +132,8 @@
133
132
  } from '../../../helpers/numberConverter'
134
133
  import InfoText from '../../infoText'
135
134
  import ErrorMessage from '../../errorMessage'
136
- import Select from '../select'
137
- import Option from '../select/option'
135
+ import RCSelect from '../select'
136
+ import RCOption from '../select/option'
138
137
  import warningIcon from '../../../assets/icons/error_icon.png'
139
138
  import Icon from '../../icon'
140
139
 
@@ -354,8 +353,8 @@
354
353
  Icon,
355
354
  SlotContainer,
356
355
  IconWrapper,
357
- Select,
358
- Option,
356
+ RCSelect,
357
+ RCOption,
359
358
  SelectWrapper,
360
359
  SelectText,
361
360
  Divider,
@@ -512,10 +511,6 @@
512
511
  type: [String, Number],
513
512
  default: null,
514
513
  },
515
- isSelectDisabled: {
516
- type: Boolean,
517
- default: false,
518
- },
519
514
  },
520
515
  data() {
521
516
  return {
@@ -13,7 +13,7 @@
13
13
  <LabelWrapper
14
14
  v-if="label"
15
15
  :data-id="labelDataId"
16
- :info-text-message="!!infoTextMessage || !!$slots.infoText"
16
+ :info-text-message="!!infoTextMessage"
17
17
  >
18
18
  <InputLabel
19
19
  :font-color="
@@ -181,7 +181,6 @@
181
181
  import Icon from '../../icon'
182
182
  import InputText from '../inputText'
183
183
  import DraggableInputHandle from '../../draggableInputHandle'
184
- import { debounce } from '../../../utils'
185
184
 
186
185
  const CARET_WIDTH = '30px'
187
186
  const BORDER_WIDTH = '1px'
@@ -734,9 +733,9 @@
734
733
  this.blur()
735
734
  this.$emit('input-change', e)
736
735
  },
737
- optionHovered: debounce(function (e) {
736
+ optionHovered(e) {
738
737
  this.hoveredValue = e
739
- }, 300),
738
+ },
740
739
  mouseEnterHandler() {
741
740
  if (this.hoverDropdown) {
742
741
  this.focus()
@@ -2,15 +2,21 @@
2
2
  <Container>
3
3
  <FlexWrapper
4
4
  :data-id="dataId"
5
+ data-test-id="page_wrapper"
5
6
  :disabled="disabled"
6
7
  :size="size"
7
8
  @click="onToggleChange"
8
9
  >
9
10
  <LabelContainer
10
11
  v-if="label && labelAlign === 'left'"
12
+ data-test-id="label_left_container"
11
13
  :has-info-message="!!infoTextMessage"
12
14
  >
13
- <LabelText :font-color="fontColor" :size="size">
15
+ <LabelText
16
+ data-test-id="label_left_text"
17
+ :font-color="fontColor"
18
+ :size="size"
19
+ >
14
20
  {{ label }}
15
21
  </LabelText>
16
22
  <InfoText v-if="infoTextMessage" :text="infoTextMessage" />
@@ -18,6 +24,7 @@
18
24
  <ToggleWrapper
19
25
  :background-color="backgroundColor"
20
26
  :checked="isChecked"
27
+ data-test-id="toggle_wrapper"
21
28
  :disabled="disabled"
22
29
  :is-checked="isChecked"
23
30
  role="checkbox"
@@ -27,10 +34,12 @@
27
34
  >
28
35
  <ToggleBackground
29
36
  :background-color="backgroundColor"
37
+ data-test-id="toggle_background"
30
38
  :disabled="disabled"
31
39
  :is-checked="isChecked"
32
40
  />
33
41
  <ToggleDot
42
+ data-test-id="toggle_dot"
34
43
  :disabled="disabled"
35
44
  :is-checked="isChecked"
36
45
  :size="size"
@@ -39,12 +48,22 @@
39
48
  </ToggleWrapper>
40
49
  <LabelContainer
41
50
  v-if="label && labelAlign === 'right'"
51
+ data-test-id="label_right_container"
42
52
  :has-info-message="!!infoTextMessage"
43
53
  >
44
- <LabelText :font-color="fontColor" :size="size">
54
+ <LabelText
55
+ data-test-id="label_left_text"
56
+ :font-color="fontColor"
57
+ :size="size"
58
+ >
45
59
  {{ label }}
46
60
  </LabelText>
47
- <InfoText v-if="infoTextMessage" :text="infoTextMessage" @click.stop />
61
+ <InfoText
62
+ v-if="infoTextMessage"
63
+ data-test-id="info_text"
64
+ :text="infoTextMessage"
65
+ @click.stop
66
+ />
48
67
  </LabelContainer>
49
68
  </FlexWrapper>
50
69
  </Container>
@@ -239,34 +258,47 @@
239
258
  label: {
240
259
  required: false,
241
260
  default: '',
261
+ type: String,
242
262
  },
243
263
  isChecked: {
244
264
  required: true,
245
265
  default: false,
266
+ type: Boolean,
246
267
  },
247
268
  toggleColor: {
248
269
  required: false,
270
+ default: '',
271
+ type: String,
249
272
  },
250
273
  backgroundColor: {
251
274
  required: false,
275
+ default: '',
276
+ type: String,
252
277
  },
253
278
  size: {
254
279
  required: false,
255
280
  default: 'small',
281
+ type: String,
256
282
  },
257
283
  labelAlign: {
258
284
  required: false,
259
285
  default: 'right',
286
+ type: String,
260
287
  },
261
288
  fontColor: {
262
289
  required: false,
290
+ default: '',
291
+ type: String,
263
292
  },
264
293
  disabled: {
265
294
  required: false,
266
295
  default: false,
296
+ type: Boolean,
267
297
  },
268
298
  infoTextMessage: {
269
299
  required: false,
300
+ default: '',
301
+ type: String,
270
302
  },
271
303
  dataId: {
272
304
  type: String,
@@ -0,0 +1,102 @@
1
+ /* eslint-disable */
2
+ import { mount } from '@vue/test-utils'
3
+ import RCToggle from '@/components/inputs/toggle'
4
+ import theme from '@/assets/theme'
5
+
6
+ jest.mock('@/components/icon/iconCache', () => ({
7
+ // need to mock this due to how jest handles import.meta
8
+ fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
9
+ }))
10
+
11
+ describe('RCToggle.vue', () => {
12
+ it('checkbox is rendered and emits correct payload on change', async () => {
13
+ const wrapper = mount(RCToggle, {
14
+ props: { isChecked: true, label: 'Test label', disabled: false },
15
+ global: {
16
+ provide: {
17
+ theme,
18
+ },
19
+ },
20
+ })
21
+ const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
22
+
23
+ // check that the element exists
24
+ expect(toggleWrapper.exists()).toBe(true)
25
+ expect(toggleWrapper.attributes('checked')).toBe('true')
26
+
27
+ // Log attributes to see what is rendered (commented out just for reference)
28
+ // console.log('attributes', toggleWrapper.attributes())
29
+ // console.log('All of the Toggles' attributes', wrapper.vm)
30
+
31
+ // Test the label
32
+ expect(wrapper.text()).toContain('Test label')
33
+
34
+ // Test the click
35
+ const pageWrapper = wrapper.find('[data-test-id="page_wrapper"]')
36
+ await pageWrapper.trigger('click')
37
+ expect(wrapper.emitted('on-toggle-change')).toBeTruthy()
38
+ const emittedEvent = wrapper.emitted('on-toggle-change')
39
+ // To inspect emitted events:
40
+ // console.log('Emitted events', wrapper.emitted())
41
+ expect(emittedEvent).toHaveLength(1) // Check if the event was emitted exactly once
42
+ // Check the payload of the event
43
+ expect(emittedEvent[0]).toEqual([false])
44
+ }),
45
+ it('checkbox disabled does not emit anything', async () => {
46
+ const wrapper = mount(RCToggle, {
47
+ props: { isChecked: false, disabled: true },
48
+ global: {
49
+ provide: {
50
+ theme,
51
+ },
52
+ },
53
+ })
54
+ const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
55
+ expect(toggleWrapper.attributes('checked')).toBe('false')
56
+
57
+ // Test the click
58
+ const pageWrapper = wrapper.find('[data-test-id="page_wrapper"]')
59
+ await pageWrapper.trigger('click')
60
+
61
+ // Inspect emitted events
62
+ const emittedEvents = wrapper.emitted('on-toggle-change')
63
+
64
+ // Verify that no events were emitted
65
+ expect(emittedEvents).toBeUndefined() // No event should be emitted
66
+ }),
67
+ it('should toggle back and forth on multiple clicks', async () => {
68
+ const wrapper = mount(RCToggle, {
69
+ props: { isChecked: false, disabled: false },
70
+ global: {
71
+ provide: {
72
+ theme,
73
+ },
74
+ },
75
+ })
76
+ const toggleWrapper = wrapper.find('[data-test-id="toggle_wrapper"]')
77
+ // Initial state
78
+ expect(toggleWrapper.attributes('checked')).toBe('false')
79
+
80
+ // Trigger click and check events
81
+ const pageWrapper = wrapper.find('[data-test-id="page_wrapper"]')
82
+ await pageWrapper.trigger('click')
83
+ let emittedEvent = wrapper.emitted('on-toggle-change')
84
+ expect(emittedEvent).toBeTruthy() // Ensure that the event was emitted
85
+ expect(emittedEvent).toHaveLength(1) // Ensure that only one event was emitted
86
+ expect(emittedEvent[0]).toEqual([true]) // Check the payload of the first click
87
+ await wrapper.setProps({ isChecked: true }) // manually update the props
88
+
89
+ // Trigger click again and check events
90
+ await pageWrapper.trigger('click')
91
+ emittedEvent = wrapper.emitted('on-toggle-change')
92
+ expect(emittedEvent).toHaveLength(2) // Ensure that the event count has increased
93
+ expect(emittedEvent[1]).toEqual([false]) // Check the payload of the second click
94
+ await wrapper.setProps({ isChecked: false }) // manually update the props
95
+
96
+ // Trigger click again and check events
97
+ await pageWrapper.trigger('click')
98
+ emittedEvent = wrapper.emitted('on-toggle-change')
99
+ expect(emittedEvent).toHaveLength(3) // Ensure that the event count has increased
100
+ expect(emittedEvent[2]).toEqual([true]) // Check the payload of the third click
101
+ })
102
+ })
package/src/main.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import App from './App.vue'
2
2
  import { createApp } from 'vue'
3
+ import router from './router/dynamicRoutes'
3
4
 
4
5
  const app = createApp(App)
5
-
6
+ app.use(router)
6
7
  app.mount('#app')
@@ -0,0 +1,23 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+ import Test from '@/Test.vue'
3
+ import Toggle from '@/components/inputs/toggle/index.vue'
4
+
5
+ const routes = [
6
+ {
7
+ path: '/',
8
+ name: 'Test',
9
+ component: Test,
10
+ },
11
+ {
12
+ path: '/toggle',
13
+ name: 'Toggle',
14
+ component: Toggle,
15
+ },
16
+ ]
17
+
18
+ const router = createRouter({
19
+ history: createWebHistory(),
20
+ routes,
21
+ })
22
+
23
+ export default router
@@ -1,12 +0,0 @@
1
- export function debounce(fn, wait) {
2
- let timer
3
- return function (...args) {
4
- if (timer) {
5
- clearTimeout(timer)
6
- }
7
- const context = this
8
- timer = setTimeout(() => {
9
- fn.apply(context, args)
10
- }, wait)
11
- }
12
- }