Skip to content

Commit

Permalink
feat(UsaValidation): allow actual validations to be run with component
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #439
  • Loading branch information
patrickcate committed Nov 5, 2022
1 parent c65f3da commit 104de29
Show file tree
Hide file tree
Showing 9 changed files with 617 additions and 49 deletions.
9 changes: 6 additions & 3 deletions src/components/UsaChecklist/UsaChecklist.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import UsaChecklist from './UsaChecklist.vue'
const testItems = [
{
id: 'item1',
text: 'Use at least one uppercase character',
checked: false,
text: 'Test item 1',
ariaLabel: 'is valid',
},
{
id: 'item2',
text: 'Use at least one number',
checked: true,
text: 'Test item 2',
ariaLabel: 'is valid',
},
{
text: 'Use at least one symbol',
checked: false,
text: 'Test item 3',
ariaLabel: 'is invalid',
},
]

Expand Down
17 changes: 10 additions & 7 deletions src/components/UsaChecklist/UsaChecklist.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@ describe('UsaChecklist', () => {
id: 'item1',
checked: false,
text: 'Test item 1',
ariaLabel: 'Test item 1: invalid',
},
{
id: 'item2',
checked: true,
text: 'Test item 2',
ariaLabel: 'Test item 2: valid',
},
{
checked: false,
text: 'Test item 3',
ariaLabel: 'Test item 3: invalid',
},
])

Expand All @@ -44,27 +47,27 @@ describe('UsaChecklist', () => {
},
})

cy.get('.usa-checklist li').should('have.length', 3)
cy.get('.usa-checklist li')
.should('have.length', 3)
.and('have.attr', 'tabindex', '0')

cy.get('li:nth-of-type(1)')
.should('have.attr', 'aria-checked', 'false')
.should('have.attr', 'aria-label', 'Test item 1: invalid')
.and('contain', 'Test item 1')

cy.get('li:nth-of-type(2)')
.should('have.class', 'usa-checklist__item--checked')
.and('have.attr', 'aria-checked', 'true')
.and('have.attr', 'aria-label', 'Test item 2: valid')
.and('contain', 'Test item 2')

