Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example node tests #68

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ env:
matrix:
- TASK=lint
- TASK=unittest GUI=1
- TASK=unittest:server
global:
secure: m1hVHTy/jgPlj2Z79Gt++NFKKUIBMYtOVtU9WbQSTpAesspPvNZbfirUSdo/50rfLD9UWO9RGITWbBx9JJ6QakbxN0reTC40O/dbJOWmhr97vZwLNENmfqfgAttb3U1WYC0BcdYo3XsKz/8dsQVhXHDLgq+WUeyj+y7Ku+R71pZgJxDuTCzyUCEXGotVMwMtWx6JjlZtyjyJX+Ec8Em2aC81z9Udcm60cFFr7RXMpSMkOeKBj7ujCUxXsIoxTigXJaWQOcsUcBNG9Gh2QO3ATc1YiRdXhxqi3O8yVAJUpm6Lt4gBk9VAGN01cIJzOZzYq5GqwmgR8ZrRBtz/8rQL/KDQLxpuo1K9iEZ1d6OXDgcdY6CpgguFKsRhLnB758LQ51ZA4K5pTSxPPN7yY39c2tRz7GqR97TMafg5lRqBEVp9qH4dlFowh1lOOEM9swO5cljc/92HsOqd2XMRP4CmatAbb25plLYnVL4tBdQrFQzluhkYHkYcpPBSwJRAITRTlvZ28jHf7ert9u+f7jUthGxbI6RpLmAwuynWcHaWjJpBRenfAOHMUWzfzMix9Zn4gS70AC1RaPuC1DMgH/jcTaR7Q3hscTrdmarHD0kSOiIvJcZp767EtNeifiW1DOHW2vWOrrgKeXm0XwQ72jlIbKkJLykjWdpjFJmMcqec9/U=
cache:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dev:disco": "APP_NAME=disco npm run dev",
"test": "npm run version-check && npm run unittest && npm run lint",
"unittest:dev": "karma start",
"unittest:server": "NODE_PATH=src:$NODE_PATH mocha --compilers js:babel-register tests/**/Test*.js",
"unittest": "karma start --single-run",
"lint": "eslint .",
"eslint": "npm run lint",
Expand Down
7 changes: 6 additions & 1 deletion src/search/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import SearchForm from './SearchForm';
import SearchResults from './SearchResults';

