From e879b174c4db87765558faa4aa62f8bdb4788f6d Mon Sep 17 00:00:00 2001 From: John Leider Date: Tue, 22 Feb 2022 13:04:58 -0600 Subject: [PATCH 01/60] chore(release): publish v3.0.0-alpha.13 --- lerna.json | 2 +- packages/api-generator/package.json | 4 ++-- packages/docs/package.json | 4 ++-- packages/vuetify/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lerna.json b/lerna.json index 2d0a4a45972..ed2f2f80132 100644 --- a/lerna.json +++ b/lerna.json @@ -13,6 +13,6 @@ } }, "npmClient": "yarn", - "version": "3.0.0-alpha.12", + "version": "3.0.0-alpha.13", "useWorkspaces": true } diff --git a/packages/api-generator/package.json b/packages/api-generator/package.json index a758b930b34..60b9e5da315 100755 --- a/packages/api-generator/package.json +++ b/packages/api-generator/package.json @@ -1,6 +1,6 @@ { "name": "@vuetify/api-generator", - "version": "3.0.0-alpha.12", + "version": "3.0.0-alpha.13", "private": true, "description": "", "main": "src/index.js", @@ -17,7 +17,7 @@ "deepmerge": "^4.0.0", "rimraf": "^3.0.2", "vue": "^3.2.22", - "vuetify": "^3.0.0-alpha.12" + "vuetify": "^3.0.0-alpha.13" }, "devDependencies": { "@babel/node": "^7.16.0" diff --git a/packages/docs/package.json b/packages/docs/package.json index 6dca5cb9efd..3e11b6319ac 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -3,7 +3,7 @@ "description": "A Vue.js project", "private": true, "author": "John Leider ", - "version": "3.0.0-alpha.12", + "version": "3.0.0-alpha.13", "repository": { "type": "git", "url": "git+https://github.com/vuetifyjs/vuetify.git", @@ -30,7 +30,7 @@ "vue": "^3.2.22", "vue-i18n": "^9.2.0-beta.23", "vue-prism-component": "^2.0.0", - "vuetify": "^3.0.0-alpha.12" + "vuetify": "^3.0.0-alpha.13" }, "devDependencies": { "@intlify/vite-plugin-vue-i18n": "^3.2.1", diff --git a/packages/vuetify/package.json b/packages/vuetify/package.json index 7c19d5d88e8..66f690bcee5 100755 --- a/packages/vuetify/package.json +++ b/packages/vuetify/package.json @@ -1,7 +1,7 @@ { "name": "vuetify", "description": "Vue Material Component Framework", - "version": "3.0.0-alpha.12", + "version": "3.0.0-alpha.13", "author": { "name": "John Leider", "email": "john@vuetifyjs.com" From cd7b748ff2d415c4a131aa03b50b13bd31ab891d Mon Sep 17 00:00:00 2001 From: Elijah Kotyluk Date: Tue, 22 Feb 2022 12:22:45 -0800 Subject: [PATCH 02/60] test(VBadge): cypress spec (#14089) Co-authored-by: John Leider --- .../vuetify/src/components/VBadge/VBadge.tsx | 20 ++- .../VBadge/__tests__/VBadge.spec.cy.tsx | 138 ++++++++++++++++++ .../VBadge/__tests__/VBadge.spec.tsx | 2 +- .../__snapshots__/VBadge.spec.tsx.snap | 70 ++++----- 4 files changed, 188 insertions(+), 42 deletions(-) create mode 100644 packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.cy.tsx diff --git a/packages/vuetify/src/components/VBadge/VBadge.tsx b/packages/vuetify/src/components/VBadge/VBadge.tsx index dcd23ea2f34..5c3ec27aca5 100644 --- a/packages/vuetify/src/components/VBadge/VBadge.tsx +++ b/packages/vuetify/src/components/VBadge/VBadge.tsx @@ -7,8 +7,11 @@ import { VIcon } from '@/components/VIcon' // Composables import { makeRoundedProps, useRounded } from '@/composables/rounded' import { makeTagProps } from '@/composables/tag' +import { makeThemeProps, useTheme } from '@/composables/theme' import { makeTransitionProps, MaybeTransition } from '@/composables/transition' import { useBackgroundColor, useTextColor } from '@/composables/color' +import { useLocale } from '@/composables/locale' +import { useRtl } from '@/composables/rtl' // Utilities import { computed, toRef } from 'vue' @@ -36,13 +39,13 @@ export const VBadge = defineComponent({ }, location: { type: String, - default: 'top-right', + default: 'top-end', validator: (value: string) => { const [vertical, horizontal] = (value ?? '').split('-') return ( ['top', 'bottom'].includes(vertical) && - ['left', 'right'].includes(horizontal) + ['start', 'end'].includes(horizontal) ) }, }, @@ -56,13 +59,17 @@ export const VBadge = defineComponent({ textColor: String, ...makeRoundedProps(), ...makeTagProps(), + ...makeThemeProps(), ...makeTransitionProps({ transition: 'scale-rotate-transition' }), }, setup (props, ctx) { const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(toRef(props, 'color')) + const { isRtl } = useRtl() const { roundedClasses } = useRounded(props) + const { t } = useLocale() const { textColorClasses, textColorStyles } = useTextColor(toRef(props, 'textColor')) + const { themeClasses } = useTheme() const position = computed(() => { return props.floating @@ -77,8 +84,6 @@ export const VBadge = defineComponent({ const locationStyles = computed(() => { const [vertical, horizontal] = (props.location ?? '').split('-') - // TODO: RTL support - const styles = { bottom: 'auto', left: 'auto', @@ -87,7 +92,9 @@ export const VBadge = defineComponent({ } if (!props.inline) { - styles[horizontal === 'left' ? 'right' : 'left'] = calculatePosition(props.offsetX) + const isRight = (isRtl.value && horizontal === 'end') || (!isRtl.value && horizontal === 'start') + + styles[isRight ? 'right' : 'left'] = calculatePosition(props.offsetX) styles[vertical === 'top' ? 'bottom' : 'top'] = calculatePosition(props.offsetY) } @@ -132,6 +139,7 @@ export const VBadge = defineComponent({ backgroundColorClasses.value, roundedClasses.value, textColorClasses.value, + themeClasses.value, ]} style={[ backgroundColorStyles.value, @@ -139,7 +147,7 @@ export const VBadge = defineComponent({ textColorStyles.value, ]} aria-atomic="true" - aria-label="locale string here" // TODO: locale string here + aria-label={ t(props.label, value) } aria-live="polite" role="status" { ...badgeAttrs } diff --git a/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.cy.tsx b/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.cy.tsx new file mode 100644 index 00000000000..2dfc6793a86 --- /dev/null +++ b/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.cy.tsx @@ -0,0 +1,138 @@ +/// + +import { VBadge } from '..' +import { generate } from '@/../cypress/templates' + +const defaultColors = ['success', 'info', 'warning', 'error', 'invalid'] +const location = ['bottom-start', 'bottom-end', 'top-start', 'top-end'] +const rounded = ['circle', 'pill', 'shaped', 'tr-xl', 'br-lg', 0] // TODO: fix pill +const offset = [8, -8, '4', '-4', undefined] + +const props = { + bordered: true, + color: defaultColors, + content: ['content'], + dot: true, + icon: ['mdi-vuetify'], + floating: true, + inline: true, + location, + modelValue: true, + rounded, +} + +const stories = { + 'Default badge': , + 'Icon badge': , + 'Offset badge': ( +
+ { ['offsetX', 'offsetY'].map(key => ( + <> +
{ key }
+
+ { offset.map(val => ( + + + + )) } +
+ + )) } +
+ ), + 'Text color': ( +
+ { defaultColors.map((color, idx) => ( + <> +
+ + + +
+ + )) } +
+ ), +} + +// Tests +describe('VBadge', () => { + describe('color', () => { + it('supports default color props', () => { + cy.mount(() => ( + <> + {defaultColors.map((color, idx) => ( + + { color } badge + + )) } + + )) + .get('.v-badge') + .should('have.length', defaultColors.length) + .then(subjects => { + Array.from(subjects).forEach((subject, idx) => { + // TODO: refactor + expect(subject.querySelector(`.bg-${defaultColors[idx]}`)).to.be.instanceOf(HTMLSpanElement) + expect(subject).to.contain(defaultColors[idx]) + }) + }) + }) + }) + + describe('label', () => { + it('should have the designated aria label', () => { + cy.mount(label) + .get('.v-badge__badge') + .should('have.attr', 'aria-label', 'label-badge') + }) + }) + + describe('max', () => { + it('should add a suffix if the content value is greater than the max value', () => { + cy.mount() + .get('.v-badge') + .should('contain.text', '+') + }) + }) + + describe('tag', () => { + it('renders the proper tag instead of a div', () => { + cy.mount(tag) + .get('custom-tag') + .should('have.text', 'tag') + }) + }) + + describe('textColor', () => { + it('supports default text color props', () => { + cy.mount(() => ( + <> + {defaultColors.map((color, idx) => ( + + { color } text badge + + )) } + + )) + .get('.v-badge') + .should('have.length', defaultColors.length) + .then(subjects => { + Array.from(subjects).forEach((subject, idx) => { + // TODO: refactor + expect(subject.querySelector(`.text-${defaultColors[idx]}`)).to.be.instanceOf(HTMLSpanElement) + expect(subject).to.contain(defaultColors[idx]) + }) + }) + }) + }) +}) + +// Useful to preview all of the variants and pre-made examples +describe('Showcase', { viewportHeight: 1130, viewportWidth: 700 }, () => { + generate({ stories, props, component: VBadge }) +}) diff --git a/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.tsx b/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.tsx index 41cd236d285..d3d460f8448 100644 --- a/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.tsx +++ b/packages/vuetify/src/components/VBadge/__tests__/VBadge.spec.tsx @@ -24,7 +24,7 @@ describe('VBadge.tsx', () => { [{ floating: true }], [{ icon: 'foo' }], // badge slot overrides icon [{ inline: true }], - [{ location: 'bottom-left' }], + [{ location: 'bottom-start' }], [{ location: undefined }], [{ location: null }], [{ content: '10', max: 9 }], diff --git a/packages/vuetify/src/components/VBadge/__tests__/__snapshots__/VBadge.spec.tsx.snap b/packages/vuetify/src/components/VBadge/__tests__/__snapshots__/VBadge.spec.tsx.snap index 9acc056b49d..33bb6cec0a9 100644 --- a/packages/vuetify/src/components/VBadge/__tests__/__snapshots__/VBadge.spec.tsx.snap +++ b/packages/vuetify/src/components/VBadge/__tests__/__snapshots__/VBadge.spec.tsx.snap @@ -7,9 +7,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { content: '10', m element - @@ -29,9 +29,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { content: '10', m element - @@ -51,9 +51,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { content: 'foo', element - @@ -73,9 +73,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { dot: true } prop element - @@ -92,9 +92,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { dot: true, float element - @@ -111,9 +111,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { floating: true } element - @@ -133,9 +133,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { floating: true } element - @@ -155,9 +155,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { icon: 'foo' } pr element - @@ -177,9 +177,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { inline: true } p element - @@ -192,16 +192,16 @@ exports[`VBadge.tsx should match snapshot with badge slot and { inline: true } p `; -exports[`VBadge.tsx should match snapshot with badge slot and { location: 'bottom-left' } props 1`] = ` +exports[`VBadge.tsx should match snapshot with badge slot and { location: 'bottom-start' } props 1`] = `
element - @@ -221,9 +221,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { location: null } element - @@ -243,9 +243,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { location: undefi element - @@ -265,9 +265,9 @@ exports[`VBadge.tsx should match snapshot with badge slot and { modelValue: fals element -