'], function (expect, subject, expected) {
59 |
60 | var actual = subject.getRenderOutput();
61 | return expect(actual, 'to contain [exactly] [with all children]', expected);
62 | });
63 |
64 | };
65 |
--------------------------------------------------------------------------------
/src/lib/equality.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var ArrayChanges = require('array-changes');
3 | var Element = require('./element');
4 |
5 |
6 | var internals = {};
7 |
8 | exports.propsMatch = internals.propsMatch = function propsMatch(actual, expected, equal, options) {
9 | if (options && options.exactly) {
10 | return equal(actual, expected);
11 | }
12 | var matching = true;
13 | Object.keys(expected).forEach(function (key) {
14 | if (!equal(actual[key], expected[key])) {
15 | matching = false;
16 | }
17 | });
18 | return matching;
19 | };
20 |
21 | exports.elementsMatch = internals.elementsMatch = function elementsMatch(actual, expected, equal, options) {
22 |
23 | if (typeof actual === 'string' && typeof expected === 'string') {
24 | return actual === expected;
25 | }
26 |
27 | if ((typeof actual === 'string' || typeof actual === 'number') &&
28 | (typeof expected === 'string' || typeof expected === 'number')) {
29 | return '' + actual === '' + expected;
30 | }
31 |
32 | if (typeof actual !== typeof expected) { // Fundamentally different e.g. string vs ReactElement
33 | return false;
34 | }
35 |
36 | if (Element.getName(actual) !== Element.getName(expected)) {
37 | return false;
38 | }
39 |
40 | if (!internals.propsMatch(Element.getProps(actual), Element.getProps(expected), equal, options)) {
41 | return false;
42 | }
43 |
44 | // For 'exactly', we can just check the count of the actual children matches,
45 | // string children will not be concatenated in this mode, and serves to also check
46 | // the case that the expected does not have children, but the actual does (ignored when exactly=false)
47 |
48 | var shouldNormalize = !options.exactly;
49 | var actualChildren = Element.getChildrenArray(actual.props.children, {
50 | normalize: shouldNormalize
51 | });
52 | var expectedChildren = Element.getChildrenArray(expected.props.children, {
53 | normalize: shouldNormalize
54 | });
55 | if ((options.exactly || options.withAllChildren) && actualChildren.length !== expectedChildren.length) {
56 | return false;
57 | }
58 |
59 | if (React.Children.count(expected.props.children)) {
60 | if (React.Children.count(actual.props.children) === 0) {
61 | return false;
62 | }
63 |
64 |
65 | var arrayDiffs = ArrayChanges(
66 | actualChildren,
67 | expectedChildren,
68 | function (a, b) {
69 | return elementsMatch(a, b, equal, options);
70 | },
71 | function () {
72 | return false;
73 | });
74 |
75 | var arrayMatches = true;
76 | arrayDiffs.forEach(function (diffItem) {
77 | switch (diffItem.type) {
78 | case 'equal':
79 | return;
80 | case 'remove':
81 | if (options.exactly || options.withAllChildren) {
82 | arrayMatches = false;
83 | }
84 | break;
85 | default:
86 | arrayMatches = false;
87 | break;
88 |
89 | }
90 | });
91 |
92 | if (!arrayMatches) {
93 | return false;
94 | }
95 | }
96 | return true;
97 |
98 | };
99 |
100 |
101 | exports.assertElementsMatch = function assertElementsMatch(actual, expected, expect, options) {
102 |
103 | var result = internals.elementsMatch(actual, expected, expect.equal.bind(expect), options);
104 | if (!result) {
105 | return expect.fail('elements are not equal');
106 | }
107 | };
108 |
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/bruderstein/unexpected-react-shallow)
2 | [](https://coveralls.io/github/bruderstein/unexpected-react-shallow?branch=master)
3 | # unexpected-react-shallow
4 |
5 | ## Deprecated - use [unexpected-react](https://npmjs.org/package/unexpected-react) instead
6 |
7 | ----
8 |
9 |
10 | A port of the excellent [unexpected-dom](https://github.com/munter/unexpected-dom) to support
11 | [React](http://reactjs.org) [shallow renderer](https://facebook.github.io/react/docs/test-utils.html#shallow-rendering).
12 |
13 | Diffing of props and content, including detailed diffing of object props.
14 |
15 | ```js
16 |
17 | var renderer = TestUtils.createRenderer();
18 |
19 | renderer.render();
20 |
21 | expect(renderer, 'to have rendered',
22 |
23 | Some simple content
24 |
);
25 |
26 | ```
27 |
28 | And you receive a beautiful error message
29 |
30 | 
31 |
32 | Object props are also diffed, when they don't match
33 |
34 | 
35 |
36 |
37 | # Status
38 |
39 | Although this project itself is well tested, it is still in early development, and there may well be issues.
40 |
41 | Use with caution. If you find any case that does not work as expected, please report it via the issues.
42 |
43 |
44 | # Setup
45 |
46 | ```js
47 |
48 | var unexpected = require('unexpected');
49 | var unexpectedReactShallow = require('unexpected-react-shallow');
50 |
51 | var expect = unexpected.clone()
52 | .installPlugin(unexpectedReactShallow);
53 |
54 | ```
55 |
56 | # Assertions
57 |
58 | ## `to have rendered`
59 |
60 | ```js
61 | expect(shallowRenderer, 'to have rendered', reactElement);
62 | ```
63 |
64 | `reactElement` in this case is a ReactElement, normally created by using JSX
65 |
66 | For example
67 |
68 | ```js
69 | expect(shallowRenderer, 'to have rendered', );
70 | ```
71 |
72 | The same thing works for `shallowRenderer.getRenderOutput()`.
73 |
74 | Extra props that are rendered are ignored (see `to have exactly rendered below`), as
75 | are extra children.
76 |
77 | Using the following simple component:
78 | ```js
79 |
80 | var Component = React.createClass({
81 | render: function () {
82 | return (
83 |
84 | one
85 | two
86 | three
87 |
88 | );
89 | }
90 | });
91 | ```
92 |
93 | You can make the following assertions:
94 | ## `to have [exactly] rendered [with all children]`
95 |
96 | ```js
97 | // Extra props and children from the render are ignored
98 | expect(renderer, 'to have rendered', );
99 |
100 | // The span "two" is missing here, but it is ignored.
101 | expect(renderer, 'to have rendered',
102 |
103 | one
104 | three
105 |
106 | );
107 |
108 | // The following assertion will fail, as 'four' does not exist
109 | expect(renderer, 'to have rendered',
110 |
111 | one
112 | four
113 |
114 | );
115 | ```
116 |
117 | If you want to check for an exact render, use `'to have exactly rendered'`.
118 |
119 | Alternatively, if you don't care about extra props, but want to check that there are no extra child nodes, use `'to have rendered with all children'`
120 | Note that `exactly` implies `with all children`, so you using both options is not necessary.
121 |
122 |
123 | ```js
124 |
125 | // The span "two" is missing here, as is `className="parent"`
126 | // The missing span will cause an assertion error, but the extra prop will be ignored
127 | // due to `to have rendered with all children` being used
128 |
129 | expect(renderer, 'to have rendered with all children',
130 |
131 | one
132 | three
133 |
134 | );
135 | ```
136 |
137 | ```js
138 |
139 | // The span "two" is missing here, as is `className="parent"`
140 | // This will cause an assertion error,
141 | // due to `to have exactly rendered` being used
142 |
143 | expect(renderer, 'to have exactly rendered',
144 |
145 | one
146 | three
147 |
148 | );
149 | ```
150 |
151 | ## `to contain`
152 |
153 | It's possible to check for a part of the subtree, without
154 | testing the entire returned tree. This allows you to test specific elements, without
155 | writing brittle tests that break when the structure changes.
156 |
157 | ```js
158 | // This will pass, as `two` can be found in the renderers output
159 | expect(renderer, 'to contain', two);
160 | ```
161 |
162 | Notice that the extra `className="middle"` in the `two` is ignored,
163 | in a similar way to the `to have rendered` assertion.
164 |
165 | You can override this behaviour by using `'to contain exactly'`, and `'to contain with all children'`
166 |
167 |
168 | ```js
169 | // This will fail, as `two` cannot be found in the renderers output, due to
170 | // the missing `className="middle"` prop
171 | expect(renderer, 'to contain exactly', two);
172 |
173 | ```
174 |
175 | The same thing applies to children for `'to contain'` as for `'to have rendered'`.
176 |
177 | # Strings
178 |
179 | String content is split up by React when you have embedded variables.
180 |
181 | For example:
182 |
183 | ```js
184 | {
185 | render: function() {
186 | return (
187 |
188 | Click on {this.props.clickCount} times
189 |
190 | );
191 | }
192 | }
193 | ```
194 |
195 | This actually produces 3 "child" elements of the div, `Click on `, the `clickCount` and the ` times`
196 | To make this simpler, `unexpected-react-shallow` concatenates these values so you can simply test the
197 | previous example as follows:
198 |
199 | ```js
200 | expect(renderer, 'to have rendered',
201 |
202 | Clicked on 3 times
203 |
);
204 | ```
205 |
206 | If you use the `exactly` variants of the assertions, you will need to split up your assertion in the same way
207 |
208 | e.g.
209 | ```js
210 | expect(renderer, 'to have exactly rendered',
211 |
212 | Clicked on {3} times
213 |
);
214 | ```
215 |
216 | # Contributing
217 |
218 | We welcome pull requests, bug reports, and extra test cases. If you find something that doesn't work
219 | as you believe it should, raise an issue!
220 |
221 | # Thanks
222 |
223 | Special thanks to all of the [unexpected](http://github.com/unexpectedjs) team. The quality failure
224 | messages and diffs have made a huge difference to the way I test, and how quickly issues are resolved.
225 |
226 | A huge thanks to @Munter, who wrote [unexpected-dom](http://github.com/munter/unexpected-dom), which enables
227 | testing DOM elements easily - it's perfect for more involved tests if you're using React and something
228 | like [jsdom](https://github.com/tmpvar/jsdom). A lot (most!) of the code for `unexpected-react-shallow` was
229 | taken from `unexpected-dom`.
230 |
231 |
232 | # License
233 |
234 | MIT
235 |
236 |
--------------------------------------------------------------------------------
/src/lib/diff.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var ArrayChanges = require('array-changes');
3 | var Element = require('./element');
4 | var Equality = require('./equality');
5 | var Write = require('./write');
6 |
7 | var internals = {};
8 |
9 | internals.isNativeType = function (element) {
10 | var type = typeof element;
11 | return type === 'string' || type === 'number' || type === 'undefined';
12 | };
13 |
14 | internals.diffChildren = function diffChildren(actual, expected, output, diff, inspect, equal, options) {
15 | if (typeof actual === 'string' && typeof expected === 'string') {
16 | var stringDiff = diff(actual.trim(), expected.trim());
17 | output.i().block(stringDiff.diff);
18 | return;
19 | }
20 |
21 | var actualChildren = Element.getChildrenArray(actual, {
22 | normalize: !options || !options.exactly
23 | });
24 |
25 | var expectedChildren = Element.getChildrenArray(expected, {
26 | normalize: !options || !options.exactly
27 | });
28 |
29 | var changes = ArrayChanges(actualChildren, expectedChildren,
30 | function (a, b) {
31 | return Equality.elementsMatch(a, b, equal, options);
32 | },
33 |
34 | function (a, b) {
35 | // Figure out whether a and b are the same element so they can be diffed inline.
36 | var aIsNativeType = internals.isNativeType(a);
37 | var bIsNativeType = internals.isNativeType(b);
38 | if (aIsNativeType && bIsNativeType) {
39 | return true;
40 | }
41 |
42 | if (aIsNativeType !== bIsNativeType) {
43 | return false;
44 | }
45 |
46 |
47 | return (
48 | Element.getName(a) === Element.getName(b)
49 | );
50 | } );
51 |
52 | changes.forEach(function (diffItem, index) {
53 | output.i().block(function () {
54 | var type = diffItem.type;
55 |
56 | if (type === 'insert') {
57 | this.annotationBlock(function () {
58 | this.error('missing ');
59 | if (typeof diffItem.value === 'string') {
60 | this.block(function () {
61 | this.text(diffItem.value);
62 | });
63 | } else {
64 | this.block(inspect(diffItem.value));
65 | }
66 | });
67 | } else if (type === 'remove') {
68 | if (typeof diffItem.value === 'string') {
69 | this.block(function () {
70 | this.text(diffItem.value).sp().error('// should be removed');
71 | });
72 | } else {
73 | var actualInspectBlock = inspect(diffItem.value);
74 | this.block(actualInspectBlock).sp().annotationBlock(function () {
75 | this.error('should be removed');
76 | this.nl(actualInspectBlock.size().height - 1);
77 | });
78 | }
79 | } else if (type === 'equal') {
80 | if (typeof diffItem.value === 'string') {
81 | this.block(function () {
82 | this.text(diffItem.value);
83 | });
84 | } else {
85 | this.block(inspect(diffItem.value));
86 | }
87 | } else {
88 | var valueDiff = internals.diffElements(diffItem.value, diffItem.expected, output.clone(), diff, inspect, equal, options);
89 |
90 | if (valueDiff) {
91 | this.block(valueDiff.diff);
92 | }
93 | }
94 | }).nl(index < changes.length - 1 ? 1 : 0);
95 | });
96 | };
97 |
98 | exports.diffElements = internals.diffElements =
99 | function diffElements(actual, expected, output, diff, inspect, equal, options) {
100 | var result = {
101 | diff: output,
102 | inline: true
103 | };
104 | var actualIsNative = internals.isNativeType(actual);
105 | var expectedIsNative = internals.isNativeType(expected);
106 | if (actualIsNative && expectedIsNative) {
107 | return diff('' + actual, '' + expected);
108 | }
109 |
110 | var stringVsComponentMismatch = actualIsNative !== expectedIsNative;
111 | var emptyElements = !stringVsComponentMismatch && (!actual.props || React.Children.count(actual.props.children) === 0) &&
112 | (!expected.props || React.Children.count(expected.props.children) === 0);
113 |
114 | var propsMatching = !stringVsComponentMismatch && Equality.propsMatch(Element.getProps(actual), Element.getProps(expected), equal, options);
115 |
116 | var conflictingElement = stringVsComponentMismatch ||
117 | Element.getName(actual) !== Element.getName(expected) ||
118 | !propsMatching;
119 |
120 | if (stringVsComponentMismatch) {
121 |
122 | if (actualIsNative) {
123 | output.append('' + actual)
124 | .sp()
125 | .annotationBlock(function () {
126 | this.error('should be').sp().block(inspect(expected));
127 | });
128 | } else if (expectedIsNative) {
129 |
130 | var actualOutput = inspect(actual);
131 | output.block(actualOutput)
132 | .annotationBlock(function () {
133 | this.nl(actualOutput.size().height - 1);
134 | this.error('should be').sp().append(inspect(expected));
135 | });
136 | }
137 |
138 | } else if (conflictingElement) {
139 | var canContinueLine = true;
140 | output
141 | .prismPunctuation('<')
142 | .prismTag(Element.getName(actual));
143 | if (Element.getName(actual) !== Element.getName(expected)) {
144 | output.sp().annotationBlock(function () {
145 | this.error('should be').sp().prismTag(Element.getName(expected));
146 | }).nl();
147 | canContinueLine = false;
148 | }
149 | var actualProps = Element.getProps(actual);
150 | var expectedProps = Element.getProps(expected);
151 | Object.keys(actualProps).forEach(function (propName) {
152 | output.sp(canContinueLine ? 1 : 2 + Element.getName(actual).length);
153 | if (propName in expectedProps) {
154 | if (actualProps[propName] === expectedProps[propName]) {
155 | Write.writeProp(output, propName, actualProps[propName]);
156 | canContinueLine = true;
157 | } else {
158 | Write.writeProp(output, propName, actualProps[propName], inspect);
159 | output.sp().annotationBlock(function () {
160 | var diffResults = diff(actualProps[propName], expectedProps[propName]);
161 | if (diffResults) {
162 | this.append(diffResults.diff);
163 | } else {
164 | this.error('should equal').sp().append(inspect(expectedProps[propName]));
165 | }
166 |
167 | }).nl();
168 | canContinueLine = false;
169 | }
170 | delete expectedProps[propName];
171 | } else if (options.exactly) {
172 | Write.writeProp(output, propName, actualProps[propName]);
173 | output.sp().annotationBlock(function () {
174 | this.error('should be removed');
175 | }).nl();
176 | canContinueLine = false;
177 | }
178 | });
179 | Object.keys(expectedProps).forEach(function (propName) {
180 | output.sp(canContinueLine ? 1 : 2 + Element.getName(actual).length);
181 | output.annotationBlock(function () {
182 | this.error('missing').sp();
183 | Write.writeProp(this, propName, expectedProps[propName]);
184 | }).nl();
185 | canContinueLine = false;
186 | });
187 | output.prismPunctuation('>');
188 | } else {
189 | output.prismPunctuation('<')
190 | .prismTag(Element.getName(actual));
191 | Write.writeProps(output, actual.props);
192 | output.prismPunctuation('>');
193 | }
194 |
195 | if (!stringVsComponentMismatch && !emptyElements) {
196 | output.nl().indentLines();
197 | internals.diffChildren(actual.props.children, expected.props.children, output, diff, inspect, equal, options);
198 | output.nl().outdentLines();
199 | }
200 |
201 | if (!stringVsComponentMismatch) {
202 | output.code('' + Element.getName(actual) + '>', 'html');
203 | }
204 | return result;
205 | };
206 |
--------------------------------------------------------------------------------
/tests/unexpected-react-shallow.spec.js:
--------------------------------------------------------------------------------
1 | var Unexpected = require('unexpected');
2 | var UnexpectedReactShallow = require('../src/unexpected-react-shallow');
3 | var React = require('react/addons');
4 |
5 | var expect = Unexpected.clone();
6 |
7 | var ES5Component = React.createClass({
8 | displayName: 'ES5Component',
9 | render() { return null;}
10 | });
11 |
12 | function createNoNameComponent() {
13 | return React.createClass({
14 | displayName: '',
15 | render() { return null;}
16 | });
17 | }
18 |
19 | var NoNameComponent = createNoNameComponent();
20 |
21 | class ClassComponent extends React.Component {
22 | render() {
23 | return (
24 |
25 | {this.props.content}
26 |
27 | );
28 | }
29 | }
30 |
31 | class MyDiv extends React.Component {
32 | render() {
33 | return React.createElement('div', this.props);
34 | }
35 | }
36 |
37 | const FunctionComp = function (props) {
38 | return ();
39 | };
40 |
41 | const versionParts = React.version.split('.');
42 | const isReact014 = (parseFloat(versionParts[0] + '.' + versionParts[1]) >= 0.14);
43 |
44 | describe('unexpected-react-shallow', () => {
45 |
46 | var testExpect;
47 | var renderer, renderer2;
48 |
49 | beforeEach(function () {
50 | renderer = React.addons.TestUtils.createRenderer();
51 | renderer2 = React.addons.TestUtils.createRenderer();
52 |
53 | testExpect = Unexpected.clone()
54 | .installPlugin(UnexpectedReactShallow);
55 | });
56 |
57 | it('identifies a ReactElement', () => {
58 |
59 | renderer.render();
60 | var element = renderer.getRenderOutput();
61 |
62 | testExpect(element, 'to be a', 'ReactElement');
63 | });
64 |
65 | if (isReact014) {
66 | it('identifies a pure function component', () => {
67 |
68 | renderer.render();
69 | var element = renderer.getRenderOutput();
70 |
71 | testExpect(element, 'to be a', 'ReactElement');
72 | });
73 | }
74 |
75 | it('identifies a ShallowRenderer', () => {
76 |
77 | testExpect(renderer, 'to be a', 'ReactShallowRenderer');
78 | });
79 |
80 | describe('inspect', () => {
81 |
82 | it('outputs a tag element with no props', () => {
83 |
84 | renderer.render();
85 | expect(() => testExpect(renderer, 'to equal', ''), 'to throw',
86 | "expected to equal ''");
87 | });
88 |
89 | it('outputs a tag element with string props', () => {
90 |
91 | renderer.render();
92 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
93 | 'expected to equal 1');
94 | });
95 |
96 | it('outputs a tag element with number props', () => {
97 |
98 | renderer.render();
99 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
100 | 'expected to equal 1');
101 | });
102 |
103 | it('outputs a tag element with boolean props', () => {
104 |
105 | renderer.render();
106 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
107 | 'expected to equal 1');
108 | });
109 |
110 | it('outputs a tag element with null props', () => {
111 |
112 | renderer.render();
113 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
114 | 'expected to equal 1');
115 | });
116 |
117 | it('outputs a tag element with an undefined prop', () => {
118 |
119 | renderer.render();
120 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
121 | 'expected to equal 1');
122 | });
123 |
124 | it('outputs a tag element with an object prop', () => {
125 |
126 | var obj = { some: 'prop' };
127 | renderer.render();
128 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
129 | 'expected to equal 1');
130 | });
131 |
132 | it('outputs a tag element with an function prop', () => {
133 |
134 | var fn = function (a, b) { return a + b; };
135 | renderer.render();
136 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
137 | 'expected to equal 1');
138 | });
139 |
140 | it('outputs a tag with a single string child', () => {
141 |
142 | renderer.render(some content);
143 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
144 | 'expected\n' +
145 | '\n' +
146 | ' some content\n' +
147 | '
\n' +
148 | 'to equal 1');
149 | });
150 |
151 | it('outputs an ES5 createClass component props and no children', () => {
152 |
153 | renderer.render(some content);
154 |
155 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
156 | 'expected\n' +
157 | '\n' +
158 | ' \n' +
159 | ' some content\n' +
160 | ' \n' +
161 | '
\n' +
162 | 'to equal 1');
163 | });
164 |
165 | it('outputs an ES5 class component props and children', () => {
166 |
167 | renderer.render(some content);
168 |
169 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
170 | 'expected\n' +
171 | '\n' +
172 | ' \n' +
173 | ' some content\n' +
174 | ' \n' +
175 | '
\n' +
176 | 'to equal 1');
177 | });
178 |
179 | it('outputs a set of deep nested components', () => {
180 |
181 | renderer.render(
182 |
183 |
184 |
185 | some content
186 |
187 |
188 | some different content
189 |
190 |
191 | );
192 |
193 | expect(() => testExpect(renderer, 'to equal', 1), 'to throw',
194 | 'expected\n' +
195 | '\n' +
196 | ' \n' +
197 | ' \n' +
198 | ' some content\n' +
199 | ' \n' +
200 | ' \n' +
201 | ' some different content\n' +
202 | ' \n' +
203 | ' \n' +
204 | '
\n' +
205 | 'to equal 1');
206 | });
207 |
208 | it('outputs a directly created custom ReactElement', function () {
209 |
210 | expect(() => testExpect(, 'to equal', 1),
211 | 'to throw', 'expected to equal 1');
212 | });
213 |
214 | it('outputs a directly created native ReactElement', function () {
215 |
216 | expect(() => testExpect(, 'to equal', 1),
217 | 'to throw', 'expected to equal 1');
218 | });
219 |
220 | it('outputs a directly created inline element (React 0.14)', function () {
221 |
222 | var inlineElement = {
223 | type: 'div',
224 | props: {
225 | className: 'foo'
226 | },
227 | key: null,
228 | ref: null
229 | };
230 |
231 | expect(() => testExpect(inlineElement, 'to equal', 1), 'to throw',
232 | 'expected to equal 1');
233 | });
234 |
235 | /* This test is disabled. There's something with the way babel(possibly) is
236 | * converting the NoNameComponent - the name is coming out as 'Constructor'
237 | * Wallaby.js runs it fine (although wallaby.js has other issues with displayNames not appearing
238 | * via the babel transform for createClass, and only appearing if displayName is explicitely set.
239 | *
240 | it('outputs a component with no-display-name', function () {
241 |
242 | expect(() => testExpect(, 'to equal', 1), 'to throw',
243 | 'expected to equal 1');
244 | });
245 | */
246 | });
247 |
248 | describe('diff', () => {
249 |
250 | it('diffs within simple text content inside native element', () => {
251 |
252 | renderer.render(Some simple content);
253 | var expected = Different content
;
254 | // testExpect(renderer, 'to have rendered', expected);
255 |
256 | expect(() => testExpect(renderer, 'to have rendered', expected), 'to throw',
257 | 'expected\n' +
258 | '\n' +
259 | ' Some simple content\n' +
260 | '
\n' +
261 | 'to have rendered\n' +
262 | '\n' +
263 | ' Different content\n' +
264 | '
\n' +
265 | '\n' +
266 | '\n'+
267 | ' -Some simple content\n' +
268 | ' +Different content\n' +
269 | '
'
270 | );
271 |
272 | });
273 |
274 | it('shows changed props within a simple native element', () => {
275 |
276 | renderer.render(Some simple content);
277 |
278 | expect(() => testExpect(renderer, 'to have rendered',
279 |
280 | Some simple content
281 |
), 'to throw',
282 | 'expected\n' +
283 | '\n' +
284 | ' Some simple content\n' +
285 | '
\n' +
286 | 'to have rendered\n' +
287 | '\n' +
288 | ' Some simple content\n' +
289 | '
\n' +
290 | '\n' +
291 | '\n' +
294 | ' Some simple content\n' +
295 | '
');
296 | });
297 |
298 | it('shows missing props within a simple native element', () => {
299 |
300 | renderer.render(Some simple content);
301 |
302 | expect(() => testExpect(renderer, 'to have rendered',
303 |
304 | Some simple content
305 |
), 'to throw',
306 | 'expected\n' +
307 | '\n' +
308 | ' Some simple content\n' +
309 | '
\n' +
310 | 'to have rendered\n' +
311 | '\n' +
312 | ' Some simple content\n' +
313 | '
\n' +
314 | '\n' +
315 | '\n' +
318 | ' Some simple content\n' +
319 | '
');
320 | });
321 |
322 | it('ignores extra props within a simple native element', () => {
323 |
324 | renderer.render(Some simple content);
325 |
326 | testExpect(renderer, 'to have rendered',
327 |
328 | Some simple content
329 |
);
330 | });
331 |
332 | it('does not ignore extra props when using `exactly`', function () {
333 |
334 | renderer.render(Some simple content);
335 | expect(() => {
336 | testExpect(renderer, 'to have exactly rendered',
337 |
338 | Some simple content
339 |
);
340 | }, 'to throw',
341 | 'expected\n' +
342 | '\n' +
343 | ' Some simple content\n' +
344 | '
\n' +
345 | 'to have exactly rendered\n' +
346 | '\n' +
347 | ' Some simple content\n' +
348 | '
\n' +
349 | '\n' +
350 | '\n' +
352 | ' Some simple content\n' +
353 | '
');
354 | });
355 |
356 | it('matches props on a custom component', function () {
357 |
358 | renderer.render(
359 |
360 |
361 | foo
362 |
363 |
364 | );
365 |
366 | testExpect(renderer, 'to have exactly rendered',
367 |
368 |
369 | foo
370 |
371 |
);
372 | });
373 |
374 | it('matches content rendered as a number', function () {
375 |
376 | renderer.render();
377 | testExpect(renderer, 'to have rendered', 0
);
378 | });
379 |
380 | it('matches content as undefined', function () {
381 |
382 | renderer.render();
383 | testExpect(renderer, 'to have rendered', );
384 | });
385 |
386 | it('matches content as null', function () {
387 |
388 | renderer.render();
389 | testExpect(renderer, 'to have rendered', );
390 | });
391 |
392 | it('highlights diffs on a nested custom component', function () {
393 |
394 | renderer.render(
395 |
396 |
397 | foo
398 |
399 |
400 | );
401 |
402 | expect(() => testExpect(renderer, 'to have exactly rendered',
403 |
404 |
405 | foo
406 |
407 |
), 'to throw',
408 | 'expected\n' +
409 | '\n' +
410 | ' \n' +
411 | ' \n' +
412 | ' foo\n' +
413 | ' \n' +
414 | ' \n' +
415 | '
\n' +
416 | 'to have exactly rendered\n' +
417 | '\n' +
418 | ' \n' +
419 | ' \n' +
420 | ' foo\n' +
421 | ' \n' +
422 | ' \n' +
423 | '
\n' +
424 | '\n' +
425 | '\n' +
426 | ' \n' +
428 | ' \n' +
429 | ' foo\n' +
430 | ' \n' +
431 | ' \n' +
432 | '
');
433 |
434 | });
435 |
436 |
437 | it('ignores extra props on a nested custom component when not using `exactly`', function () {
438 |
439 | renderer.render(
440 |
441 |
442 | foo
443 |
444 |
445 | );
446 |
447 | testExpect(renderer, 'to have rendered',
448 |
449 |
450 | foo
451 |
452 |
);
453 |
454 | });
455 |
456 | it('highlights extra props on a nested custom component when using `exactly`', function () {
457 |
458 | renderer.render(
459 |
460 |
461 | foo
462 |
463 |
464 | );
465 |
466 | expect(() => testExpect(renderer, 'to have exactly rendered',
467 |
468 |
469 | foo
470 |
471 |
), 'to throw',
472 | 'expected\n' +
473 | '\n' +
474 | ' \n' +
475 | ' \n' +
476 | ' foo\n' +
477 | ' \n' +
478 | ' \n' +
479 | '
\n' +
480 | 'to have exactly rendered\n' +
481 | '\n' +
482 | ' \n' +
483 | ' \n' +
484 | ' foo\n' +
485 | ' \n' +
486 | ' \n' +
487 | '
\n' +
488 | '\n' +
489 | '\n' +
490 | ' \n' +
492 | ' \n' +
493 | ' foo\n' +
494 | ' \n' +
495 | ' \n' +
496 | '
');
497 |
498 |
499 | });
500 |
501 | it('matches array of children in a custom component', function () {
502 |
503 | renderer.render(
504 |
505 |
506 | 1
507 | 2
508 |
509 |
510 | );
511 |
512 | testExpect(renderer, 'to have exactly rendered',
513 |
514 |
515 | 1
516 | 2
517 |
518 |
);
519 | });
520 |
521 | it('highlights a removed item in an array of children in a custom component', function () {
522 |
523 | renderer.render(
524 |
525 |
526 | 1
527 | 3
528 |
529 |
530 | );
531 |
532 | expect(() => testExpect(renderer, 'to have exactly rendered',
533 |
534 |
535 | 1
536 | 2
537 | 3
538 |
539 |
), 'to throw',
540 | 'expected\n' +
541 | '\n' +
542 | ' \n' +
543 | ' \n' +
544 | ' 1\n' +
545 | ' \n' +
546 | ' \n' +
547 | ' 3\n' +
548 | ' \n' +
549 | ' \n' +
550 | '
\n' +
551 | 'to have exactly rendered\n' +
552 | '\n' +
553 | ' \n' +
554 | ' \n' +
555 | ' 1\n' +
556 | ' \n' +
557 | ' \n' +
558 | ' 2\n' +
559 | ' \n' +
560 | ' \n' +
561 | ' 3\n' +
562 | ' \n' +
563 | ' \n' +
564 | '
\n' +
565 | '\n' +
566 | '\n' +
567 | ' \n' +
568 | ' \n' +
569 | ' 1\n' +
570 | ' \n' +
571 | ' \n' +
574 | ' -3\n' +
575 | ' +2\n' +
576 | ' \n' +
577 | ' // missing \n' +
578 | ' // 3\n' +
579 | ' // \n' +
580 | ' \n' +
581 | '
');
582 | });
583 |
584 |
585 | it('highlights an added item in an array of children in a custom component', function () {
586 |
587 | renderer.render(
588 |
589 |
590 | 1
591 | 3
592 |
593 |
594 | );
595 |
596 | expect(() => testExpect(renderer, 'to have exactly rendered',
597 |
598 |
599 | 1
600 | 2
601 | 3
602 |
603 |
604 | ), 'to throw',
605 | 'expected\n' +
606 | '\n' +
607 | ' \n' +
608 | ' \n' +
609 | ' 1\n' +
610 | ' \n' +
611 | ' \n' +
612 | ' 3\n' +
613 | ' \n' +
614 | ' \n' +
615 | '
\n' +
616 | 'to have exactly rendered\n' +
617 | '\n' +
618 | ' \n' +
619 | ' \n' +
620 | ' 1\n' +
621 | ' \n' +
622 | ' \n' +
623 | ' 2\n' +
624 | ' \n' +
625 | ' \n' +
626 | ' 3\n' +
627 | ' \n' +
628 | ' \n' +
629 | '
\n' +
630 | '\n' +
631 | '\n' +
632 | ' \n' +
633 | ' \n' +
634 | ' 1\n' +
635 | ' \n' +
636 | ' \n' +
639 | ' -3\n' +
640 | ' +2\n' +
641 | ' \n' +
642 | ' // missing \n' +
643 | ' // 3\n' +
644 | ' // \n' +
645 | ' \n' +
646 | '
');
647 |
648 | });
649 |
650 | it('accepts added children at the end of an array when not using `exactly`', function () {
651 |
652 | renderer.render(
653 |
654 |
655 | 1
656 | 2
657 | 3
658 |
659 |
660 | );
661 |
662 | testExpect(renderer, 'to have rendered',
663 |
664 |
665 | 1
666 | 2
667 |
668 |
);
669 | });
670 |
671 | it('accepts added children in the middle of an array when not using `exactly`', function () {
672 |
673 | renderer.render(
674 |
675 |
676 | 1
677 | 2
678 | 3
679 |
680 |
681 | );
682 |
683 | testExpect(renderer, 'to have rendered',
684 |
685 |
686 | 1
687 | 3
688 |
689 |
);
690 | });
691 |
692 | it('highlights different typed children', function () {
693 |
694 | renderer.render(
695 |
696 |
697 |
698 |
699 |
700 | );
701 |
702 | expect(() => testExpect(renderer, 'to have rendered',
703 |
704 |
705 |
706 |
707 |
), 'to throw',
708 | 'expected\n' +
709 | '\n' +
710 | ' \n' +
711 | ' \n' +
712 | ' \n' +
713 | '
\n' +
714 | 'to have rendered\n' +
715 | '\n' +
716 | ' \n' +
717 | ' \n' +
718 | ' \n' +
719 | '
\n' +
720 | '\n' +
721 | '\n' +
722 | ' \n' +
723 | ' \n' +
725 | ' \n' +
726 | '
');
727 | });
728 |
729 | it('matches matching objects as props deeply not be reference', function () {
730 |
731 | var objectA = { some: 'prop', arr: [ 1, 2, 3 ] };
732 | var objectB = { some: 'prop', arr: [ 1, 2, 3 ] };
733 |
734 | renderer.render(
735 |
736 |
737 |
738 | );
739 |
740 | testExpect(renderer, 'to have rendered',
741 |
742 |
743 |
);
744 | });
745 |
746 | it('highlights different objects as props deeply not be reference', function () {
747 |
748 | var objectA = { some: 'prop', arr: [ 1, 2, 3 ] };
749 | var objectB = { some: 'prop', arr: [ 1, 2, 4 ] };
750 |
751 | renderer.render(
752 |
753 |
754 |
755 | );
756 |
757 | expect(() => testExpect(renderer, 'to have rendered',
758 |
759 |
760 |
), 'to throw',
761 | 'expected\n' +
762 | '\n' +
763 | ' \n' +
764 | '
\n' +
765 | 'to have rendered\n' +
766 | '\n' +
767 | ' \n' +
768 | '
\n' +
769 | '\n' +
770 | '\n' +
771 | " \n' +
780 | '
');
781 | });
782 |
783 | it('matches a multi-text child', function () {
784 |
785 | var content = 'test';
786 | var content2 = 'test';
787 | renderer.render(
788 |
789 |
790 | some text {content}
791 |
792 |
793 | );
794 |
795 | testExpect(renderer, 'to have rendered',
796 |
797 |
798 | some text {content2}
799 |
800 |
);
801 | });
802 |
803 | it('matches a multi-text child to a single text child without exactly', function () {
804 |
805 | var content = 'test';
806 | renderer.render(
807 |
808 |
809 | some text {content}
810 |
811 |
812 | );
813 |
814 | testExpect(renderer, 'to have rendered',
815 |
816 |
817 | some text test
818 |
819 |
);
820 | });
821 |
822 | it('matches a multi-text child including a number to a single text child without exactly', function () {
823 |
824 | var content = 5;
825 | renderer.render(
826 |
827 |
828 | some {content} value
829 |
830 |
831 | );
832 |
833 | testExpect(renderer, 'to have rendered',
834 |
835 |
836 | some 5 value
837 |
838 |
);
839 | });
840 |
841 | it('matches a multi-text child including a null to a single text child without exactly', function () {
842 |
843 | var content = null;
844 | renderer.render(
845 |
846 |
847 | some {content} value
848 |
849 |
850 | );
851 |
852 | testExpect(renderer, 'to have rendered',
853 |
854 |
855 | some value
856 |
857 |
);
858 | });
859 |
860 | it('matches a multi-text child including an undefined to a single text child without exactly', function () {
861 |
862 | var content = undefined;
863 | renderer.render(
864 |
865 |
866 | some {content} value
867 |
868 |
869 | );
870 |
871 | testExpect(renderer, 'to have rendered',
872 |
873 |
874 | some value
875 |
876 |
);
877 | });
878 |
879 | it('matches a multi-text child including a boolean to a single text child without exactly', function () {
880 |
881 | var content = true;
882 | renderer.render(
883 |
884 |
885 | some {content} value
886 |
887 |
888 | );
889 |
890 | // An inline boolean is converted to null, so this "just works"
891 | testExpect(renderer, 'to have rendered',
892 |
893 |
894 | some value
895 |
896 |
);
897 | });
898 |
899 | it('highlights string break-down changes in a multi-text child with `exactly`', function () {
900 |
901 | var content = 'test';
902 | renderer.render(
903 |
904 |
905 | some text {content}
906 |
907 |
908 | );
909 |
910 | expect(() => testExpect(renderer, 'to have exactly rendered',
911 |
912 |
913 | some text test
914 |
915 |
), 'to throw',
916 | 'expected\n' +
917 | '\n' +
918 | ' \n' +
919 | ' some text test\n' +
920 | ' \n' +
921 | '
\n' +
922 | 'to have exactly rendered\n' +
923 | '\n' +
924 | ' \n' +
925 | ' some text test\n' +
926 | ' \n' +
927 | '
\n' +
928 | '\n' +
929 | '\n' +
930 | ' \n' +
931 | ' -some text \n' +
932 | ' +some text test\n' +
933 | ' test // should be removed\n' +
934 | ' \n' +
935 | '
');
936 | });
937 |
938 | it('highlights changed in a multi-text child', function () {
939 |
940 | var content = 'foo';
941 | var content2 = 'bar';
942 | renderer.render(
943 |
944 |
945 | some text {content}
946 |
947 |
948 | );
949 |
950 | expect(() => testExpect(renderer, 'to have rendered',
951 |
952 |
953 | some text {content2}
954 |
955 |
), 'to throw',
956 | 'expected\n' +
957 | '\n' +
958 | ' \n' +
959 | ' some text foo\n' +
960 | ' \n' +
961 | '
\n' +
962 | 'to have rendered\n' +
963 | '\n' +
964 | ' \n' +
965 | ' some text bar\n' +
966 | ' \n' +
967 | '
\n' +
968 | '\n' +
969 | '\n' +
970 | ' \n' +
971 | ' -some text foo\n' +
972 | ' +some text bar\n' +
973 | ' \n' +
974 | '
');
975 | });
976 |
977 | it('matches a mixed content child', function () {
978 |
979 | var content = ;
980 | var content2 = ;
981 |
982 | renderer.render(
983 |
984 |
985 | some text {content}
986 |
987 |
988 | );
989 |
990 | testExpect(renderer, 'to have rendered',
991 |
992 |
993 | some text {content2}
994 |
995 |
);
996 | });
997 |
998 | it('highlights changes in a mixed content child', function () {
999 |
1000 | var content = ;
1001 | var content2 = ;
1002 |
1003 | renderer.render(
1004 |
1005 |
1006 | some text {content}
1007 |
1008 |
1009 | );
1010 |
1011 | expect(() => testExpect(renderer, 'to have rendered',
1012 |
1013 |
1014 | some text {content2}
1015 |
1016 |
), 'to throw',
1017 | 'expected\n' +
1018 | '\n' +
1019 | ' \n' +
1020 | ' some text \n' +
1021 | ' \n' +
1022 | ' \n' +
1023 | '
\n' +
1024 | 'to have rendered\n' +
1025 | '\n' +
1026 | ' \n' +
1027 | ' some text \n' +
1028 | ' \n' +
1029 | ' \n' +
1030 | '
\n' +
1031 | '\n' +
1032 | '\n' +
1033 | ' \n' +
1034 | ' some text \n' +
1035 | ' \n' +
1038 | ' \n' +
1039 | '
');
1040 | });
1041 |
1042 | it('highlights removals in multi-string content', function () {
1043 | var content = 'test';
1044 |
1045 | renderer.render(
1046 |
1047 |
1048 | some text
1049 |
1050 |
1051 | );
1052 | expect(() => testExpect(renderer, 'to have exactly rendered',
1053 |
1054 |
1055 | some text {content}
1056 |
1057 |
), 'to throw',
1058 | 'expected\n' +
1059 | '\n' +
1060 | ' \n' +
1061 | ' some text\n' +
1062 | ' \n' +
1063 | '
\n' +
1064 | 'to have exactly rendered\n' +
1065 | '\n' +
1066 | ' \n' +
1067 | ' some text test\n' +
1068 | ' \n' +
1069 | '
\n' +
1070 | '\n' +
1071 | '\n' +
1072 | ' \n' +
1073 | ' -some text\n' +
1074 | ' +some text \n' +
1075 | ' // missing test\n' +
1076 | ' \n' +
1077 | '
');
1078 | });
1079 |
1080 | it('highlights removals in complex content with exactly', function () {
1081 | var content = 'test';
1082 |
1083 | renderer.render(
1084 |
1085 |
1086 |
1087 |
1088 | foo
1089 |
1090 |
1091 | );
1092 |
1093 | expect(() => testExpect(renderer, 'to have exactly rendered',
1094 |
1095 |
1096 |
1097 | foo
1098 |
1099 |
), 'to throw',
1100 | 'expected\n' +
1101 | '\n' +
1102 | '
\n' +
1103 | ' \n' +
1104 | ' \n' +
1105 | ' \n' +
1106 | ' foo\n' +
1107 | ' \n' +
1108 | ' \n' +
1109 | '
\n' +
1110 | 'to have exactly rendered\n' +
1111 | '\n' +
1112 | '
\n' +
1113 | ' \n' +
1114 | ' \n' +
1115 | ' foo\n' +
1116 | ' \n' +
1117 | ' \n' +
1118 | '
\n' +
1119 | '\n' +
1120 | '\n' +
1121 | '
\n' +
1122 | ' \n' +
1123 | ' // should be removed\n' +
1124 | ' \n' +
1125 | ' foo\n' +
1126 | ' \n' +
1127 | ' \n' +
1128 | '
');
1129 | });
1130 |
1131 | it('highlights removals in complex content with `with all children`', function () {
1132 | var content = 'test';
1133 |
1134 | renderer.render(
1135 |
1136 |
1137 |
1138 |
1139 | foo
1140 |
1141 |
1142 | );
1143 |
1144 | expect(() => testExpect(renderer, 'to have rendered with all children',
1145 |
1146 |
1147 |
1148 | foo
1149 |
1150 |
), 'to throw',
1151 | 'expected\n' +
1152 | '\n' +
1153 | '
\n' +
1154 | ' \n' +
1155 | ' \n' +
1156 | ' \n' +
1157 | ' foo\n' +
1158 | ' \n' +
1159 | ' \n' +
1160 | '
\n' +
1161 | 'to have rendered with all children\n' +
1162 | '\n' +
1163 | '
\n' +
1164 | ' \n' +
1165 | ' \n' +
1166 | ' foo\n' +
1167 | ' \n' +
1168 | ' \n' +
1169 | '
\n' +
1170 | '\n' +
1171 | '\n' +
1172 | '
\n' +
1173 | ' \n' +
1174 | ' // should be removed\n' +
1175 | ' \n' +
1176 | ' foo\n' +
1177 | ' \n' +
1178 | ' \n' +
1179 | '
');
1180 | });
1181 |
1182 | it('highlights the block removal for deep children', function () {
1183 | renderer.render(
1184 |
1185 |
1186 | - one
1187 | - two
1188 | - three
1189 |
1190 |
1191 | );
1192 |
1193 | expect(() => testExpect(renderer, 'to have rendered with all children',
1194 |
1195 |
1196 | - one
1197 | - two
1198 |
1199 |
), 'to throw',
1200 | 'expected\n' +
1201 | '\n' +
1202 | '
\n' +
1203 | ' - \n' +
1204 | ' one\n' +
1205 | '
\n' +
1206 | ' - \n' +
1207 | ' two\n' +
1208 | '
\n' +
1209 | ' - \n' +
1210 | ' three\n' +
1211 | '
\n' +
1212 | '
\n' +
1213 | '
\n' +
1214 | 'to have rendered with all children\n' +
1215 | '\n' +
1216 | '
\n' +
1217 | ' - \n' +
1218 | ' one\n' +
1219 | '
\n' +
1220 | ' - \n' +
1221 | ' two\n' +
1222 | '
\n' +
1223 | '
\n' +
1224 | '
\n' +
1225 | '\n' +
1226 | '\n' +
1227 | '
\n' +
1228 | ' - \n' +
1229 | ' one\n' +
1230 | '
\n' +
1231 | ' - \n' +
1232 | ' two\n' +
1233 | '
\n' +
1234 | ' - // should be removed\n' +
1235 | ' three //\n' +
1236 | '
//\n' +
1237 | '
\n' +
1238 | '
');
1239 | });
1240 |
1241 | it('identifies when a string element should be a real element', function () {
1242 |
1243 | renderer.render(
1244 |
1245 | 123
1246 | );
1247 |
1248 | expect(() => testExpect(renderer, 'to have rendered',
1249 |
1250 | 123
1251 |
), 'to throw',
1252 | 'expected\n' +
1253 | '\n' +
1254 | ' \n' +
1255 | ' 123\n' +
1256 | ' \n' +
1257 | '
\n' +
1258 | 'to have rendered\n' +
1259 | '\n' +
1260 | ' 123\n' +
1261 | '
\n' +
1262 | '\n' +
1263 | '\n' +
1264 | ' // \n' +
1265 | ' 123 //\n' +
1266 | " // should be '123'\n" +
1267 | '
');
1268 | });
1269 |
1270 | it('identifies when a number element should be a real element', function () {
1271 |
1272 | renderer.render(
1273 |
1274 | {123}
1275 | );
1276 |
1277 | expect(() => testExpect(renderer, 'to have rendered',
1278 |
1279 | {123}
1280 |
), 'to throw',
1281 | 'expected\n' +
1282 | '\n' +
1283 | ' \n' +
1284 | ' 123\n' +
1285 | ' \n' +
1286 | '
\n' +
1287 | 'to have rendered\n' +
1288 | '\n' +
1289 | ' 123\n' +
1290 | '
\n' +
1291 | '\n' +
1292 | '\n' +
1293 | ' // \n' +
1294 | ' 123 //\n' +
1295 | " // should be 123\n" +
1296 | '
');
1297 | });
1298 |
1299 |
1300 |
1301 | it('identifies when a real element should be a string element', function () {
1302 |
1303 | renderer.render(
1304 |
1305 | 123
1306 | );
1307 |
1308 | expect(() => testExpect(renderer, 'to have rendered',
1309 |
1310 | 123
1311 |
), 'to throw',
1312 | 'expected\n' +
1313 | '\n' +
1314 | ' 123\n' +
1315 | '
\n' +
1316 | 'to have rendered\n' +
1317 | '\n' +
1318 | ' \n' +
1319 | ' 123\n' +
1320 | ' \n' +
1321 | '
\n' +
1322 | '\n' +
1323 | '\n' +
1324 | " 123 // should be \n" +
1325 | ' // 123\n' +
1326 | ' // \n' +
1327 | '
');
1328 | });
1329 |
1330 | it('identifies when a real element should be a number element', function () {
1331 |
1332 | renderer.render(
1333 |
1334 | {123}
1335 | );
1336 |
1337 | expect(() => testExpect(renderer, 'to have rendered',
1338 |
1339 | 123
1340 |
), 'to throw',
1341 | 'expected\n' +
1342 | '\n' +
1343 | ' 123\n' +
1344 | '
\n' +
1345 | 'to have rendered\n' +
1346 | '\n' +
1347 | ' \n' +
1348 | ' 123\n' +
1349 | ' \n' +
1350 | '
\n' +
1351 | '\n' +
1352 | '\n' +
1353 | ' 123 // should be \n' +
1354 | ' // 123\n' +
1355 | ' // \n' +
1356 | '
');
1357 | });
1358 |
1359 | it('ignores components that render null in an array when using `with all children`', function () {
1360 |
1361 | const RenderNull = React.createClass({
1362 |
1363 | render: function () {
1364 |
1365 | const children = [ one, null, two ];
1366 | return (
1367 |
1368 |
1369 | {children}
1370 |
1371 | );
1372 | }
1373 | });
1374 | renderer.render();
1375 | testExpect(renderer, 'to have rendered with all children',
1376 |
1377 | one
1378 | two
1379 |
);
1380 | });
1381 |
1382 | it('ignores null children when using `with all children`', function () {
1383 |
1384 | const RenderNull = React.createClass({
1385 |
1386 | render: function () {
1387 |
1388 | return (
1389 |
1390 | {null}
1391 |
1392 | );
1393 | }
1394 | });
1395 | renderer.render();
1396 |
1397 | testExpect(renderer, 'to have rendered with all children', );
1398 | });
1399 |
1400 | it("highlights when an element renders children when it shouldn't when using `with all children`", function () {
1401 |
1402 | const RenderNull = React.createClass({
1403 |
1404 | render: function () {
1405 |
1406 | return (
1407 |
1410 | );
1411 | }
1412 | });
1413 | renderer.render();
1414 |
1415 | expect(() => testExpect(renderer, 'to have rendered with all children',
1416 |
1417 | ), 'to throw',
1418 | 'expected\n' +
1419 | '\n' +
1420 | '
\n' +
1421 | '
\n' +
1422 | 'to have rendered with all children \n' +
1423 | '\n' +
1424 | '\n' +
1425 | '
// should be removed\n' +
1426 | '
' );
1427 | });
1428 | });
1429 |
1430 |
1431 | describe('`to equal`', function () {
1432 |
1433 | it('matches renderer output to a component tree', function () {
1434 |
1435 | renderer.render();
1436 | testExpect(renderer.getRenderOutput(), 'to equal',
);
1437 | });
1438 |
1439 | it('outputs a diff when the expected is different', function () {
1440 |
1441 | renderer.render();
1442 |
1443 | expect(() => testExpect(renderer.getRenderOutput(),
1444 | 'to equal',
),
1445 | 'to throw',
1446 | 'expected\n' +
1447 | '\n' +
1448 | ' \n' +
1449 | '
\n' +
1450 | 'to equal\n' +
1451 | '\n' +
1452 | ' \n' +
1453 | '
\n' +
1454 | '\n' +
1455 | '\n' +
1456 | ' \n' +
1459 | '
');
1460 | });
1461 | });
1462 |
1463 |
1464 | describe('contains', function () {
1465 |
1466 | it('finds an match at the top level', function () {
1467 |
1468 | renderer.render();
1469 | testExpect(renderer, 'to contain',
);
1470 | });
1471 |
1472 | it('finds a match at a deeper level', function () {
1473 |
1474 | renderer.render();
1475 | testExpect(renderer, 'to contain', );
1476 | });
1477 |
1478 | it('finds a string content', function () {
1479 | renderer.render(some content onesome content two);
1480 | testExpect(renderer, 'to contain', 'some content two');
1481 | });
1482 |
1483 | it('does not find a string that does not exist', function () {
1484 |
1485 | renderer.render(some content onesome content two);
1486 | expect(() => testExpect(renderer, 'to contain', 'some content three'), 'to throw',
1487 | 'expected\n' +
1488 | '\n' +
1489 | ' \n' +
1490 | ' some content one\n'+
1491 | ' \n' +
1492 | ' \n' +
1493 | ' some content two\n'+
1494 | ' \n' +
1495 | '
\n' +
1496 | "to contain 'some content three'");
1497 | });
1498 |
1499 |
1500 |
1501 | it('does not find a partial string', function () {
1502 |
1503 | // This behaviour may change in a major version bump at some point.
1504 | // Currently it's quite difficult to implement sensibly, as it would mean that searching
1505 | // for an element with text content would also match if a partial string matched.
1506 | // Maybe we allow a regex... :)
1507 | renderer.render(some content onesome content two);
1508 | expect(() => testExpect(renderer, 'to contain', 'some content'), 'to throw',
1509 | 'expected\n' +
1510 | '\n' +
1511 | ' \n' +
1512 | ' some content one\n'+
1513 | ' \n' +
1514 | ' \n' +
1515 | ' some content two\n'+
1516 | ' \n' +
1517 | '
\n' +
1518 | "to contain 'some content'");
1519 | });
1520 |
1521 | it('finds a multi-part string', function () {
1522 |
1523 | renderer.render(button clicked {5} times);
1524 | testExpect(renderer, 'to contain', 'button clicked 5 times');
1525 | });
1526 |
1527 | it('does not find a multi-part string when `exactly` is used', function () {
1528 |
1529 | renderer.render(button clicked {5} times);
1530 | expect(() => testExpect(renderer, 'to contain exactly', 'button clicked 5 times'),
1531 | 'to throw',
1532 | 'expected\n' +
1533 | '\n' +
1534 | ' \n' +
1535 | ' button clicked 5 times\n' +
1536 | ' \n' +
1537 | '
\n' +
1538 | "to contain exactly 'button clicked 5 times'");
1539 | });
1540 |
1541 | it('does not find a part of a multi-part string', function () {
1542 |
1543 | // See the 'does not find a partial string' test above
1544 | // This behaviour may change
1545 | renderer.render(button clicked {5} times);
1546 | expect(() => testExpect(renderer, 'to contain', 'button clicked '), 'to throw',
1547 | 'expected\n' +
1548 | '\n' +
1549 | ' \n' +
1550 | ' button clicked 5 times\n' +
1551 | ' \n' +
1552 | '
\n' +
1553 | "to contain 'button clicked '");
1554 | });
1555 |
1556 | it('finds part of a multi-part string when exactly is used', function () {
1557 |
1558 | renderer.render(button clicked {5} times);
1559 | testExpect(renderer, 'to contain exactly', 'button clicked ');
1560 | });
1561 |
1562 | it('finds a match in an array of children', function () {
1563 |
1564 | renderer.render(
1565 |
1566 | nested
1567 |
1568 |
1569 |
1570 |
1571 |
1572 | );
1573 | testExpect(renderer, 'to contain', );
1574 | });
1575 |
1576 | it('does not find a match when it does not exist', function () {
1577 |
1578 | renderer.render(
1579 |
1580 | nested
1581 |
1582 |
1583 |
1584 |
1585 |
1586 | );
1587 |
1588 | expect(() => testExpect(renderer, 'to contain', ),
1589 | 'to throw',
1590 | 'expected\n' +
1591 | '\n' +
1592 | ' \n' +
1593 | ' nested\n' +
1594 | ' \n' +
1595 | ' \n' +
1596 | ' \n' +
1597 | ' \n' +
1598 | ' \n' +
1599 | ' \n' +
1600 | '
\n' +
1601 | 'to contain ');
1602 | });
1603 |
1604 | it('does not find a match when the children of a candidate match are different', function () {
1605 |
1606 | renderer.render(
1607 |
1608 | nested
1609 |
1610 |
1611 |
1612 |
1613 | something else
1614 |
1615 |
1616 | );
1617 |
1618 | expect(() => testExpect(renderer, 'to contain',
1619 |
1620 | cheese
1621 | ),
1622 | 'to throw',
1623 | 'expected\n' +
1624 | '\n' +
1625 | ' \n' +
1626 | ' nested\n' +
1627 | ' \n' +
1628 | ' \n' +
1629 | ' \n' +
1630 | ' \n' +
1631 | ' \n' +
1632 | ' \n' +
1633 | ' something else\n' +
1634 | ' \n' +
1635 | ' \n' +
1636 | ' \n' +
1637 | '
\n' +
1638 | 'to contain\n' +
1639 | '\n' +
1640 | ' \n' +
1641 | ' cheese\n' +
1642 | ' \n' +
1643 | '');
1644 | });
1645 |
1646 | it('finds the match when there are extra children in the render, but `exactly` is not used', function () {
1647 | renderer.render(
1648 |
1649 | nested
1650 |
1651 |
1652 |
1653 |
1654 | one
1655 | two
1656 | three
1657 |
1658 |
1659 | );
1660 |
1661 | testExpect(renderer, 'to contain',
1662 |
1663 | one
1664 | three
1665 | );
1666 | });
1667 |
1668 | it('finds the match when there are extra props in the render, but `exactly` is not used', function () {
1669 | renderer.render(
1670 |
1671 | nested
1672 |
1673 |
1674 |
1675 |
1676 |
1677 | );
1678 |
1679 | testExpect(renderer, 'to contain', );
1680 | });
1681 |
1682 | it('does not find a match when there are extra props in the render, and `exactly` is used', function () {
1683 | renderer.render(
1684 |
1685 | nested
1686 |
1687 |
1688 |
1689 |
1690 |
1691 | );
1692 |
1693 | expect(() => testExpect(renderer, 'to contain exactly', ),
1694 | 'to throw',
1695 | 'expected\n' +
1696 | '\n' +
1697 | ' \n' +
1698 | ' nested\n' +
1699 | ' \n' +
1700 | ' \n' +
1701 | ' \n' +
1702 | ' \n' +
1703 | ' \n' +
1704 | ' \n' +
1705 | '
\n' +
1706 | 'to contain exactly ');
1707 | });
1708 |
1709 |
1710 | it('does not find a match when there are extra children in the render, and `exactly` is used', function () {
1711 | renderer.render(
1712 |
1713 | nested
1714 |
1715 |
1716 |
1717 |
1718 | one
1719 | two
1720 | three
1721 |
1722 |
1723 | );
1724 |
1725 | expect(() => testExpect(renderer, 'to contain exactly',
1726 |
1727 | one
1728 | three
1729 | ), 'to throw',
1730 | 'expected\n' +
1731 | '\n' +
1732 | ' \n' +
1733 | ' nested\n' +
1734 | ' \n' +
1735 | ' \n' +
1736 | ' \n' +
1737 | ' \n' +
1738 | ' \n' +
1739 | ' \n' +
1740 | ' one\n' +
1741 | ' \n' +
1742 | ' \n' +
1743 | ' two\n' +
1744 | ' \n' +
1745 | ' \n' +
1746 | ' three\n' +
1747 | ' \n' +
1748 | ' \n' +
1749 | ' \n' +
1750 | '
\n' +
1751 | 'to contain exactly\n' +
1752 | '\n' +
1753 | ' \n' +
1754 | ' one\n' +
1755 | ' \n' +
1756 | ' \n' +
1757 | ' three\n' +
1758 | ' \n' +
1759 | '');
1760 | });
1761 |
1762 | it('does not find a match when there are extra children in the render, and `with all children` is used', function () {
1763 | renderer.render(
1764 |
1765 | nested
1766 |
1767 |
1768 |
1769 |
1770 | one
1771 | two
1772 | three
1773 |
1774 |
1775 | );
1776 |
1777 | expect(() => testExpect(renderer, 'to contain with all children',
1778 |
1779 | one
1780 | three
1781 | ), 'to throw',
1782 | 'expected\n' +
1783 | '\n' +
1784 | ' \n' +
1785 | ' nested\n' +
1786 | ' \n' +
1787 | ' \n' +
1788 | ' \n' +
1789 | ' \n' +
1790 | ' \n' +
1791 | ' \n' +
1792 | ' one\n' +
1793 | ' \n' +
1794 | ' \n' +
1795 | ' two\n' +
1796 | ' \n' +
1797 | ' \n' +
1798 | ' three\n' +
1799 | ' \n' +
1800 | ' \n' +
1801 | ' \n' +
1802 | '
\n' +
1803 | 'to contain with all children\n' +
1804 | '\n' +
1805 | ' \n' +
1806 | ' one\n' +
1807 | ' \n' +
1808 | ' \n' +
1809 | ' three\n' +
1810 | ' \n' +
1811 | '');
1812 | });
1813 |
1814 | it('finds a match when the render contains children, but the expected does not, and `exactly` is not used', function () {
1815 | renderer.render(
1816 |
1817 | nested
1818 |
1819 |
1820 |
1821 |
1822 | one
1823 | two
1824 | three
1825 |
1826 |
1827 | );
1828 |
1829 | testExpect(renderer, 'to contain', );
1830 | });
1831 |
1832 | it('does not find a match when the render contains children, but the expected does not, and `exactly` is used', function () {
1833 | renderer.render(
1834 |
1835 | nested
1836 |
1837 |
1838 |
1839 |
1840 | one
1841 | two
1842 | three
1843 |
1844 |
1845 | );
1846 |
1847 | expect(() => testExpect(renderer, 'to contain exactly', ),
1848 | 'to throw',
1849 | 'expected\n' +
1850 | '\n' +
1851 | ' \n' +
1852 | ' nested\n' +
1853 | ' \n' +
1854 | ' \n' +
1855 | ' \n' +
1856 | ' \n' +
1857 | ' \n' +
1858 | ' \n' +
1859 | ' one\n' +
1860 | ' \n' +
1861 | ' \n' +
1862 | ' two\n' +
1863 | ' \n' +
1864 | ' \n' +
1865 | ' three\n' +
1866 | ' \n' +
1867 | ' \n' +
1868 | ' \n' +
1869 | '
\n' +
1870 | 'to contain exactly ');
1871 | });
1872 |
1873 | it('does not find a match if the expected has children, but the candidate match does not', function () {
1874 |
1875 | renderer.render(
1876 |
1877 | nested
1878 |
1879 |
1880 |
1881 |
1882 | );
1883 |
1884 | expect(() => testExpect(renderer, 'to contain',
1885 |
1886 | foo
1887 | ), 'to throw',
1888 | 'expected\n' +
1889 | '\n' +
1890 | ' \n' +
1891 | ' nested\n' +
1892 | ' \n' +
1893 | ' \n' +
1894 | ' \n' +
1895 | ' \n' +
1896 | ' \n' +
1897 | '
\n' +
1898 | 'to contain\n' +
1899 | '\n' +
1900 | ' \n' +
1901 | ' foo\n' +
1902 | ' \n' +
1903 | '');
1904 | });
1905 |
1906 | it('matches even with removals in complex content without `exactly`', function () {
1907 |
1908 | renderer.render(
1909 |
1910 |
1911 |
1912 |
1913 | foo
1914 |
1915 |
1916 | );
1917 |
1918 | testExpect(renderer, 'to contain',
1919 |
1920 |
1921 | foo
1922 |
1923 | );
1924 | });
1925 |
1926 | it('does not match with a removal and an addition in complex content with `exactly`', function () {
1927 |
1928 | renderer.render(
1929 |
1930 |
1931 |
1932 |
1933 | foo
1934 |
1935 |
1936 | );
1937 |
1938 | expect(() => testExpect(renderer, 'to contain exactly',
1939 |
1940 |
1941 |
1942 | foo
1943 |
1944 | ), 'to throw',
1945 | 'expected\n' +
1946 | '\n' +
1947 | '
\n' +
1948 | ' \n' +
1949 | ' \n' +
1950 | ' \n' +
1951 | ' foo\n' +
1952 | ' \n' +
1953 | ' \n' +
1954 | '
\n' +
1955 | 'to contain exactly\n' +
1956 | '\n' +
1957 | ' \n' +
1958 | ' \n' +
1959 | ' \n' +
1960 | ' foo\n' +
1961 | ' \n' +
1962 | '');
1963 | });
1964 | });
1965 |
1966 | describe('to satisfy', () => {
1967 |
1968 | describe('renderOutput', () => {
1969 |
1970 | it('should satisfy a matching output', () => {
1971 |
1972 | renderer.render(
1973 |
1974 | foo
1975 | bar
1976 |
1977 | );
1978 |
1979 | testExpect(renderer.getRenderOutput(), 'to satisfy',
1980 |
1981 | foo
1982 | bar
1983 |
);
1984 | });
1985 | });
1986 | });
1987 |
1988 | });
1989 |
--------------------------------------------------------------------------------