Skip to content

Commit

Permalink
feat: implement BaseLink component
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #84
  • Loading branch information
patrickcate committed Nov 9, 2021
1 parent 83e9d6a commit 365ad6b
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 2 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"storybook-builder-vite": "^0.1.3",
"uswds": "^2.12.2",
"vite": "^2.6.4",
"vue-loader": "^16.8.2"
"vue-loader": "^16.8.2",
"vue-router": "^4.0.12"
},
"config": {
"commitizen": {
Expand Down
48 changes: 48 additions & 0 deletions src/components/BaseLink/BaseLink.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import BaseLink from './BaseLink.vue'

const defaultProps = {
href: '',
to: '',
routerComponentName: '',
}

export default {
component: BaseLink,
title: 'Components/BaseLink',
argTypes: {
href: {
control: { type: 'text' },
},
to: {
control: { type: 'text' },
},
routerComponentName: {
control: { type: 'text' },
},
defaultSlot: {
control: { type: 'text' },
},
},
args: {
href: defaultProps.href,
to: defaultProps.to,
routerComponentName: defaultProps.routerComponentName,
defaultSlot: 'Test',
},
}

const DefaultTemplate = (args, { argTypes }) => ({
components: { BaseLink },
props: Object.keys(argTypes),
setup() {
return { ...args }
},
template: `<BaseLink :href="href" :to="to" router-component-name="routerComponentName">${args.defaultSlot}</BaseLink>`,
})

export const DefaultBaseLink = DefaultTemplate.bind({})
DefaultBaseLink.args = {
...defaultProps,
to: '/user',
}
DefaultBaseLink.storyName = 'Default'
97 changes: 97 additions & 0 deletions src/components/BaseLink/BaseLink.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import '@module/uswds/dist/css/uswds.min.css'
import { createRouter, createWebHistory } from 'vue-router'
import { mount } from '@cypress/vue'
import BaseLink from './BaseLink.vue'

describe('BaseLink', () => {
let router

beforeEach(() => {
const TestPage = { template: '<div>Test Page</div>' }

const routes = [{ path: '/test-page', component: TestPage }]
router = createRouter({
history: createWebHistory(),
routes,
})
})

it('renders the component', () => {
mount(BaseLink, {
props: {
to: '/link/to/page',
},
slots: {
default: () => 'Test Link',
},
global: {
plugins: [router],
},
})

cy.get('a').should('contain', 'Test Link')

cy.get('a').should('have.attr', 'href').and('contain', '/link/to/page')
})

it('renders a regular `a` tag if the `href` prop is used', () => {
mount(BaseLink, {
props: {
href: '/link/to/page',
},
slots: {
default: () => 'Test Regular Link',
},
global: {
plugins: [router],
},
})

cy.get('a').should('contain', 'Test Regular Link')
cy.get('a').should('have.attr', 'href').and('contain', '/link/to/page')
})

it('renders as a `nuxt-link` if $nuxt is detected', () => {
mount(BaseLink, {
props: {
to: '/link/to/page',
},
slots: {
default: () => 'Test Nuxt Link',
},
global: {
mocks: {
$nuxt: {},
},
plugins: [router],
},
})

cy.get('nuxt-link').should('contain', 'Test Nuxt Link')

cy.get('nuxt-link')
.should('have.attr', 'to')
.and('contain', '/link/to/page')
})

it('`routerComponentName` prop overrides what component is rendered', () => {
mount(BaseLink, {
props: {
to: '/link/to/page',
routerComponentName: 'g-link',
},
slots: {
default: () => 'Test Custom Component Link',
},
global: {
mocks: {
$nuxt: {},
},
plugins: [router],
},
})

cy.get('g-link').should('contain', 'Test Custom Component Link')
cy.get('g-link').should('have.attr', 'to').and('contain', '/link/to/page')
})
})
41 changes: 41 additions & 0 deletions src/components/BaseLink/BaseLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script>
export default {
name: 'BaseLink',
inheritAttrs: false,
props: {
href: {
type: String,
default: '',
},
to: {
type: [String, Object],
default: '',
},
routerComponentName: {
type: String,
default: '',
},
},
computed: {
isExternalLink() {
return (
!!this.href ||
(typeof this.to === 'string' && this.to.startsWith('http'))
)
},
linkComponent() {
if (this.routerComponentName) {
return this.routerComponentName
}
return this.$nuxt ? 'nuxt-link' : 'router-link'
},
},
}
</script>

<template>
<a v-if="isExternalLink" v-bind="$attrs" :href="href"><slot></slot></a>
<component :is="linkComponent" v-else :to="to" v-bind="$attrs"
><slot></slot
></component>
</template>
4 changes: 4 additions & 0 deletions src/components/BaseLink/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import BaseLink from './BaseLink.vue'

export { BaseLink }
export default BaseLink
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export default {
}

app.provide('vueUswds', vueUswdsOptions)
app.provide('nextId', () => nextId(app.config.globalProperties))
app.provide('nextId', nextId)
},
}

0 comments on commit 365ad6b

Please sign in to comment.