export default class App extends React.Component {
state = {query: '', results: []}

state = {
query: null,
results: [],
}

handleSearch = (query) => {
const results = [{title: 'Foo'}, {title: 'Bar'}, {title: 'Baz'}];
Expand All @@ -15,6 +19,7 @@ export default class App extends React.Component {
const { query, results } = this.state;
return (
<div className="search-app">
<h1>Add-on Search</h1>
<SearchForm onSearch={this.handleSearch} />
<SearchResults results={results} query={query} />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/search/components/SearchForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class SearchForm extends React.Component {
render() {
return (
<form ref="form" className="search-form" onSubmit={this.handleSubmit}>
<input ref="query" type="text" name="q" placeholder="Search" />
<input ref="query" type="search" name="q" placeholder="Search" />
<button ref="submit" type="submit">Search</button>
</form>
);
Expand Down
32 changes: 29 additions & 3 deletions src/search/components/SearchResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,42 @@ export default class SearchResults extends React.Component {
}

static defaultProps = {
query: '',
query: null,
results: [],
}

render() {
const { query, results } = this.props;
const searchResultsClass = 'search-results';

let searchResults;

if (query && results.length > 0) {
searchResults = (
<div className={searchResultsClass}>
<p>Your search for "{query}" returned {results.length} results.</p>
<ul>
{results.map((result) => <li key={result.title}>{result.title}</li>)}
</ul>
</div>
);
} else if (query && results.length === 0) {
searchResults = (
<div className={searchResultsClass}>
<p>No results were found for "{query}".</p>
</div>
);
} else if (query !== null) {
searchResults = (
<div className={searchResultsClass}>
<p>Please supply a valid search</p>
</div>
);
}

return (
<div className="search-results">
<h3>Your search for "{query}" returned {results.length} results.</h3>
{results.map((result) => <div key={result.title}>{result.title}</div>)}
{searchResults}
</div>
);
}
Expand Down
11 changes: 0 additions & 11 deletions src/search/components/hello-world.js

This file was deleted.

53 changes: 39 additions & 14 deletions tests/search/components/TestSearchForm.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,55 @@
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import { createRenderer, renderIntoDocument, Simulate } from 'react-addons-test-utils';

import SearchForm from 'search/components/SearchForm';

const render = ReactTestUtils.renderIntoDocument;
const findByTag = ReactTestUtils.findRenderedDOMComponentWithTag;
if (typeof window === 'undefined' && typeof global !== 'undefined') {
global.sinon = require('sinon');
global.assert = require('chai').assert;
}

function browser(message, test) {
if (typeof document === 'undefined') {
xit(message, test);
} else {
it(message, test);
}
}

function render(component) {
const renderer = createRenderer();
renderer.render(component);
return renderer.getRenderOutput();
}

describe('<SearchForm />', () => {
let onSearch;
let root;

beforeEach(() => {
onSearch = sinon.spy();
root = render(<SearchForm onSearch={onSearch} />);
});

it('is a form', () => {
assert.equal(root.type, 'form');
assert.equal(root.props.className, 'search-form');
});

it('renders a form', () => {
const root = render(<SearchForm onSearch={sinon.spy()} />);
const form = findByTag(root, 'form');
assert.ok(form.classList.contains('search-form'));
assert.include(root.props.className, 'search-form');
});

it('renders a search input', () => {
const root = render(<SearchForm onSearch={sinon.spy()} />);
const input = findByTag(root, 'input');
assert.equal(input.placeholder, 'Search');
assert.equal(input.type, 'text');
const query = root.props.children.filter(({ ref }) => ref === 'query')[0];
assert.equal(query.props.placeholder, 'Search');
assert.equal(query.props.type, 'search');
});

it('calls onSearch with a search query', () => {
const onSearch = sinon.spy();
const root = render(<SearchForm onSearch={onSearch} />);
browser('calls onSearch with a search query', () => {
root = renderIntoDocument(<SearchForm onSearch={onSearch} />);
root.refs.query.value = 'adblock';
ReactTestUtils.Simulate.submit(root.refs.form);
Simulate.submit(root.refs.form);
assert.ok(onSearch.calledWith('adblock'));
});
});
66 changes: 66 additions & 0 deletions tests/search/components/TestSearchResults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';

import SearchResults from 'search/components/SearchResults';

const render = ReactTestUtils.renderIntoDocument;
const findByTag = ReactTestUtils.findRenderedDOMComponentWithTag;
const findByClass = ReactTestUtils.findRenderedDOMComponentWithClass;
const isDOMComponent = ReactTestUtils.isDOMComponent;

if (typeof window === 'undefined' && typeof global !== 'undefined') {
global.sinon = require('sinon');
global.assert = require('chai').assert;
}

function browser(message, test) {
if (typeof document === 'undefined') {
xit(message, test);
} else {
it(message, test);
}
}


describe('<SearchResults />', () => {
function renderResults(props) {
return render(<SearchResults {...props} />);
}

browser('renders empty search results container', () => {
const root = renderResults();
const searchResults = findByClass(root, 'search-results');
assert.ok(isDOMComponent(searchResults));
assert.equal(searchResults.childNodes.length, 0);
});

browser('renders error when query is an empty string', () => {
const root = renderResults({query: ''});
const searchResultsMsg = findByTag(root, 'p');
assert.include(searchResultsMsg.firstChild.nodeValue, 'supply a valid search');
});

browser('renders error when no results and valid query', () => {
const root = renderResults({query: 'test'});
const searchResultsMsg = findByTag(root, 'p');
// Using textContent here since we want to see the text inside the p.
// Since it has dynamic content is wrapped in a span implicitly.
assert.include(searchResultsMsg.textContent, 'No results were found');
});

browser('renders search results when supplied', () => {
const root = renderResults({
query: 'test',
results: [
{title: 'result 1'},
{title: 'result 2'},
],
});
const searchResultsMsg = findByTag(root, 'p');
assert.include(searchResultsMsg.textContent, 'Your search for "test" returned 2');

const searchResultsList = findByTag(root, 'ul');
assert.include(searchResultsList.textContent, 'result 1');
assert.include(searchResultsList.textContent, 'result 2');
});
});