Skip to content

Commit

Permalink
Feat #30 - Update Link, Icon conditional props, address PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-dassana committed Aug 21, 2020
1 parent 3683a7d commit 45fb102
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 93 deletions.
24 changes: 14 additions & 10 deletions .github/workflows/verify-labels.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
name: Verify Labels

name: Pull Request Labels
on:
pull_request:
types: [opened, labeled, unlabeled, synchronize]

jobs:
check_pr_labels:
name: Verify that the PR has the appropriate label(s)
runs-on: ubuntu-latest
name: Verify that the PR has a valid label
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Verify PR label action
uses: jesusvasquez333/[email protected]
- name: Check for version label
if: ${{ github.base_ref == 'master' }}
uses: mheap/github-action-required-labels@v1
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
valid-labels: 'fix, bug, bugfix, feature, enhancement, chore'
mode: exactly
count: 1
labels: 'patch, minor, major'
- name: Check for issue type label
uses: mheap/github-action-required-labels@v1
with:
mode: minimum
count: 1
labels: 'fix, bug, bugfix, feature, enhancement, chore'
38 changes: 23 additions & 15 deletions src/__snapshots__/storybook.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,43 @@ exports[`Storyshots Button Primary Disabled 1`] = `
</button>
`;

exports[`Storyshots Icon AWS 1`] = `
exports[`Storyshots Icon Custom 1`] = `
<img
alt="aws-logo"
alt="https://dummyimage.com/600x400/000/fff&text=Dassana"
height={64}
src="aws.svg"
src="https://dummyimage.com/600x400/000/fff&text=Dassana"
/>
`;

exports[`Storyshots Icon Dassana Blue 1`] = `
exports[`Storyshots Icon Predefined 1`] = `
<img
alt="dassana-blue"
alt="dassana-orange"
height={64}
src="dassana-blue.png"
src="dassana-orange.png"
/>
`;

