'use strict';

Object.defineProperty(exports, '__esModule', {
    value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _reactRenderHook = require('react-render-hook');

var _reactRenderHook2 = _interopRequireDefault(_reactRenderHook);

var _unexpectedHtmllike = require('unexpected-htmllike');

var _unexpectedHtmllike2 = _interopRequireDefault(_unexpectedHtmllike);

var _unexpectedHtmllikeReactrenderedAdapter = require('unexpected-htmllike-reactrendered-adapter');

var _unexpectedHtmllikeReactrenderedAdapter2 = _interopRequireDefault(_unexpectedHtmllikeReactrenderedAdapter);

var _unexpectedHtmllikeJsxAdapter = require('unexpected-htmllike-jsx-adapter');

var _unexpectedHtmllikeJsxAdapter2 = _interopRequireDefault(_unexpectedHtmllikeJsxAdapter);

function checkAttached(expect) {
    if (!_reactRenderHook2['default'].isAttached) {
        expect.errorMode = 'bubble';
        expect.fail(function (output) {
            return output.error('The global rendering hook is not attached').nl().text('This probably means React was required before unexpected-react. Check that unexpected-react is required first');
        });
    }
}

function installInto(expect) {

    var renderedReactElementAdapter = new _unexpectedHtmllikeReactrenderedAdapter2['default']({ convertToString: true });
    var htmlLikeRenderedReactElement = (0, _unexpectedHtmllike2['default'])(renderedReactElementAdapter);
    var reactElementAdapter = new _unexpectedHtmllikeJsxAdapter2['default']({ convertToString: true });

    expect.addAssertion(['<RenderedReactElement> to have [exactly] rendered <ReactElement>', '<RenderedReactElement> to have rendered [with all children] [with all wrappers] <ReactElement>'], function (expect, subject, element) {

        checkAttached(expect);

        var exactly = this.flags.exactly;
        var withAllChildren = this.flags['with all children'];
        var withAllWrappers = this.flags['with all wrappers'];

        var jsxAdapter = new _unexpectedHtmllikeJsxAdapter2['default']();
        if (!exactly) {
            jsxAdapter.setOptions({ concatTextContent: true });
        }

        var options = {
            diffWrappers: exactly || withAllWrappers,
            diffExtraChildren: exactly || withAllChildren,
            diffExtraAttributes: exactly,
            diffExactClasses: false, // TODO: This should be exactly - need to check the tests around this
            diffExtraClasses: exactly
        };
        var data = _reactRenderHook2['default'].findComponent(subject);
        var diffResult = htmlLikeRenderedReactElement.diff(jsxAdapter, data, element, expect.output.clone(), expect, options);

        var checkEqualCreateOutput = function checkEqualCreateOutput(result) {
            return expect.withError(function () {
                return expect(result.weight, 'to equal', 0);
            }, function () {
                expect.fail({
                    diff: function diff(output, _diff, inspect, equal) {
                        return {
                            diff: result.output
                        };
                    }
                });
            });
        };

        if (typeof diffResult.then === 'function') {
            return diffResult.then(function (result) {
                return checkEqualCreateOutput(result);
            });
        }
        return checkEqualCreateOutput(diffResult);
    });

    expect.addAssertion(['<RenderedReactElement> [not] to contain [exactly] <ReactElement|string>', '<RenderedReactElement> [not] to contain [with all children] [with all wrappers] <ReactElement|string>'], function (expect, subject, element) {

        checkAttached(expect);

        var not = this.flags.not;
        var exactly = this.flags.exactly;
        var withAllChildren = this.flags['with all children'];
        var withAllWrappers = this.flags['with all wrappers'];

        var jsxAdapter = new _unexpectedHtmllikeJsxAdapter2['default']();
        if (!exactly) {
            jsxAdapter.setOptions({ concatTextContent: true });
        }

        var options = {
            diffWrappers: exactly || withAllWrappers,
            diffExtraChildren: exactly || withAllChildren,
            diffExtraAttributes: exactly,
            diffExactClasses: false,
            diffExtraClasses: exactly
        };

        var data = _reactRenderHook2['default'].findComponent(subject);
        var containsResult = htmlLikeRenderedReactElement.contains(jsxAdapter, data, element, expect.output.clone(), expect, options);

        var checkAndCreateOutput = function checkAndCreateOutput(result) {
            if (not) {
                if (result.found) {
                    expect.fail({
                        diff: function diff(output) {
                            return {
                                diff: output.error('but found the following match').nl().append(result.bestMatch.output)
                            };
                        }
                    });
                }
                return;
            }

            if (!result.found) {
                expect.fail({
                    diff: function diff(output) {
                        return {
                            diff: output.error('the best match was').nl().append(result.bestMatch.output)
                        };
                    }
                });
            }
        };

        if (typeof containsResult.then === 'function') {
            return containsResult.then(function (result) {
                return checkAndCreateOutput(result);
            });
        }

        return checkAndCreateOutput(containsResult);
    });

    expect.addAssertion(['<ReactElement> to have [exactly] rendered <ReactElement>', '<ReactElement> to have rendered [with all children] [with all wrappers] <ReactElement>'], function (expect, subject, expected) {

        var exactly = this.flags.exactly;
        var withAllChildren = this.flags['with all children'];
        var withAllWrappers = this.flags['with all wrappers'];

        var adapter = new _unexpectedHtmllikeJsxAdapter2['default']();
        var jsxHtmlLike = new _unexpectedHtmllike2['default'](adapter);
        if (!exactly) {
            adapter.setOptions({ concatTextContent: true });
        }

        var options = {
            diffWrappers: exactly || withAllWrappers,
            diffExtraChildren: exactly || withAllChildren,
            diffExtraAttributes: exactly,
            diffExactClasses: false,
            diffExtraClasses: exactly
        };

        var diffResult = jsxHtmlLike.diff(adapter, subject, expected, expect.output.clone(), expect, options);

        var checkAndCreateOutput = function checkAndCreateOutput(result) {

            if (result.weight !== 0) {
                return expect.fail({
                    diff: function diff() {
                        return {
                            diff: result.output
                        };
                    }
                });
            }
        };

        if (typeof diffResult.then === 'function') {
            return diffResult.then(function (result) {
                return checkAndCreateOutput(result);
            });
        }

        return checkAndCreateOutput(diffResult);
    });

    expect.addAssertion(['<ReactElement> [not] to contain [exactly] <ReactElement|string>', '<ReactElement> [not] to contain [with all children] [with all wrappers] <ReactElement|string>'], function (expect, subject, expected) {

        var not = this.flags.not;
        var exactly = this.flags.exactly;
        var withAllChildren = this.flags['with all children'];
        var withAllWrappers = this.flags['with all wrappers'];

        var adapter = new _unexpectedHtmllikeJsxAdapter2['default']();
        var jsxHtmlLike = new _unexpectedHtmllike2['default'](adapter);
        if (!exactly) {
            adapter.setOptions({ concatTextContent: true });
        }

        var options = {
            diffWrappers: exactly || withAllWrappers,
            diffExtraChildren: exactly || withAllChildren,
            diffExtraAttributes: exactly
        };

        var containsResult = jsxHtmlLike.contains(adapter, subject, expected, expect.output, expect, options);

        var checkAndCreateOutput = function checkAndCreateOutput(result) {

            if (not) {
                if (result.found) {
                    expect.fail({
                        diff: function diff(output) {
                            return {
                                diff: output.error('but found the following match').nl().append(result.bestMatch.output)
                            };
                        }
                    });
                }
                return;
            }

            if (!result.found) {
                expect.fail({
                    diff: function diff(output) {
                        return {
                            diff: output.error('the best match was').nl().append(result.bestMatch.output)
                        };
                    }
                });
            }
        };

        if (typeof containsResult.then === 'function') {
            return containsResult.then(function (result) {
                return checkAndCreateOutput(result);
            });
        }

        return checkAndCreateOutput(containsResult);
    });

    expect.addAssertion('<ReactElement> to equal <ReactElement>', function (expect, subject, value) {
        return expect(subject, 'to have exactly rendered', value);
    });

    expect.addAssertion('<ReactShallowRenderer> to equal <ReactElement>', function (expect, subject, value) {
        return expect(subject.getRenderOutput(), 'to have exactly rendered', value);
    });

    expect.addAssertion('<ReactElement> to satisfy <ReactElement>', function (expect, subject, renderOutput) {
        return expect(subject, 'to have rendered', renderOutput);
    });

    expect.addAssertion(['<ReactShallowRenderer> to have [exactly] rendered <ReactElement>', '<ReactShallowRenderer> to have rendered [with all children] [with all wrappers] <ReactElement>'], function (expect, subject, renderOutput) {
        var actual = subject.getRenderOutput();
        return expect(actual, 'to have [exactly] rendered [with all children] [with all wrappers]', renderOutput);
    });

    expect.addAssertion(['<ReactShallowRenderer> [not] to contain [exactly] <ReactElement|string>', '<ReactShallowRenderer> [not] to contain [with all children] [with all wrappers] <ReactElement|string>'], function (expect, subject, renderOutput) {
        var actual = subject.getRenderOutput();
        return expect(actual, '[not] to contain [exactly] [with all children] [with all wrappers]', renderOutput);
    });

    expect.addAssertion('<ReactModule> to have been injected', function (expect, subject) {
        checkAttached(expect);
    });
}

exports['default'] = { installInto: installInto };
module.exports = exports['default'];
//# sourceMappingURL=assertions.js.map