cy.get('li:nth-of-type(3)')
.as('item3')
.should('have.attr', 'aria-checked', 'false')
.should('have.attr', 'aria-label', 'Test item 3: invalid')
.and('contain', 'Test item 3')
.then(() => {
testItems.value[2].checked = true

cy.get('@item3')
.should('have.attr', 'aria-checked', 'true')
.and('have.class', 'usa-checklist__item--checked')
cy.get('@item3').should('have.class', 'usa-checklist__item--checked')
})
})
})
1 change: 1 addition & 0 deletions src/components/UsaChecklist/UsaChecklist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defineProps({
v-for="item in items"
:key="item?.id || item.text"
:checked="item.checked"
:aria-label="item.ariaLabel"
>{{ item.text }}</UsaChecklistItem
>
</slot>
Expand Down
14 changes: 11 additions & 3 deletions src/components/UsaChecklistItem/UsaChecklistItem.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export default {
checked: {
control: { type: 'boolean' },
},
defaultSlot: {
ariaLabel: {
control: { type: 'text' },
},
},
args: {
checked: defaultProps.checked,
defaultSlot: '',
ariaLabel: '',
},
decorators: [
() => ({
Expand All @@ -33,7 +33,7 @@ const DefaultTemplate = (args, { argTypes }) => ({
setup() {
return { ...args }
},
template: `<UsaChecklistItem :checked="checked">
template: `<UsaChecklistItem :checked="checked" :aria-label="ariaLabel">
<template v-if="${!!args.defaultSlot}" #default>${
args.defaultSlot
}</template>
Expand All @@ -54,3 +54,11 @@ CheckedChecklistItem.args = {
checked: true,
}
CheckedChecklistItem.storyName = 'Checked'

export const CustomAriaLabelChecklistItem = DefaultTemplate.bind({})
CustomAriaLabelChecklistItem.args = {
...defaultProps,
defaultSlot: 'Test item',
ariaLabel: 'is invalid',
}
CustomAriaLabelChecklistItem.storyName = 'Custom Aria Label'
10 changes: 7 additions & 3 deletions src/components/UsaChecklistItem/UsaChecklistItem.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@ import UsaChecklistItem from './UsaChecklistItem.vue'
describe('UsaChecklistItem', () => {
it('renders the component', () => {
mount(UsaChecklistItem, {
props: {
checked: false,
ariaLabel: 'invalid',
},
slots: {
default: () => 'Test item 1',
},
}).as('wrapper')

cy.get('li.usa-checklist__item')
.as('item1')
.should('have.attr', 'aria-checked', 'false')
.should('have.attr', 'aria-label', 'invalid')
.and('contain', 'Test item 1')

cy.get('@wrapper').invoke('setProps', { checked: true })
cy.get('@wrapper').invoke('setProps', { checked: true, ariaLabel: 'valid' })

cy.get('@item1')
.should('have.attr', 'aria-checked', 'true')
.should('have.attr', 'aria-label', 'valid')
.and('have.class', 'usa-checklist__item--checked')
})
})
10 changes: 9 additions & 1 deletion src/components/UsaChecklistItem/UsaChecklistItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
ariaLabel: {
type: String,
default: '',
},
})
const classes = computed(() => [
Expand All @@ -14,7 +18,11 @@ const classes = computed(() => [
</script>

<template>
<li class="usa-checklist__item" :class="classes" :aria-checked="checked"
<li
class="usa-checklist__item"
:aria-label="ariaLabel"
:class="classes"
tabindex="0"
><slot></slot
></li>
</template>
71 changes: 58 additions & 13 deletions src/components/UsaValidation/UsaValidation.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,69 @@ const testItems = [
{
id: 'item1',
text: 'Use at least one uppercase character',
checked: false,
validator: /[A-Z]/,
},
{
id: 'item2',
text: 'Use at least one number',
checked: true,
validator: '\\d',
},
{
id: 'item3',
text: 'Use at least one symbol',
checked: false,
validator: value => value.length > 6,
},
]

const defaultProps = {
items: UsaValidation.props.items.default(),
validations: UsaValidation.props.validations.default(),
validationValue: UsaValidation.props.validationValue.default,
heading: UsaValidation.props.heading.default,
headingTag: UsaValidation.props.headingTag.default,
validLabel: UsaValidation.props.validLabel.default,
invalidLabel: UsaValidation.props.invalidLabel.default,
id: UsaValidation.props.id.default,
customClasses: UsaValidation.props.customClasses.default(),
}

export default {
component: UsaValidation,
title: 'Components/UsaValidation',
argTypes: {
items: {
validations: {
control: { type: 'object' },
},
validationValue: {
control: { type: 'text' },
},
heading: {
control: { type: 'text' },
},
headingTag: {
options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
control: { type: 'select' },
},
validLabel: {
control: { type: 'text' },
},
invalidLabel: {
control: { type: 'text' },
},
id: {
control: { type: 'text' },
},
customClasses: {
control: { type: 'object' },
},
},
args: {
items: defaultProps.items,
validations: defaultProps.validations,
validationValue: defaultProps.validationValue,
heading: defaultProps.heading,
headingTag: defaultProps.headingTag,
validLabel: defaultProps.validLabel,
invalidLabel: defaultProps.invalidLabel,
id: defaultProps.id,
customClasses: defaultProps.customClasses,
defaultSlot: '',
},
}

Expand All @@ -56,18 +77,22 @@ const DefaultTemplate = (args, { argTypes }) => ({
return { ...args }
},
template: `<UsaValidation
:items="items"
:validations="validations"
:validationValue="validationValue"
:heading="heading"
:heading-tag="headingTag"
:validLabel="validLabel"
:invalidLabel="invalidLabel"
:id="id"
:custom-classes="customClasses"
>${args.defaultSlot}</UsaValidation>`,
></UsaValidation>`,
})

export const DefaultValidation = DefaultTemplate.bind({})
DefaultValidation.args = {
...defaultProps,
heading: 'Code requirements',
items: testItems,
validations: testItems,
}
DefaultValidation.storyName = 'Default'

Expand All @@ -76,18 +101,38 @@ HeadingTagValidation.args = {
...defaultProps,
heading: 'Custom Heading Tag',
headingTag: 'h4',
items: testItems,
validations: testItems,
}
HeadingTagValidation.storyName = 'Custom Heading Tag'

export const CustomIdValidation = DefaultTemplate.bind({})
CustomIdValidation.args = {
...defaultProps,
heading: 'Custom Heading Tag',
id: 'test-id',
validations: testItems,
}
CustomIdValidation.storyName = 'Custom ID'

export const CustomValidityLabelsValidation = DefaultTemplate.bind({})
CustomValidityLabelsValidation.args = {
...defaultProps,
heading: 'Custom Heading Tag',
validLabel: 'is valid',
invalidLabel: 'is invalid',
validations: testItems,
}
CustomValidityLabelsValidation.storyName = 'Custom Validity Labels'

export const CustomClassesValidation = DefaultTemplate.bind({})
CustomClassesValidation.args = {
...defaultProps,
heading: 'Custom CSS classes',
items: testItems,
validations: testItems,
customClasses: {
body: ['test-body-class'],
heading: ['test-heading-class'],
checklist: ['test-checklist-class'],
},
}
CustomClassesValidation.storyName = 'Custom Classes'
Loading

0 comments on commit 104de29

Please sign in to comment.