mirror of
https://github.com/marko-js/marko.git
synced 2026-01-25 15:03:04 +00:00
[Optimizations] Simplified bookkeeping for component tree A component stack is no longer used Small API improvements Improved how component boundaries are managed Assign keys to all HTML elements and custom tags for better diffing Checking in progress Just build the src when calculating size
238 lines
7.4 KiB
JavaScript
238 lines
7.4 KiB
JavaScript
'use strict';
|
|
const jsdom = require("jsdom").jsdom;
|
|
const defaultDocument = jsdom('<html><body></body></html>');
|
|
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const marko = require('marko');
|
|
const fsExtra = require('fs-extra');
|
|
const domToHTML = require('./domToHTML');
|
|
const domToString = require('./domToString');
|
|
|
|
const expect = require('chai').expect;
|
|
|
|
|
|
|
|
function createAsyncVerifier(main, helpers, out) {
|
|
var events = [];
|
|
var eventsByAwaitInstance = {};
|
|
|
|
var addEventListener = function(event) {
|
|
out.on(event, function(arg) {
|
|
var name = arg.name;
|
|
|
|
if (!eventsByAwaitInstance[name]) {
|
|
eventsByAwaitInstance[name] = [];
|
|
}
|
|
|
|
eventsByAwaitInstance[name].push(event);
|
|
|
|
events.push({
|
|
event: event,
|
|
arg: arg
|
|
});
|
|
});
|
|
};
|
|
|
|
addEventListener('await:begin');
|
|
addEventListener('await:beforeRender');
|
|
addEventListener('await:finish');
|
|
|
|
return {
|
|
verify() {
|
|
if (main.checkEvents) {
|
|
main.checkEvents(events, helpers, out);
|
|
}
|
|
|
|
// Make sure all of the await instances were correctly ended
|
|
Object.keys(eventsByAwaitInstance).forEach(function(name) {
|
|
var events = eventsByAwaitInstance[name];
|
|
expect(events).to.deep.equal([
|
|
'await:begin',
|
|
'await:beforeRender',
|
|
'await:finish'
|
|
]);
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
module.exports = function runRenderTest(dir, helpers, done, options) {
|
|
let output = options.output || 'html';
|
|
|
|
global.document = defaultDocument;
|
|
|
|
let isVDOM = output === 'vdom';
|
|
let checkAsyncEvents = options.checkAsyncEvents === true;
|
|
|
|
let actualDir;
|
|
|
|
require('marko/compiler').configure({ output });
|
|
|
|
if (isVDOM) {
|
|
actualDir = path.join(dir, '../~vdom.skip/' + path.basename(dir));
|
|
|
|
fsExtra.removeSync(actualDir);
|
|
|
|
fsExtra.copySync(dir, actualDir, {
|
|
filter: function(file) {
|
|
if (file.endsWith('.marko.js') || file.indexOf('.generated.') !== -1) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
} else {
|
|
actualDir = dir;
|
|
}
|
|
|
|
let templatePath = path.join(actualDir, 'template.marko');
|
|
let mainPath = path.join(actualDir, 'test.js');
|
|
let main = fs.existsSync(mainPath) ? require(mainPath) : {};
|
|
let loadOptions = main && main.loadOptions;
|
|
|
|
if (isVDOM && main.vdomSkip) {
|
|
return done();
|
|
}
|
|
|
|
var compilerOptions = {
|
|
output: output,
|
|
writeToDisk: main.writeToDisk !== false,
|
|
preserveWhitespace: main.preserveWhitespaceGlobal === true,
|
|
ignoreUnrecognizedTags: main.ignoreUnrecognizedTags === true,
|
|
escapeAtTags: main.escapeAtTags === true
|
|
};
|
|
|
|
require('marko/compiler').configure(compilerOptions);
|
|
|
|
var oldDone = done;
|
|
done = function(err) {
|
|
require('marko/compiler').configure();
|
|
|
|
if (err) {
|
|
return oldDone(err);
|
|
}
|
|
|
|
return oldDone();
|
|
};
|
|
|
|
try {
|
|
if (main.checkError) {
|
|
let e;
|
|
|
|
try {
|
|
marko.load(templatePath, loadOptions);
|
|
} catch(_e) {
|
|
e = _e;
|
|
let errorFile = path.join(actualDir, 'error.txt');
|
|
fs.writeFileSync(errorFile, e.stack.toString(), { encoding: 'utf8' });
|
|
}
|
|
|
|
if (!e) {
|
|
throw new Error('Error expected');
|
|
}
|
|
|
|
main.checkError(e);
|
|
return done();
|
|
} else {
|
|
let template = marko.load(templatePath, loadOptions);
|
|
let templateData = Object.assign({}, main.templateData || {});
|
|
|
|
let out = template.createOut();
|
|
let asyncEventsVerifier;
|
|
|
|
if (checkAsyncEvents) {
|
|
asyncEventsVerifier = createAsyncVerifier(main, helpers, out);
|
|
}
|
|
|
|
out.on('error', done);
|
|
out.on('finish', function(result) {
|
|
var renderOutput = result.getOutput();
|
|
|
|
if (isVDOM) {
|
|
var getExpectedHtml = function(callback) {
|
|
var expectedHtml;
|
|
try {
|
|
expectedHtml = fs.readFileSync(path.join(dir, 'vdom-expected.html'), { encoding: 'utf8'});
|
|
} catch(e) {}
|
|
|
|
if (expectedHtml) {
|
|
return callback(null, expectedHtml);
|
|
}
|
|
|
|
require('marko/compiler').configure(Object.assign({}, compilerOptions, { output: 'html' }));
|
|
|
|
require('marko/runtime/vdom/AsyncVDOMBuilder').prototype.___document = defaultDocument;
|
|
global.document = defaultDocument;
|
|
|
|
|
|
|
|
let htmlTemplatePath = path.join(dir, 'template.marko');
|
|
let htmlTemplate = marko.load(htmlTemplatePath);
|
|
let htmlMainPath = path.join(dir, 'test.js');
|
|
let htmlMain = fs.existsSync(htmlMainPath) ? require(htmlMainPath) : {};
|
|
|
|
htmlTemplate.render(htmlMain.templateData || {}, function(err, html) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
let document = jsdom('<html><body>' + html + '</body></html>');
|
|
let expectedHtml = domToString(document.body, { childrenOnly: true });
|
|
|
|
callback(null, expectedHtml);
|
|
});
|
|
};
|
|
|
|
|
|
getExpectedHtml(function(err, expectedHtml) {
|
|
if (err) {
|
|
return done(err);
|
|
}
|
|
|
|
fs.writeFileSync(path.join(dir, 'vdom-expected.generated.html'), expectedHtml, { encoding: 'utf8' });
|
|
|
|
|
|
// let actualizedDom = vdomTree.actualize(defaultDocument);
|
|
|
|
// NOTE: We serialie the virtual DOM tree into an HTML string and reparse so that we can
|
|
// normalize the text
|
|
let actualNode = result.getNode();
|
|
|
|
|
|
let vdomHtml = domToHTML(actualNode);
|
|
|
|
let vdomRealDocument = jsdom('<html><body>' + vdomHtml + '</body></html>');
|
|
let vdomString = domToString(vdomRealDocument.body, { childrenOnly: true });
|
|
helpers.compare(vdomString, 'vdom-', '.generated.html');
|
|
|
|
if (checkAsyncEvents) {
|
|
asyncEventsVerifier.verify();
|
|
}
|
|
|
|
done();
|
|
});
|
|
} else {
|
|
let html = renderOutput;
|
|
if (main.checkHtml) {
|
|
fs.writeFileSync(path.join(dir, 'actual.html'), html, { encoding: 'utf8' });
|
|
main.checkHtml(html);
|
|
} else {
|
|
helpers.compare(html, '.html');
|
|
}
|
|
|
|
if (checkAsyncEvents) {
|
|
asyncEventsVerifier.verify();
|
|
}
|
|
|
|
done();
|
|
}
|
|
});
|
|
|
|
template.render(templateData, out).end();
|
|
}
|
|
} finally {
|
|
require('marko/compiler').configure();
|
|
}
|
|
};
|