test/unit/jsonx_spec.js
import * as jsonx from '../../src/main';
import mochaJSDOM from 'jsdom-global';
import path from 'path';
import chai from 'chai';
import sinon from 'sinon';
import React from 'react';
import ReactTestUtils from 'react-dom/test-utils'; // ES6
import ReactDOM from 'react-dom';
import ReactDOMElements from 'react-dom-factories';
import { expect, } from 'chai';
import { JSDOM, } from 'jsdom';
chai.use(require('sinon-chai'));
import 'mocha-sinon';
import useGlobalHook from 'use-global-hook';
const sampleJSONX = {
component: 'div',
props: {
id: 'generatedJSONX',
className:'jsonx',
},
children: [
{
component: 'p',
props: {
style: {
color: 'red',
fontWeight:'bold',
},
},
children:'hello world',
},
],
};
const simpleJSONX = {
div: {
props: {
id: 'generatedJSONX',
className:'jsonx',
},
children: [
{
p: {
props: {
style: {
color: 'red',
fontWeight:'bold',
},
},
children:'hello world',
},
},
],
},
};
const sampleJSONXJSON = jsonx.getReactElementFromJSONX.call({ returnJSON: true }, sampleJSONX);
const simpleJSONXJSON = jsonx.getReactElementFromJSONX.call({ returnJSON: true }, simpleJSONX);
const simpleDiv = {
component: 'div',
props: { title: 'test', },
children: 'hello',
};
const complexDiv = {
component: 'div',
props: { title: 'test', },
children: [
{
button: {
props: {
onClick: function (e) {
console.log({ e, });
},
},
children:'log event',
},
},
{
component: 'button',
__dangerouslyBindEvalProps: {
onClick:`(function(e){
console.log({ e });
})`,
},
children:'log even two',
},
],
};
const simpleDivJSON = jsonx.getReactElementFromJSONX.call({ returnJSON: true, }, simpleDiv);
const complexDivJSON = jsonx.getReactElementFromJSONX.call({ returnJSON: true, exposeEval:true, }, complexDiv);
describe('jsonx', function () {
describe('helper functions', () => {
it('should return useGlobalHook', () => {
expect(jsonx.__getUseGlobalHook()).to.be.a('function');
});
it('should return React', () => {
expect(jsonx.__getReact()).to.eql(React);
});
it('should return ReactDOM', () => {
expect(jsonx.__getReactDOM()).to.eql(ReactDOM);
});
});
describe('getReactElementFromJSONX', () => {
it('should return an instance of a react element', () => {
const ReactiveJSON = jsonx.getReactElementFromJSONX(sampleJSONX);
const ReactiveSimpleJSON = jsonx.getReactElementFromJSONX(simpleJSONX);
expect(ReactTestUtils.isElement(ReactiveJSON));
expect(ReactTestUtils.isElement(ReactiveSimpleJSON));
expect(ReactiveJSON).to.be.an('object');
expect(ReactiveJSON).to.haveOwnProperty('$$typeof');
expect(ReactiveJSON).to.haveOwnProperty('type');
expect(ReactiveJSON).to.haveOwnProperty('key');
expect(ReactiveJSON).to.haveOwnProperty('ref');
expect(ReactiveJSON).to.haveOwnProperty('props');
});
it('should handle errors with empty components', () => {
const emptySpanComponent = jsonx.getReactElementFromJSONX({});
const emptySpanComponentDebugged = jsonx.getReactElementFromJSONX.call({ debug: true, }, {}, {});
expect(emptySpanComponent).to.be.an('object');
expect(emptySpanComponentDebugged).to.be.an('object');
expect(emptySpanComponentDebugged.props.children).to.eql('Error: Missing Component Object');
});
it('should throw an error with invalid components', () => {
const loggerSpy = sinon.spy();
expect(jsonx.getReactElementFromJSONX.bind({}, { component: 'somethingInvalid', })).to.throw('Invalid React Component (somethingInvalid)');
try {
jsonx.getReactElementFromJSONX.call({ debug: true, logError: loggerSpy, }, { component: 'somethingInvalid', }, {});
} catch (e) {
expect(loggerSpy.called).to.be.true;
expect(e).to.be.an('error');
}
});
});
describe('getReactElementFromJSON', () => {
it('should return an instance of a react element', () => {
const ReactiveJSON = jsonx.getReactElementFromJSON(sampleJSONXJSON);
const ReactiveSimpleJSON = jsonx.getReactElementFromJSON(simpleJSONXJSON);
expect(ReactTestUtils.isElement(ReactiveJSON)).to.be.true;
expect(ReactTestUtils.isElement(ReactiveSimpleJSON)).to.be.true;
expect(ReactiveJSON).to.be.an('object');
expect(ReactiveJSON).to.haveOwnProperty('$$typeof');
expect(ReactiveJSON).to.haveOwnProperty('type');
expect(ReactiveJSON).to.haveOwnProperty('key');
expect(ReactiveJSON).to.haveOwnProperty('ref');
expect(ReactiveJSON).to.haveOwnProperty('props');
});
});
describe('compile', () => {
it('should convert JSONX to React Element', () => {
const dom = new JSDOM(`<!DOCTYPE html>
<body>
<div id="root"/>
</body>`);
// global.document = dom.window.document;
// global.document.createElement = React.createElement;
// console.log('dom.window',dom.window)
global.window = dom.window;
global.window.React = React;
global.document = global.window.document;
// console.log("dom.window.document.querySelector('#root')",dom.window.document.querySelector('#root'));
const ReactiveJSON = jsonx.compile(sampleJSONXJSON);
const testDOM = ReactTestUtils.renderIntoDocument(ReactiveJSON());
// console.log({testDOM});
expect(ReactTestUtils.isDOMComponent(testDOM)).to.be.true;
expect(ReactiveJSON).to.be.a('function');
// expect(ReactTestUtils.isCompositeComponent(ReactiveJSON)).to.be.true;
});
});
describe('outputJSON', () => {
it('should convert JSONX to JSON', () => {
const compiledJSON = jsonx.outputJSON(simpleDiv);
const compiledJSONXJSON = jsonx.getReactElementFromJSONX.call({ returnJSON: true, }, simpleDiv);
expect(compiledJSON.children).to.eql(compiledJSONXJSON.children);
expect(compiledJSON.type).to.eql(compiledJSONXJSON.type);
});
});
describe('outputJSX', () => {
it('should compile to JSX String', () => {
const JSXString = jsonx.outputJSX(simpleDiv);
expect(JSXString).to.include('title="test">hello</div>');
// console.log({ JSXString, complexJSXString, });
});
});
describe('jsonToJSX', () => {
// const util = require('util');
// console.log(util.inspect({ simpleDivJSON, complexDivJSON, },{depth:20}));
it('should compile to JSX String', () => {
const JSXString = jsonx.jsonToJSX(simpleDivJSON);
const complexJSXString = jsonx.jsonToJSX(complexDivJSON);
expect(JSXString).to.include('title="test">hello</div>');
expect(complexJSXString).to.be.a('string');
// console.log({ JSXString, complexJSXString, });
});
});
describe('outputHTML', () => {
it('should be an alias for jsonxHTMLString', () => {
expect(jsonx.outputHTML).to.eql(jsonx.jsonxHTMLString);
});
});
describe('jsonxHTMLString', () => {
it('should return an HTML string', () => {
const jsonxString = jsonx.jsonxHTMLString({ jsonx: sampleJSONX, });
const dom = new JSDOM(`<!DOCTYPE html><body>${jsonxString}</body>`);
expect(jsonxString).to.be.a('string');
expect(dom.window.document.body.querySelector('p').innerHTML).to.eql('hello world');
expect(dom.window.document.body.querySelector('p').style.color).to.eql('red');
});
});
describe('__express', () => {
const sampleJSONXFilepath = path.resolve('./test/mock/sample.jsonx');
const spantext = 'should render in express';
it('should return an HTML string', (done) => {
jsonx.__express(
sampleJSONXFilepath,
{
spantext,
__boundConfig: {
debug:true,
},
__DOCTYPE:'',
},
((err, renderedString) => {
const dom = new JSDOM(renderedString);
if (renderedString) {
expect(dom.window.document.querySelector('#generatedJSONX').getAttribute('title')).to.eql(spantext);
expect(err).to.be.null;
expect(renderedString).to.be.a('String');
}
done(err);
})
);
});
it('it should handle errors', (done) => {
expect(jsonx.__express.bind()).to.throw;
jsonx.__express(null,null, (err) => {
expect(err).to.be.a('error');
done();
})
});
});
describe('jsonxRender', () => {
before(function () {
this.jsdom = mochaJSDOM();
});
it('should render component inside of querySelector', function () {
const containerDiv = document.createElement('div');
containerDiv.setAttribute('id', 'reactContainer');
document.body.appendChild(containerDiv);
jsonx.jsonxRender({ jsonx: sampleJSONX, querySelector:'#reactContainer', });
expect(document.body.querySelector('p').innerHTML).to.eql('hello world');
expect(document.body.querySelector('p').style.color).to.eql('red');
});
after(function () {
this.jsdom();
});
});
});