Skip to content

Commit

Permalink
chore(tests): fail on console activity (#1542)
Browse files Browse the repository at this point in the history
* chore(karma): serve assets, show logs, improve output

* chore(tests): fail on all console activity

* test(Popup): fix hover test

* test(implementsClassNameProps): fix console activity

* test(implementsCreateMethod): fix console activity

* fix(mixed): fix lint issues, restore es-shim

* fix(GridRow): fix value in test

* fix(Header): fix value in test

* fix(package): add react-test-renderer

* test(TableRow-test): fix console messages

* test(Modal): fix console errors

* chore(karma): filter node_modules from stack

* fix(package): manually merge chromium changes

* test(Dropdown|Search): make getOptions always unique

* test(Select): fix isConformant options, now fails

* test(hasValidTypings): update test descriptions

* test(Breadcrumb): add missing section keys

* test(Dropdown): fix prop warnings

* test(factories): silence prop.key access warning

* fix(Select): fix options propTypes and typings

* chore(karma): do not print coverage summary

* test(FormSelect): define requireProps

* test(Advertisement): fix missing requiredProps

* test(Embed): fix default icon children conflict

* test(Search): prevent duplicate opts in getOptions

* chore(yarn): update yarn.lock

* fix(Dimmer|Form|Progress): fixes in tests

* test(Table): fix broken test

* test(Dropdown): fix broken test

* test(Search): fix broken tests

* fix(Form): fix typings in FormSelect

* style(Table): fix lint issue

* test(docs): restore unmount

* test(mixed): fix wrong image urls

* fix(Visibility|Sticky): do not run updates on unmounted components

* fix(Popup): do not run setState() when component is unmounted

* style(Breadcrumb|Form): restore style changes

* style(mixed): restore style changes

* fix(Dimmer): update DimmerInner test

* style(mixed): restore style-only changes
  • Loading branch information
levithomason authored and layershifter committed Jun 1, 2018
1 parent 500df9a commit 3a30105
Show file tree
Hide file tree
Showing 32 changed files with 504 additions and 247 deletions.
301 changes: 241 additions & 60 deletions index.d.ts

Large diffs are not rendered by default.

33 changes: 28 additions & 5 deletions karma.conf.babel.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import fs from 'fs'
import { executablePath } from 'puppeteer'

import config from './config'
import webpackConfig from './webpack.config.babel'

process.env.CHROME_BIN = executablePath()

const { paths } = config

const formatError = (msg) => {
// filter out empty lines and node_modules
if (!msg.trim() || /~/.test(msg)) return ''
if (!msg.trim() || /~/.test(msg) || /node_modules\//.test(msg)) return ''

// indent the error beneath the it() message
let newLine = ` ${msg}`
Expand All @@ -24,16 +28,20 @@ const formatError = (msg) => {

export default (karmaConfig) => {
karmaConfig.set({
basePath: process.cwd(),
basePath: __dirname,
browsers: ['puppeteer'],
browserConsoleLogOptions: {
level: 'log',
terminal: true,
},
client: {
mocha: {
reporter: 'html', // change Karma's debug.html to mocha web reporter
ui: 'bdd',
},
},
coverageReporter: {
reporters: [{ type: 'lcov', dir: 'coverage', subdir: '.' }, { type: 'text-summary' }],
reporters: [{ type: 'lcov', dir: 'coverage', subdir: '.' }],
includeAllSources: true,
},
customLaunchers: {
Expand All @@ -47,15 +55,30 @@ export default (karmaConfig) => {
],
},
},
files: ['./test/tests.bundle.js'],
files: [
{ pattern: 'docs/app/logo.png', watched: false, included: false, served: true },
{ pattern: 'docs/app/assets/**/*.jpg', watched: false, included: false, served: true },
{ pattern: 'docs/app/assets/**/*.png', watched: false, included: false, served: true },
'./test/tests.bundle.js',
],
formatError,
frameworks: ['mocha'],
// make karma serve all files that the web server does: /* => /docs/app/*
proxies: fs.readdirSync(paths.docsSrc()).reduce((acc, file) => {
const isDir = fs.statSync(paths.docsSrc(file)).isDirectory()
const trailingSlash = isDir ? '/' : ''

const original = `/${file}${trailingSlash}`
acc[original] = `/base/docs/app/${file}${trailingSlash}`
return acc
}, {}),
reporters: ['mocha', 'coverage'],
reportSlowerThan: 100,
singleRun: true,
preprocessors: {
// do not include 'coverage' preprocessor for karma-coverage
// code is already instrumented by babel-plugin-__coverage__
'./test/tests.bundle.js': ['webpack'],
'test/tests.bundle.js': ['webpack'],
},
webpack: {
entry: './test/tests.bundle.js',
Expand Down
5 changes: 4 additions & 1 deletion src/addons/Select/Select.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import * as React from 'react';
import { DropdownProps } from '../../modules/Dropdown';
import DropdownDivider from '../../modules/Dropdown/DropdownDivider';
import DropdownHeader from '../../modules/Dropdown/DropdownHeader';
import DropdownItem from '../../modules/Dropdown/DropdownItem';
import DropdownItem, { DropdownItemProps } from '../../modules/Dropdown/DropdownItem';
import DropdownMenu from '../../modules/Dropdown/DropdownMenu';

export interface SelectProps extends DropdownProps {
[key: string]: any;

/** Array of Dropdown.Item props e.g. `{ text: '', value: '' }` */
options: Array<DropdownItemProps>;
}

interface SelectComponent extends React.StatelessComponent<SelectProps> {
Expand Down
6 changes: 6 additions & 0 deletions src/addons/Select/Select.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import PropTypes from 'prop-types'
import React from 'react'

import Dropdown from '../../modules/Dropdown'
Expand All @@ -11,6 +12,11 @@ function Select(props) {
return <Dropdown {...props} selection />
}

Select.propTypes = {
/** Array of Dropdown.Item props e.g. `{ text: '', value: '' }` */
options: PropTypes.arrayOf(PropTypes.shape(Dropdown.Item.propTypes)).isRequired,
}

Select.Divider = Dropdown.Divider
Select.Header = Dropdown.Header
Select.Item = Dropdown.Item
Expand Down
5 changes: 5 additions & 0 deletions src/behaviors/Visibility/Visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ export default class Visibility extends Component {
}

componentDidMount() {
this.mounted = true

if (!isBrowser()) return
const { context, fireOnMount, updateOn } = this.props

Expand All @@ -216,6 +218,7 @@ export default class Visibility extends Component {
const { context } = this.props

this.unattachHandlers(context)
this.mounted = false
}

attachHandlers(context, updateOn) {
Expand Down Expand Up @@ -300,6 +303,8 @@ export default class Visibility extends Component {
}

update = () => {
if (!this.mounted) return

this.ticking = false

this.oldCalculations = this.calculations
Expand Down
4 changes: 4 additions & 0 deletions src/collections/Form/FormSelect.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';

import { SelectProps } from '../../addons/Select';
import { DropdownItemProps } from '../../modules/Dropdown/DropdownItem';
import { FormFieldProps } from './FormField';

export interface FormSelectProps extends FormFieldProps, SelectProps {
Expand All @@ -11,6 +12,9 @@ export interface FormSelectProps extends FormFieldProps, SelectProps {

/** A FormField control prop. */
control?: any;

/** Array of Dropdown.Item props e.g. `{ text: '', value: '' }` */
options: Array<DropdownItemProps>;
}

declare const FormSelect: React.StatelessComponent<FormSelectProps>;
Expand Down
9 changes: 7 additions & 2 deletions src/collections/Form/FormSelect.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import PropTypes from 'prop-types'
import React from 'react'

import { customPropTypes, getElementType, getUnhandledProps } from '../../lib'
import Select from '../../addons/Select'
import Dropdown from '../../modules/Dropdown'
import FormField from './FormField'

/**
Expand All @@ -10,11 +12,11 @@ import FormField from './FormField'
* @see Select
*/
function FormSelect(props) {
const { control } = props
const { control, options } = props
const rest = getUnhandledProps(FormSelect, props)
const ElementType = getElementType(FormSelect, props)

return <ElementType {...rest} control={control} />
return <ElementType {...rest} control={control} options={options} />
}

FormSelect.propTypes = {
Expand All @@ -23,6 +25,9 @@ FormSelect.propTypes = {

/** A FormField control prop. */
control: FormField.propTypes.control,

/** Array of Dropdown.Item props e.g. `{ text: '', value: '' }` */
options: PropTypes.arrayOf(PropTypes.shape(Dropdown.Item.propTypes)).isRequired,
}

FormSelect.defaultProps = {
Expand Down
8 changes: 3 additions & 5 deletions src/modules/Embed/Embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ export default class Embed extends Component {

static autoControlledProps = ['active']

static defaultProps = {
icon: 'video play',
}

getSrc() {
const {
autoplay = true,
Expand Down Expand Up @@ -145,9 +141,11 @@ export default class Embed extends Component {
const rest = getUnhandledProps(Embed, this.props)
const ElementType = getElementType(Embed, this.props)

const iconShorthand = icon !== undefined ? icon : 'video play'

return (
<ElementType {...rest} className={classes} onClick={this.handleClick}>
{Icon.create(icon, { autoGenerateKey: false })}
{Icon.create(iconShorthand, { autoGenerateKey: false })}
{placeholder && <img className='placeholder' src={placeholder} />}
{this.renderEmbed()}
</ElementType>
Expand Down
12 changes: 11 additions & 1 deletion src/modules/Popup/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ export default class Popup extends Component {

state = {}

componentDidMount() {
this.mounted = true
}

componentWillUnmount() {
this.mounted = false
}

computePopupStyle(positions) {
const style = { position: 'absolute' }

Expand Down Expand Up @@ -295,7 +303,9 @@ export default class Popup extends Component {
this.setState({ closed: true })

eventStack.unsub('scroll', this.hideOnScroll, { target: window })
setTimeout(() => this.setState({ closed: false }), 50)
setTimeout(() => {
if (this.mounted) this.setState({ closed: false })
}, 50)

this.handleClose(e)
}
Expand Down
3 changes: 2 additions & 1 deletion src/modules/Progress/Progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class Progress extends Component {
getPercent = () => {
const { precision, progress, total, value } = this.props
const percent = _.clamp(this.calculatePercent(), 0, 100)

if (!_.isUndefined(total) && !_.isUndefined(value) && progress === 'value') {
return (value / total) * 100
}
Expand Down Expand Up @@ -175,7 +176,7 @@ class Progress extends Component {
)
const rest = getUnhandledProps(Progress, this.props)
const ElementType = getElementType(Progress, this.props)
const percent = this.getPercent()
const percent = this.getPercent() || 0

return (
<ElementType {...rest} className={classes} data-percent={Math.floor(percent)}>
Expand Down
46 changes: 40 additions & 6 deletions test/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import Adapter from 'enzyme-adapter-react-16'
import dirtyChai from 'dirty-chai'
import sinonChai from 'sinon-chai'

//
// ----------------------------------------
// Enzyme
//
// ----------------------------------------
global.enzyme = enzyme
global.shallow = enzyme.shallow
global.render = enzyme.render
Expand All @@ -22,18 +22,52 @@ enzyme.configure({
disableLifecycleMethods: true,
})

//
// ----------------------------------------
// Mocha
//
// ----------------------------------------
mocha.setup({
ui: 'bdd',
})

//
// ----------------------------------------
// Chai
//
// ----------------------------------------
global.expect = chai.expect
chai.should()
chai.use(chaiEnzyme())
chai.use(dirtyChai)
chai.use(sinonChai)

// ----------------------------------------
// Console
// ----------------------------------------
// Fail on all activity.
// It is important we overload console here, before consoleUtil.js is loaded and caches it.
let log
let info
let warn
let error

const throwOnConsole = method => (...args) => {
throw new Error(`console.${method} should never be called but was called with:\n${args.join(' ')}`)
}

/* eslint-disable no-console */
beforeEach(() => {
log = console.log
info = console.info
warn = console.warn
error = console.error

console.log = throwOnConsole('log')
console.info = throwOnConsole('info')
console.warn = throwOnConsole('warn')
console.error = throwOnConsole('error')
})
afterEach(() => {
console.log = log
console.info = info
console.warn = warn
console.error = error
})
/* eslint-enable no-console */
2 changes: 1 addition & 1 deletion test/specs/addons/Select/Select-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const requiredProps = {
}

describe('Select', () => {
common.isConformant(Select, requiredProps)
common.isConformant(Select, { requiredProps })
common.hasSubcomponents(Select, [Dropdown.Divider, Dropdown.Header, Dropdown.Item, Dropdown.Menu])

it('renders a selection Dropdown', () => {
Expand Down
8 changes: 5 additions & 3 deletions test/specs/collections/Form/Form-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import FormSelect from 'src/collections/Form/FormSelect'
import FormTextArea from 'src/collections/Form/FormTextArea'
import { SUI } from 'src/lib'
import * as common from 'test/specs/commonTests'
import { sandbox } from 'test/utils'
import { consoleUtil, sandbox } from 'test/utils'

describe('Form', () => {
common.isConformant(Form)
Expand Down Expand Up @@ -62,12 +62,14 @@ describe('Form', () => {

describe('onSubmit', () => {
it('prevents default on the event when there is no action', () => {
// Heads up!
// In this test we pass some invalid values to verify correct work.
consoleUtil.disableOnce()

const event = { preventDefault: sandbox.spy() }

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

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

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

event.preventDefault.should.have.been.calledThrice()
Expand Down
10 changes: 7 additions & 3 deletions test/specs/collections/Form/FormSelect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import Select from 'src/addons/Select/Select'
import FormSelect from 'src/collections/Form/FormSelect'
import * as common from 'test/specs/commonTests'

const requiredProps = {
options: [],
}

describe('FormSelect', () => {
common.isConformant(FormSelect)
common.labelImplementsHtmlForProp(FormSelect)
common.isConformant(FormSelect, { requiredProps })
common.labelImplementsHtmlForProp(FormSelect, { requiredProps })

it('renders a FormField with a Select control', () => {
shallow(<FormSelect />)
shallow(<FormSelect {...requiredProps} />)
.find('FormField')
.should.have.prop('control', Select)
})
Expand Down
Loading

0 comments on commit 3a30105

Please sign in to comment.