react-oc
Version:
A React component that allows OpenComponents to operate within a react application.
670 lines (615 loc) • 27 kB
JavaScript
;
require("jest-plugin-console-matchers/setup");
var _react = _interopRequireDefault(require("react"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _server = _interopRequireDefault(require("react-dom/server"));
var _jquery = _interopRequireDefault(require("jquery"));
var _bluebird = _interopRequireDefault(require("bluebird"));
var _reactHelpers = require("./__test__/react-helpers");
var _OpenComponentsContext = require("./OpenComponentsContext");
var _OCContext = require("./OCContext");
var _OpenComponent = require("./OpenComponent");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
describe('<OpenComponent />', function () {
var callCountScript = 'window.callCount = window.callCount || 0; window.callCount++;';
beforeEach(function () {
delete window.callCount;
document.body.innerHTML = '';
});
describe('When not mounted within a <ComponentContext />', function () {
it('throws an error', function () {
var node = document.createElement('div');
return expect((0, _reactHelpers.renderAsync)(_react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
}), node)).rejects.toThrow(/must be nested within a <ComponentContext \/>/);
});
});
var baseContext, baseContextServer;
beforeEach(function () {
baseContext = {
getElement: jest.fn(function () {}),
getHtml: jest.fn(function () {
return 'hello world';
}),
saveElement: jest.fn(function () {}),
oc: {
renderNestedComponent: jest.fn(function (_, cb) {
return cb();
}),
$: _jquery.default
}
};
baseContextServer = {
getElement: baseContext.getElement,
getHtml: baseContext.getHtml,
saveElement: baseContext.saveElement
};
});
it('throws an error if prefetchKey prop was not defined', function () {
var node = document.createElement('div');
return expect((0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, null)), node)).rejects.toThrow(/Mandatory prop 'prefetchKey' was not provided/);
});
it('should apply the given id to a container div',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee() {
var node;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
node = document.createElement('div');
_context.next = 3;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
id: "my-unique-id",
prefetchKey: "my-component"
})), node);
case 3:
expect(node.childNodes[0].id).toBe('my-unique-id');
case 4:
case "end":
return _context.stop();
}
}
}, _callee, this);
})));
it('should apply the given className to a container div',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2() {
var node;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
node = document.createElement('div');
_context2.next = 3;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
className: "my-class",
prefetchKey: "my-component"
})), node);
case 3:
expect(node.childNodes[0].className).toBe('my-class');
case 4:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
})));
it('renders an empty div if no html is provided by context.getHtml',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee3() {
var node;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
node = document.createElement('div');
baseContext.getHtml.mockImplementation(function () {
return undefined;
});
_context3.next = 4;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node);
case 4:
expect(node.innerHTML).toBe('<div></div>');
case 5:
case "end":
return _context3.stop();
}
}
}, _callee3, this);
})));
it('renders the fallback if no html is provided by context.getHtml and fallback is provided',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee4() {
var node;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
node = document.createElement('div');
baseContext.getHtml.mockImplementation(function () {
return undefined;
});
_context4.next = 4;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component",
fallback: "<span>Hello world</span>"
})), node);
case 4:
expect(node.innerHTML).toBe('<div><span>Hello world</span></div>');
case 5:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
})));
it('should render markup from context.getHtml with prefetchKey in container div',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee5() {
var node, fakeHtml;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
node = document.createElement('div');
fakeHtml = "<h1>Hello world</h1>";
baseContext.getHtml.mockImplementation(function (key) {
return key === 'my-component' ? fakeHtml : undefined;
});
_context5.next = 5;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node);
case 5:
expect(node.innerHTML).toContain(fakeHtml);
case 6:
case "end":
return _context5.stop();
}
}
}, _callee5, this);
})));
it('should run any scripts from context.getHtml with prefetchKey in container div',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee6() {
var node, fakeHtml;
return regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
node = document.createElement('div');
document.body.append(node);
fakeHtml = "<h1>Hello world</h1><script>".concat(callCountScript, "</script>");
baseContext.getHtml.mockImplementation(function (key) {
return key === 'my-component' ? fakeHtml : undefined;
});
_context6.next = 6;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node);
case 6:
expect(window.callCount).toBe(1);
case 7:
case "end":
return _context6.stop();
}
}
}, _callee6, this);
})));
describe('when getHtml returns an unrendered oc-component tag', function () {
var fakeHtml = "<oc-component data-rendered=\"false\" name=\"my-component\"></oc-component>";
it('should call oc.renderNestedComponent',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee7() {
var node;
return regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
node = document.createElement('div');
baseContext.getHtml.mockImplementation(function () {
return fakeHtml;
});
_context7.next = 4;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node);
case 4:
expect(baseContext.oc.renderNestedComponent).toBeCalledWith(expect.objectContaining({
jquery: expect.anything(),
0: expect.objectContaining({
outerHTML: fakeHtml
})
}), expect.anything());
case 5:
case "end":
return _context7.stop();
}
}
}, _callee7, this);
})));
});
it('should render markup from context.getHtml with prefetchKey in container div',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee8() {
var node, fakeHtml;
return regeneratorRuntime.wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
node = document.createElement('div');
fakeHtml = "<h1>Hello world</h1>";
baseContext.getHtml.mockImplementation(function (key) {
return key === 'my-component' ? fakeHtml : undefined;
});
_context8.next = 5;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node);
case 5:
expect(node.innerHTML).toContain(fakeHtml);
case 6:
case "end":
return _context8.stop();
}
}
}, _callee8, this);
})));
describe('when server side rendering', function () {
it('should render markup from context.getHtml with prefetchKey in container div', function () {
var fakeHtml = "<h1>Hello world</h1>";
baseContextServer.getHtml.mockImplementation(function (key) {
return key === 'my-component' ? fakeHtml : undefined;
});
var render = _server.default.renderToString(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContextServer)
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})));
expect(render).toContain(fakeHtml);
});
});
describe('when hydrating over server side rendered markup', function () {
it('should not change markup',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee9() {
var node, existingMarkup;
return regeneratorRuntime.wrap(function _callee9$(_context9) {
while (1) {
switch (_context9.prev = _context9.next) {
case 0:
node = document.createElement('div');
node.innerHTML = _server.default.renderToString(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContextServer, {
getHtml: function getHtml() {
return '<h1>Hello</h1><p>World</p>';
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})));
existingMarkup = node.innerHTML;
_context9.next = 5;
return new _bluebird.default(function (resolve) {
return _reactDom.default.hydrate(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getHtml: function getHtml() {
return undefined;
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node, resolve);
});
case 5:
expect(node.innerHTML).toBe(existingMarkup);
case 6:
case "end":
return _context9.stop();
}
}
}, _callee9, this);
})));
it('should warn if getHtml provides a different value than server',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee10() {
var node, existingMarkup, expectedWarning;
return regeneratorRuntime.wrap(function _callee10$(_context10) {
while (1) {
switch (_context10.prev = _context10.next) {
case 0:
node = document.createElement('div');
node.innerHTML = _server.default.renderToString(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContextServer, {
getHtml: function getHtml() {
return '<h1>Hello</h1><p>World</p>';
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})));
existingMarkup = node.innerHTML;
expectedWarning = /Warning: Prop `[^`]+` did not match./;
suppress.console('error', expectedWarning);
_context10.next = 7;
return new _bluebird.default(function (resolve) {
return _reactDom.default.hydrate(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getHtml: function getHtml() {
return '<h1>Goodbye</h1><p>Universe</p>';
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node, resolve);
});
case 7:
expect(console.error).toHaveBeenCalledWith(expect.stringMatching(expectedWarning), 'dangerouslySetInnerHTML', expect.anything(), expect.anything());
case 8:
case "end":
return _context10.stop();
}
}
}, _callee10, this);
})));
it('should not run script tags again',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee11() {
var node, existingMarkup;
return regeneratorRuntime.wrap(function _callee11$(_context11) {
while (1) {
switch (_context11.prev = _context11.next) {
case 0:
node = document.createElement('div');
document.body.append(node);
node.innerHTML = _server.default.renderToString(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContextServer, {
getHtml: function getHtml() {
return "<h1>Hello</h1><p>World</p><script>".concat(callCountScript, "</script>");
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
}))); // simulate browser called script tag.
eval(callCountScript);
existingMarkup = node.innerHTML;
_context11.next = 7;
return new _bluebird.default(function (resolve) {
return _reactDom.default.hydrate(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getHtml: function getHtml() {
return undefined;
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node, resolve);
});
case 7:
expect(window.callCount).toBe(1);
case 8:
case "end":
return _context11.stop();
}
}
}, _callee11, this);
})));
it('should run script tags again if getHtml returns the same markup during hydration',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee12() {
var node, fakeMarkup, existingMarkup;
return regeneratorRuntime.wrap(function _callee12$(_context12) {
while (1) {
switch (_context12.prev = _context12.next) {
case 0:
node = document.createElement('div');
document.body.append(node);
fakeMarkup = "<h1>Hello</h1><p>World</p><script>".concat(callCountScript, "</script>");
node.innerHTML = _server.default.renderToString(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContextServer, {
getHtml: function getHtml() {
return fakeMarkup;
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
}))); // simulate browser called script tag.
eval(callCountScript);
existingMarkup = node.innerHTML;
_context12.next = 8;
return new _bluebird.default(function (resolve) {
return _reactDom.default.hydrate(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getHtml: function getHtml() {
return fakeMarkup;
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component"
})), node, resolve);
});
case 8:
expect(window.callCount).toBe(2);
case 9:
case "end":
return _context12.stop();
}
}
}, _callee12, this);
})));
});
describe('when given a captureAs prop', function () {
it('calls saveElements on context with the captureAs value and elements from getHtml',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee13() {
var node, html, saveElements, getElements;
return regeneratorRuntime.wrap(function _callee13$(_context13) {
while (1) {
switch (_context13.prev = _context13.next) {
case 0:
node = document.createElement('div');
html = '<div>hello</div><h1>world</h1>';
saveElements = jest.fn();
getElements = jest.fn();
_context13.next = 6;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
saveElements: saveElements,
getElements: getElements,
getHtml: function getHtml() {
return html;
}
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component",
captureAs: "my-component-1"
})), node);
case 6:
expect(saveElements).toBeCalledWith('my-component-1', [expect.objectContaining({
innerHTML: 'hello',
tagName: 'DIV'
}), expect.objectContaining({
innerHTML: 'world',
tagName: 'H1'
})]);
case 7:
case "end":
return _context13.stop();
}
}
}, _callee13, this);
})));
describe('when context.getElements returns a html element', function () {
it('calls getElements with the captureAs key',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee14() {
var node, element, getElements;
return regeneratorRuntime.wrap(function _callee14$(_context14) {
while (1) {
switch (_context14.prev = _context14.next) {
case 0:
node = document.createElement('div');
element = document.createElement('span');
getElements = jest.fn().mockImplementation(function (key) {
return element;
});
_context14.next = 5;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getElements: getElements
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component",
captureAs: "my-component-1"
})), node);
case 5:
expect(getElements).toBeCalledWith('my-component-1');
case 6:
case "end":
return _context14.stop();
}
}
}, _callee14, this);
})));
it('injects the elements into the container',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee15() {
var node, prevNode, elements, getElements, div, i;
return regeneratorRuntime.wrap(function _callee15$(_context15) {
while (1) {
switch (_context15.prev = _context15.next) {
case 0:
node = document.createElement('div');
prevNode = document.createElement('span');
prevNode.innerHTML = '<span>span</span>hello<div>div</div>';
elements = _toConsumableArray(prevNode.childNodes);
getElements = jest.fn().mockImplementation(function (key) {
return elements;
});
_context15.next = 7;
return (0, _reactHelpers.renderAsync)(_react.default.createElement(_OCContext.OCContext.Provider, {
value: _objectSpread({}, baseContext, {
getElements: getElements
})
}, _react.default.createElement(_OpenComponent.OpenComponent.Prefetched, {
prefetchKey: "my-component",
captureAs: "my-component-1"
})), node);
case 7:
div = node.childNodes[0];
expect(div.childNodes.length).toBe(elements.length);
for (i = 0; i < elements.length; i++) {
// using toBe ensures that it is the same element with
// all event handlers etc. in-tact.
expect(div.childNodes[i]).toBe(elements[i]);
}
case 10:
case "end":
return _context15.stop();
}
}
}, _callee15, this);
})));
});
});
});
//# sourceMappingURL=OpenComponent.Prefetched.test.js.map