diff --git a/examples/sites/demos/apis/tag.js b/examples/sites/demos/apis/tag.js index fb6e0acba..9be76a9ea 100644 --- a/examples/sites/demos/apis/tag.js +++ b/examples/sites/demos/apis/tag.js @@ -16,6 +16,21 @@ export default { mode: ['pc'], pcDemo: 'delete' }, + { + name: 'round', + type: 'boolean', + defaultValue: '', + desc: { + 'zh-CN': '是否设置圆角标签', + 'en-US': 'Whether to set the rounded corner label' + }, + mode: ['pc', 'mobile-first'], + meta: { + stable: '3.31.0' + }, + pcDemo: 'rounded', + mfDemo: 'rounded' + }, { name: 'closable', type: 'boolean', @@ -246,7 +261,7 @@ type ISize = 'medium' | 'small' | '' name: 'IType', type: 'type', code: ` -type IType = 'success' | 'info' | 'warning' | 'danger' +type IType = 'success' | 'info' | 'warning' | 'danger' | 'alerting' | 'error' ` } ] diff --git a/examples/sites/demos/mobile-first/app/tag/rounded.vue b/examples/sites/demos/mobile-first/app/tag/rounded.vue new file mode 100644 index 000000000..70925fb2c --- /dev/null +++ b/examples/sites/demos/mobile-first/app/tag/rounded.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/examples/sites/demos/mobile-first/app/tag/webdoc/tag.js b/examples/sites/demos/mobile-first/app/tag/webdoc/tag.js index e30672562..f88671c6d 100644 --- a/examples/sites/demos/mobile-first/app/tag/webdoc/tag.js +++ b/examples/sites/demos/mobile-first/app/tag/webdoc/tag.js @@ -151,6 +151,18 @@ export default { 'en-US': '

Set custom content by binding the `value` property

' }, codeFiles: ['content.vue'] + }, + { + demoId: 'rounded', + name: { + 'zh-CN': '设置圆角按钮', + 'en-US': 'Set rounded corner button' + }, + desc: { + 'zh-CN': '

通过设置round属性设置圆角按钮

', + 'en-US': '

Set the round button by setting theroundattribute

' + }, + codeFiles: ['rounded.vue'] } ] } diff --git a/examples/sites/demos/pc/app/tag/delete.spec.ts b/examples/sites/demos/pc/app/tag/delete.spec.ts index 6bbbaec70..172472882 100644 --- a/examples/sites/demos/pc/app/tag/delete.spec.ts +++ b/examples/sites/demos/pc/app/tag/delete.spec.ts @@ -1,19 +1,30 @@ import { expect, test } from '@playwright/test' test('是否能阻止删除或正常删除标签', async ({ page }) => { - page.on('pageerror', (exception) => expect(exception).not.toBeNull()) + page.on('pageerror', (exception) => expect(exception).toBeNull()) + await page.goto('tag#delete') + await page.waitForLoadState('networkidle') - const first = page.locator('.tiny-tag').filter({ hasText: '标签一' }) - const close = first.locator('.tiny-tag__close') - const modal = page.locator('.tiny-modal__box').getByText('消息提示确认删除?确认取消') + // 修正:用 #delete 限定当前 demo 范围,避免匹配到其他 demo 的"标签一" + const tag1 = page.locator('#delete .tiny-tag').filter({ hasText: '标签一' }) + const closeBtn = tag1.locator('.tiny-tag__close') - await close.click() - await modal.isVisible() - await page.getByRole('button', { name: '取消' }).click() - await first.isVisible() - await close.click() - await modal.isVisible() - await page.getByRole('button', { name: '确定' }).click() - await expect(first).not.toBeVisible() + // 第一次点击关闭:触发 before-delete 确认对话框 + await closeBtn.click() + + const confirmModal = page.locator('.tiny-modal__box').filter({ hasText: '确认删除?' }) + await expect(confirmModal).toBeVisible() + + // 点击取消,标签应保留 + await confirmModal.getByRole('button', { name: '取消' }).click() + await expect(tag1).toBeVisible() + + // 第二次点击关闭,再次弹出确认 + await closeBtn.click() + await expect(confirmModal).toBeVisible() + + // 点击确定,标签应被删除 + await confirmModal.getByRole('button', { name: '确定' }).click() + await expect(tag1).not.toBeVisible() }) diff --git a/examples/sites/demos/pc/app/tag/disabled.spec.ts b/examples/sites/demos/pc/app/tag/disabled.spec.ts index 60cae05a5..bebe72836 100644 --- a/examples/sites/demos/pc/app/tag/disabled.spec.ts +++ b/examples/sites/demos/pc/app/tag/disabled.spec.ts @@ -1,13 +1,28 @@ import { expect, test } from '@playwright/test' test('是否正常禁用', async ({ page }) => { - page.on('pageerror', (exception) => expect(exception).not.toBeNull()) + page.on('pageerror', (exception) => expect(exception).toBeNull()) + await page.goto('tag#disabled') + await page.waitForLoadState('networkidle') - const tags = page.locator('.all-demos-container').locator('.tiny-tag') - const close = tags.last().locator('.tiny-tag__close') + // 修正:用 #disabled 限定当前 demo 范围,避免匹配到其他 demo 的"标签" + const tags = page.locator('#disabled .tiny-tag') + await expect(tags).toHaveCount(3) - await expect(tags).toHaveClass([/is-disabled/, /is-disabled/, /is-disabled/]) - await close.click() - await expect(tags.last(), 'Disabling Errors').toBeVisible() + await expect(tags.nth(0)).toHaveClass(/is-disabled/) + await expect(tags.nth(1)).toHaveClass(/is-disabled/) + await expect(tags.nth(2)).toHaveClass(/is-disabled/) + + // 定位最后一个标签的关闭按钮 + const lastTag = tags.last() + const closeBtn = lastTag.locator('.tiny-tag__close') + await expect(closeBtn).toBeVisible() + + // 尝试点击关闭按钮(disabled 状态下应无响应) + await closeBtn.click() + + // 验证禁用状态下标签未被删除,仍然可见且数量不变 + await expect(lastTag, '禁用状态下标签不应被关闭').toBeVisible() + await expect(tags).toHaveCount(3) }) diff --git a/examples/sites/demos/pc/app/tag/effect-composition-api.vue b/examples/sites/demos/pc/app/tag/effect-composition-api.vue index c83323850..65cce2aa7 100644 --- a/examples/sites/demos/pc/app/tag/effect-composition-api.vue +++ b/examples/sites/demos/pc/app/tag/effect-composition-api.vue @@ -26,7 +26,9 @@ const items = ref([ { type: 'success', label: '标签二' }, { type: 'info', label: '标签三' }, { type: 'danger', label: '标签四' }, - { type: 'warning', label: '标签五' } + { type: 'warning', label: '标签五' }, + { type: 'alerting', label: '标签六' }, + { type: 'error', label: '标签七' } ]) diff --git a/examples/sites/demos/pc/app/tag/effect.spec.ts b/examples/sites/demos/pc/app/tag/effect.spec.ts index 3c3bca163..f2c98f916 100644 --- a/examples/sites/demos/pc/app/tag/effect.spec.ts +++ b/examples/sites/demos/pc/app/tag/effect.spec.ts @@ -1,36 +1,52 @@ import { expect, test } from '@playwright/test' -test('三大主题分别对应的五种类型', async ({ page }) => { - page.on('pageerror', (exception) => expect(exception).not.toBeNull()) +test('三大主题分别对应的七种类型', async ({ page }) => { + page.on('pageerror', (exception) => expect(exception).toBeNull()) + await page.goto('tag#effect') + await page.waitForLoadState('networkidle') - const scoped = page.locator('.all-demos-container') - const light = scoped.locator('.tiny-tag--light') - const dark = scoped.locator('.tiny-tag--dark') - const plain = scoped.locator('.tiny-tag--plain') + // 用 #effect 限定当前 demo 范围 + const demo = page.locator('#effect') + const light = demo.locator('.tiny-tag--light') + const dark = demo.locator('.tiny-tag--dark') + const plain = demo.locator('.tiny-tag--plain') - await expect(light).toHaveCount(5) - await expect(dark).toHaveCount(5) - await expect(plain).toHaveCount(5) + // 修正:每组都有7个标签(默认 + success/info/danger/warning/alerting/error) + await expect(light).toHaveCount(7) + await expect(dark).toHaveCount(7) + await expect(plain).toHaveCount(7) + + // 修正:验证 light 组包含7种类型 await expect(light, 'At least one of the types is wrong').toHaveClass([ /tiny-tag/, /tiny-tag--success/, /tiny-tag--info/, /tiny-tag--danger/, - /tiny-tag--warning/ + /tiny-tag--warning/, + /tiny-tag--alerting/, + /tiny-tag--error/ ]) + + // 修正:验证 dark 组包含7种类型 await expect(dark, 'At least one of the types is wrong').toHaveClass([ /tiny-tag/, /tiny-tag--success/, /tiny-tag--info/, /tiny-tag--danger/, - /tiny-tag--warning/ + /tiny-tag--warning/, + /tiny-tag--alerting/, + /tiny-tag--error/ ]) + + // 修正:验证 plain 组包含7种类型 await expect(plain, 'At least one of the types is wrong').toHaveClass([ /tiny-tag/, /tiny-tag--success/, /tiny-tag--info/, /tiny-tag--danger/, - /tiny-tag--warning/ + /tiny-tag--warning/, + /tiny-tag--alerting/, + /tiny-tag--error/ ]) }) diff --git a/examples/sites/demos/pc/app/tag/effect.vue b/examples/sites/demos/pc/app/tag/effect.vue index b09d6f0e0..bd2d63f7d 100644 --- a/examples/sites/demos/pc/app/tag/effect.vue +++ b/examples/sites/demos/pc/app/tag/effect.vue @@ -31,7 +31,9 @@ export default { { type: 'success', label: '标签二' }, { type: 'info', label: '标签三' }, { type: 'danger', label: '标签四' }, - { type: 'warning', label: '标签五' } + { type: 'warning', label: '标签五' }, + { type: 'alerting', label: '标签六' }, + { type: 'error', label: '标签七' } ] } } diff --git a/examples/sites/demos/pc/app/tag/max-width.spec.ts b/examples/sites/demos/pc/app/tag/max-width.spec.ts index c6ba1c0f1..ffd86017d 100644 --- a/examples/sites/demos/pc/app/tag/max-width.spec.ts +++ b/examples/sites/demos/pc/app/tag/max-width.spec.ts @@ -1,10 +1,28 @@ import { test, expect } from '@playwright/test' test('测试最大宽度', async ({ page }) => { - page.on('pageerror', (exception) => expect(exception).not.toBeNull()) + page.on('pageerror', (exception) => expect(exception).toBeNull()) + await page.goto('tag#max-width') + await page.waitForLoadState('networkidle') - const normal = page.getByLabel('示例', { exact: true }).locator('span').first() + // 修正:用 #max-width 精确限定当前 demo,避免匹配到其他 demo + const tag = page.locator('#max-width .tiny-tag').first() - await expect(normal).toHaveCSS('max-width', '80px') + // 验证标签可见 + await expect(tag).toBeVisible() + + // 验证 max-width CSS 属性 + await expect(tag).toHaveCSS('max-width', '80px') + + // 验证文本溢出样式为省略号(ellipsis) + await expect(tag).toHaveCSS('text-overflow', 'ellipsis') + + // 修正:textContent 返回 DOM 完整文本(包含被 CSS 隐藏的部分),所以只验证包含原文本即可 + const text = await tag.textContent() + expect(text).toContain('文本超长超长的标签') + + // 验证标签实际渲染宽度不超过 80px + const box = await tag.boundingBox() + expect(box.width).toBeLessThanOrEqual(80) }) diff --git a/examples/sites/demos/pc/app/tag/rounded-composition-api.vue b/examples/sites/demos/pc/app/tag/rounded-composition-api.vue new file mode 100644 index 000000000..d5668321b --- /dev/null +++ b/examples/sites/demos/pc/app/tag/rounded-composition-api.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/examples/sites/demos/pc/app/tag/rounded.spec.ts b/examples/sites/demos/pc/app/tag/rounded.spec.ts new file mode 100644 index 000000000..9a4417659 --- /dev/null +++ b/examples/sites/demos/pc/app/tag/rounded.spec.ts @@ -0,0 +1,70 @@ +import { expect, test } from '@playwright/test' + +test('圆角标签', async ({ page }) => { + // 监听页面错误,期望无 JavaScript 异常 + page.on('pageerror', (exception) => expect(exception).toBeNull()) + + // 导航到圆角标签示例页面 + await page.goto('tag#rounded') + + // 等待页面加载完成 + await page.waitForLoadState('networkidle') + + // 只定位 .tiny-tag-demo 容器内的标签 + const demoContainer = page.locator('.tiny-tag-demo') + const tags = demoContainer.locator('.tiny-tag') + + // 验证演示区域内存在3个标签 + await expect(tags).toHaveCount(3) + + // ========== 第一个标签:success + light + round ========== + const tag1 = tags.nth(0) + await expect(tag1).toHaveText('圆角按钮1') + await expect(tag1).toHaveClass(/tiny-tag--success/) + await expect(tag1).toHaveClass(/tiny-tag--light/) + await expect(tag1).toHaveClass(/is-round/) // 修正:round 对应的类名是 is-round + await expect(tag1).toBeVisible() + + // ========== 第二个标签:danger + dark + round ========== + const tag2 = tags.nth(1) + await expect(tag2).toHaveText('圆角按钮2') + await expect(tag2).toHaveClass(/tiny-tag--danger/) + await expect(tag2).toHaveClass(/tiny-tag--dark/) + await expect(tag2).toHaveClass(/is-round/) + await expect(tag2).toBeVisible() + + // ========== 第三个标签:warning + plain + round ========== + const tag3 = tags.nth(2) + await expect(tag3).toHaveText('圆角按钮3') + await expect(tag3).toHaveClass(/tiny-tag--warning/) + await expect(tag3).toHaveClass(/tiny-tag--plain/) + await expect(tag3).toHaveClass(/is-round/) + await expect(tag3).toBeVisible() + + // ========== 验证圆角样式效果 ========== + const tag1BorderRadius = await tag1.evaluate((el) => window.getComputedStyle(el).borderRadius) + const tag2BorderRadius = await tag2.evaluate((el) => window.getComputedStyle(el).borderRadius) + const tag3BorderRadius = await tag3.evaluate((el) => window.getComputedStyle(el).borderRadius) + + expect(tag1BorderRadius).toBe(tag2BorderRadius) + expect(tag2BorderRadius).toBe(tag3BorderRadius) + expect(tag1BorderRadius).not.toBe('0px') + expect(tag1BorderRadius).not.toBe('0') + + // ========== 验证布局样式 ========== + const tag1MarginRight = await tag1.evaluate((el) => window.getComputedStyle(el).marginRight) + const tag1MarginBottom = await tag1.evaluate((el) => window.getComputedStyle(el).marginBottom) + expect(tag1MarginRight).toBe('10px') + expect(tag1MarginBottom).toBe('10px') + + // ========== 验证不同 effect 的样式差异 ========== + const tag1BgColor = await tag1.evaluate((el) => window.getComputedStyle(el).backgroundColor) + expect(tag1BgColor).not.toBe('rgba(0, 0, 0, 0)') + expect(tag1BgColor).not.toBe('transparent') + + const tag2Color = await tag2.evaluate((el) => window.getComputedStyle(el).color) + expect(tag2Color).toMatch(/rgb\(255,\s*255,\s*255\)|white|#fff/i) + + const tag3BgColor = await tag3.evaluate((el) => window.getComputedStyle(el).backgroundColor) + expect(tag3BgColor).toMatch(/rgba\(0, 0, 0, 0\)|transparent|rgb\(255, 255, 255\)/) +}) diff --git a/examples/sites/demos/pc/app/tag/rounded.vue b/examples/sites/demos/pc/app/tag/rounded.vue new file mode 100644 index 000000000..70925fb2c --- /dev/null +++ b/examples/sites/demos/pc/app/tag/rounded.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/examples/sites/demos/pc/app/tag/tag-event-click-composition-api.vue b/examples/sites/demos/pc/app/tag/tag-event-click-composition-api.vue index 3d2d5f6cb..081a82b94 100644 --- a/examples/sites/demos/pc/app/tag/tag-event-click-composition-api.vue +++ b/examples/sites/demos/pc/app/tag/tag-event-click-composition-api.vue @@ -1,6 +1,6 @@