@nexxtmove/ui 2.5.0 → 2.7.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/dist/components/editor/molecules/EditorBorder/EditorBorder.vue.d.ts +12 -0
- package/dist/components/editor/molecules/EditorColor/_ThemeRoleSwatches.vue.d.ts +16 -0
- package/dist/index.js +1094 -1135
- package/dist/nuxt.js +0 -1
- package/package.json +38 -36
- package/src/attribute-contract.test.ts +151 -0
- package/src/components/atoms/AnimatedNumber/AnimatedNumber.stories.ts +36 -0
- package/src/components/atoms/AnimatedNumber/AnimatedNumber.test.ts +21 -0
- package/src/components/atoms/Avatar/Avatar.stories.ts +122 -0
- package/src/components/atoms/Avatar/Avatar.test.ts +134 -0
- package/src/components/atoms/Button/Button.stories.ts +290 -0
- package/src/components/atoms/Button/Button.test.ts +406 -0
- package/src/components/atoms/Card/Card.stories.ts +45 -0
- package/src/components/atoms/Card/Card.test.ts +46 -0
- package/src/components/atoms/Checkbox/Checkbox.stories.ts +35 -0
- package/src/components/atoms/Checkbox/Checkbox.test.ts +55 -0
- package/src/components/atoms/Chip/Chip.stories.ts +274 -0
- package/src/components/atoms/Chip/Chip.test.ts +230 -0
- package/src/components/atoms/EnergyLabel/EnergyLabel.stories.ts +189 -0
- package/src/components/atoms/EnergyLabel/EnergyLabel.test.ts +100 -0
- package/src/components/atoms/FloatingPanel/FloatingPanel.stories.ts +677 -0
- package/src/components/atoms/FloatingPanel/FloatingPanel.test.ts +864 -0
- package/src/components/atoms/Icon/Icon.stories.ts +63 -0
- package/src/components/atoms/Icon/Icon.test.ts +89 -0
- package/src/components/atoms/Loader/Loader.stories.ts +36 -0
- package/src/components/atoms/Loader/Loader.test.ts +40 -0
- package/src/components/atoms/PickerItem/PickerItem.stories.ts +172 -0
- package/src/components/atoms/PickerItem/PickerItem.test.ts +142 -0
- package/src/components/atoms/PickerPreview/PickerPreview.stories.ts +183 -0
- package/src/components/atoms/PickerPreview/PickerPreview.test.ts +137 -0
- package/src/components/atoms/PresenceIndicator/PresenceIndicator.stories.ts +21 -0
- package/src/components/atoms/PropertyListing/PropertyListing.stories.ts +38 -0
- package/src/components/atoms/PropertyListing/PropertyListing.test.ts +46 -0
- package/src/components/atoms/SelectableOption/SelectableOption.stories.ts +131 -0
- package/src/components/atoms/SelectableOption/SelectableOption.test.ts +96 -0
- package/src/components/atoms/Skeleton/Skeleton.stories.ts +27 -0
- package/src/components/atoms/Skeleton/Skeleton.test.ts +28 -0
- package/src/components/atoms/Slider/Slider.stories.ts +151 -0
- package/src/components/atoms/Slider/Slider.test.ts +191 -0
- package/src/components/atoms/Squircle/Squircle.stories.ts +114 -0
- package/src/components/atoms/Squircle/Squircle.test.ts +70 -0
- package/src/components/atoms/Switch/Switch.stories.ts +91 -0
- package/src/components/atoms/Switch/Switch.test.ts +183 -0
- package/src/components/atoms/Tooltip/Tooltip.stories.ts +158 -0
- package/src/components/atoms/Tooltip/Tooltip.test.ts +134 -0
- package/src/components/editor/atoms/EditorDimensionField/EditorDimensionField.stories.ts +124 -0
- package/src/components/editor/atoms/EditorDimensionField/EditorDimensionField.test.ts +464 -0
- package/src/components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.stories.ts +266 -0
- package/src/components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.test.ts +421 -0
- package/src/components/editor/atoms/EditorSettingsGroup/EditorSettingsGroup.stories.ts +365 -0
- package/src/components/editor/atoms/EditorSettingsGroup/EditorSettingsGroup.test.ts +484 -0
- package/src/components/editor/composables/useRadioGrid.test.ts +261 -0
- package/src/components/editor/molecules/EditorAlignItems/EditorAlignItems.stories.ts +73 -0
- package/src/components/editor/molecules/EditorAlignItems/EditorAlignItems.test.ts +189 -0
- package/src/components/editor/molecules/EditorAlignmentGrid/EditorAlignmentGrid.stories.ts +309 -0
- package/src/components/editor/molecules/EditorAlignmentGrid/EditorAlignmentGrid.test.ts +359 -0
- package/src/components/editor/molecules/EditorAnchor/EditorAnchor.stories.ts +138 -0
- package/src/components/editor/molecules/EditorAnchor/EditorAnchor.test.ts +344 -0
- package/src/components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.stories.ts +87 -0
- package/src/components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.test.ts +262 -0
- package/src/components/editor/molecules/EditorBlur/EditorBlur.stories.ts +115 -0
- package/src/components/editor/molecules/EditorBlur/EditorBlur.test.ts +243 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.stories.ts +187 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.test.ts +456 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.vue +58 -2
- package/src/components/editor/molecules/EditorColor/EditorColor.stories.ts +563 -0
- package/src/components/editor/molecules/EditorColor/EditorColor.test.ts +689 -0
- package/src/components/editor/molecules/EditorColor/EditorColorGradient.test.ts +793 -0
- package/src/components/editor/molecules/EditorColor/_ColorField.vue +7 -29
- package/src/components/editor/molecules/EditorColor/_ThemeRoleSwatches.vue +57 -0
- package/src/components/editor/molecules/EditorColor/gradientClass.test.ts +303 -0
- package/src/components/editor/molecules/EditorDashPattern/EditorDashPattern.stories.ts +72 -0
- package/src/components/editor/molecules/EditorDashPattern/EditorDashPattern.test.ts +124 -0
- package/src/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.stories.ts +46 -0
- package/src/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.test.ts +97 -0
- package/src/components/editor/molecules/EditorFontSize/EditorFontSize.stories.ts +248 -0
- package/src/components/editor/molecules/EditorFontSize/EditorFontSize.test.ts +288 -0
- package/src/components/editor/molecules/EditorGap/EditorGap.stories.ts +129 -0
- package/src/components/editor/molecules/EditorGap/EditorGap.test.ts +253 -0
- package/src/components/editor/molecules/EditorHeadingType/EditorHeadingType.stories.ts +68 -0
- package/src/components/editor/molecules/EditorHeadingType/EditorHeadingType.test.ts +150 -0
- package/src/components/editor/molecules/EditorJustifyContent/EditorJustifyContent.stories.ts +71 -0
- package/src/components/editor/molecules/EditorJustifyContent/EditorJustifyContent.test.ts +161 -0
- package/src/components/editor/molecules/EditorLetterSpacing/EditorLetterSpacing.stories.ts +204 -0
- package/src/components/editor/molecules/EditorLetterSpacing/EditorLetterSpacing.test.ts +238 -0
- package/src/components/editor/molecules/EditorLineHeight/EditorLineHeight.stories.ts +257 -0
- package/src/components/editor/molecules/EditorLineHeight/EditorLineHeight.test.ts +286 -0
- package/src/components/editor/molecules/EditorLineStyle/EditorLineStyle.stories.ts +135 -0
- package/src/components/editor/molecules/EditorLineStyle/EditorLineStyle.test.ts +230 -0
- package/src/components/editor/molecules/EditorMaxWidth/EditorMaxWidth.stories.ts +154 -0
- package/src/components/editor/molecules/EditorMaxWidth/EditorMaxWidth.test.ts +112 -0
- package/src/components/editor/molecules/EditorOverrideStatus/EditorOverrideStatus.stories.ts +206 -0
- package/src/components/editor/molecules/EditorOverrideStatus/EditorOverrideStatus.test.ts +332 -0
- package/src/components/editor/molecules/EditorPadding/EditorPadding.stories.ts +374 -0
- package/src/components/editor/molecules/EditorPadding/EditorPadding.test.ts +712 -0
- package/src/components/editor/molecules/EditorRadius/EditorRadius.stories.ts +64 -0
- package/src/components/editor/molecules/EditorRadius/EditorRadius.test.ts +137 -0
- package/src/components/editor/molecules/EditorShadow/EditorShadow.stories.ts +103 -0
- package/src/components/editor/molecules/EditorShadow/EditorShadow.test.ts +168 -0
- package/src/components/editor/molecules/EditorSize/EditorSize.stories.ts +84 -0
- package/src/components/editor/molecules/EditorSize/EditorSize.test.ts +253 -0
- package/src/components/editor/molecules/EditorSizeLimit/EditorSizeLimit.stories.ts +49 -0
- package/src/components/editor/molecules/EditorSizeLimit/EditorSizeLimit.test.ts +43 -0
- package/src/components/editor/molecules/EditorTextAlign/EditorTextAlign.stories.ts +69 -0
- package/src/components/editor/molecules/EditorTextAlign/EditorTextAlign.test.ts +155 -0
- package/src/components/molecules/Announcement/Announcement.stories.ts +224 -0
- package/src/components/molecules/Announcement/Announcement.test.ts +161 -0
- package/src/components/molecules/ContactInfoCard/ContactInfoCard.stories.ts +99 -0
- package/src/components/molecules/ContactInfoCard/ContactInfoCard.test.ts +70 -0
- package/src/components/molecules/CustomerJourneyTile/CustomerJourneyTile.stories.ts +148 -0
- package/src/components/molecules/CustomerJourneyTile/CustomerJourneyTile.test.ts +271 -0
- package/src/components/molecules/DoughnutChart/DoughnutChart.stories.ts +45 -0
- package/src/components/molecules/DoughnutChart/DoughnutChart.test.ts +205 -0
- package/src/components/molecules/InfoBlock/InfoBlock.stories.ts +84 -0
- package/src/components/molecules/InfoBlock/InfoBlock.test.ts +101 -0
- package/src/components/molecules/InputField/InputField.stories.ts +117 -0
- package/src/components/molecules/InputField/InputField.test.ts +138 -0
- package/src/components/molecules/InputSelect/InputSelect.stories.ts +116 -0
- package/src/components/molecules/InputSelect/InputSelect.test.ts +127 -0
- package/src/components/molecules/ModalFooter/ModalFooter.stories.ts +204 -0
- package/src/components/molecules/ModalFooter/ModalFooter.test.ts +276 -0
- package/src/components/molecules/PageCard/PageCard.stories.ts +100 -0
- package/src/components/molecules/PageCard/PageCard.test.ts +91 -0
- package/src/components/molecules/PageContainer/PageContainer.stories.ts +90 -0
- package/src/components/molecules/PageContainer/PageContainer.test.ts +50 -0
- package/src/components/molecules/PageMockup/PageMockup.stories.ts +38 -0
- package/src/components/molecules/PageMockup/PageMockup.test.ts +20 -0
- package/src/components/molecules/PageTypeTile/PageTypeTile.stories.ts +63 -0
- package/src/components/molecules/PageTypeTile/PageTypeTile.test.ts +41 -0
- package/src/components/molecules/Pagination/Pagination.stories.ts +72 -0
- package/src/components/molecules/Pagination/Pagination.test.ts +130 -0
- package/src/components/molecules/PickerGroup/PickerGroup.stories.ts +90 -0
- package/src/components/molecules/PickerGroup/PickerGroup.test.ts +145 -0
- package/src/components/molecules/PickerList/PickerList.stories.ts +436 -0
- package/src/components/molecules/PickerList/PickerList.test.ts +870 -0
- package/src/components/molecules/PlaceholderInput/PlaceholderInput.stories.ts +48 -0
- package/src/components/molecules/PlaceholderInput/PlaceholderInput.test.ts +107 -0
- package/src/components/molecules/PropertyCard/PropertyCard.stories.ts +46 -0
- package/src/components/molecules/PropertyCard/PropertyCard.test.ts +59 -0
- package/src/components/molecules/Select/Select.stories.ts +264 -0
- package/src/components/molecules/Select/Select.test.ts +315 -0
- package/src/components/molecules/SidebarMenuItem/SidebarMenuItem.stories.ts +84 -0
- package/src/components/molecules/SidebarMenuItem/SidebarMenuItem.test.ts +103 -0
- package/src/components/molecules/SkeletonPropertyCard/SkeletonPropertyCard.stories.ts +11 -0
- package/src/components/molecules/SkeletonPropertyCard/SkeletonPropertyCard.test.ts +38 -0
- package/src/components/molecules/SocialIcons/SocialIcons.stories.ts +28 -0
- package/src/components/molecules/SocialIcons/SocialIcons.test.ts +58 -0
- package/src/components/molecules/SocialMediaCustomTemplate/SocialMediaCustomTemplate.stories.ts +11 -0
- package/src/components/molecules/SocialMediaCustomTemplate/SocialMediaCustomTemplate.test.ts +116 -0
- package/src/components/molecules/SocialMediaType/SocialMediaType.stories.ts +37 -0
- package/src/components/molecules/SocialMediaType/SocialMediaType.test.ts +126 -0
- package/src/components/molecules/Source/Source.stories.ts +35 -0
- package/src/components/molecules/Source/Source.test.ts +45 -0
- package/src/components/molecules/TabbedContent/TabbedContent.stories.ts +96 -0
- package/src/components/molecules/TabbedContent/TabbedContent.test.ts +109 -0
- package/src/components/molecules/Tabs/Tabs.stories.ts +230 -0
- package/src/components/molecules/Tabs/Tabs.test.ts +280 -0
- package/src/components/molecules/TemplateCard/TemplateCard.stories.ts +327 -0
- package/src/components/molecules/TemplateCard/TemplateCard.test.ts +339 -0
- package/src/components/molecules/Textarea/Textarea.stories.ts +216 -0
- package/src/components/molecules/Textarea/Textarea.test.ts +191 -0
- package/src/components/molecules/TimelineEvent/TimelineEvent.stories.ts +319 -0
- package/src/components/molecules/TimelineEvent/TimelineEvent.test.ts +224 -0
- package/src/components/molecules/TimelineLanes/TimelineLanes.stories.ts +29 -0
- package/src/components/molecules/TimelineLanes/TimelineLanes.test.ts +30 -0
- package/src/components/molecules/Toast/Toast.stories.ts +110 -0
- package/src/components/molecules/Toast/Toast.test.ts +103 -0
- package/src/components/molecules/ToggleGroup/ToggleGroup.stories.ts +297 -0
- package/src/components/molecules/ToggleGroup/ToggleGroup.test.ts +578 -0
- package/src/components/molecules/Tree/Tree.stories.ts +884 -0
- package/src/components/molecules/Tree/Tree.test.ts +1247 -0
- package/src/components/molecules/Tree/tree-drop.test.ts +223 -0
- package/src/components/organisms/Calendar/Calendar.stories.ts +108 -0
- package/src/components/organisms/Calendar/Calendar.test.ts +279 -0
- package/src/components/organisms/Calendar/_CalendarDayView.test.ts +104 -0
- package/src/components/organisms/Calendar/_CalendarHeader.test.ts +86 -0
- package/src/components/organisms/Calendar/_CalendarMonthView.test.ts +52 -0
- package/src/components/organisms/Calendar/_CalendarTimePicker.test.ts +89 -0
- package/src/components/organisms/Calendar/_CalendarYearView.test.ts +56 -0
- package/src/components/organisms/ColorPicker/ColorPicker.stories.ts +229 -0
- package/src/components/organisms/ColorPicker/ColorPicker.test.ts +638 -0
- package/src/components/organisms/ColorPicker/gradient.test.ts +67 -0
- package/src/components/organisms/ColorPicker/gradientGeometry.test.ts +206 -0
- package/src/components/organisms/Combobox/Combobox.stories.ts +234 -0
- package/src/components/organisms/Combobox/Combobox.test.ts +512 -0
- package/src/components/organisms/Combobox/Combobox.vue +1 -1
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.stories.ts +158 -0
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.test.ts +524 -0
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.vue +1 -1
- package/src/components/organisms/CountrySelect/CountrySelect.stories.ts +139 -0
- package/src/components/organisms/CountrySelect/CountrySelect.test.ts +149 -0
- package/src/components/organisms/DatePicker/DatePicker.stories.ts +163 -0
- package/src/components/organisms/DatePicker/DatePicker.test.ts +214 -0
- package/src/components/organisms/DropdownButton/DropdownButton.stories.ts +123 -0
- package/src/components/organisms/DropdownButton/DropdownButton.test.ts +379 -0
- package/src/components/organisms/FontPicker/FontPicker.stories.ts +476 -0
- package/src/components/organisms/FontPicker/FontPicker.test.ts +873 -0
- package/src/components/organisms/Header/Header.stories.ts +75 -0
- package/src/components/organisms/Header/Header.test.ts +233 -0
- package/src/components/organisms/IconPicker/IconPicker.stories.ts +734 -0
- package/src/components/organisms/IconPicker/IconPicker.test.ts +669 -0
- package/src/components/organisms/IconPicker/_IconPickerGrid.test.ts +184 -0
- package/src/components/organisms/IconPicker/_IconPickerRail.test.ts +102 -0
- package/src/components/organisms/IconPicker/useIconPickerNavigation.test.ts +215 -0
- package/src/components/organisms/Modal/Modal.stories.ts +350 -0
- package/src/components/organisms/Modal/Modal.test.ts +275 -0
- package/src/components/organisms/PickerPanel/PickerPanel.stories.ts +452 -0
- package/src/components/organisms/PickerPanel/PickerPanel.test.ts +358 -0
- package/src/components/organisms/ProgressBar/ProgressBar.stories.ts +100 -0
- package/src/components/organisms/ProgressBar/ProgressBar.test.ts +417 -0
- package/src/components/organisms/ReferenceCard/ReferenceCard.stories.ts +191 -0
- package/src/components/organisms/ReferenceCard/ReferenceCard.test.ts +165 -0
- package/src/components/organisms/SocialMediaTemplate/SocialMediaTemplate.stories.ts +65 -0
- package/src/components/organisms/SocialMediaTemplate/SocialMediaTemplate.test.ts +466 -0
- package/src/components/organisms/StepperHeader/StepperHeader.stories.ts +91 -0
- package/src/components/organisms/StepperHeader/StepperHeader.test.ts +279 -0
- package/src/components/organisms/Table/Table.stories.ts +332 -0
- package/src/components/organisms/Table/Table.test.ts +320 -0
- package/src/components/organisms/TimelinePhaseblock/TimelinePhaseblock.stories.ts +198 -0
- package/src/components/organisms/TimelinePhaseblock/TimelinePhaseblock.test.ts +283 -0
- package/src/components/organisms/TimelineTrack/TimelineTrack.stories.ts +120 -0
- package/src/components/organisms/TimelineTrack/TimelineTrack.test.ts +91 -0
- package/src/components/organisms/Toaster/Toaster.stories.ts +51 -0
- package/src/components/organisms/Toaster/Toaster.test.ts +75 -0
- package/src/components/organisms/VideoControls/VideoControls.stories.ts +792 -0
- package/src/components/organisms/VideoControls/VideoControls.test.ts +1056 -0
- package/src/components/organisms/VideoPlayer/VideoPlayer.stories.ts +327 -0
- package/src/components/organisms/VideoPlayer/VideoPlayer.test.ts +439 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils'
|
|
3
|
+
import EditorDimensionField from './EditorDimensionField.vue'
|
|
4
|
+
import type { EditorDimensionValue } from './EditorDimensionField.vue'
|
|
5
|
+
|
|
6
|
+
let wrapper: VueWrapper
|
|
7
|
+
|
|
8
|
+
const mountField = (
|
|
9
|
+
modelValue: EditorDimensionValue | null,
|
|
10
|
+
props: Record<string, unknown> = {},
|
|
11
|
+
) => {
|
|
12
|
+
wrapper = mount(EditorDimensionField, {
|
|
13
|
+
props: {
|
|
14
|
+
label: 'Breedte',
|
|
15
|
+
modelValue,
|
|
16
|
+
// Feed every write back in, the way `v-model` does.
|
|
17
|
+
'onUpdate:modelValue': (value: EditorDimensionValue | null) =>
|
|
18
|
+
wrapper.setProps({ modelValue: value }),
|
|
19
|
+
...props,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
return wrapper
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const input = () => wrapper.get('input')
|
|
26
|
+
|
|
27
|
+
const shown = () => (input().element as HTMLInputElement).value
|
|
28
|
+
|
|
29
|
+
const writes = () => wrapper.emitted('update:modelValue')?.map(([value]) => value) ?? []
|
|
30
|
+
|
|
31
|
+
const commits = () => wrapper.emitted('commit')?.length ?? 0
|
|
32
|
+
|
|
33
|
+
const commit = async (typed: string) => {
|
|
34
|
+
await input().setValue(typed)
|
|
35
|
+
await input().trigger('blur')
|
|
36
|
+
await flushPromises()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const press = async (key: string, options: Record<string, unknown> = {}) => {
|
|
40
|
+
await input().trigger('keydown', { key, ...options })
|
|
41
|
+
await flushPromises()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const release = async (key: string) => {
|
|
45
|
+
await input().trigger('keyup', { key })
|
|
46
|
+
await flushPromises()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Types text the number input cannot parse. jsdom empties the value as a
|
|
51
|
+
* browser does, but never sets `badInput`, so that part is stubbed.
|
|
52
|
+
*/
|
|
53
|
+
const typeUnparseable = async (typed: string) => {
|
|
54
|
+
Object.defineProperty(input().element, 'validity', { value: { badInput: true } })
|
|
55
|
+
await input().setValue(typed)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const pickUnit = async (unit: string) => {
|
|
59
|
+
await wrapper.get('select').setValue(unit)
|
|
60
|
+
await flushPromises()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('EditorDimensionField', () => {
|
|
64
|
+
it('is a whole-number input bounded by the range of its unit', async () => {
|
|
65
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'], max: { px: 800 } })
|
|
66
|
+
|
|
67
|
+
expect(input().attributes()).toMatchObject({ type: 'number', step: '1', min: '40', max: '800' })
|
|
68
|
+
|
|
69
|
+
await pickUnit('%')
|
|
70
|
+
expect(input().attributes()).toMatchObject({ min: '1', max: '100' })
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe('typing', () => {
|
|
74
|
+
it('writes a confirmed value in the current unit', async () => {
|
|
75
|
+
mountField({ value: 200, unit: 'px' })
|
|
76
|
+
|
|
77
|
+
await commit('320')
|
|
78
|
+
|
|
79
|
+
expect(writes()).toEqual([{ value: 320, unit: 'px' }])
|
|
80
|
+
expect(shown()).toBe('320')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('writes nothing while typing, only on blur or Enter', async () => {
|
|
84
|
+
mountField({ value: 200, unit: 'px' })
|
|
85
|
+
|
|
86
|
+
await input().setValue('3')
|
|
87
|
+
expect(writes()).toEqual([])
|
|
88
|
+
|
|
89
|
+
await press('Enter')
|
|
90
|
+
expect(writes()).toEqual([{ value: 40, unit: 'px' }])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('clamps px to 40..1600 by default', async () => {
|
|
94
|
+
mountField({ value: 200, unit: 'px' })
|
|
95
|
+
|
|
96
|
+
await commit('10')
|
|
97
|
+
expect(shown()).toBe('40')
|
|
98
|
+
|
|
99
|
+
await commit('5000')
|
|
100
|
+
expect(shown()).toBe('1600')
|
|
101
|
+
expect(writes()).toEqual([
|
|
102
|
+
{ value: 40, unit: 'px' },
|
|
103
|
+
{ value: 1600, unit: 'px' },
|
|
104
|
+
])
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('clamps % to 1..100 by default', async () => {
|
|
108
|
+
mountField({ value: 50, unit: '%' }, { units: ['px', '%'] })
|
|
109
|
+
|
|
110
|
+
await commit('0')
|
|
111
|
+
expect(shown()).toBe('1')
|
|
112
|
+
|
|
113
|
+
await commit('150')
|
|
114
|
+
expect(shown()).toBe('100')
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('takes min and max per unit, keeping the defaults of the other unit', async () => {
|
|
118
|
+
mountField(
|
|
119
|
+
{ value: 50, unit: '%' },
|
|
120
|
+
{ units: ['px', '%'], min: { '%': 10 }, max: { px: 800 } },
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
await commit('5')
|
|
124
|
+
expect(shown()).toBe('10')
|
|
125
|
+
|
|
126
|
+
await pickUnit('px')
|
|
127
|
+
await commit('1000')
|
|
128
|
+
expect(shown()).toBe('800')
|
|
129
|
+
|
|
130
|
+
await commit('1')
|
|
131
|
+
expect(shown()).toBe('40')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('puts the old value back for text that is not a number', async () => {
|
|
135
|
+
mountField({ value: 200, unit: 'px' })
|
|
136
|
+
|
|
137
|
+
await typeUnparseable('12a')
|
|
138
|
+
await input().trigger('blur')
|
|
139
|
+
await flushPromises()
|
|
140
|
+
|
|
141
|
+
expect(writes()).toEqual([])
|
|
142
|
+
expect(shown()).toBe('200')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('does not take unparseable text in an optional field for an emptied one', async () => {
|
|
146
|
+
mountField({ value: 200, unit: 'px' }, { optional: true })
|
|
147
|
+
|
|
148
|
+
await typeUnparseable('12a')
|
|
149
|
+
await press('Enter')
|
|
150
|
+
|
|
151
|
+
expect(writes()).toEqual([])
|
|
152
|
+
expect(commits()).toBe(0)
|
|
153
|
+
expect(shown()).toBe('200')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('puts the old value back for numbers that are not whole and positive', async () => {
|
|
157
|
+
mountField({ value: 200, unit: 'px' })
|
|
158
|
+
|
|
159
|
+
await commit('1.5')
|
|
160
|
+
await commit('-5')
|
|
161
|
+
await commit('1e2')
|
|
162
|
+
|
|
163
|
+
expect(writes()).toEqual([])
|
|
164
|
+
expect(shown()).toBe('200')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('puts the old value back for an emptied field that is not optional', async () => {
|
|
168
|
+
mountField({ value: 200, unit: 'px' })
|
|
169
|
+
|
|
170
|
+
await commit('')
|
|
171
|
+
|
|
172
|
+
expect(writes()).toEqual([])
|
|
173
|
+
expect(shown()).toBe('200')
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('writes null for an emptied optional field, and shows the placeholder', async () => {
|
|
177
|
+
mountField({ value: 200, unit: 'px' }, { optional: true })
|
|
178
|
+
|
|
179
|
+
await commit('')
|
|
180
|
+
|
|
181
|
+
expect(writes()).toEqual([null])
|
|
182
|
+
expect(input().attributes('placeholder')).toBe('Geen')
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('shows the unit next to the placeholder of an empty optional field', () => {
|
|
186
|
+
mountField(null, { optional: true })
|
|
187
|
+
|
|
188
|
+
expect(input().attributes('placeholder')).toBe('Geen')
|
|
189
|
+
expect(wrapper.get('[data-testid="editor-dimension-unit"]').text()).toBe('px')
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
describe('Escape', () => {
|
|
194
|
+
it('reverts the typing without writing, and keeps the key to itself', async () => {
|
|
195
|
+
mountField({ value: 200, unit: 'px' })
|
|
196
|
+
const bubbled: Event[] = []
|
|
197
|
+
wrapper.element.parentElement?.addEventListener('keydown', (event: Event) =>
|
|
198
|
+
bubbled.push(event),
|
|
199
|
+
)
|
|
200
|
+
wrapper.element.addEventListener('keydown', (event: Event) => bubbled.push(event))
|
|
201
|
+
|
|
202
|
+
await input().setValue('999')
|
|
203
|
+
await press('Escape')
|
|
204
|
+
|
|
205
|
+
expect(shown()).toBe('200')
|
|
206
|
+
expect(writes()).toEqual([])
|
|
207
|
+
expect(bubbled).toEqual([])
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('reverts unparseable text in an empty field, though the value reads as empty', async () => {
|
|
211
|
+
mountField(null, { optional: true })
|
|
212
|
+
const bubbled: Event[] = []
|
|
213
|
+
wrapper.element.addEventListener('keydown', (event: Event) => bubbled.push(event))
|
|
214
|
+
|
|
215
|
+
await typeUnparseable('abc')
|
|
216
|
+
await press('Escape')
|
|
217
|
+
|
|
218
|
+
expect(bubbled).toEqual([])
|
|
219
|
+
expect(writes()).toEqual([])
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('lets the key through when there is nothing to revert', async () => {
|
|
223
|
+
mountField({ value: 200, unit: 'px' })
|
|
224
|
+
const bubbled: Event[] = []
|
|
225
|
+
wrapper.element.addEventListener('keydown', (event: Event) => bubbled.push(event))
|
|
226
|
+
|
|
227
|
+
await press('Escape')
|
|
228
|
+
|
|
229
|
+
expect(bubbled).toHaveLength(1)
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
describe('arrow keys', () => {
|
|
234
|
+
it('steps by 1, and by 10 with Shift', async () => {
|
|
235
|
+
mountField({ value: 200, unit: 'px' })
|
|
236
|
+
|
|
237
|
+
await press('ArrowUp')
|
|
238
|
+
await press('ArrowDown', { shiftKey: true })
|
|
239
|
+
|
|
240
|
+
expect(writes()).toEqual([
|
|
241
|
+
{ value: 201, unit: 'px' },
|
|
242
|
+
{ value: 191, unit: 'px' },
|
|
243
|
+
])
|
|
244
|
+
expect(shown()).toBe('191')
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('stops at the ends of the range', async () => {
|
|
248
|
+
mountField({ value: 1595, unit: 'px' })
|
|
249
|
+
|
|
250
|
+
await press('ArrowUp', { shiftKey: true })
|
|
251
|
+
await press('ArrowUp')
|
|
252
|
+
|
|
253
|
+
expect(writes()).toEqual([{ value: 1600, unit: 'px' }])
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it('starts an empty field at the minimum', async () => {
|
|
257
|
+
mountField(null, { optional: true })
|
|
258
|
+
|
|
259
|
+
await press('ArrowDown')
|
|
260
|
+
|
|
261
|
+
expect(writes()).toEqual([{ value: 40, unit: 'px' }])
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
describe('commit', () => {
|
|
266
|
+
it('follows a typed value straight away', async () => {
|
|
267
|
+
mountField({ value: 200, unit: 'px' })
|
|
268
|
+
|
|
269
|
+
await commit('300')
|
|
270
|
+
|
|
271
|
+
expect(commits()).toBe(1)
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('is not emitted when a typed value changes nothing', async () => {
|
|
275
|
+
mountField({ value: 200, unit: 'px' })
|
|
276
|
+
|
|
277
|
+
await commit('200')
|
|
278
|
+
await commit('abc')
|
|
279
|
+
|
|
280
|
+
expect(commits()).toBe(0)
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
it('ends a stream of arrow steps once, when the key is let go', async () => {
|
|
284
|
+
mountField({ value: 200, unit: 'px' })
|
|
285
|
+
|
|
286
|
+
await press('ArrowUp')
|
|
287
|
+
await press('ArrowUp')
|
|
288
|
+
await press('ArrowUp')
|
|
289
|
+
expect(commits()).toBe(0)
|
|
290
|
+
|
|
291
|
+
await release('ArrowUp')
|
|
292
|
+
expect(commits()).toBe(1)
|
|
293
|
+
expect(writes()).toHaveLength(3)
|
|
294
|
+
|
|
295
|
+
// Blurring afterwards has nothing left to close.
|
|
296
|
+
await input().trigger('blur')
|
|
297
|
+
await flushPromises()
|
|
298
|
+
expect(commits()).toBe(1)
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('ends a stream on blur when the keyup never came', async () => {
|
|
302
|
+
mountField({ value: 200, unit: 'px' })
|
|
303
|
+
|
|
304
|
+
await press('ArrowUp')
|
|
305
|
+
await input().trigger('blur')
|
|
306
|
+
await flushPromises()
|
|
307
|
+
|
|
308
|
+
expect(commits()).toBe(1)
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('is not emitted for an arrow key that changed nothing', async () => {
|
|
312
|
+
mountField({ value: 1600, unit: 'px' })
|
|
313
|
+
|
|
314
|
+
await press('ArrowUp')
|
|
315
|
+
await release('ArrowUp')
|
|
316
|
+
|
|
317
|
+
expect(commits()).toBe(0)
|
|
318
|
+
})
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
describe('units', () => {
|
|
322
|
+
it('shows one unit as text, without a selector', () => {
|
|
323
|
+
mountField({ value: 200, unit: 'px' })
|
|
324
|
+
|
|
325
|
+
expect(wrapper.find('select').exists()).toBe(false)
|
|
326
|
+
expect(input().attributes('aria-label')).toBe('Breedte (px)')
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
it('offers more than one unit as a named selector', () => {
|
|
330
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'] })
|
|
331
|
+
|
|
332
|
+
const select = wrapper.get('select')
|
|
333
|
+
expect(select.attributes('aria-label')).toBe('Eenheid')
|
|
334
|
+
expect(select.findAll('option').map((option) => option.text())).toEqual(['px', '%'])
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
it('shows the selector of an empty optional field', () => {
|
|
338
|
+
mountField(null, { units: ['px', '%'], optional: true })
|
|
339
|
+
|
|
340
|
+
expect(input().attributes('placeholder')).toBe('Geen')
|
|
341
|
+
expect(wrapper.get('[data-testid="editor-dimension-unit"]').classes()).not.toContain('hidden')
|
|
342
|
+
expect(wrapper.find('select').exists()).toBe(true)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
it('keeps its keyboard focus style for the keyboard, not for a pick with the pointer', async () => {
|
|
346
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'] })
|
|
347
|
+
const select = wrapper.get('select')
|
|
348
|
+
|
|
349
|
+
// Chromium counts a clicked <select> as :focus-visible; the attribute opts out.
|
|
350
|
+
await select.trigger('pointerdown')
|
|
351
|
+
await pickUnit('%')
|
|
352
|
+
expect(select.attributes('data-pointer')).toBe('true')
|
|
353
|
+
|
|
354
|
+
await select.trigger('keydown', { key: 'ArrowDown' })
|
|
355
|
+
expect(select.attributes('data-pointer')).toBeUndefined()
|
|
356
|
+
|
|
357
|
+
await select.trigger('pointerdown')
|
|
358
|
+
await select.trigger('blur')
|
|
359
|
+
expect(select.attributes('data-pointer')).toBeUndefined()
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('gives keyboard focus its style after a click that did not focus the selector', async () => {
|
|
363
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'] })
|
|
364
|
+
const select = wrapper.get('select')
|
|
365
|
+
|
|
366
|
+
// Safari and Firefox on macOS: the click does not focus the select.
|
|
367
|
+
await select.trigger('pointerdown')
|
|
368
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
369
|
+
|
|
370
|
+
// Later, Tab or Shift+Tab lands on it.
|
|
371
|
+
await select.trigger('focus')
|
|
372
|
+
expect(select.attributes('data-pointer')).toBeUndefined()
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it('treats a focus in the same task as the pointerdown as a click', async () => {
|
|
376
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'] })
|
|
377
|
+
const select = wrapper.get('select')
|
|
378
|
+
|
|
379
|
+
select.element.dispatchEvent(new Event('pointerdown'))
|
|
380
|
+
select.element.dispatchEvent(new Event('focus'))
|
|
381
|
+
await flushPromises()
|
|
382
|
+
|
|
383
|
+
expect(select.attributes('data-pointer')).toBe('true')
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('always shows the selector of a field that has a value', () => {
|
|
387
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'], optional: true })
|
|
388
|
+
|
|
389
|
+
expect(wrapper.get('[data-testid="editor-dimension-unit"]').classes()).not.toContain('hidden')
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
it('clamps the value into the range of the unit switched to', async () => {
|
|
393
|
+
mountField({ value: 800, unit: 'px' }, { units: ['px', '%'] })
|
|
394
|
+
|
|
395
|
+
await pickUnit('%')
|
|
396
|
+
|
|
397
|
+
expect(writes()).toEqual([{ value: 100, unit: '%' }])
|
|
398
|
+
expect(shown()).toBe('100')
|
|
399
|
+
expect(input().attributes('aria-label')).toBe('Breedte (%)')
|
|
400
|
+
expect(commits()).toBe(1)
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
it('keeps a value that fits the new range', async () => {
|
|
404
|
+
mountField({ value: 50, unit: '%' }, { units: ['px', '%'] })
|
|
405
|
+
|
|
406
|
+
await pickUnit('px')
|
|
407
|
+
|
|
408
|
+
expect(writes()).toEqual([{ value: 50, unit: 'px' }])
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it('writes nothing when switching the unit of an empty field, but types in it next', async () => {
|
|
412
|
+
mountField(null, { units: ['px', '%'], optional: true })
|
|
413
|
+
|
|
414
|
+
await pickUnit('%')
|
|
415
|
+
expect(writes()).toEqual([])
|
|
416
|
+
|
|
417
|
+
await commit('250')
|
|
418
|
+
expect(writes()).toEqual([{ value: 100, unit: '%' }])
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
it('follows a unit change from outside', async () => {
|
|
422
|
+
mountField({ value: 200, unit: 'px' }, { units: ['px', '%'] })
|
|
423
|
+
|
|
424
|
+
await wrapper.setProps({ modelValue: { value: 30, unit: '%' } })
|
|
425
|
+
|
|
426
|
+
expect((wrapper.get('select').element as HTMLSelectElement).value).toBe('%')
|
|
427
|
+
expect(shown()).toBe('30')
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
it('falls back to the first unit when the model turns null from outside', async () => {
|
|
431
|
+
mountField({ value: 50, unit: '%' }, { units: ['px', '%'], optional: true })
|
|
432
|
+
|
|
433
|
+
// Another element without a limit is selected.
|
|
434
|
+
await wrapper.setProps({ modelValue: null })
|
|
435
|
+
expect((wrapper.get('select').element as HTMLSelectElement).value).toBe('px')
|
|
436
|
+
|
|
437
|
+
await commit('300')
|
|
438
|
+
expect(writes()).toEqual([{ value: 300, unit: 'px' }])
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
it('keeps the unit of a field the user emptied', async () => {
|
|
442
|
+
mountField({ value: 50, unit: '%' }, { units: ['px', '%'], optional: true })
|
|
443
|
+
|
|
444
|
+
await commit('')
|
|
445
|
+
expect(writes()).toEqual([null])
|
|
446
|
+
expect((wrapper.get('select').element as HTMLSelectElement).value).toBe('%')
|
|
447
|
+
|
|
448
|
+
await commit('30')
|
|
449
|
+
expect(writes()).toEqual([null, { value: 30, unit: '%' }])
|
|
450
|
+
})
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('merges messages per key', () => {
|
|
454
|
+
mountField(null, {
|
|
455
|
+
units: ['px', '%'],
|
|
456
|
+
optional: true,
|
|
457
|
+
messages: { placeholder: 'None', unit: 'Unit' },
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
expect(input().attributes('placeholder')).toBe('None')
|
|
461
|
+
expect(wrapper.get('select').attributes('aria-label')).toBe('Unit')
|
|
462
|
+
expect(wrapper.findAll('option').map((option) => option.text())).toEqual(['px', '%'])
|
|
463
|
+
})
|
|
464
|
+
})
|