Skip to content

Commit

Permalink
[spec] improves existing specs and adds new ones
Browse files Browse the repository at this point in the history
  • Loading branch information
josemigallas committed Aug 2, 2019
1 parent 861be24 commit 10d4ac9
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 103 deletions.
1 change: 1 addition & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
[lints]

[options]
module.system.node.resolve_dirname=node_modules
module.name_mapper.extension='scss' -> 'empty/object'
module.system=haste
module.name_mapper='\(Applications\|Dashboard\|LoginPage\|Navigation\|Onboarding\|Policies\|services\|Stats\|Types\|Users\|utilities\|NewService\)\(.*\)$' -> '<PROJECT_ROOT>/app/javascript/src/\1/\2'
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @flow

import React from 'react'
import {useState, useEffect} from 'react'
import React, {useEffect} from 'react'

import {FormWrapper, ErrorMessage,
ServiceDiscoveryListItems} from 'NewService/components/FormElements'
Expand All @@ -15,8 +14,9 @@ type Props = {
}

const ServiceDiscoveryForm = ({formActionPath, setLoadingProjects}: Props) => {
const [projects, setProjects] = useState([])
const [fetchErrorMessage, setFetchErrorMessage] = useState('')
// Don't use named imports so that useState can be mocked in specs
const [projects, setProjects] = React.useState([])
const [fetchErrorMessage, setFetchErrorMessage] = React.useState('')

const fetchProjects = async () => {
setLoadingProjects(true)
Expand Down
51 changes: 16 additions & 35 deletions spec/javascripts/NewService/NewServiceForm.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
// @flow

import React from 'react'
import Enzyme, {mount} from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

import {NewServiceForm} from 'NewService'
import {NewServiceForm, ServiceManualForm, ServiceDiscoveryForm} from 'NewService'

import * as utils from 'utilities/utils'
jest.spyOn(utils, 'CSRFToken')
.mockImplementation(() => '')

Enzyme.configure({adapter: new Adapter()})

Expand All @@ -13,51 +19,26 @@ const props = {
providerAdminServiceDiscoveryServicesPath: 'my-path',
adminServicesPath: 'my-other-path'
}
const discoveryNotUsableProps = {
...props,
isServiceDiscoveryUsable: false
}

it('should render itself', () => {
const wrapper = mount(<NewServiceForm {...props}/>)
expect(wrapper.find('#new_service_source').exists()).toEqual(true)
expect(wrapper.find(`input[name='source']`).length).toEqual(2)
})

it('should render new Service Manual form', () => {
it('should render the correct form depending on which mode is selected', () => {
const wrapper = mount(<NewServiceForm {...props}/>)
expect(wrapper.find('#new_service').exists()).toEqual(true)
expect(wrapper.find('#service_discovery').exists()).toEqual(false)
})
const clickEvent = value => ({ currentTarget: { value } })

// TODO: remove `skip` when this is merged: https://github.com/airbnb/enzyme/pull/2008
it.skip('should render new Service Discovery form when click on input', () => {
const wrapper = mount(<NewServiceForm {...props}/>)
wrapper.find('#source_discover').simulate('click')
wrapper.find('input#source_discover').props().onChange(clickEvent(''))
wrapper.update()
expect(wrapper.find('#new_service').exists()).toEqual(false)
expect(wrapper.find('#service_discovery').exists()).toEqual(true)
})
expect(wrapper.find(ServiceManualForm).exists()).toEqual(false)
expect(wrapper.find(ServiceDiscoveryForm).exists()).toEqual(true)

it('should render `Import from OpenShift` input enabled when Service Discovery is usable', () => {
const wrapper = mount(<NewServiceForm {...props}/>)
expect(wrapper.props().isServiceDiscoveryUsable).toEqual(true)
expect(wrapper.find('#source_discover').props().disabled).toEqual(false)
expect(wrapper.find('#source_discover + span').text()).toEqual('Import from OpenShift')
})

it('should render `Import from OpenShift` input disabled when Service Discovery is not usable', () => {
const wrapper = mount(<NewServiceForm {...discoveryNotUsableProps}/>)
expect(wrapper.props().isServiceDiscoveryUsable).toEqual(false)
expect(wrapper.find('#source_discover').props().disabled).toEqual(true)
})

it('should render `(Authenticate to enable this option)` link when Service Discovery is not usable', () => {
const wrapper = mount(<NewServiceForm {...discoveryNotUsableProps}/>)
const link = wrapper.find(`label[htmlFor='source_discover'] a`)
expect(link.exists()).toEqual(true)
expect(link.text()).toEqual(' (Authenticate to enable this option)')
expect(link.props().href).toEqual('authenticate-url')
wrapper.find('input#source_manual').props().onChange(clickEvent('manual'))
wrapper.update()
expect(wrapper.find(ServiceManualForm).exists()).toEqual(true)
expect(wrapper.find(ServiceDiscoveryForm).exists()).toEqual(false)
})

describe('when Service Discovery is not accessible', () => {
Expand Down
51 changes: 45 additions & 6 deletions spec/javascripts/NewService/ServiceDiscoveryForm.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @flow

import React from 'react'
import Enzyme, {shallow, mount} from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
Expand All @@ -6,10 +8,15 @@ import {ServiceDiscoveryForm} from 'NewService'
import {FormWrapper, ErrorMessage,
ServiceDiscoveryListItems} from 'NewService/components/FormElements'

import * as utils from 'utilities/utils'
jest.spyOn(utils, 'CSRFToken')
.mockImplementation(() => '')

Enzyme.configure({adapter: new Adapter()})

const props = {
formActionPath: 'action-path'
formActionPath: 'action-path',
setLoadingProjects: () => {}
}

it('should render itself', () => {
Expand All @@ -19,11 +26,6 @@ it('should render itself', () => {
expect(form.props().formActionPath).toEqual('action-path')
})

it('should not render `ErrorMessage` child by default', () => {
const wrapper = shallow(<ServiceDiscoveryForm {...props}/>)
expect(wrapper.find(ErrorMessage).exists()).toEqual(false)
})

it('should render `FormWrapper` child', () => {
const wrapper = mount(<ServiceDiscoveryForm {...props}/>)
expect(wrapper.find(FormWrapper).exists()).toEqual(true)
Expand All @@ -33,3 +35,40 @@ it('should render `ServiceDiscoveryListItems` child', () => {
const wrapper = mount(<ServiceDiscoveryForm {...props}/>)
expect(wrapper.find(ServiceDiscoveryListItems).exists()).toEqual(true)
})

describe('fetchProjects', () => {
const fetch = jest.spyOn(utils, 'fetchData')

afterEach(() => {
fetch.mockClear()
})

it('should render an error when fetching projects is unsuccessful', done => {
const msg = 'Something went wrong'
fetch.mockImplementation(url => { throw new Error(msg) })

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

expect(wrapper.find(ErrorMessage).exists()).toBe(true)
expect(wrapper.find(ErrorMessage).text()).toContain(msg)

setImmediate(done)
})

it('should fetch projects when first redendered', done => {
const projects = [{ name: 'project_00' }]
fetch.mockImplementation(url => projects)

const setState = jest.fn(val => {
expect(val).toEqual(projects)
done()
})
const useState = jest.spyOn(React, 'useState')
.mockImplementationOnce(init => [init, setState])

mount(<ServiceDiscoveryForm {...props}/>)

expect(useState).toHaveBeenCalled()
expect(fetch).toHaveBeenCalled()
})
})
4 changes: 4 additions & 0 deletions spec/javascripts/NewService/ServiceManualForm.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import Adapter from 'enzyme-adapter-react-16'
import {ServiceManualForm} from 'NewService'
import {FormWrapper, ServiceManualListItems} from 'NewService/components/FormElements'

import * as utils from 'utilities/utils'
jest.spyOn(utils, 'CSRFToken')
.mockImplementation(() => '')

Enzyme.configure({adapter: new Adapter()})

const props = {
Expand Down
65 changes: 52 additions & 13 deletions spec/javascripts/NewService/ServiceSourceForm.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,70 @@
// @flow

import React from 'react'
import Enzyme, {shallow} from 'enzyme'
import { act } from 'react-dom/test-utils'
import Enzyme, {mount, shallow} from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

import {ServiceSourceForm} from 'NewService'

Enzyme.configure({adapter: new Adapter()})

const serviceDiscoveryAuthenticateUrl = 'my-url'
const props = {
isServiceDiscoveryUsable: true,
serviceDiscoveryAuthenticateUrl: 'my-url',
handleFormsVisibility: jest.fn()
serviceDiscoveryAuthenticateUrl,
handleFormsVisibility: () => {},
loadingProjects: false
}

it('should render itself', () => {
const wrapper = shallow(<ServiceSourceForm {...props}/>)
expect(wrapper.find('#new_service_source').exists()).toEqual(true)
const wrapper = mount(<ServiceSourceForm {...props} />)
expect(wrapper.find(ServiceSourceForm).exists()).toEqual(true)
})

it('should render all possible sources for the new service', () => {
const wrapper = shallow(<ServiceSourceForm {...props} />)

const manual = wrapper.find('[htmlFor="source_manual"]')
expect(manual.exists()).toBe(true)
expect(manual.find('input').prop('type')).toBe('radio')
expect(manual.text()).toBe('Define manually')

const discovery = wrapper.find('[htmlFor="source_discover"]')
expect(discovery.exists()).toBe(true)
expect(discovery.find('input').prop('type')).toBe('radio')
expect(discovery.text()).toBe('Import from OpenShift')
})

it('should call `handleFormsVisibility`', () => {
const wrapper = shallow(<ServiceSourceForm {...props}/>)
it('should call `handleFormsVisibility` when changing the source', () => {
const wrapper = shallow(<ServiceSourceForm {...props} />)
const handleFormsVisibility = jest.fn()
wrapper.setProps({ handleFormsVisibility })

wrapper.find('#source_discover').simulate('change')
expect(props.handleFormsVisibility).toHaveBeenCalled()
expect(handleFormsVisibility).toHaveBeenCalled()
})

it('should render `Import from OpenShift` input disabled when Service Discovery is not usable', () => {
const propsNotUsable = {...props, isServiceDiscoveryUsable: false}
const wrapper = shallow(<ServiceSourceForm {...propsNotUsable}/>)
expect(wrapper.find('#source_discover + span').text()).toEqual('Import from OpenShift')
expect(wrapper.find('#source_discover').props().disabled).toEqual(true)
it('should render a spinner when loading projects', () => {
const wrapper = shallow(<ServiceSourceForm {...props} />)

wrapper.setProps({ loadingProjects: true })
expect(wrapper.find('.fa-spinner').exists()).toBe(true)

wrapper.setProps({ loadingProjects: false })
expect(wrapper.find('.fa-spinner').exists()).toBe(false)
})

it('should render a link to authenticate when Service Discovery is not usable', () => {
const wrapper = shallow(<ServiceSourceForm {...props} />)

act(() => {
wrapper.setProps({ isServiceDiscoveryUsable: false })
})
expect(wrapper.find(`a[href="${serviceDiscoveryAuthenticateUrl}"]`).exists()).toBe(true)

act(() => {
wrapper.setProps({ isServiceDiscoveryUsable: true })
})
expect(wrapper.find(`a[href="${serviceDiscoveryAuthenticateUrl}"]`).exists()).toBe(false)
})
37 changes: 25 additions & 12 deletions spec/javascripts/NewService/formElements/FormWrapper.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
// @flow

import React from 'react'
import Enzyme, {mount} from 'enzyme'
import Enzyme, {shallow} from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

import {FormWrapper} from 'NewService/components/FormElements'
import {HiddenServiceDiscoveryInput} from 'NewService/components/FormElements'
import {CSRFToken} from 'utilities/utils'

Enzyme.configure({adapter: new Adapter()})

const submitText = 'Add API'
const props = {
id: 'form-id',
formActionPath: 'my-path',
hasHiddenServiceDiscoveryInput: true,
submitText: 'Add API'
submitText
}

it('should render itself', () => {
const wrapper = mount(<FormWrapper {...props}/>)
const wrapper = shallow(<FormWrapper {...props}/>)
expect(wrapper.find('#form-id').exists()).toEqual(true)
})

it('should render an empty input', () => {
const wrapper = shallow(<FormWrapper {...props}/>)
const input = wrapper.find(`input[name="utf8"][type='hidden']`)
expect(input.exists()).toBe(true)
})

it('should render submit button with proper text', () => {
const wrapper = mount(<FormWrapper {...props}/>)
expect(wrapper.find(`input[type='submit']`).props().value).toEqual('Add API')
expect(wrapper.find(HiddenServiceDiscoveryInput).exists()).toEqual(true)
expect(wrapper.find(CSRFToken).exists()).toEqual(true)
const wrapper = shallow(<FormWrapper {...props}/>)
const button = wrapper.find(`input[type='submit']`)
expect(button.exists()).toBe(true)
expect(button.prop('value')).toEqual(submitText)
})

it('should render `HiddenServiceDiscoveryInput` child', () => {
const wrapper = mount(<FormWrapper {...props}/>)
it('should render a hidden input for service discovery when required', () => {
const wrapper = shallow(<FormWrapper {...props}/>)

wrapper.setProps({ hasHiddenServiceDiscoveryInput: false })
expect(wrapper.find(HiddenServiceDiscoveryInput).exists()).toEqual(false)

wrapper.setProps({ hasHiddenServiceDiscoveryInput: true })
expect(wrapper.find(HiddenServiceDiscoveryInput).exists()).toEqual(true)
})

it('should render `CSRFToken` child', () => {
const wrapper = mount(<FormWrapper {...props}/>)
expect(wrapper.find(CSRFToken).exists()).toEqual(true)
const wrapper = shallow(<FormWrapper {...props}/>)
expect(wrapper.find('CSRFToken').exists()).toEqual(true)
})
37 changes: 23 additions & 14 deletions spec/javascripts/NewService/formElements/Select.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
// @flow

import React from 'react'
import Enzyme, {mount} from 'enzyme'
import Enzyme, {mount, shallow} from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

import {Select} from 'NewService/components/FormElements'

Enzyme.configure({adapter: new Adapter()})

const options = ['project_01', 'project_02']
const props = {
name: 'my-select',
id: 'select-id',
onChange: jest.fn(),
options: [
{metadata: {name: 'one'}},
{metadata: {name: 'two'}}
]
options
}

it('should render itself properly', () => {
const wrapper = mount(<Select {...props}/>)
expect(wrapper.find('select').exists()).toEqual(true)
expect(wrapper.find('select').props().name).toEqual('my-select')
expect(wrapper.find('select').props().id).toEqual('select-id')
expect(wrapper.find('select').props().onChange).toEqual(props.onChange)
expect(wrapper.find(Select).exists()).toEqual(true)
})

it('should render with proper options', () => {
it('should render a select with options', () => {
const wrapper = mount(<Select {...props}/>)
expect(wrapper.find('option').length).toEqual(2)
expect(wrapper.find('option').first().props().value).toEqual('one')
expect(wrapper.find('option').last().props().value).toEqual('two')
expect(wrapper.find('select').exists()).toEqual(true)

for (let option of options) {
expect(wrapper.exists(`option[value="${option}"]`)).toEqual(true)
}
})

it('should call onChange when an option is selected', () => {
const option = 'foo'
const onChange = jest.fn()
const wrapper = shallow(<Select {...props}/>)

wrapper.setProps({ onChange })
wrapper.find('select').simulate('change', option)

expect(onChange).toHaveBeenCalledWith(option)
})

0 comments on commit 10d4ac9

Please sign in to comment.