diff --git a/packages/renderless/src/ip-address/index.ts b/packages/renderless/src/ip-address/index.ts
index 1fa05b1771..43aede9267 100644
--- a/packages/renderless/src/ip-address/index.ts
+++ b/packages/renderless/src/ip-address/index.ts
@@ -89,32 +89,31 @@ export const getValue =
export const setValue =
({ api, props, state }: { api: IIpAddressApi; props: IIpAddressProps; state: IIpAddressState }) =>
(value: string) => {
- if (value) {
- /* istanbul ignore else */
- if (api?.ipValidator?.(value)) {
- if (api.isIP6(props.type)) {
- state.address = value.split(':').map((item) => ({ value: item }))
- if (state.address.length < 8) {
- let insertIndex = 0
- state.address.forEach((item, index) => {
- if (item.value === '') {
- item.value = '0000'
- insertIndex = index
- }
- })
- for (let i = 0; i <= 8 - state.address.length; i++) {
- state.address.splice(insertIndex, 0, { value: '0000' })
- }
- }
- } else {
- state.address = value.split('.').map((item) => ({ value: item }))
+ if (!value || !api?.ipValidator?.(value)) {
+ const createValue = () => ({ value: '' })
+ state.address = api.isIP6(props.type)
+ ? Array.from({ length: 8 }, createValue)
+ : Array.from({ length: 4 }, createValue)
+
+ return
+ }
+
+ if (api.isIP6(props.type)) {
+ state.address = value.split(':').map((item) => ({ value: item }))
+ if (state.address.length < 8) {
+ const missingCount = 8 - state.address.length
+ const emptyIndex = state.address.findIndex((item) => item.value === '')
+ const insertIndex = emptyIndex >= 0 ? emptyIndex : 0
+
+ if (emptyIndex >= 0) {
+ state.address[emptyIndex].value = '0000'
}
+
+ const newItems = Array(missingCount).fill({ value: '0000' })
+ state.address.splice(insertIndex, 0, ...newItems)
}
} else {
- const createValue = () => ({ value: '' })
- state.address = api.isIP6(props.type)
- ? new Array(8).fill('').map(createValue)
- : new Array(4).fill('').map(createValue)
+ state.address = value.split('.').map((item) => ({ value: item }))
}
}
diff --git a/packages/vue/src/ip-address/__tests__/ip-address.test.tsx b/packages/vue/src/ip-address/__tests__/ip-address.test.tsx
index 0cc90ecce3..d25751040a 100644
--- a/packages/vue/src/ip-address/__tests__/ip-address.test.tsx
+++ b/packages/vue/src/ip-address/__tests__/ip-address.test.tsx
@@ -2,6 +2,7 @@ import { mountPcMode } from '@opentiny-internal/vue-test-utils'
import { describe, expect, test, vi } from 'vitest'
import IpAddress from '@opentiny/vue-ip-address'
import { nextTick } from 'vue'
+import { iconBoat } from '@opentiny/vue-icon'
let value = ''
@@ -14,17 +15,64 @@ describe('PC Mode', () => {
expect(wrapper.find('input').attributes()).toHaveProperty('readonly')
})
- test.todo('delimiter ,设置IP段之间的分隔符,默认为 "." ')
+ describe('delimiter ,设置IP段之间的分隔符', () => {
+ test('默认为 "." ', async () => {
+ const wrapper = mount(() => )
+ expect(wrapper.findAll('svg')).toHaveLength(3)
+ })
- test.todo('size ,设置组件大小;该属性的可选值为 medium / small / mini')
+ test('设置为 "-" ', async () => {
+ const wrapper = mount(() => (
+
+ -
+
+ ))
+ expect(wrapper.findAll('span').map((i) => i.text())).toEqual(['-', '-', '-'])
+ })
- test.todo('disabled ,设置文本的禁用属性,默认为 false ')
+ test('设置为 icon', async () => {
+ const IconBoat = iconBoat()
+ const wrapper = mount(() => )
+ expect(wrapper.findAll('svg')).toHaveLength(3)
+ })
+ })
- test.todo('type ,设置IpAddress框的类型,默认是IPv4,当为IPv6时,只有一个IP端输入框,无分隔符')
+ describe('size, 设置组件大小', () => {
+ ;['medium', 'small', 'mini'].forEach((size) => {
+ test(size, async () => {
+ const wrapper = mount(() => )
+ expect(wrapper.find('.tiny-ip-address__input').classes()).toContain(size)
+ })
+ })
+ })
- test.todo('value ,设置文本显示的默认值')
+ test('disabled ,设置文本的禁用属性,默认为 false ', async () => {
+ const wrapper = mount(() => )
+ expect(wrapper.find('input').attributes()).toHaveProperty('disabled')
+ })
+
+ test('value ,设置文本显示的默认值', async () => {
+ value = '127.0.0.1'
+ const wrapper = mount(() => )
+ expect(wrapper.findAll('input').map((inputEl) => inputEl.element.value)).toEqual(['127', '0', '0', '1'])
+ })
+
+ test('invalid value in ipv6', async () => {
+ value = '127.0.0.1'
+ const wrapper = mount(() => )
+ const values = wrapper.findAll('input').map((inputEl) => inputEl.element.value)
+ expect(values).toHaveLength(8)
+ expect(values).toEqual(Array.from({ length: 8 }, () => ''))
+ })
+
+ test('invalid value in ipv4', async () => {
+ value = 'fe80::204:61ff:fe9d:f156'
+ const wrapper = mount(() => )
+ const values = wrapper.findAll('input').map((inputEl) => inputEl.element.value)
+ expect(values).toHaveLength(4)
+ expect(values).toEqual(Array.from({ length: 4 }, () => ''))
+ })
- // slots
test('default slot', async () => {
const wrapper = mount(() => (
{
v-slots={{
default: () => --
}}
- >
+ />
))
expect(wrapper.find('i').text()).toBe('--')
})
@@ -40,7 +88,7 @@ describe('PC Mode', () => {
// events
test('events', async () => {
const focus = vi.fn()
- const wrapper = mount(() => )
+ const wrapper = mount(() => )
await wrapper.find('input').trigger('focus')
await nextTick()
expect(focus).toHaveBeenCalled()