exports[`Storyshots Icon Dassana Orange 1`] = `
<img
alt="dassana-orange"
height={32}
src="dassana-orange.png"
/>
exports[`Storyshots Link Click 1`] = `
<a
className="ant-typography"
onClick={[Function]}
style={
Object {
"WebkitLineClamp": null,
}
}
target="_self"
>
<u>
Click
</u>
</a>
`;

exports[`Storyshots Link Default 1`] = `
exports[`Storyshots Link Href 1`] = `
<a
className="ant-typography"
href=" "
onClick={[Function]}
style={
Object {
"WebkitLineClamp": null,
Expand All @@ -122,7 +130,7 @@ exports[`Storyshots Link Default 1`] = `
target="_self"
>
<u>
Default
Href
</u>
</a>
`;
Expand Down
28 changes: 17 additions & 11 deletions src/components/Icon/Icon.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@ import Icon, { IconProps } from '.'
import { Meta, Story } from '@storybook/react/types-6-0'

export default {
argTypes: {
height: { defaultValue: 64 }
},
component: Icon,
title: 'Icon'
} as Meta

const Template: Story<IconProps> = args => <Icon {...args} />

export const DassanaBlue = Template.bind({})
DassanaBlue.args = {
height: 64,
iconKey: 'dassana-blue'
export const Predefined = Template.bind({})
Predefined.argTypes = {
icon: {
control: { disable: true }
}
}

export const DassanaOrange = Template.bind({})
DassanaOrange.args = {
Predefined.args = {
iconKey: 'dassana-orange'
}

export const AWS = Template.bind({})
AWS.args = {
height: 64,
iconKey: 'aws-logo'
export const Custom = Template.bind({})
Custom.argTypes = {
iconKey: {
control: { disable: true }
}
}
Custom.args = {
icon: 'https://dummyimage.com/600x400/000/fff&text=Dassana'
}
50 changes: 39 additions & 11 deletions src/components/Icon/Icon.test.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React from 'react'
import Icon, { IconProps } from '.'
import { mount, ReactWrapper, shallow } from 'enzyme'
import { mount, ReactWrapper } from 'enzyme'

let wrapper: ReactWrapper
const mockProps: IconProps = {
height: 64,
iconKey: 'dassana-blue'
}

beforeEach(() => {
wrapper = mount(<Icon {...mockProps} />)
})
describe('Predefined Icon', () => {
const mockProps: IconProps = {
height: 64,
iconKey: 'dassana-blue'
}

beforeEach(() => {
wrapper = mount(<Icon {...mockProps} />)
})

describe('Icon', () => {
it('renders', () => {
expect(wrapper).toHaveLength(1)
})
Expand All @@ -30,8 +31,35 @@ describe('Icon', () => {
it('has the correct height', () => {
expect(wrapper.getDOMNode().getAttribute('height')).toBe('64')
})
})

describe('Custom Icon', () => {
const mockProps: IconProps = {
height: 64,
icon: 'https://dummyimage.com/600x400/000/fff&text=Dassana'
}

beforeEach(() => {
wrapper = mount(<Icon {...mockProps} />)
})

it('renders', () => {
expect(wrapper).toHaveLength(1)
})

it('throws an error if both icon and iconType props are undefined', () => {
expect(() => shallow(<Icon />)).toThrow()
it('renders with correct src url', () => {
expect(wrapper.getDOMNode().getAttribute('src')).toBe(
'https://dummyimage.com/600x400/000/fff&text=Dassana'
)
})

it('has the correct alt attribute', () => {
expect(wrapper.getDOMNode().getAttribute('alt')).toBe(
'https://dummyimage.com/600x400/000/fff&text=Dassana'
)
})

it('has the correct height', () => {
expect(wrapper.getDOMNode().getAttribute('height')).toBe('64')
})
})
31 changes: 21 additions & 10 deletions src/components/Icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@ import React, { FC } from 'react'

export type { IconName }

export interface IconProps {
interface SharedIconProps {
/**
* The url of the icon if you want Icon to render a custom icon.
* The height of the icon, in pixels. Width will be calculated by default.
*/
icon?: string
height?: number
}

interface IconPath extends SharedIconProps {
/**
* The name of the icon if using icons provided by Dassana.
* The url of the icon if rendering a custom icon.
*
*/
iconKey?: IconName
icon: string
/**
* The height of the icon, in pixels. Width will be calculated by default.
* The name of the icon if using icons provided by Dassana. **Note**: Either an `icon` or `iconKey` is required.
*/
height?: number
iconKey?: never
}

interface IconKey extends SharedIconProps {
iconKey: IconName
icon?: never
}

const Icon: FC<IconProps> = ({ icon, iconKey, height = 32 }: IconProps) => {
if (!icon && !iconKey)
throw new Error('Icon requires either an iconKey or icon prop.')
export type IconProps = IconKey | IconPath

const Icon: FC<IconProps> = ({ height = 32, ...props }: IconProps) => {
const { icon } = props as IconPath
const { iconKey } = props as IconKey

const imgSrc = iconKey ? Icons[iconKey] : icon
const imgAlt = iconKey ? iconKey : icon
Expand Down
29 changes: 21 additions & 8 deletions src/components/Link/Link.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,26 @@ export default {
title: 'Link'
} as Meta

const linkProps: LinkProps = {
children: 'Default',
href: ' ',
onClick: action('onClick')
}

const Template: Story<LinkProps> = args => <Link {...args} />

export const Default = Template.bind({})
Default.args = linkProps
export const Href = Template.bind({})
Href.argTypes = {
onClick: {
control: { disable: true }
}
}
Href.args = {
children: 'Href',
href: ' '
}

export const Click = Template.bind({})
Click.argTypes = {
href: {
control: { disable: true }
}
}
Click.args = {
children: 'Click',
onClick: action('onClick')
}
57 changes: 39 additions & 18 deletions src/components/Link/Link.test.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
import React from 'react'
import Link, { LinkProps } from '.'
import { mount, ReactWrapper, shallow } from 'enzyme'
import { mount, ReactWrapper } from 'enzyme'

let wrapper: ReactWrapper
let mockClick: jest.Mock<void>
const mockProps: LinkProps = {
children: 'Test',
href: '/test',
target: '_blank'
}

beforeEach(() => {
mockClick = jest.fn()
wrapper = mount(<Link {...mockProps} onClick={mockClick} />)
let mockProps: LinkProps

describe('Link with href', () => {
beforeEach(() => {
mockProps = {
children: 'Test',
href: '/test',
target: '_blank'
}

wrapper = mount(<Link {...mockProps} />)
})

it('renders', () => {
expect(wrapper).toHaveLength(1)
})

it('has the correct href attribute', () => {
expect(wrapper.getDOMNode().getAttribute('href')).toBe(mockProps.href)
})

it('has the correct target attribute', () => {
expect(wrapper.getDOMNode().getAttribute('target')).toBe(
mockProps.target
)
})
})

describe('Link', () => {
beforeEach(() => {
mockClick = jest.fn()

mockProps = {
children: 'Test',
onClick: mockClick,
target: '_blank'
}

wrapper = mount(<Link {...mockProps} />)
})

it('renders', () => {
expect(wrapper).toHaveLength(1)
})
Expand All @@ -25,17 +54,9 @@ describe('Link', () => {
expect(mockClick).toHaveBeenCalledTimes(1)
})

it('has the correct href attribute', () => {
expect(wrapper.getDOMNode().getAttribute('href')).toBe(mockProps.href)
})

it('has the correct target attribute', () => {
expect(wrapper.getDOMNode().getAttribute('target')).toBe(
mockProps.target
)
})

it('throws an error if both onClick and href props are undefined', () => {
expect(() => shallow(<Link>Test</Link>)).toThrow()
})
})
Loading

0 comments on commit 45fb102

Please sign in to comment.