Пример #1
0
describe('Segment', () => {
  common.isConformant(Segment)
  common.hasSubcomponents(Segment, [SegmentGroup])
  common.hasUIClassName(Segment)
  common.rendersChildren(Segment)

  common.implementsTextAlignProp(Segment, ['left', 'center', 'right'])

  common.propKeyAndValueToClassName(Segment, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(Segment, 'basic')
  common.propKeyOnlyToClassName(Segment, 'circular')
  common.propKeyOnlyToClassName(Segment, 'clearing')
  common.propKeyOnlyToClassName(Segment, 'compact')
  common.propKeyOnlyToClassName(Segment, 'disabled')
  common.propKeyOnlyToClassName(Segment, 'inverted')
  common.propKeyOnlyToClassName(Segment, 'loading')
  common.propKeyOnlyToClassName(Segment, 'piled')
  common.propKeyOnlyToClassName(Segment, 'raised')
  common.propKeyOnlyToClassName(Segment, 'secondary')
  common.propKeyOnlyToClassName(Segment, 'stacked')
  common.propKeyOnlyToClassName(Segment, 'tertiary')
  common.propKeyOnlyToClassName(Segment, 'vertical')

  common.propKeyOrValueAndKeyToClassName(Segment, 'attached', ['top', 'bottom'])
  common.propKeyOrValueAndKeyToClassName(Segment, 'padded', ['very'])

  common.propValueOnlyToClassName(Segment, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(Segment, 'size', _.without(SUI.SIZES, 'medium'))
})
Пример #2
0
describe('StatisticGroup', () => {
  common.isConformant(StatisticGroup)
  common.implementsWidthProp(StatisticGroup, { propKey: 'widths', canEqual: false })
  common.hasUIClassName(StatisticGroup)
  common.rendersChildren(StatisticGroup)

  common.propValueOnlyToClassName(StatisticGroup, 'color')
  common.propKeyOnlyToClassName(StatisticGroup, 'horizontal')
  common.propKeyOnlyToClassName(StatisticGroup, 'inverted')
  common.propValueOnlyToClassName(StatisticGroup, 'size')

  it('renders an div element', () => {
    shallow(<StatisticGroup />)
      .should.have.tagName('div')
  })

  it('renders children with `items` prop', () => {
    const items = [
      { label: 'Faves', value: 22 },
      { label: 'Views', value: '31,200' },
    ]

    shallow(<StatisticGroup items={items} />)
      .should.have.exactly(2).descendants('Statistic')
  })
})
describe('StatisticGroup', () => {
  common.isConformant(StatisticGroup)
  common.hasUIClassName(StatisticGroup)
  common.rendersChildren(StatisticGroup)

  common.implementsWidthProp(StatisticGroup, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'widths',
  })

  common.propKeyOnlyToClassName(StatisticGroup, 'horizontal')
  common.propKeyOnlyToClassName(StatisticGroup, 'inverted')

  common.propValueOnlyToClassName(StatisticGroup, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(StatisticGroup, 'size', _.without(SUI.SIZES, 'big', 'massive', 'medium'))

  describe('items', () => {
    it('renders children', () => {
      const wrapper = shallow(<StatisticGroup items={['foo', 'bar']} />)
      const items = wrapper.children()

      wrapper.should.have.exactly(2).descendants('Statistic')
      items.at(0).should.have.prop('content', 'foo')
      items.at(1).should.have.prop('content', 'bar')
    })
  })
})
Пример #4
0
describe('LabelGroup', () => {
  common.isConformant(LabelGroup)
  common.hasUIClassName(LabelGroup)
  common.rendersChildren(LabelGroup)

  common.propKeyOnlyToClassName(LabelGroup, 'circular')
  common.propKeyOnlyToClassName(LabelGroup, 'tag')

  common.propValueOnlyToClassName(LabelGroup, 'color')
  common.propValueOnlyToClassName(LabelGroup, 'size')
})
Пример #5
0
describe('Rail', () => {
  common.isConformant(Rail)
  common.hasUIClassName(Rail)
  common.propValueOnlyToClassName(Rail, 'position')
  common.propKeyOnlyToClassName(Rail, 'attached')
  common.propKeyOrValueToClassName(Rail, 'close')
  common.propKeyOnlyToClassName(Rail, 'dividing')
  common.propKeyOnlyToClassName(Rail, 'internal')
  common.propValueOnlyToClassName(Rail, 'size')
  common.rendersChildren(Rail)

  it('renders an div element', () => {
    shallow(<Rail />)
      .should.have.tagName('div')
  })
})
describe('DropdownMenu', () => {
  common.isConformant(DropdownMenu)
  common.rendersChildren(DropdownMenu)

  common.propValueOnlyToClassName(DropdownMenu, 'direction', ['left', 'right'])
  common.propKeyOnlyToClassName(DropdownMenu, 'open', { className: 'visible' })
  common.propKeyOnlyToClassName(DropdownMenu, 'scrolling')
})
Пример #7
0
describe('Sidebar', () => {
  common.isConformant(Sidebar)
  common.hasUIClassName(Sidebar)
  common.rendersChildren(Sidebar)

  common.propKeyOnlyToClassName(Sidebar, 'visible')

  common.propValueOnlyToClassName(Sidebar, 'animation', [
    'overlay', 'push', 'scale down', 'uncover', 'slide out', 'slide along',
  ])
  common.propValueOnlyToClassName(Sidebar, 'direction', ['top', 'right', 'bottom', 'left'])
  common.propValueOnlyToClassName(Sidebar, 'width', ['very thin', 'thin', 'wide', 'very wide'])

  it('renders a <div /> element', () => {
    shallow(<Sidebar />)
      .should.have.tagName('div')
  })
})
describe('Statistic', () => {
  common.isConformant(Statistic)
  common.implementsCreateMethod(Statistic)
  common.hasSubcomponents(Statistic, [StatisticGroup, StatisticLabel, StatisticValue])
  common.hasUIClassName(Statistic)
  common.rendersChildren(Statistic)

  common.implementsShorthandProp(Statistic, {
    autoGenerateKey: false,
    propKey: 'label',
    ShorthandComponent: StatisticLabel,
    mapValueToProps: content => ({ content }),
  })
  common.implementsShorthandProp(Statistic, {
    autoGenerateKey: false,
    propKey: 'value',
    ShorthandComponent: StatisticValue,
    mapValueToProps: content => ({ content }),
    shorthandDefaultProps: {
      text: undefined,
    },
  })

  common.propKeyAndValueToClassName(Statistic, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(Statistic, 'horizontal')
  common.propKeyOnlyToClassName(Statistic, 'inverted')

  common.propValueOnlyToClassName(Statistic, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(
    Statistic,
    'size',
    _.without(SUI.SIZES, 'big', 'massive', 'medium'),
  )

  describe('text', () => {
    it('passes value to StatisticValue', () => {
      shallow(<Statistic text value='foo' />)
        .find('StatisticValue')
        .first()
        .should.have.prop('text', true)
    })
  })
})
describe('CommentGroup', () => {
  common.isConformant(CommentGroup)
  common.rendersChildren(CommentGroup)

  common.propKeyOnlyToClassName(CommentGroup, 'collapsed')
  common.propKeyOnlyToClassName(CommentGroup, 'minimal')
  common.propKeyOnlyToClassName(CommentGroup, 'threaded')

  common.propValueOnlyToClassName(CommentGroup, 'size', _.without(SUI.SIZES, 'medium'))
})
Пример #10
0
describe('Rail', () => {
  common.isConformant(Rail, { requiredProps })
  common.hasUIClassName(Rail, { requiredProps })
  common.rendersChildren(Rail, { requiredProps })

  common.propKeyOnlyToClassName(Rail, 'attached', { requiredProps })
  common.propKeyOnlyToClassName(Rail, 'dividing', { requiredProps })
  common.propKeyOnlyToClassName(Rail, 'internal', { requiredProps })

  common.propKeyOrValueAndKeyToClassName(Rail, 'close', ['very'], { requiredProps })

  common.propValueOnlyToClassName(Rail, 'position', SUI.FLOATS, { requiredProps })
  common.propValueOnlyToClassName(Rail, 'size', _.without(SUI.SIZES, 'medium'), { requiredProps })

  it('renders an div element', () => {
    shallow(<Rail {...requiredProps} />)
      .should.have.tagName('div')
  })
})
Пример #11
0
describe('Flag', () => {
  common.isConformant(Flag, { requiredProps })
  common.implementsCreateMethod(Flag)
  common.propValueOnlyToClassName(Flag, 'name', { requiredProps })

  it('renders an <i /> element', () => {
    shallow(<Flag {...requiredProps} />)
      .should.have.tagName('i')
  })
})
describe('ButtonGroup', () => {
  common.isConformant(ButtonGroup)
  common.hasUIClassName(ButtonGroup)
  common.rendersChildren(ButtonGroup)

  common.implementsWidthProp(ButtonGroup, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'widths',
    widthClass: 'buttons',
  })

  common.propKeyAndValueToClassName(ButtonGroup, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(ButtonGroup, 'basic')
  common.propKeyOnlyToClassName(ButtonGroup, 'compact')
  common.propKeyOnlyToClassName(ButtonGroup, 'fluid')
  common.propKeyOnlyToClassName(ButtonGroup, 'icon')
  common.propKeyOnlyToClassName(ButtonGroup, 'inverted')
  common.propKeyOnlyToClassName(ButtonGroup, 'labeled')
  common.propKeyOnlyToClassName(ButtonGroup, 'negative')
  common.propKeyOnlyToClassName(ButtonGroup, 'positive')
  common.propKeyOnlyToClassName(ButtonGroup, 'primary')
  common.propKeyOnlyToClassName(ButtonGroup, 'secondary')
  common.propKeyOnlyToClassName(ButtonGroup, 'toggle')
  common.propKeyOnlyToClassName(ButtonGroup, 'vertical')

  common.propKeyOrValueAndKeyToClassName(ButtonGroup, 'attached', ['left', 'right', 'top', 'bottom'])

  common.propValueOnlyToClassName(ButtonGroup, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(ButtonGroup, 'size', SUI.SIZES)

  describe('buttons', () => {
    it('renders shorthand collection', () => {
      const wrapper = shallow(<ButtonGroup buttons={['one', 'two']} />)
      const buttons = wrapper.children()

      wrapper.should.have.exactly(2).descendants('Button')
      buttons.at(0).should.have.prop('content', 'one')
      buttons.at(1).should.have.prop('content', 'two')
    })
  })
})
Пример #13
0
describe('GridRow', () => {
  common.isConformant(GridRow)
  common.rendersChildren(GridRow)

  common.propKeyOnlyToClassName(GridRow, 'centered')
  common.propValueOnlyToClassName(GridRow, 'color')
  common.implementsColumnsProp(GridRow, false)
  common.propKeyAndValueToClassName(GridRow, 'only')
  common.propKeyAndValueToClassName(GridRow, 'reversed')
  common.propKeyOnlyToClassName(GridRow, 'stretched')
  common.implementsTextAlignProp(GridRow)
  common.implementsVerticalAlignProp(GridRow)
})
Пример #14
0
describe('Reveal', () => {
  common.isConformant(Reveal)
  common.hasSubComponents(Reveal, [RevealContent])
  common.hasUIClassName(Reveal)
  common.rendersChildren(Reveal)

  common.propKeyOnlyToClassName(Reveal, 'active')
  common.propKeyOnlyToClassName(Reveal, 'disabled')
  common.propKeyOnlyToClassName(Reveal, 'instant')

  common.propValueOnlyToClassName(Reveal, 'animated', [
    'fade', 'small fade',
    'move', 'move right', 'move up', 'move down',
    'rotate', 'rotate left',
  ])
})
Пример #15
0
describe('Feed', () => {
  common.hasUIClassName(Feed)
  common.isConformant(Feed)
  common.propValueOnlyToClassName(Feed, 'size')
  common.rendersChildren(Feed)

  describe('events prop', () => {
    it('renders <FeedEvent>', () => {
      const events = _.times(3, () => {
        return { summary: faker.hacker.phrase() }
      })

      shallow(<Feed events={events} />)
        .should.have.exactly(3).descendants('FeedEvent')
    })
  })
})
describe('GridColumn', () => {
  common.isConformant(GridColumn)
  common.rendersChildren(GridColumn)

  common.implementsOnlyProp(GridColumn)
  common.implementsTextAlignProp(GridColumn)
  common.implementsVerticalAlignProp(GridColumn)

  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'computer',
    widthClass: 'wide computer',
  })
  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'largeScreen',
    widthClass: 'wide large screen',
  })
  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'mobile',
    widthClass: 'wide mobile',
  })
  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'tablet',
    widthClass: 'wide tablet',
  })
  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'widescreen',
    widthClass: 'wide widescreen',
  })
  common.implementsWidthProp(GridColumn, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'width',
    widthClass: 'wide',
  })

  common.propKeyAndValueToClassName(GridColumn, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(GridColumn, 'stretched')

  common.propValueOnlyToClassName(GridColumn, 'color', SUI.COLORS)
})
Пример #17
0
describe('_Header', () => {
  common.hasUIClassName(_Header)
  common.rendersChildren(_Header)

  common.propKeyOnlyToClassName(_Header, 'dividing')
  common.propKeyOnlyToClassName(_Header, 'block')
  common.propKeyOnlyToClassName(_Header, 'inverted')
  common.propKeyOnlyToClassName(_Header, 'disabled')

  common.propKeyAndValueToClassName(_Header, 'floated')
  common.propKeyOrValueToClassName(_Header, 'attached')

  common.propValueOnlyToClassName(_Header, 'color')

  common.implementsAlignedProp(_Header)
  common.implementsIconProp(_Header)
  common.implementsImageProp(_Header)
})
Пример #18
0
describe('Card', () => {
  common.isConformant(Card)
  common.hasSubcomponents(Card, [CardContent, CardDescription, CardGroup, CardHeader, CardMeta])
  common.hasUIClassName(Card)
  common.rendersChildren(Card)

  common.propKeyOnlyToClassName(Card, 'centered')
  common.propKeyOnlyToClassName(Card, 'fluid')
  common.propKeyOnlyToClassName(Card, 'link')
  common.propKeyOnlyToClassName(Card, 'raised')

  common.propValueOnlyToClassName(Card, 'color', SUI.COLORS)

  it('renders a <div> by default', () => {
    shallow(<Card />).should.have.tagName('div')
  })

  describe('href', () => {
    it('renders an <a> with an href attr', () => {
      const url = faker.internet.url()
      const wrapper = shallow(<Card href={url} />)

      wrapper.should.have.tagName('a')
      wrapper.should.have.attr('href', url)
    })
  })

  describe('onClick', () => {
    it('renders <a> instead of <div>', () => {
      const handleClick = sandbox.spy()
      const wrapper = shallow(<Card onClick={handleClick} />)

      wrapper.should.have.tagName('a')
    })
  })

  describe('extra', () => {
    it('renders a CardContent', () => {
      const wrapper = shallow(<Card extra={faker.hacker.phrase()} />)

      wrapper.should.have.descendants('CardContent')
    })
  })
})
Пример #19
0
describe('Feed', () => {
  common.isConformant(Feed)
  common.hasUIClassName(Feed)
  common.rendersChildren(Feed)

  common.propValueOnlyToClassName(Feed, 'size',
    _.without(SUI.SIZES, 'mini', 'tiny', 'medium', 'big', 'huge', 'massive')
  )

  describe('events prop', () => {
    it('renders <FeedEvent>', () => {
      const events = _.times(3, () => {
        return { summary: faker.hacker.phrase() }
      })

      shallow(<Feed events={events} />)
        .should.have.exactly(3).descendants('FeedEvent')
    })
  })
})
Пример #20
0
describe('_Header', () => {
  common.hasUIClassName(_Header)
  common.rendersChildren(_Header)

  common.propKeyOnlyToClassName(_Header, 'dividing')
  common.propKeyOnlyToClassName(_Header, 'block')
  common.propKeyOnlyToClassName(_Header, 'inverted')
  common.propKeyOnlyToClassName(_Header, 'disabled')

  common.propKeyAndValueToClassName(_Header, 'floated')
  common.propKeyOrValueToClassName(_Header, 'attached')

  common.propValueOnlyToClassName(_Header, 'color')

  common.implementsAlignedProp(_Header)
  common.implementsIconProp(_Header)
  common.implementsImageProp(_Header)

  it('has an icon class when adding an icon', () => {
    const iconClass = faker.hacker.noun()
    const wrapper = mount(<_Header icon={iconClass} />)
    wrapper.should.have.className('icon')
  })
})
Пример #21
0
describe('Header', () => {
  common.hasUIClassName(Header)
  common.hasSubComponents(Header, [HeaderContent, HeaderSubheader])
  common.rendersChildren(Header)

  common.implementsIconProp(Header)
  common.implementsImageProp(Header)
  common.implementsShorthandProp(Header, {
    propKey: 'subheader',
    ShorthandComponent: HeaderSubheader,
    mapValueToProps: val => ({ content: val }),
  })
  common.implementsTextAlignProp(Header)

  common.propKeyAndValueToClassName(Header, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(Header, 'block')
  common.propKeyOnlyToClassName(Header, 'disabled')
  common.propKeyOnlyToClassName(Header, 'dividing')
  common.propKeyOnlyToClassName(Header, 'inverted')
  common.propKeyOnlyToClassName(Header, 'sub')

  common.propKeyOrValueAndKeyToClassName(Header, 'attached', ['top', 'bottom'])

  common.propValueOnlyToClassName(Header, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(Header, 'size', _.without(SUI.SIZES, 'big', 'massive', 'mini'))

  describe('icon', () => {
    it('adds an icon class when true', () => {
      shallow(<Header icon />).should.have.className('icon')
    })
    it('does not add an icon class given a name', () => {
      shallow(<Header icon='user' />).should.not.have.className('icon')
    })
  })

  describe('image', () => {
    it('adds an image class when true', () => {
      shallow(<Header image />).should.have.className('image')
    })
    it('does not add an Image when true', () => {
      shallow(<Header image />).should.not.have.descendants('Image')
    })
  })

  describe('content', () => {
    it('is wrapped in HeaderContent when there is an image src', () => {
      shallow(<Header image='foo.png' content='Bar' />)
        .find('HeaderContent')
        .shallow()
        .should.contain.text('Bar')
    })
    it('is wrapped in HeaderContent when there is an icon name', () => {
      shallow(<Header icon='users' content='Friends' />)
        .find('HeaderContent')
        .shallow()
        .should.contain.text('Friends')
    })
    it('is not wrapped in HeaderContent when icon is true', () => {
      const wrapper = shallow(<Header icon content='Friends' />)

      wrapper.should.contain.text('Friends')
      wrapper.should.not.have.descendants('HeaderContent')
    })
  })

  describe('subheader', () => {
    it('adds HeaderSubheader as child when there is an icon', () => {
      const text = faker.hacker.phrase()

      shallow(<Header icon='user' subheader={text} />)
        .find('HeaderSubheader')
        .should.have.prop('content', text)
    })
    it('adds HeaderSubheader as child when there is an image', () => {
      const text = faker.hacker.phrase()

      shallow(<Header image='foo.png' subheader={text} />)
        .find('HeaderSubheader')
        .should.have.prop('content', text)
    })
  })
})
Пример #22
0
describe('MenuItem', () => {
  common.isConformant(MenuItem)
  common.implementsIconProp(MenuItem)
  common.implementsCreateMethod(MenuItem)
  common.propKeyOnlyToClassName(MenuItem, 'active')
  common.propValueOnlyToClassName(MenuItem, 'color')
  common.propKeyOrValueAndKeyToClassName(MenuItem, 'fitted')
  common.propKeyOnlyToClassName(MenuItem, 'icon')
  common.propKeyOnlyToClassName(MenuItem, 'header')
  common.propKeyOnlyToClassName(MenuItem, 'link')
  common.propValueOnlyToClassName(MenuItem, 'position')
  common.rendersChildren(MenuItem)

  it('renders a `div` by default', () => {
    shallow(<MenuItem />)
      .should.have.tagName('div')
  })

  describe('content', () => {
    it('renders text', () => {
      const text = faker.hacker.phrase()

      shallow(<MenuItem content={text} />)
        .should.contain.text(text)
    })
  })

  describe('name', () => {
    it('uses the name prop as Start Cased child text', () => {
      shallow(<MenuItem name='upcomingEvents' />)
        .should.contain.text('Upcoming Events')
    })
  })

  describe('icon', () => {
    it('does not add `icon` className if there is also `name`', () => {
      shallow(<MenuItem icon='user' name='users' />)
        .should.not.have.className('icon')
    })
    it('does not add `icon` className if there is also `content`', () => {
      shallow(<MenuItem icon='user' content='Users' />)
        .should.not.have.className('icon')
    })
    it('adds `icon` className if there is an `icon` without `name` or `content`', () => {
      shallow(<MenuItem icon='user' />)
        .should.have.className('icon')
    })
  })

  describe('onClick', () => {
    it('omitted when not defined', () => {
      const click = () => shallow(<MenuItem />).simulate('click')
      expect(click).to.not.throw()
    })

    it('is called with (e, { name, index }) when clicked', () => {
      const spy = sandbox.spy()
      const event = { target: null }
      const props = { name: 'home', index: 0 }

      shallow(<MenuItem onClick={spy} {...props} />)
        .simulate('click', event)

      spy.should.have.been.calledOnce()
      spy.should.have.been.calledWithMatch(event, props)
    })

    it('renders an `a` tag', () => {
      shallow(<MenuItem onClick={() => null} />)
        .should.have.tagName('a')
    })
  })
})
Пример #23
0
describe('Embed', () => {
  common.isConformant(Embed)
  common.hasUIClassName(Embed)
  common.rendersChildren(Embed, {
    requiredProps: { active: true },
  })

  common.implementsHTMLIFrameProp(Embed, {
    alwaysPresent: true,
    assertExactMatch: false,
    requiredProps: {
      active: true,
      id: 'default-test-id',
      source: 'youtube',
    },
    shorthandDefaultProps: {
      allowFullScreen: false,
      frameBorder: 0,
      height: '100%',
      scrolling: 'no',
      title: 'Embedded content from youtube.',
      width: '100%',
    },
  })
  common.implementsIconProp(Embed)

  common.propKeyOnlyToClassName(Embed, 'active')

  common.propValueOnlyToClassName(Embed, 'aspectRatio', ['4:3', '16:9', '21:9'])

  describe('active', () => {
    it('defaults to false', () => {
      shallow(<Embed />)
        .should.have.not.state('active')
    })

    it('passes to state', () => {
      shallow(<Embed active />)
        .should.have.state('active', true)
    })

    it('renders nothing when false', () => {
      const children = 'child text'

      shallow(<Embed>{children}</Embed>)
        .should.not.contain(<div className='embed'>{children}</div>)
    })
  })

  describe('autoplay', () => {
    it('generates url part for source', () => {
      assertIframeSrc({ autoplay: true }, '&amp;autoplay=true')
      assertIframeSrc({ autoplay: false }, '&amp;autoplay=false')
    })
  })

  describe('brandedUI', () => {
    it('generates "modestbranding" url parameter', () => {
      assertIframeSrc({ brandedUI: true }, '&amp;modestbranding=true')
      assertIframeSrc({ brandedUI: false }, '&amp;modestbranding=false')
    })

    it('generates "rel" url parameter', () => {
      assertIframeSrc({ brandedUI: true }, '&amp;rel=0')
      assertIframeSrc({ brandedUI: false }, '&amp;rel=1')
    })
  })

  describe('color', () => {
    it('generates url part for source', () => {
      const color = 'red'
      assertIframeSrc({ color }, `&amp;color=${encodeURIComponent(color)}`)
    })
  })

  describe('defaultActive', () => {
    it('sets the initial active state', () => {
      shallow(<Embed defaultActive />)
        .should.have.state('active', true)

      shallow(<Embed defaultActive={false} />)
        .should.have.state('active', false)
    })
  })

  describe('hd', () => {
    it('generates url part for source', () => {
      assertIframeSrc({ hd: true }, '&amp;hq=true')
      assertIframeSrc({ hd: false }, '&amp;hq=false')
    })
  })

  describe('placeholder', () => {
    it('omitted by default', () => {
      shallow(<Embed />)
        .find('img.placeholder')
        .should.have.length(0)
    })

    it('renders img when defined', () => {
      const url = 'foo.png'

      shallow(<Embed placeholder={url} />)
        .should.contain(<img className='placeholder' src={url} />)
    })
  })

  describe('onClick', () => {
    it('omitted when not defined', () => {
      const click = () => shallow(<Embed />).simulate('click')
      expect(click).to.not.throw()
    })

    it('updates state', () => {
      const wrapper = mount(<Embed />)

      wrapper.simulate('click')
      wrapper.should.have.state('active', true)
    })

    it('omits state update if active', () => {
      const wrapper = mount(<Embed active />)

      wrapper.simulate('click')
      wrapper.should.have.state('active', true)
    })
  })

  describe('source', () => {
    it('generates url for YouTube', () => {
      const id = 'foo'

      assertIframeSrc({ id }, `//www.youtube.com/embed/${id}`)
    })

    it('generates url for Vimeo', () => {
      const id = 'foo'

      assertIframeSrc({ source: 'vimeo', id }, `//player.vimeo.com/video/${id}`)
    })

    it('sets the iframe title', () => {
      const sources = ['youtube', 'vimeo']

      sources.forEach((source) => {
        shallow(<Embed active id='foo' source={source} />)
          .find('iframe')
          .should.have.attr('title')
          .which.equals(`Embedded content from ${source}.`)
      })
    })
  })

  describe('url', () => {
    it('passes url to iframe', () => {
      const url = 'https://google.com'

      shallow(<Embed active url={url} />)
        .find('iframe')
        .should.have.attr('src', url)
    })
  })
})
describe('Button', () => {
  common.isConformant(Button)
  common.hasSubComponents(Button, [ButtonContent, ButtonGroup, ButtonOr])
  common.hasUIClassName(Button)
  common.rendersChildren(Button)

  common.implementsCreateMethod(Button)
  common.implementsIconProp(Button)
  common.implementsLabelProp(Button, {
    shorthandDefaultProps: {
      basic: true,
      pointing: 'left',
    },
  })

  common.propKeyAndValueToClassName(Button, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(Button, 'active')
  common.propKeyOnlyToClassName(Button, 'basic')
  common.propKeyOnlyToClassName(Button, 'circular')
  common.propKeyOnlyToClassName(Button, 'compact')
  common.propKeyOnlyToClassName(Button, 'disabled')
  common.propKeyOnlyToClassName(Button, 'fluid')
  common.propKeyOnlyToClassName(Button, 'inverted')
  common.propKeyOnlyToClassName(Button, 'loading')
  common.propKeyOnlyToClassName(Button, 'primary')
  common.propKeyOnlyToClassName(Button, 'negative')
  common.propKeyOnlyToClassName(Button, 'positive')
  common.propKeyOnlyToClassName(Button, 'secondary')

  common.propKeyOrValueAndKeyToClassName(Button, 'animated', ['fade', 'vertical'])
  common.propKeyOrValueAndKeyToClassName(Button, 'attached', ['left', 'right', 'top', 'bottom'])
  common.propKeyOrValueAndKeyToClassName(Button, 'labelPosition', ['right', 'left'], {
    className: 'labeled',
  })

  common.propValueOnlyToClassName(Button, 'color', [
    ...SUI.COLORS,
    'facebook',
    'twitter',
    'google plus',
    'vk',
    'linkedin',
    'instagram',
    'youtube',
  ])
  common.propValueOnlyToClassName(Button, 'size', SUI.SIZES)

  it('renders a button by default', () => {
    shallow(<Button />)
      .first()
      .should.have.tagName('button')
  })

  describe('attached', () => {
    it('renders a div', () => {
      shallow(<Button attached />)
        .should.have.tagName('div')
    })
  })

  describe('disabled', () => {
    it('is not set by default', () => {
      shallow(<Button />)
        .should.not.have.prop('disabled')
    })

    it('applied when defined', () => {
      shallow(<Button disabled />)
        .should.have.prop('disabled', true)
    })

    it("don't apply when the element's type isn't button", () => {
      shallow(<Button as='div' disabled />)
        .should.not.have.prop('disabled')
    })

    it('is not set by default when has a label', () => {
      shallow(<Button label='foo' />)
        .find('button')
        .should.not.have.prop('disabled')
    })

    it('applied when defined and has a label', () => {
      shallow(<Button disabled label='foo' />)
        .find('button')
        .should.have.prop('disabled', true)
    })
  })

  describe('focus', () => {
    it('can be set via a ref', () => {
      const mountNode = document.createElement('div')
      document.body.appendChild(mountNode)

      const wrapper = mount(<Button />, { attachTo: mountNode })
      wrapper.instance().focus()

      const button = document.querySelector('button')
      document.activeElement.should.equal(button)

      wrapper.detach()
      document.body.removeChild(mountNode)
    })
  })

  describe('icon', () => {
    it('adds className icon', () => {
      shallow(<Button icon='user' />)
        .should.have.className('icon')
    })

    it('adds className icon when true', () => {
      shallow(<Button icon />)
        .should.have.className('icon')
    })

    it('does not add className icon when there is content', () => {
      shallow(<Button icon='user' content={0} />)
        .should.not.have.className('icon')
      shallow(<Button icon='user' content='Yo' />)
        .should.not.have.className('icon')
    })

    it('adds className icon given labelPosition and content', () => {
      shallow(<Button labelPosition='left' icon='user' content='My Account' />)
        .should.have.className('icon')
      shallow(<Button labelPosition='right' icon='user' content='My Account' />)
        .should.have.className('icon')
    })
  })

  describe('label', () => {
    it('renders as a div', () => {
      shallow(<Button label='http' />)
        .should.have.tagName('div')
    })
    it('renders a div with a button and Label child', () => {
      const wrapper = shallow(<Button label='hi' />)

      wrapper.should.have.tagName('div')
      wrapper.should.have.exactly(1).descendants('button')
      wrapper.should.have.exactly(1).descendants('Label')
    })
    it('adds the labeled className to the root element', () => {
      shallow(<Button label='hi' />)
        .should.have.className('labeled')
    })
    it('contains children without disabled class when disabled attribute is set', () => {
      const wrapper = shallow(<Button label='hi' disabled />)

      wrapper.should.have.className('disabled')
      wrapper.find('Label').should.not.have.className('disabled')
      wrapper.find('button').should.not.have.className('disabled')
    })
    it('contains children without floated class when floated attribute is set', () => {
      const wrapper = shallow(<Button label='hi' floated='left' />)

      wrapper.should.have.className('floated')
      wrapper.find('Label').should.not.have.className('floated')
      wrapper.find('button').should.not.have.className('floated')
    })
    it('creates a basic pointing label', () => {
      shallow(<Button label='foo' />)
        .should.have.exactly(1).descendants('Label[basic][pointing]')
    })
    it('is before the button and pointing="right" when labelPosition="left"', () => {
      const wrapper = shallow(<Button labelPosition='left' label='foo' />)
      wrapper.should.have.exactly(1).descendants('Label[pointing="right"]')

      wrapper.children().at(0).shallow().should.match('.ui.label')
      wrapper.children().at(1).should.match('button')
    })
    it('is after the button and pointing="left" when labelPosition="right"', () => {
      const wrapper = shallow(<Button labelPosition='right' label='foo' />)
      wrapper.should.have.exactly(1).descendants('Label[pointing="left"]')

      wrapper.children().at(0).should.match('button')
      wrapper.children().at(1).shallow().should.match('.ui.label')
    })
    it('is after the button and pointing="left" by default', () => {
      const wrapper = shallow(<Button label='foo' />)
      wrapper.should.have.exactly(1).descendants('Label[pointing="left"]')

      wrapper.children().at(0).should.match('button')
      wrapper.children().at(1).shallow().should.match('.ui.label')
    })
  })

  describe('labelPosition', () => {
    it('renders as a button when given an icon', () => {
      shallow(<Button labelPosition='left' icon='user' />)
        .should.have.tagName('button')
      shallow(<Button labelPosition='right' icon='user' />)
        .should.have.tagName('button')
    })
  })

  describe('onClick', () => {
    it('is called with (e, data) when clicked', () => {
      const onClick = sandbox.spy()

      shallow(<Button onClick={onClick} />)
        .simulate('click', syntheticEvent)

      onClick.should.have.been.calledOnce()
      onClick.should.have.been.calledWithExactly(syntheticEvent, { onClick, as: 'button' })
    })

    it('is not called when is disabled', () => {
      const onClick = sandbox.spy()

      shallow(<Button disabled onClick={onClick} />)
        .simulate('click', syntheticEvent)
      onClick.should.have.callCount(0)
    })
  })

  describe('tabIndex', () => {
    it('is not set by default', () => {
      shallow(<Button />)
        .should.not.have.prop('tabIndex')
    })
    it('defaults to 0 as div', () => {
      shallow(<Button as='div' />)
        .should.have.prop('tabIndex', 0)
    })
    it('defaults to -1 when disabled', () => {
      shallow(<Button disabled />)
        .should.have.prop('tabIndex', -1)
    })
    it('can be set explicitly', () => {
      shallow(<Button tabIndex={123} />)
        .should.have.prop('tabIndex', 123)
    })
    it('can be set explicitly when disabled', () => {
      shallow(<Button tabIndex={123} disabled />)
        .should.have.prop('tabIndex', 123)
    })
  })
})
Пример #25
0
describe('Table', () => {
  common.isConformant(Table)
  common.hasSubcomponents(Table, [
    TableBody,
    TableCell,
    TableFooter,
    TableHeader,
    TableHeaderCell,
    TableRow,
  ])
  common.hasUIClassName(Table)
  common.rendersChildren(Table, {
    rendersContent: false,
  })

  common.implementsWidthProp(Table, SUI.WIDTHS, {
    canEqual: false,
    propKey: 'columns',
    widthClass: 'column',
  })

  common.implementsTextAlignProp(Table, ['left', 'center', 'right'])
  common.implementsVerticalAlignProp(Table)

  common.propKeyOnlyToClassName(Table, 'celled')
  common.propKeyOnlyToClassName(Table, 'collapsing')
  common.propKeyOnlyToClassName(Table, 'definition')
  common.propKeyOnlyToClassName(Table, 'fixed')
  common.propKeyOnlyToClassName(Table, 'inverted')
  common.propKeyOnlyToClassName(Table, 'selectable')
  common.propKeyOnlyToClassName(Table, 'singleLine', {
    className: 'single line',
  })
  common.propKeyOnlyToClassName(Table, 'stackable')
  common.propKeyOnlyToClassName(Table, 'sortable')
  common.propKeyOnlyToClassName(Table, 'striped')
  common.propKeyOnlyToClassName(Table, 'structured')
  common.propKeyOnlyToClassName(Table, 'unstackable')

  common.propKeyOrValueAndKeyToClassName(Table, 'attached', ['top', 'bottom'])
  common.propKeyOrValueAndKeyToClassName(Table, 'basic', ['very'])
  common.propKeyOrValueAndKeyToClassName(Table, 'compact', ['very'])
  common.propKeyOrValueAndKeyToClassName(Table, 'padded', ['very'])

  common.propValueOnlyToClassName(Table, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(
    Table,
    'size',
    _.without(SUI.SIZES, 'mini', 'tiny', 'medium', 'big', 'huge', 'massive'),
  )

  describe('as', () => {
    it('renders as a table by default', () => {
      shallow(<Table />).should.have.tagName('table')
    })
  })

  describe('shorthand', () => {
    let wrapper
    let thead
    let tbody
    let tfoot

    beforeEach(() => {
      wrapper = undefined
      thead = undefined
      tbody = undefined
      tfoot = undefined
    })

    const headerRow = ['Name', 'Status', 'Notes']

    const renderBodyRow = ({ name, status, notes }, index) => ({
      key: index,
      cells: [name || { key: 0 }, status || { key: 1 }, notes || { key: 2 }],
    })

    const footerRow = [{ colSpan: 3, content: 'Total', key: 'total' }]

    const tableData = [
      { name: undefined, status: undefined, notes: undefined },
      { name: 'Jimmy', status: 'Requires Action', notes: undefined },
      { name: 'Jamie', status: undefined, notes: 'Hostile' },
      { name: 'Jill', status: undefined, notes: undefined },
    ]

    const wrapperMount = (props) => {
      wrapper = mount(<Table {...props} />)

      thead = wrapper.find('thead')
      tbody = wrapper.find('tbody')
      tfoot = wrapper.find('tfoot')
    }

    it('renders empty tbody with no shorthand', () => {
      wrapperMount()

      thead.should.have.lengthOf(0)

      tbody.should.have.lengthOf(1)
      tbody.find('tr').should.have.lengthOf(0)

      tfoot.should.have.lengthOf(0)
    })

    it('renders the table', () => {
      wrapperMount({ headerRow, renderBodyRow, footerRow, tableData })

      thead.should.have.lengthOf(1)
      thead.find('tr').should.have.lengthOf(1)
      thead
        .find('tr')
        .find('th')
        .should.have.lengthOf(headerRow.length)

      tbody.should.have.lengthOf(1)
      tbody.find('tr').should.have.lengthOf(tableData.length)
      tbody
        .find('tr')
        .first()
        .find('td')
        .should.have.lengthOf(3)

      tfoot.should.have.lengthOf(1)
      tfoot.find('tr').should.have.lengthOf(1)
      tfoot
        .find('tr')
        .find('td')
        .should.have.lengthOf(footerRow.length)
    })
  })
})
Пример #26
0
describe('Label Component', () => {
  common.isConformant(Label)
  common.hasUIClassName(Label)
  common.rendersChildren(Label)

  common.propKeyOnlyToClassName(Label, 'basic')
  common.propKeyOnlyToClassName(Label, 'circular')
  common.propKeyOnlyToClassName(Label, 'floating')
  common.propKeyOnlyToClassName(Label, 'horizontal')
  common.propKeyOnlyToClassName(Label, 'tag')

  common.propValueOnlyToClassName(Label, 'color')
  common.propValueOnlyToClassName(Label, 'size')

  common.propKeyAndValueToClassName(Label, 'attached')

  common.propKeyOrValueToClassName(Label, 'corner')
  common.propKeyOrValueToClassName(Label, 'pointing')
  common.propKeyOrValueToClassName(Label, 'ribbon')

  common.implementsIconProp(Label)

  it('is a div by default', () => {
    shallow(<Label />)
      .should.have.tagName('div')
  })

  describe('(empty) circular', () => {
    it('is added to className when there are no children', () => {
      shallow(<Label circular />)
        .should.have.className('empty circular')
    })

    it('is not added to className when there are children', () => {
      shallow(<Label circular>Child</Label>)
        .should.not.have.className('empty circular')
    })
  })

  describe('detail', () => {
    it('renders detail as a div', () => {
      shallow(<Label detail={faker.hacker.noun()} />)
        .find('.detail')
        .should.have.tagName('div')
    })

    it('has no detail when not defined', () => {
      shallow(<Label />)
        .should.not.have.descendants('.detail')
    })

    it('adds a detail last child', () => {
      shallow(<Label detail={faker.hacker.noun()}><br /></Label>)
        .children()
        .last()
        .should.match('.detail')
    })

    it('adds the value as the detail text', () => {
      const detail = faker.hacker.noun()
      shallow(<Label detail={detail} />)
        .find('.detail')
        .should.contain.text(detail)
    })
  })

  describe('detailLink', () => {
    it('has no detail when not defined', () => {
      shallow(<Label />)
        .should.not.have.descendants('.detail')
    })

    it('renders detail as an a tag', () => {
      shallow(<Label detail={faker.hacker.noun()} detailLink />)
        .find('.detail')
        .should.have.tagName('a')
    })
  })

  describe('icon', () => {
    it('adds a i as first child', () => {
      shallow(<Label icon={faker.hacker.noun()}><br /></Label>)
        .childAt(0)
        .should.match('i')
    })
  })

  describe('image', () => {
    it('has no img when prop is not defined', () => {
      shallow(<Label />)
        .should.not.have.descendants('img')
    })

    it('adds image className when defined', () => {
      const src = faker.internet.avatar()
      shallow(<Label image={src} />)
        .should.have.className('image')
    })

    it('adds image className when there is an img child', () => {
      shallow(<Label><img /></Label>)
        .should.have.className('image')
    })

    it('adds image className when there is an Image child', () => {
      shallow(<Label><Image /></Label>)
        .should.have.className('image')
    })

    it('adds an img as first child', () => {
      shallow(<Label image={faker.internet.avatar()}><br /></Label>)
        .find('Image')
        .should.have.tagName('img')
    })

    it('adds the value to the Image className', () => {
      const src = faker.internet.avatar()
      shallow(<Label image={src} />)
        .find('Image')
        .should.have.prop('src', src)
    })
  })

  describe('link', () => {
    it('does not render label as an "a" when not defined', () => {
      shallow(<Label />)
        .should.not.have.tagName('a')
    })

    it('renders label as an "a"', () => {
      shallow(<Label link />)
        .should.have.tagName('a')
    })
  })

  describe('onClick', () => {
    it('does not render as an "a" when not defined', () => {
      shallow(<Label />)
        .should.not.have.tagName('a')
    })
    it('renders label as an "a"', () => {
      shallow(<Label onClick={() => null} />)
        .should.have.tagName('a')
    })
    it('is called when label is clicked', () => {
      const props = {
        onClick: sandbox.spy(),
      }

      // mount to get click event to propagate on click
      mount(<Label {...props} />)
        .simulate('click')

      props.onClick.should.have.been.calledOnce()
    })
  })

  describe('onRemove', () => {
    it('has no delete icon when not defined', () => {
      shallow(<Label />)
        .should.not.have.descendants('.delete')
    })

    it('adds a delete icon as last child', () => {
      shallow(<Label onRemove={() => null}><br /></Label>)
        .children()
        .last()
        .should.match('.delete')
    })

    it('is called when delete icon is clicked', () => {
      const props = {
        onRemove: sandbox.spy(),
      }

      // mount to get click event to propagate on click
      mount(<Label {...props} />)
        .find('.delete')
        .simulate('click')

      props.onRemove.should.have.been.calledOnce()
    })
  })

  describe('onDetailClick', () => {
    it('renders detail as an a tag', () => {
      shallow(<Label detail={faker.hacker.noun()} onDetailClick={() => null} />)
        .should.have.descendants('a.detail')
    })

    it('is called when detail is clicked', () => {
      const props = {
        detail: faker.hacker.noun(),
        onDetailClick: sandbox.spy(),
      }

      // mount to get click event to propagate on click
      mount(<Label {...props} />)
        .find('.detail')
        .simulate('click')

      props.onDetailClick.should.have.been.calledOnce()
    })
  })

  describe('removable', () => {
    it('has no delete icon when not defined', () => {
      shallow(<Label />)
        .should.not.have.descendants('.delete')
    })

    it('adds a delete icon as last child', () => {
      shallow(<Label removable><br /></Label>)
        .children()
        .last()
        .should.match('.delete')
    })
  })

  describe('text', () => {
    it('has no text by default', () => {
      shallow(<Label />)
        .text()
        .should.be.empty()
    })

    it('adds the value as children', () => {
      const text = faker.hacker.phrase()
      shallow(<Label text={text} />)
        .children()
        .should.contain.text(text)
    })
  })
})
Пример #27
0
describe('Message', () => {
  common.isConformant(Message)
  common.hasSubComponents(Message, [MessageContent, MessageHeader, MessageList])
  common.hasUIClassName(Message)
  common.rendersChildren(Message, {
    rendersContent: false,
  })

  common.implementsIconProp(Message)
  common.implementsShorthandProp(Message, {
    propKey: 'content',
    ShorthandComponent: 'p',
    mapValueToProps: val => ({ children: val }),
  })
  common.implementsShorthandProp(Message, {
    propKey: 'header',
    ShorthandComponent: MessageHeader,
    mapValueToProps: val => ({ content: val }),
  })
  common.implementsShorthandProp(Message, {
    propKey: 'list',
    ShorthandComponent: MessageList,
    mapValueToProps: val => ({ items: val }),
  })

  common.propKeyOnlyToClassName(Message, 'compact')
  common.propKeyOnlyToClassName(Message, 'error')
  common.propKeyOnlyToClassName(Message, 'floating')
  common.propKeyOnlyToClassName(Message, 'hidden')
  common.propKeyOnlyToClassName(Message, 'icon')
  common.propKeyOnlyToClassName(Message, 'info')
  common.propKeyOnlyToClassName(Message, 'negative')
  common.propKeyOnlyToClassName(Message, 'positive')
  common.propKeyOnlyToClassName(Message, 'success')
  common.propKeyOnlyToClassName(Message, 'visible')
  common.propKeyOnlyToClassName(Message, 'warning')

  common.propKeyOrValueAndKeyToClassName(Message, 'attached', ['bottom', 'top'])

  common.propValueOnlyToClassName(Message, 'color', SUI.COLORS)
  common.propValueOnlyToClassName(Message, 'size', _.without(SUI.SIZES, 'medium'))

  describe('header', () => {
    it('adds MessageContent when defined', () => {
      shallow(<Message header='This is a message' />)
        .should.have.descendants('MessageContent')
    })
  })

  describe('icon', () => {
    it('does not have MessageContent by default', () => {
      shallow(<Message />)
        .should.not.have.descendants('.content')
    })
    it('renders children when "true"', () => {
      const text = 'child text'
      const node = <div id='foo' />

      shallow(<Message icon>{text}</Message>)
        .should.have.text(text)

      shallow(<Message icon>{node}</Message>)
        .should.contain(node)
    })
  })

  describe('list', () => {
    it('adds MessageContent when defined', () => {
      shallow(<Message list={[]} />)
        .should.have.descendants('MessageContent')
    })
  })

  describe('onDismiss', () => {
    it('has no close icon by default', () => {
      shallow(<Message />)
        .should.not.have.descendants('.close.icon')
    })

    it('adds a close icon when defined', () => {
      render(<Message onDismiss={() => undefined} />)
        .should.have.descendants('.close.icon')
    })

    it('is called with (event) on close icon click', () => {
      const event = { fake: 'event data' }
      const props = { icon: true }

      const spy = sandbox.spy()
      const wrapper = mount(<Message {...props} onDismiss={spy} />)

      wrapper.should.have.descendants('.close.icon')
      wrapper.find('.close.icon')
        .simulate('click', event)

      spy.should.have.been.calledOnce()
      spy.should.have.been.calledWithMatch(event, props)
    })
  })
})
Пример #28
0
describe('List', () => {
  common.isConformant(List)
  common.hasSubcomponents(List, [
    ListContent,
    ListDescription,
    ListHeader,
    ListIcon,
    ListItem,
    ListList,
  ])
  common.hasUIClassName(List)
  common.rendersChildren(List)

  common.implementsVerticalAlignProp(List)

  common.propKeyAndValueToClassName(List, 'floated', SUI.FLOATS)

  common.propKeyOnlyToClassName(List, 'animated')
  common.propKeyOnlyToClassName(List, 'bulleted')
  common.propKeyOnlyToClassName(List, 'celled')
  common.propKeyOnlyToClassName(List, 'divided')
  common.propKeyOnlyToClassName(List, 'horizontal')
  common.propKeyOnlyToClassName(List, 'inverted')
  common.propKeyOnlyToClassName(List, 'link')
  common.propKeyOnlyToClassName(List, 'ordered')
  common.propKeyOnlyToClassName(List, 'selection')

  common.propKeyOrValueAndKeyToClassName(List, 'relaxed', ['very'])

  common.propValueOnlyToClassName(List, 'size', SUI.SIZES)

  const items = ['Name', 'Status', 'Notes']

  describe('onItemClick', () => {
    it('can be omitted', () => {
      const click = () => shallow(<List items={items} />).simulate('click')
      expect(click).to.not.throw()
    })

    it('is called with (e, itemProps) when clicked', () => {
      const onClick = sandbox.spy()
      const onItemClick = sandbox.spy()
      const event = { target: null }

      const callbackData = { content: 'Notes', 'data-foo': 'bar' }
      const itemProps = { key: 'notes', content: 'Notes', 'data-foo': 'bar', onClick }

      shallow(<List items={[itemProps]} onItemClick={onItemClick} />)
        .find('ListItem')
        .first()
        .shallow()
        .simulate('click', event)

      onClick.should.have.been.calledOnce()
      onClick.should.have.been.calledWithMatch(event, callbackData)

      onItemClick.should.have.been.calledOnce()
      onItemClick.should.have.been.calledWithMatch(event, callbackData)
    })
  })

  describe('role', () => {
    it('is accessibile with no items', () => {
      const wrapper = shallow(<List />)
      wrapper.should.have.prop('role', 'list')
    })

    it('is accessibile with items', () => {
      const wrapper = shallow(<List items={items} />)
      wrapper.should.have.prop('role', 'list')
    })

    it('allows overriding with no items', () => {
      const wrapper = shallow(<List role='listbox' />)
      wrapper.should.have.prop('role', 'listbox')
    })

    it('allows overriding with items', () => {
      const wrapper = shallow(<List role='listbox' items={items} />)
      wrapper.should.have.prop('role', 'listbox')
    })

    it('allows overriding with children', () => {
      const wrapper = shallow(
        <List role='listbox'>
          <ListItem />
        </List>,
      )
      wrapper.should.have.prop('role', 'listbox')
    })
  })

  describe('shorthand', () => {
    it('renders empty tr with no shorthand', () => {
      const wrapper = shallow(<List />)

      wrapper.find('ListItem').should.have.lengthOf(0)
    })

    it('renders the items', () => {
      const wrapper = shallow(<List items={items} />)

      wrapper.find('ListItem').should.have.lengthOf(items.length)
    })
  })
})
Пример #29
0
describe('Input', () => {
  common.isConformant(Input, {
    eventTargets: {
      // keyboard
      onKeyDown: 'input',
      onKeyPress: 'input',
      onKeyUp: 'input',

      // focus
      onFocus: 'input',
      onBlur: 'input',

      // form
      onChange: 'input',
      onInput: 'input',

      // mouse
      onClick: 'input',
      onContextMenu: 'input',
      onDrag: 'input',
      onDragEnd: 'input',
      onDragEnter: 'input',
      onDragExit: 'input',
      onDragLeave: 'input',
      onDragOver: 'input',
      onDragStart: 'input',
      onDrop: 'input',
      onMouseDown: 'input',
      onMouseEnter: 'input',
      onMouseLeave: 'input',
      onMouseMove: 'input',
      onMouseOut: 'input',
      onMouseOver: 'input',
      onMouseUp: 'input',

      // selection
      onSelect: 'input',

      // touch
      onTouchCancel: 'input',
      onTouchEnd: 'input',
      onTouchMove: 'input',
      onTouchStart: 'input',
    },
  })
  common.hasUIClassName(Input)
  common.rendersChildren(Input)

  common.implementsButtonProp(Input, {
    propKey: 'action',
  })
  common.implementsCreateMethod(Input)
  common.implementsLabelProp(Input, {
    shorthandDefaultProps: { className: 'label' },
  })
  common.implementsHTMLInputProp(Input, {
    alwaysPresent: true,
    assertExactMatch: false,
    shorthandDefaultProps: { type: 'text' },
  })

  common.propKeyAndValueToClassName(Input, 'actionPosition', ['left'], { className: 'action' })
  common.propKeyAndValueToClassName(Input, 'iconPosition', ['left'], { className: 'icon' })
  common.propKeyAndValueToClassName(Input, 'labelPosition', ['left', 'right', 'left corner', 'right corner'], {
    className: 'labeled',
  })

  common.propKeyOnlyToClassName(Input, 'action')
  common.propKeyOnlyToClassName(Input, 'disabled')
  common.propKeyOnlyToClassName(Input, 'error')
  common.propKeyOnlyToClassName(Input, 'fluid')
  common.propKeyOnlyToClassName(Input, 'focus')
  common.propKeyOnlyToClassName(Input, 'inverted')
  common.propKeyOnlyToClassName(Input, 'label', { className: 'labeled' })
  common.propKeyOnlyToClassName(Input, 'loading')
  common.propKeyOnlyToClassName(Input, 'loading', { className: 'icon' })
  common.propKeyOnlyToClassName(Input, 'transparent')
  common.propKeyOnlyToClassName(Input, 'icon')
  common.propKeyOnlyToClassName(Input, 'icon')

  common.propValueOnlyToClassName(Input, 'size', SUI.SIZES)

  it('renders with conditional children', () => {
    shallow(
      <Input>
        {true && <span></span>}
        {false && <div></div>}
      </Input>,
    )
      .should.contain(<span></span>)
      .should.not.contain(<div></div>)
  })

  it('renders a text <input> by default', () => {
    shallow(<Input />)
      .find('input')
      .should.have.prop('type', 'text')
  })

  describe('input props', () => {
    htmlInputProps.forEach(propName => {
      it(`passes \`${propName}\` to the <input>`, () => {
        const propValue = propName === 'onChange' ? () => null : 'foo'
        const wrapper = shallow(<Input {...{ [propName]: propValue }} />)

        // account for overloading the onChange prop
        const expectedValue = propName === 'onChange'
          ? wrapper.instance().handleChange
          : propValue

        wrapper
          .find('input')
          .should.have.prop(propName, expectedValue)
      })

      it(`passes \`${propName}\` to the <input> when using children`, () => {
        const propValue = propName === 'onChange' ? () => null : 'foo'
        const wrapper = shallow(
          <Input {...{ [propName]: propValue }}>
            <input />
          </Input>,
        )

        // account for overloading the onChange prop
        const expectedValue = propName === 'onChange'
          ? wrapper.instance().handleChange
          : propValue

        wrapper
          .find('input')
          .should.have.prop(propName, expectedValue)
      })
    })
  })

  describe('focus', () => {
    it('can be set via a ref', () => {
      const mountNode = document.createElement('div')
      document.body.appendChild(mountNode)

      const wrapper = mount(<Input />, { attachTo: mountNode })
      wrapper.instance().focus()

      const input = document.querySelector('.ui.input input')
      document.activeElement.should.equal(input)

      wrapper.detach()
      document.body.removeChild(mountNode)
    })
  })

  describe('loading', () => {
    it("don't add icon if it's defined", () => {
      shallow(<Input icon='user' loading />)
        .find('Icon')
        .should.have.prop('name', 'user')
    })

    it("adds icon if it's not defined", () => {
      shallow(<Input loading />)
        .find('Icon')
        .should.have.prop('name', 'spinner')
    })
  })

  describe('onChange', () => {
    it('is called with (e, data) on change', () => {
      const spy = sandbox.spy()
      const e = { target: { value: 'name' } }
      const props = { 'data-foo': 'bar', onChange: spy }

      const wrapper = shallow(<Input {...props} />)

      wrapper.find('input').simulate('change', e)

      spy.should.have.been.calledOnce()
      spy.should.have.been.calledWithMatch(e, { ...props, value: e.target.value })
    })

    it('is called with (e, data) on change when using children', () => {
      const spy = sandbox.spy()
      const e = { target: { value: 'name' } }
      const props = { 'data-foo': 'bar', onChange: spy }

      const wrapper = shallow(
        <Input {...props}>
          <input />
        </Input>,
      )

      wrapper.find('input').simulate('change', e)

      spy.should.have.been.calledOnce()
      spy.should.have.been.calledWithMatch(e, { ...props, value: e.target.value })
    })
  })

  describe('ref', () => {
    it('maintains ref on child node', () => {
      const ref = sandbox.spy()
      const mountNode = document.createElement('div')
      document.body.appendChild(mountNode)

      const wrapper = mount(<Input><input ref={ref} /></Input>, { attachTo: mountNode })
      const input = document.querySelector('.ui.input input')

      ref.should.have.been.calledOnce()
      ref.should.have.been.calledWithMatch(input)
      wrapper.instance().inputRef.should.equal(input)

      wrapper.detach()
      document.body.removeChild(mountNode)
    })
  })

  describe('disabled', () => {
    it('is applied to the underlying html input element', () => {
      shallow(<Input disabled />)
        .find('input')
        .should.have.prop('disabled', true)

      shallow(<Input disabled={false} />)
        .find('input')
        .should.have.prop('disabled', false)
    })
  })

  describe('tabIndex', () => {
    it('is not set by default', () => {
      shallow(<Input />)
        .find('input')
        .should.not.have.prop('tabIndex')
    })

    it('defaults to -1 when disabled', () => {
      shallow(<Input disabled />)
        .find('input')
        .should.have.prop('tabIndex', -1)
    })

    it('can be set explicitly', () => {
      shallow(<Input tabIndex={123} />)
        .find('input')
        .should.have.prop('tabIndex', 123)
    })

    it('can be set explicitly when disabled', () => {
      shallow(<Input tabIndex={123} disabled />)
        .find('input')
        .should.have.prop('tabIndex', 123)
    })
  })
})
Пример #30
0
describe('Form', () => {
  common.isConformant(Form)
  common.hasSubComponents(Form, [
    FormButton,
    FormCheckbox,
    FormDropdown,
    FormField,
    FormTextArea,
    FormGroup,
    FormInput,
    FormRadio,
    FormSelect,
  ])
  common.hasUIClassName(Form)
  common.rendersChildren(Form)

  common.implementsWidthProp(Form, _.without(SUI.SIZES, 'medium'), { propKey: 'widths' })

  common.propKeyOnlyToClassName(Form, 'error')
  common.propKeyOnlyToClassName(Form, 'inverted')
  common.propKeyOnlyToClassName(Form, 'loading')
  common.propKeyOnlyToClassName(Form, 'reply')
  common.propKeyOnlyToClassName(Form, 'success')
  common.propKeyOnlyToClassName(Form, 'warning')

  common.propValueOnlyToClassName(Form, 'size', _.without(SUI.SIZES, 'medium'))

  describe('onSubmit', () => {
    it('prevents default on the event when there is no action', () => {
      const event = { preventDefault: sandbox.spy() }

      shallow(<Form />)
        .simulate('submit', event)

      event.preventDefault.should.have.been.calledOnce()
    })

    it('does not prevent default on the event when there is an action', () => {
      const event = { preventDefault: sandbox.spy() }

      shallow(<Form action='do not prevent default!' />)
        .simulate('submit', event)

      event.preventDefault.should.not.have.been.called()
    })

    it('is called with (e, props) on submit', () => {
      const onSubmit = sandbox.spy()
      const event = { name: 'foo' }
      const props = { 'data-bar': 'baz' }

      shallow(<Form {...props} onSubmit={onSubmit} />)
        .simulate('submit', event)

      onSubmit.should.have.been.calledOnce()
      onSubmit.should.have.been.calledWithMatch(event, props)
    })

    it('passes all args to onSubmit', () => {
      const onSubmit = sandbox.spy()
      const props = { 'data-baz': 'baz' }
      const event = { fake: 'event' }
      const args = ['some', 'extra', 'args']

      shallow(<Form {...props} onSubmit={onSubmit} />)
        .simulate('submit', event, ...args)

      onSubmit.should.have.been.calledOnce()
      onSubmit.should.have.been.calledWithMatch(event, props, ...args)
    })
  })
})