mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Fixes #176 - Marko v3: Migrate async taglib
This commit is contained in:
parent
90234c5bb1
commit
70716e2209
@ -143,6 +143,7 @@ exports.taglibLoader = require('./taglib-loader');
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/core/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/layout/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/html/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/async/marko-taglib.json'));
|
||||
|
||||
/*
|
||||
exports.Taglib = require('./Taglib');
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 eBay Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
function AsyncFragmentErrorNode(props) {
|
||||
AsyncFragmentErrorNode.$super.call(this, 'async-fragment-error');
|
||||
if (props) {
|
||||
this.setProperties(props);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFragmentErrorNode.nodeType = 'element';
|
||||
|
||||
AsyncFragmentErrorNode.prototype = {
|
||||
doGenerateCode: function (template) {
|
||||
throw new Error('Illegal State. This node should have been removed');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AsyncFragmentErrorNode;
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 eBay Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
function AsyncFragmentPlaceholderNode(props) {
|
||||
AsyncFragmentPlaceholderNode.$super.call(this, 'async-fragment-placeholder');
|
||||
if (props) {
|
||||
this.setProperties(props);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFragmentPlaceholderNode.nodeType = 'element';
|
||||
|
||||
AsyncFragmentPlaceholderNode.prototype = {
|
||||
doGenerateCode: function (template) {
|
||||
throw new Error('Illegal State. This node should have been removed');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AsyncFragmentPlaceholderNode;
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 eBay Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
function AsyncFragmentTimeoutNode(props) {
|
||||
AsyncFragmentTimeoutNode.$super.call(this, 'async-fragment-timeout');
|
||||
if (props) {
|
||||
this.setProperties(props);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFragmentTimeoutNode.nodeType = 'element';
|
||||
|
||||
AsyncFragmentTimeoutNode.prototype = {
|
||||
doGenerateCode: function (template) {
|
||||
throw new Error('Illegal State. This node should have been removed');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AsyncFragmentTimeoutNode;
|
||||
@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function transform(node, compiler, template) {
|
||||
|
||||
var asyncFragmentNode = node.parentNode;
|
||||
|
||||
if (!asyncFragmentNode) {
|
||||
template.addError('<async-fragment-error> should be nested directly below an <async-fragment> tag.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the node from the tree
|
||||
node.detach();
|
||||
|
||||
asyncFragmentNode.setProperty('errorMessage', node.getBodyContentExpression(template));
|
||||
};
|
||||
25
taglibs/async/async-fragment-nested-tag-transformer.js
Normal file
25
taglibs/async/async-fragment-nested-tag-transformer.js
Normal file
@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function transform(el, context) {
|
||||
var parentNode = el.parentNode;
|
||||
|
||||
if (parentNode.tagName !== 'async-fragment') {
|
||||
context.addError(el, 'The <' + el.tagName + '> should be nested within an <async-fragment> tag.');
|
||||
return;
|
||||
}
|
||||
|
||||
var targetProp;
|
||||
|
||||
if (el.tagName === 'async-fragment-error') {
|
||||
targetProp = 'renderError';
|
||||
} else if (el.tagName === 'async-fragment-timeout') {
|
||||
targetProp = 'renderTimeout';
|
||||
} else if (el.tagName === 'async-fragment-placeholder') {
|
||||
targetProp = 'renderPlaceholder';
|
||||
}
|
||||
|
||||
var builder = context.builder;
|
||||
|
||||
parentNode.setAttributeValue(targetProp, builder.renderBodyFunction(el.body));
|
||||
el.detach();
|
||||
};
|
||||
@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function transform(node, compiler, template) {
|
||||
|
||||
var asyncFragmentNode = node.parentNode;
|
||||
|
||||
// Remove the node from the tree
|
||||
node.detach();
|
||||
|
||||
asyncFragmentNode.setProperty('placeholder', node.getBodyContentExpression(template));
|
||||
};
|
||||
@ -1,50 +1,103 @@
|
||||
'use strict';
|
||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
||||
module.exports = function transform(node, compiler, template) {
|
||||
var varName = node.getAttribute('var') || node.getAttribute('data-provider') || node.getAttribute('dependency');
|
||||
|
||||
var isObjectEmpty = require('raptor-util/isObjectEmpty');
|
||||
|
||||
module.exports = function transform(el, context) {
|
||||
var varName = el.getAttributeValue('var');
|
||||
if (varName) {
|
||||
if (!varNameRegExp.test(varName)) {
|
||||
node.addError('Invalid variable name of "' + varName + '"');
|
||||
if (varName.type !== 'Literal' || typeof varName.value !== 'string') {
|
||||
context.addError(el, 'The "var" attribute value should be a string');
|
||||
return;
|
||||
}
|
||||
|
||||
varName = varName.value;
|
||||
|
||||
if (!context.util.isValidJavaScriptIdentifier(varName)) {
|
||||
context.addError(el, 'The "var" attribute value should be a valid JavaScript identifier');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
node.addError('Either "var" or "data-provider" is required');
|
||||
context.addError(el, 'The "var" attribute is required');
|
||||
return;
|
||||
}
|
||||
|
||||
var attrs = el.getAttributes().concat([]);
|
||||
var arg = {};
|
||||
var builder = context.builder;
|
||||
|
||||
var argProps = [];
|
||||
var propsToRemove = [];
|
||||
|
||||
var hasNameProp = false;
|
||||
node.forEachProperty(function (name, value) {
|
||||
if (name.startsWith('arg-')) {
|
||||
var argName = name.substring('arg-'.length);
|
||||
argProps.push(JSON.stringify(argName) + ': ' + value);
|
||||
propsToRemove.push(name);
|
||||
} else if (name === 'name') {
|
||||
hasNameProp = true;
|
||||
attrs.forEach((attr) => {
|
||||
var attrName = attr.name;
|
||||
if (attrName.startsWith('arg-')) {
|
||||
let argName = attrName.substring('arg-'.length);
|
||||
arg[argName] = attr.value;
|
||||
el.removeAttribute(attrName);
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasNameProp) {
|
||||
var name = node.getAttribute('data-provider');
|
||||
node.setProperty('_name', name);
|
||||
var dataProviderAttr = el.getAttribute('data-provider');
|
||||
if (!dataProviderAttr) {
|
||||
context.addError(el, 'The "data-provider" attribute is required');
|
||||
return;
|
||||
}
|
||||
|
||||
propsToRemove.forEach(function (propName) {
|
||||
node.removeProperty(propName);
|
||||
});
|
||||
var argString;
|
||||
if (argProps.length) {
|
||||
argString = '{' + argProps.join(', ') + '}';
|
||||
if (dataProviderAttr.value == null) {
|
||||
context.addError(el, 'A value is required for the "data-provider" attribute');
|
||||
return;
|
||||
}
|
||||
var arg = node.getProperty('arg');
|
||||
|
||||
if (dataProviderAttr.value.type == 'Literal') {
|
||||
context.addError(el, 'The "data-provider" attribute value should not be a literal ' + (typeof dataProviderAttr.value.value));
|
||||
return;
|
||||
}
|
||||
|
||||
var name = el.getAttributeValue('name');
|
||||
if (name == null) {
|
||||
el.setAttributeValue('_name', builder.literal(dataProviderAttr.rawValue));
|
||||
}
|
||||
|
||||
if (el.hasAttribute('arg')) {
|
||||
if (isObjectEmpty(arg)) {
|
||||
arg = el.getAttributeValue('arg');
|
||||
} else {
|
||||
let mergeVar = context.addStaticVar('__merge', '__helpers.m');
|
||||
arg = builder.functionCall(mergeVar, [
|
||||
builder.literal(arg), // Input props from the attributes take precedence
|
||||
el.getAttributeValue('arg')
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (isObjectEmpty(arg)) {
|
||||
arg = null;
|
||||
} else {
|
||||
arg = builder.literal(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg) {
|
||||
var extendFuncName = template.getStaticHelperFunction('extend', 'xt');
|
||||
argString = extendFuncName + '(' + arg + ', ' + argString + ')';
|
||||
el.setAttributeValue('arg', arg);
|
||||
}
|
||||
if (argString) {
|
||||
node.setProperty('arg', template.makeExpression(argString));
|
||||
|
||||
var timeoutMessage = el.getAttributeValue('timeout-message');
|
||||
if (timeoutMessage) {
|
||||
el.removeAttribute('timeout-message');
|
||||
el.setAttributeValue('renderTimeout', builder.renderBodyFunction([
|
||||
builder.text(timeoutMessage)
|
||||
]));
|
||||
}
|
||||
|
||||
var errorMessage = el.getAttributeValue('error-message');
|
||||
if (errorMessage) {
|
||||
el.removeAttribute('error-message');
|
||||
el.setAttributeValue('renderError', builder.renderBodyFunction([
|
||||
builder.text(errorMessage)
|
||||
]));
|
||||
}
|
||||
|
||||
var placeholder = el.getAttributeValue('placeholder');
|
||||
if (placeholder) {
|
||||
el.removeAttribute('placeholder');
|
||||
el.setAttributeValue('renderPlaceholder', builder.renderBodyFunction([
|
||||
builder.text(placeholder)
|
||||
]));
|
||||
}
|
||||
};
|
||||
|
||||
@ -77,7 +77,7 @@ module.exports = function render(input, out) {
|
||||
var name = input.name || input._name;
|
||||
var scope = input.scope || this;
|
||||
|
||||
function renderBody(err, data, timeoutMessage) {
|
||||
function renderBody(err, data, renderTimeout) {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
@ -94,14 +94,14 @@ module.exports = function render(input, out) {
|
||||
});
|
||||
|
||||
if (err) {
|
||||
if (input.errorMessage) {
|
||||
if (input.renderError) {
|
||||
console.error('Async fragment (' + name + ') failed. Error:', (err.stack || err));
|
||||
targetOut.write(input.errorMessage);
|
||||
input.renderError(targetOut);
|
||||
} else {
|
||||
targetOut.error(err);
|
||||
}
|
||||
} else if (timeoutMessage) {
|
||||
asyncOut.write(timeoutMessage);
|
||||
} else if (renderTimeout) {
|
||||
renderTimeout(asyncOut);
|
||||
} else {
|
||||
if (input.renderBody) {
|
||||
input.renderBody(targetOut, data);
|
||||
@ -135,7 +135,7 @@ module.exports = function render(input, out) {
|
||||
|
||||
if (!done) {
|
||||
var timeout = input.timeout;
|
||||
var timeoutMessage = input.timeoutMessage;
|
||||
var renderTimeout = input.renderTimeout;
|
||||
|
||||
if (timeout == null) {
|
||||
timeout = 10000;
|
||||
@ -147,9 +147,9 @@ module.exports = function render(input, out) {
|
||||
timeoutId = setTimeout(function() {
|
||||
var message = 'Async fragment (' + name + ') timed out after ' + timeout + 'ms';
|
||||
|
||||
if (timeoutMessage) {
|
||||
if (renderTimeout) {
|
||||
logger.error(message);
|
||||
renderBody(null, null, timeoutMessage);
|
||||
renderBody(null, null, renderTimeout);
|
||||
} else {
|
||||
renderBody(new Error(message));
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function transform(node, compiler, template) {
|
||||
|
||||
var asyncFragmentNode = node.parentNode;
|
||||
|
||||
// Remove the node from the tree
|
||||
node.detach();
|
||||
|
||||
asyncFragmentNode.setProperty('timeoutMessage', node.getBodyContentExpression(template));
|
||||
};
|
||||
@ -1,76 +1,62 @@
|
||||
{
|
||||
"tags": {
|
||||
"async-fragment": {
|
||||
"renderer": "./async-fragment-tag",
|
||||
"attributes": {
|
||||
"data-provider": {
|
||||
"type": "expression"
|
||||
},
|
||||
"arg": {
|
||||
"type": "expression",
|
||||
"preserve-name": true
|
||||
},
|
||||
"arg-*": {
|
||||
"pattern": true,
|
||||
"type": "string",
|
||||
"preserve-name": true
|
||||
},
|
||||
"var": {
|
||||
"type": "identifier"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer"
|
||||
},
|
||||
"method": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeout-message": {
|
||||
"type": "string"
|
||||
},
|
||||
"error-message": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of async fragment (for debugging purposes only)"
|
||||
},
|
||||
"client-reorder": {
|
||||
"type": "boolean",
|
||||
"description": "Use JavaScript on client to move async fragment into the proper place."
|
||||
},
|
||||
"scope": {
|
||||
"type": "expression"
|
||||
},
|
||||
"show-after": {
|
||||
"type": "string"
|
||||
},
|
||||
"placeholder": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"vars": [
|
||||
{
|
||||
"name-from-attribute": "var"
|
||||
}
|
||||
],
|
||||
"transformer": "./async-fragment-tag-transformer"
|
||||
"<async-fragment>": {
|
||||
"renderer": "./async-fragment-tag",
|
||||
"@data-provider": "expression",
|
||||
"@arg": {
|
||||
"type": "expression",
|
||||
"preserve-name": true
|
||||
},
|
||||
"async-fragments": {
|
||||
"renderer": "./async-fragments-tag",
|
||||
"attributes": {
|
||||
}
|
||||
"@arg-*": {
|
||||
"pattern": true,
|
||||
"type": "string",
|
||||
"preserve-name": true
|
||||
},
|
||||
"async-fragment-placeholder": {
|
||||
"node-class": "./AsyncFragmentPlaceholderNode",
|
||||
"transformer": "./async-fragment-placeholder-tag-transformer"
|
||||
"@var": "identifier",
|
||||
|
||||
"@method": "string",
|
||||
|
||||
"@timeout": "integer",
|
||||
|
||||
"@timeout-message": "string",
|
||||
"@error-message": "string",
|
||||
"@placeholder": "string",
|
||||
|
||||
"@renderTimeout": "function",
|
||||
"@renderError": "function",
|
||||
"@renderPlaceholder": "function",
|
||||
|
||||
"@name": {
|
||||
"type": "string",
|
||||
"description": "Name of async fragment"
|
||||
},
|
||||
"async-fragment-timeout": {
|
||||
"node-class": "./AsyncFragmentTimeoutNode",
|
||||
"transformer": "./async-fragment-timeout-tag-transformer"
|
||||
"@_name": "string",
|
||||
"@client-reorder": {
|
||||
"type": "boolean",
|
||||
"description": "Use JavaScript on client to move async fragment into the proper place."
|
||||
},
|
||||
"async-fragment-error": {
|
||||
"node-class": "./AsyncFragmentErrorNode",
|
||||
"transformer": "./async-fragment-error-tag-transformer"
|
||||
}
|
||||
"@scope": {
|
||||
"type": "expression",
|
||||
"description": "The value of 'this' when invoking the data provider function (N/A with promises)"
|
||||
},
|
||||
"@show-after": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"vars": [{
|
||||
"name-from-attribute": "var"
|
||||
}],
|
||||
"transformer": "./async-fragment-tag-transformer"
|
||||
},
|
||||
"<async-fragments>": {
|
||||
"renderer": "./async-fragments-tag"
|
||||
},
|
||||
"<async-fragment-placeholder>": {
|
||||
"transformer": "./async-fragment-nested-tag-transformer"
|
||||
},
|
||||
"<async-fragment-timeout>": {
|
||||
"transformer": "./async-fragment-nested-tag-transformer"
|
||||
},
|
||||
"<async-fragment-error>": {
|
||||
"transformer": "./async-fragment-nested-tag-transformer"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,20 +4,44 @@ chai.config.includeStack = true;
|
||||
var path = require('path');
|
||||
var marko = require('../');
|
||||
var autotest = require('./autotest');
|
||||
var fs = require('fs');
|
||||
|
||||
describe('render-async', function() {
|
||||
var autoTestDir = path.join(__dirname, 'fixtures/render-async/autotest');
|
||||
require('../node-require').install();
|
||||
|
||||
describe('render', function() {
|
||||
var autoTestDir = path.join(__dirname, 'fixtures/async-render/autotest');
|
||||
|
||||
autotest.scanDir(
|
||||
autoTestDir,
|
||||
function run(dir) {
|
||||
function run(dir, callback) {
|
||||
var templatePath = path.join(dir, 'template.marko');
|
||||
var mainPath = path.join(dir, 'test.js');
|
||||
var template = marko.load(templatePath);
|
||||
var main = require(mainPath);
|
||||
var templateData = main.templateData || {};
|
||||
var html = template.renderSync(templateData);
|
||||
return html;
|
||||
|
||||
var main = fs.existsSync(mainPath) ? require(mainPath) : {};
|
||||
var loadOptions = main && main.loadOptions;
|
||||
|
||||
if (main.checkError) {
|
||||
var e;
|
||||
|
||||
try {
|
||||
marko.load(templatePath, loadOptions);
|
||||
} catch(_e) {
|
||||
e = _e;
|
||||
}
|
||||
|
||||
if (!e) {
|
||||
throw new Error('Error expected');
|
||||
}
|
||||
|
||||
main.checkError(e);
|
||||
return callback(null, '$PASS$');
|
||||
} else {
|
||||
var template = marko.load(templatePath, loadOptions);
|
||||
var templateData = main.templateData || {};
|
||||
template.render(templateData, function(err, html) {
|
||||
callback(err, html);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
compareExtension: '.html'
|
||||
|
||||
103
test/autotest.js
103
test/autotest.js
@ -1,56 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var enabledTest = process.env.TEST;
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
|
||||
function autoTest(name, dir, run, options) {
|
||||
function autoTest(name, dir, run, options, done) {
|
||||
var compareExtension = (options && options.compareExtension) || '.js';
|
||||
var isJSON = compareExtension === '.json';
|
||||
|
||||
var actualPath = path.join(dir, 'actual' + compareExtension);
|
||||
var expectedPath = path.join(dir, 'expected' + compareExtension);
|
||||
|
||||
function verify(actual) {
|
||||
if (actual === '$PASS$') {
|
||||
return;
|
||||
}
|
||||
|
||||
var actualJSON = isJSON ? JSON.stringify(actual, null, 2) : null;
|
||||
|
||||
fs.writeFileSync(
|
||||
actualPath,
|
||||
isJSON ? actualJSON : actual,
|
||||
{encoding: 'utf8'});
|
||||
|
||||
var expected;
|
||||
|
||||
try {
|
||||
expected = fs.readFileSync(expectedPath, { encoding: 'utf8' });
|
||||
} catch(e) {
|
||||
expected = isJSON ? '"TBD"' : 'TBD';
|
||||
fs.writeFileSync(expectedPath, expected, {encoding: 'utf8'});
|
||||
}
|
||||
|
||||
var expectedJSON;
|
||||
|
||||
if (isJSON) {
|
||||
expectedJSON = expected;
|
||||
expected = JSON.parse(expectedJSON);
|
||||
}
|
||||
|
||||
assert.deepEqual(
|
||||
(isJSON ? JSON.parse(actualJSON) : actual),
|
||||
expected,
|
||||
'Unexpected output for "' + name + '":\nEXPECTED (' + expectedPath + '):\n---------\n' +
|
||||
(isJSON ? expectedJSON : expected) +
|
||||
'\n---------\nACTUAL (' + actualPath + '):\n---------\n' +
|
||||
(isJSON ? actualJSON : actual) +
|
||||
'\n---------');
|
||||
}
|
||||
|
||||
try {
|
||||
fs.unlinkSync(actualPath);
|
||||
} catch(e) {}
|
||||
|
||||
if (done) {
|
||||
// Async test
|
||||
run(dir, function(err, actual) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var actual = run(dir);
|
||||
if (actual === '$PASS$') {
|
||||
return;
|
||||
verify(actual);
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
let actual = run(dir);
|
||||
verify(actual);
|
||||
}
|
||||
|
||||
var actualJSON = isJSON ? JSON.stringify(actual, null, 2) : null;
|
||||
|
||||
fs.writeFileSync(
|
||||
actualPath,
|
||||
isJSON ? actualJSON : actual,
|
||||
{encoding: 'utf8'});
|
||||
|
||||
var expected;
|
||||
|
||||
try {
|
||||
expected = fs.readFileSync(expectedPath, { encoding: 'utf8' });
|
||||
} catch(e) {
|
||||
expected = isJSON ? '"TBD"' : 'TBD';
|
||||
fs.writeFileSync(expectedPath, expected, {encoding: 'utf8'});
|
||||
}
|
||||
|
||||
var expectedJSON;
|
||||
|
||||
if (isJSON) {
|
||||
expectedJSON = expected;
|
||||
expected = JSON.parse(expectedJSON);
|
||||
}
|
||||
|
||||
assert.deepEqual(
|
||||
(isJSON ? JSON.parse(actualJSON) : actual),
|
||||
expected,
|
||||
'Unexpected output for "' + name + '":\nEXPECTED (' + expectedPath + '):\n---------\n' +
|
||||
(isJSON ? expectedJSON : expected) +
|
||||
'\n---------\nACTUAL (' + actualPath + '):\n---------\n' +
|
||||
(isJSON ? actualJSON : actual) +
|
||||
'\n---------');
|
||||
}
|
||||
|
||||
exports.scanDir = function(autoTestDir, run, options) {
|
||||
@ -76,9 +93,17 @@ exports.scanDir = function(autoTestDir, run, options) {
|
||||
|
||||
var dir = path.join(autoTestDir, name);
|
||||
|
||||
itFunc(`[${name}] `, function() {
|
||||
autoTest(name, dir, run, options);
|
||||
});
|
||||
if (run.length === 2) {
|
||||
itFunc(`[${name}] `, function(done) {
|
||||
autoTest(name, dir, run, options, done);
|
||||
});
|
||||
} else {
|
||||
itFunc(`[${name}] `, function() {
|
||||
autoTest(name, dir, run, options);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
2
test/fixtures/api-tests/hello-async.marko
vendored
2
test/fixtures/api-tests/hello-async.marko
vendored
@ -1,3 +1,3 @@
|
||||
<async-fragment data-provider="data.nameDataProvider" var="name">
|
||||
<async-fragment data-provider=data.nameDataProvider var="name">
|
||||
Hello ${name}!
|
||||
</async-fragment>
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
<ul>
|
||||
<li for="userId in [0, 1, 2, 3]">
|
||||
<async-fragment data-provider="data.userInfo" var="userInfo" arg-userId="$userId">
|
||||
<ul>
|
||||
<li>
|
||||
<b>Name:</b> $userInfo.name
|
||||
</li>
|
||||
<li>
|
||||
<b>Gender:</b> $userInfo.gender
|
||||
</li>
|
||||
<li>
|
||||
<b>Occupation:</b> $userInfo.occupation
|
||||
</li>
|
||||
</ul>
|
||||
</async-fragment>
|
||||
</li>
|
||||
</ul>
|
||||
@ -1,14 +0,0 @@
|
||||
<async-fragment data-provider="data.outer" var="outer" client-reorder>
|
||||
<h1>Outer</h1>
|
||||
|
||||
<async-fragment data-provider="data.inner1" var="inner1" client-reorder>
|
||||
<h2>Inner 1</h2>
|
||||
</async-fragment>
|
||||
|
||||
<async-fragment data-provider="data.inner2" var="inner2" client-reorder>
|
||||
<h2>Inner 2</h2>
|
||||
</async-fragment>
|
||||
|
||||
</async-fragment>
|
||||
|
||||
<async-fragments/>
|
||||
@ -1,7 +0,0 @@
|
||||
<async-fragment data-provider="data.contextData" var="d1">
|
||||
$d1.name
|
||||
</async-fragment>
|
||||
|
||||
<async-fragment data-provider="data.sharedData" var="d2">
|
||||
$d2.name
|
||||
</async-fragment>
|
||||
@ -1,3 +0,0 @@
|
||||
<async-fragment data-provider="data.userInfo" var="userInfo">
|
||||
Hello $userInfo.name
|
||||
</async-fragment>
|
||||
@ -1,33 +0,0 @@
|
||||
exports.tests = [
|
||||
{
|
||||
templateData: {
|
||||
userInfo: function() {
|
||||
var deferred = require('raptor-promises').defer();
|
||||
setTimeout(function() {
|
||||
deferred.resolve({
|
||||
name: 'John'
|
||||
});
|
||||
}, 200);
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
templateData: {
|
||||
userInfo: function() {
|
||||
return {
|
||||
name: 'John'
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
templateData: {
|
||||
userInfo: function(arg, done) {
|
||||
done(null, {
|
||||
name: 'John'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1,7 +0,0 @@
|
||||
<def function="asyncMacro(num)">
|
||||
$num
|
||||
</def>1
|
||||
<async-fragment data-provider="data.D1" var="D1">
|
||||
<invoke function="asyncMacro" num="2"/>
|
||||
</async-fragment>
|
||||
3
|
||||
@ -1,17 +0,0 @@
|
||||
1
|
||||
<async-fragment data-provider="data.D1" var="d1">
|
||||
2
|
||||
<async-fragment data-provider="data.D2" var="d2">
|
||||
3
|
||||
</async-fragment>
|
||||
4
|
||||
<async-fragment data-provider="data.D3" var="d3">
|
||||
5
|
||||
</async-fragment>
|
||||
6
|
||||
</async-fragment>
|
||||
7
|
||||
<async-fragment data-provider="data.D4" var="d4">
|
||||
8
|
||||
</async-fragment>
|
||||
9
|
||||
@ -1,33 +0,0 @@
|
||||
1
|
||||
<async-fragment data-provider="data.D1" var="d1">
|
||||
2
|
||||
<async-fragment data-provider="data.D2" var="d2">
|
||||
3
|
||||
</async-fragment>
|
||||
4
|
||||
<async-fragment data-provider="data.D3" var="d3">
|
||||
5
|
||||
<async-fragment data-provider="data.D4" var="d4">
|
||||
6
|
||||
</async-fragment>
|
||||
7
|
||||
</async-fragment>
|
||||
8
|
||||
</async-fragment>
|
||||
9
|
||||
<async-fragment data-provider="data.D5" var="d5">
|
||||
10
|
||||
<async-fragment data-provider="data.D6" var="d6">
|
||||
11
|
||||
</async-fragment>
|
||||
12
|
||||
<async-fragment data-provider="data.D7" var="d7">
|
||||
13
|
||||
</async-fragment>
|
||||
14
|
||||
<async-fragment data-provider="data.D7" var="d7">
|
||||
15
|
||||
</async-fragment>
|
||||
16
|
||||
</async-fragment>
|
||||
17
|
||||
@ -1,3 +0,0 @@
|
||||
<async-fragment data-provider="data.promiseData" var="promiseData">
|
||||
$promiseData
|
||||
</async-fragment>
|
||||
@ -1,3 +0,0 @@
|
||||
<async-fragment data-provider="data.userInfo" var="userInfo" timeout="100" timeout-message="Server is busy!">
|
||||
Hello World
|
||||
</async-fragment>
|
||||
@ -1,9 +0,0 @@
|
||||
<async-fragment data-provider="data.userInfo" var="user" timeout="300">
|
||||
<async-fragment-timeout>
|
||||
1-A timeout has occurred!
|
||||
</async-fragment-timeout>
|
||||
1
|
||||
</async-fragment>
|
||||
<async-fragment data-provider="data.userInfo" var="user" timeout-message="2-A timeout has occurred!" timeout="300">
|
||||
2
|
||||
</async-fragment>
|
||||
@ -1,3 +0,0 @@
|
||||
<var name="helper" value="data.helper"/>
|
||||
|
||||
A<invoke function="helper.beginAsync(out)"/>C
|
||||
17
test/fixtures/async-render/autotest/async-fragment-args/template.marko
vendored
Normal file
17
test/fixtures/async-render/autotest/async-fragment-args/template.marko
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<ul>
|
||||
<li for(userId in [0, 1, 2, 3])>
|
||||
<async-fragment data-provider=data.userInfo var="userInfo" arg-userId=userId>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Name:</b> ${userInfo.name}
|
||||
</li>
|
||||
<li>
|
||||
<b>Gender:</b> ${userInfo.gender}
|
||||
</li>
|
||||
<li>
|
||||
<b>Occupation:</b> ${userInfo.occupation}
|
||||
</li>
|
||||
</ul>
|
||||
</async-fragment>
|
||||
</li>
|
||||
</ul>
|
||||
14
test/fixtures/async-render/autotest/async-fragment-client-reorder/template.marko
vendored
Normal file
14
test/fixtures/async-render/autotest/async-fragment-client-reorder/template.marko
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<async-fragment data-provider=data.outer var="outer" client-reorder>
|
||||
<h1>Outer</h1>
|
||||
|
||||
<async-fragment data-provider=data.inner1 var="inner1" client-reorder>
|
||||
<h2>Inner 1</h2>
|
||||
</async-fragment>
|
||||
|
||||
<async-fragment data-provider=data.inner2 var="inner2" client-reorder>
|
||||
<h2>Inner 2</h2>
|
||||
</async-fragment>
|
||||
|
||||
</async-fragment>
|
||||
|
||||
<async-fragments/>
|
||||
7
test/fixtures/async-render/autotest/async-fragment-data-providers/template.marko
vendored
Normal file
7
test/fixtures/async-render/autotest/async-fragment-data-providers/template.marko
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<async-fragment data-provider=data.contextData var="d1">
|
||||
${d1.name}
|
||||
</async-fragment>
|
||||
|
||||
<async-fragment data-provider=data.sharedData var="d2">
|
||||
${d2.name}
|
||||
</async-fragment>
|
||||
7
test/fixtures/async-render/autotest/async-fragment-error-message-attr/template.marko
vendored
Normal file
7
test/fixtures/async-render/autotest/async-fragment-error-message-attr/template.marko
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
BEFORE
|
||||
<async-fragment data-provider=data.testDataProvider var="testData" error-message="something went wrong!">
|
||||
Success!
|
||||
</async-fragment>
|
||||
AFTER
|
||||
---
|
||||
1
test/fixtures/async-render/autotest/async-fragment-error/expected.html
vendored
Normal file
1
test/fixtures/async-render/autotest/async-fragment-error/expected.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
BEFORE something went wrong! AFTER
|
||||
@ -1,9 +1,11 @@
|
||||
---
|
||||
BEFORE
|
||||
<async-fragment data-provider="data.testDataProvider" var="testData">
|
||||
<async-fragment data-provider=data.testDataProvider var="testData">
|
||||
Success!
|
||||
|
||||
<async-fragment-error>
|
||||
something went wrong!
|
||||
</async-fragment-error>
|
||||
</async-fragment>
|
||||
AFTER
|
||||
AFTER
|
||||
---
|
||||
8
test/fixtures/async-render/autotest/async-fragment-error/test.js
vendored
Normal file
8
test/fixtures/async-render/autotest/async-fragment-error/test.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
exports.templateData = {
|
||||
testDataProvider: function(done) {
|
||||
setTimeout(function() {
|
||||
var err = new Error('Something went wrong!');
|
||||
done(err, null);
|
||||
}, 200);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
<async-fragment data-provider=data.userInfo var="userInfo">
|
||||
Hello ${userInfo.name}
|
||||
</async-fragment>
|
||||
7
test/fixtures/async-render/autotest/async-fragment-function-data-provider-callback/test.js
vendored
Normal file
7
test/fixtures/async-render/autotest/async-fragment-function-data-provider-callback/test.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
exports.templateData = {
|
||||
userInfo: function(arg, done) {
|
||||
done(null, {
|
||||
name: 'John'
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
Hello John
|
||||
@ -0,0 +1,3 @@
|
||||
<async-fragment data-provider=data.userInfo var="userInfo">
|
||||
Hello ${userInfo.name}
|
||||
</async-fragment>
|
||||
11
test/fixtures/async-render/autotest/async-fragment-function-data-provider-return-promise/test.js
vendored
Normal file
11
test/fixtures/async-render/autotest/async-fragment-function-data-provider-return-promise/test.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
exports.templateData = {
|
||||
userInfo: function() {
|
||||
var deferred = require('raptor-promises').defer();
|
||||
setTimeout(function() {
|
||||
deferred.resolve({
|
||||
name: 'John'
|
||||
});
|
||||
}, 200);
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
1
test/fixtures/async-render/autotest/async-fragment-function-data-provider-sync/expected.html
vendored
Normal file
1
test/fixtures/async-render/autotest/async-fragment-function-data-provider-sync/expected.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
Hello John
|
||||
@ -0,0 +1,3 @@
|
||||
<async-fragment data-provider=data.userInfo var="userInfo">
|
||||
Hello ${userInfo.name}
|
||||
</async-fragment>
|
||||
7
test/fixtures/async-render/autotest/async-fragment-function-data-provider-sync/test.js
vendored
Normal file
7
test/fixtures/async-render/autotest/async-fragment-function-data-provider-sync/test.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
exports.templateData = {
|
||||
userInfo: function() {
|
||||
return {
|
||||
name: 'John'
|
||||
};
|
||||
}
|
||||
};
|
||||
9
test/fixtures/async-render/autotest/async-fragment-macros/template.marko
vendored
Normal file
9
test/fixtures/async-render/autotest/async-fragment-macros/template.marko
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
<macro asyncMacro(num)>
|
||||
${num}
|
||||
</macro>1
|
||||
<async-fragment data-provider=data.D1 var="D1">
|
||||
<asyncMacro num=2/>
|
||||
</async-fragment>
|
||||
3
|
||||
---
|
||||
19
test/fixtures/async-render/autotest/async-fragment-ordering/template.marko
vendored
Normal file
19
test/fixtures/async-render/autotest/async-fragment-ordering/template.marko
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
1
|
||||
<async-fragment data-provider=data.D1 var="d1">
|
||||
2
|
||||
<async-fragment data-provider=data.D2 var="d2">
|
||||
3
|
||||
</async-fragment>
|
||||
4
|
||||
<async-fragment data-provider=data.D3 var="d3">
|
||||
5
|
||||
</async-fragment>
|
||||
6
|
||||
</async-fragment>
|
||||
7
|
||||
<async-fragment data-provider=data.D4 var="d4">
|
||||
8
|
||||
</async-fragment>
|
||||
9
|
||||
---
|
||||
35
test/fixtures/async-render/autotest/async-fragment-ordering2/template.marko
vendored
Normal file
35
test/fixtures/async-render/autotest/async-fragment-ordering2/template.marko
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
1
|
||||
<async-fragment data-provider=data.D1 var="d1">
|
||||
2
|
||||
<async-fragment data-provider=data.D2 var="d2">
|
||||
3
|
||||
</async-fragment>
|
||||
4
|
||||
<async-fragment data-provider=data.D3 var="d3">
|
||||
5
|
||||
<async-fragment data-provider=data.D4 var="d4">
|
||||
6
|
||||
</async-fragment>
|
||||
7
|
||||
</async-fragment>
|
||||
8
|
||||
</async-fragment>
|
||||
9
|
||||
<async-fragment data-provider=data.D5 var="d5">
|
||||
10
|
||||
<async-fragment data-provider=data.D6 var="d6">
|
||||
11
|
||||
</async-fragment>
|
||||
12
|
||||
<async-fragment data-provider=data.D7 var="d7">
|
||||
13
|
||||
</async-fragment>
|
||||
14
|
||||
<async-fragment data-provider=data.D7 var="d7">
|
||||
15
|
||||
</async-fragment>
|
||||
16
|
||||
</async-fragment>
|
||||
17
|
||||
---
|
||||
@ -1,7 +1,7 @@
|
||||
<async-fragment data-provider="data.promiseData" var="promiseData">
|
||||
<async-fragment data-provider=data.promiseData var="promiseData">
|
||||
BEFORE
|
||||
<if test="true">
|
||||
$promiseData.noprop.value
|
||||
<if(true)>
|
||||
${promiseData.noprop.value}
|
||||
</if>
|
||||
AFTER
|
||||
<async-fragment-error>
|
||||
@ -1,7 +1,7 @@
|
||||
<async-fragment data-provider="data.promiseData" var="promiseData">
|
||||
<async-fragment data-provider=data.promiseData var="promiseData">
|
||||
BEFORE
|
||||
<if test="true">
|
||||
$promiseData.noprop.value
|
||||
<if(true)>
|
||||
${promiseData.noprop.value}
|
||||
</if>
|
||||
AFTER
|
||||
<async-fragment-error>
|
||||
3
test/fixtures/async-render/autotest/async-fragment-promise/template.marko
vendored
Normal file
3
test/fixtures/async-render/autotest/async-fragment-promise/template.marko
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<async-fragment data-provider=data.promiseData var="promiseData">
|
||||
${promiseData}
|
||||
</async-fragment>
|
||||
3
test/fixtures/async-render/autotest/async-fragment-timeout-message/template.marko
vendored
Normal file
3
test/fixtures/async-render/autotest/async-fragment-timeout-message/template.marko
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<async-fragment data-provider=data.userInfo var="userInfo" timeout=100 timeout-message="Server is busy!">
|
||||
Hello World
|
||||
</async-fragment>
|
||||
9
test/fixtures/async-render/autotest/async-fragment-timeout/template.marko
vendored
Normal file
9
test/fixtures/async-render/autotest/async-fragment-timeout/template.marko
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<async-fragment data-provider=data.userInfo var="user" timeout=300>
|
||||
<async-fragment-timeout>
|
||||
1-A timeout has occurred!
|
||||
</async-fragment-timeout>
|
||||
1
|
||||
</async-fragment>
|
||||
<async-fragment data-provider=data.userInfo var="user" timeout-message="2-A timeout has occurred!" timeout=300>
|
||||
2
|
||||
</async-fragment>
|
||||
3
test/fixtures/async-render/autotest/beginAsync/template.marko
vendored
Normal file
3
test/fixtures/async-render/autotest/beginAsync/template.marko
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
A<invoke data.beginAsync(out)/>C
|
||||
---
|
||||
9
test/fixtures/async-render/autotest/beginAsync/test.js
vendored
Normal file
9
test/fixtures/async-render/autotest/beginAsync/test.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
exports.templateData = {
|
||||
beginAsync: function(out) {
|
||||
var asyncOut = out.beginAsync();
|
||||
setTimeout(function() {
|
||||
asyncOut.write('B');
|
||||
asyncOut.end();
|
||||
}, 20);
|
||||
}
|
||||
};
|
||||
3
test/fixtures/codegen/autotest/renderBodyFunction/expected.js
vendored
Normal file
3
test/fixtures/codegen/autotest/renderBodyFunction/expected.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
function renderBody(out) {
|
||||
out.w("Hello World!");
|
||||
}
|
||||
7
test/fixtures/codegen/autotest/renderBodyFunction/index.js
vendored
Normal file
7
test/fixtures/codegen/autotest/renderBodyFunction/index.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function(builder) {
|
||||
return builder.renderBodyFunction([
|
||||
builder.text(builder.literal('Hello World!'))
|
||||
]);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user