define([
'intern!object',
'intern/chai!assert',
'../../../parser',
'dojo/dom-construct',
'dojo/_base/array',
'dojo/aspect',
'dojo/_base/declare',
'dojo/dom',
'dojo/dom-attr',
'dojo/_base/lang',
'dojo/on',
'dojo/_base/window',
'dojo/date/stamp',
'dojo/Stateful',
'dojo/Evented',
'dojo/text!./parser.html',
'./support/util'
], function (
registerSuite,
assert,
parser,
domConstruct,
array,
aspect,
declare,
dom,
domAttr,
lang,
on,
win,
dstamp,
Stateful,
Evented,
template,
util
) {
var container;
/* global tests */
function setup(id, shouldReturn) {
return function () {
delete window.tests;
var MyNonDojoClass = window.MyNonDojoClass = function () {};
MyNonDojoClass.extend = function () {
var args = arguments;
return function () {
this.expectedClass = true;
this.params = args;
};
};
declare('tests.parser.Widget', null, {
constructor: function (args) {
this.params = args;
}
});
declare('tests.parser.Class1', null, {
constructor: function (args) {
this.params = args;
lang.mixin(this, args);
},
preambleTestProp: 1,
preamble: function () {
this.preambleTestProp++;
},
intProp: 1,
callCount: 0, // for connect testing
callInc: function () { this.callCount++; },
callCount2: 0, // for assignment testing
strProp1: 'original1',
strProp2: 'original2',
arrProp: [],
arrProp2: ['foo'],
boolProp1: false,
boolProp2: true,
boolProp3: false,
boolProp4: true,
dateProp1: dstamp.fromISOString('2007-01-01'),
dateProp2: dstamp.fromISOString('2007-01-01'),
dateProp3: dstamp.fromISOString('2007-01-01'),
funcProp: function () {},
funcProp2: function () {},
funcProp3: function () {},
onclick: function () { this.prototypeOnclick = true; }
// FIXME: have to test dates!!
// FIXME: need to test the args property!!
});
declare('tests.parser.Class2', null, {
constructor: function () {
this.fromMarkup = false;
},
fromMarkup: false,
markupFactory: function () {
var i = new tests.parser.Class2();
i.fromMarkup = true;
return i;
}
});
declare('tests.parser.Class3', tests.parser.Class2, {
fromMarkup: false,
markupFactory: function (args, node, ClassCtor) {
var i = new ClassCtor();
i.classCtor = ClassCtor;
i.params = args;
return i;
}
});
declare('tests.parser.InputClass', null, {
constructor: function (args) {
this.params = args;
lang.mixin(this, args);
},
// these attributes are special in HTML, they don't have a value specified
disabled: false,
readonly: false,
checked: false,
// other attributes native to HTML
value: 'default value',
title: 'default title',
tabIndex: '0', // special because mixed case
// custom widget attributes that don't match a native HTML attributes
custom1: 123,
custom2: 456
});
// Test that dir, lang, etc. attributes can be inherited from ancestor node
declare('tests.parser.BidiClass', tests.parser.Widget, {
constructor: function (args) { lang.mixin(this, args); },
dir: '',
lang: '',
textdir: '',
name: ''
});
// For testing that parser recurses correctly, except when the prototype has a
// stopParser flag
declare('tests.parser.NormalContainer', null, {
constructor: function (args) { lang.mixin(this, args); }
});
declare('tests.parser.ShieldedContainer', null, {
constructor: function (args) { lang.mixin(this, args); },
// flag to tell parser not to instantiate nodes inside of me
stopParser: true
});
declare('tests.parser.HTML5Props', null, {
constructor: function (args) { lang.mixin(this, args); },
simple: false,
a: 2,
b: null,
c: null,
d: null,
e: null,
f: null,
afn: function () {
return this.a * 2;
}
});
// not on .prototype:
tests.parser.HTML5Props._aDefaultObj = {
a: 1,
b: 2,
simple: true
};
declare('tests.parser.HTML5withMethod', null, {
constructor: function (args) { lang.mixin(this, args); },
baseValue: 10,
someMethod: function () {
return this.baseValue;
},
diffMethod: function () {
this._ran = true;
}
});
declare('tests.parser.StatefulClass', [Evented, Stateful], {
strProp1: '',
objProp1: {},
boolProp1: false,
prototypeOnclick: false,
onclick: function () { this.prototypeOnclick = true; }
});
declare('tests.parser.MethodClass', null, {
method1ran: false,
method1after: false,
method2ran: false,
method2before: false,
method2after: false,
method3result: '',
method4ran: false,
method4after: false,
method1: function () { this.method1ran = true; },
method2: function () { this.method2ran = true; },
method3: function (result) { this.method3result = result; },
method4: function () { this.method4ran = true; }
});
declare('tests.parser.ClassForMixins', null, {
classDone: true
});
declare('tests.parser.Mixin1', null, {
mixin1Done: true
});
declare('tests.parser.Mixin2', null, {
mixin2Done: true
});
declare('tests.resources.AMDWidget', null, {
constructor: function (args) {
this.params = args;
}
});
declare('tests.resources.AMDWidget2', null, {
constructor: function (args) {
this.params = args;
},
method1: function (value) {
value++;
return value;
}
});
declare('tests.resources.AMDWidget3', null, {
constructor: function (args) {
this.params = args;
}
});
window.deepTestProp = {
blah: {
thinger: 1
}
};
tests.parser.FormClass = declare(tests.parser.Widget, {
encType: ''
});
window.foo = function () {
this.fooCalled = true;
};
container = domConstruct.place(util.fixScope(template), document.body);
var el = id ? dom.byId(id) : null,
ret = parser.parse(el);
return shouldReturn && ret;
};
}
function teardown() {
domConstruct.destroy(container);
container = null;
delete window.foo;
delete window.tests;
}
registerSuite({
name: 'dojo/parser basic tests',
setup: setup('main', true),
teardown: teardown,
/* global obj */
'data-dojo-id': function () {
assert.isObject(obj);
},
/* global obj3 */
'JsId': function () {
assert.isObject(obj3);
},
'string property': function () {
assert.isString(obj.strProp1);
assert.equal(obj.strProp1, 'text');
},
'int property': function () {
assert.isNumber(obj.intProp);
assert.equal(obj.intProp, 5);
},
'array property': function () {
assert.lengthOf(obj.arrProp, 3);
assert.lengthOf(obj.arrProp[1], 3);
assert.equal(obj.arrProp[1], 'bar');
},
'boolean property': function () {
// boolProp1
assert.isBoolean(obj.boolProp1);
assert.isTrue(obj.boolProp1);
// boolProp2
assert.isBoolean(obj.boolProp2);
assert.isFalse(obj.boolProp2);
// boolProp3 not specified (prototype says false)
assert.isBoolean(obj.boolProp3);
// assert.isFalse(obj.boolprop3);
// boolProp4 not specified (prototype says true)
// assert.isBoolean(obj.boolProp4);
// assert.isTrue(obj.boolProp4);
},
'date property': function () {
assert.equal(dstamp.toISOString(obj.dateProp1, { selector: 'date' }), '2006-01-01');
// dateProp2='', should map to NaN (a blank value on DateTextBox)
assert.ok(isNaN(obj.dateProp2));
// dateProp3='now', should map to current date
assert.equal(dstamp.toISOString(obj.dateProp3, { selector: 'date' }),
dstamp.toISOString(new Date(), { selector: 'date' }));
},
'unwanted params': function () {
// Make sure that parser doesn't pass any unwanted parameters to
// widget constructor, especially 'toString' or 'constructor'.
// Make exception for dir/lang which parser gleans from document itself.
for (var param in obj.params) {
assert.ok(array.indexOf(
[
'strProp1', 'strProp2',
'intProp',
'arrProp', 'arrProp2',
'boolProp1', 'boolProp2',
'dateProp1', 'dateProp2', 'dateProp3',
'funcProp2', 'funcProp3',
'preamble',
'callInc1', 'callInc2', 'dir', 'lang', 'textDir'
],
param) >= 0, param + ' should not be in the parameters passed to the widget constructor');
}
},
'disabled flag': function () {
/* global disabledObj */
assert.isBoolean(disabledObj.disabled);
assert.isTrue(disabledObj.disabled);
assert.isFalse(disabledObj.checked);
},
'checked flag': function () {
/* global checkedObj */
assert.isBoolean(checkedObj.checked);
assert.isFalse(checkedObj.disabled);
assert.isTrue(checkedObj.checked);
},
'function property': function () {
// make sure that unspecified functions (even with common names)
// don't get overridden (bug #3074)
obj.onclick();
assert.isTrue(obj.prototypeOnclick, 'prototypeOnClick');
// funcProp2='foo'
obj.funcProp2();
assert.isTrue(obj.fooCalled, 'fooCalled');
// funcProp3='this.func3Called=true;'
obj.funcProp3();
assert.isTrue(obj.func3Called, 'func3Called');
},
'connect': function () {
obj.callInc();
assert.equal(obj.callCount, 2);
},
'function assignment': function () {
obj.callInc2();
assert.equal(obj.callCount2, 1);
},
'subnode parse': function () {
assert.isFalse(lang.exists('obj2'), 'exists before parse');
var toParse = dom.byId('toParse');
parser.parse(toParse.parentNode);
assert.isTrue(lang.exists('obj2'), 'exists after parse');
assert.equal(obj.declaredClass, 'tests.parser.Class1');
},
'markup factory': function () {
assert.isTrue(lang.exists('obj3'), 'obj3 exists');
assert.isTrue(obj3.fromMarkup);
},
/* global obj4 */
'markup factory class': function () {
assert.isTrue(lang.exists('obj4'), 'obj4 exists');
assert.equal(obj4.classCtor, tests.parser.Class3);
assert.instanceOf(obj4, tests.parser.Class3);
assert.instanceOf(obj4, tests.parser.Class2);
},
'no start': function () {
var started = false;
declare('SampleThinger', null, {
startup: function () {
started = true;
}
});
domConstruct.create('div', {
dojoType: 'SampleThinger'
}, 'parsertest');
parser.parse('parsertest', { noStart: true });
assert.isFalse(started, 'first started check');
domConstruct.empty('parsertest');
started = false;
domConstruct.create('div', {
dojoType: 'SampleThinger'
}, 'parsertest');
parser.parse('parsertest', { noStart: true, rootNode: 'parserTest' });
assert.isFalse(started, 'second started check');
},
// test the varios iterations of parser test
// TODO: the following test doesn't acutally test anything because
// the parser is calling dojo/query's function instead of dojo.query
// This also causes other tests to fail because the aspect call replaces
// dojo.query which has functions on it (like dojo.query.matches)
/*'root test': function () {
var tmp = aspect.after(dojo, 'query', function (sel, root) {
assert.equal(root, 'parsertest2');
});
parser.parse('parsertest2');
parser.parse({ rootNode: 'parsertest2' });
parser.parse('parsertest2', { noStart: true });
tmp.remove();
},*/
// Test that when BorderContainer etc. extends _Widget,
// parser is aware of the new parameters added (to _Widget
// and all of it's subclasses)
'cache refresh': function () {
// Add new node to be parsed, referencing a widget that the parser has already
// dealt with (and thus cached)
var wrapper = domConstruct.place(
util.fixScope('
'),
win.body(), 'last');
try {
// Modify Class3's superclass widget to have new parameter (thus Class3 inherits it)
lang.extend(tests.parser.Class2, {
newParam: 0
});
// Run the parser and see if it reads in newParam
var widgets = parser.parse({ rootNode: wrapper });
assert.lengthOf(widgets, 1);
assert.equal(widgets[0].params.newparam || widgets[0].params.newParam, 12345);
}
finally {
domConstruct.destroy(wrapper);
}
},
// Test that parser recurses correctly, except when there's a stopParser flag not to
/* global container1, contained1, container2, contained2 */
'recurse': function () {
assert.isDefined(container1, 'normal container created');
assert.isDefined(container1.incr, 'script tag works too');
assert.isDefined(contained1, 'child widget also created');
assert.isDefined(contained2, 'child widget 2 also created');
assert.isDefined(container2, 'shielded container created');
assert.isDefined(container2.incr, 'script tag works too');
assert.isUndefined(window.contained3, 'child widget not created');
assert.isUndefined(window.contained4, 'child widget 2 not created');
},
/* global html5simple, html5simple2 */
'simple HTML5': function () {
assert.isObject(html5simple, 'data-dojo-id export');
assert.isObject(html5simple2, 'data-dojo-id export');
assert.isTrue(html5simple.simple, 'default respecified in props=""');
assert.isFalse(html5simple2.simple, 'default overridden by props=""');
// test data-dojo-props='simple:false, a:1, b:'two', c:[1,2,3], d:function(){ return this; }, e:{ f:'g' }'
var it = html5simple2;
assert.equal(it.a, 1, 'number in param');
assert.equal(it.b, 'two', 'string in param');
assert.isArray(it.c, 'array in param');
assert.lengthOf(it.c, 3, 'array sanity');
assert.equal(it.e.f, 'g', 'nested object with string');
// test the function
assert.equal(it.d(), it, 'simple \'return this\' function');
},
/* global html5simple3 */
'HTML5 inherited': function () {
assert.isObject(html5simple3);
var val = html5simple3.afn();
assert.equal(val, html5simple3.a * 2, 'afn() overrides default but calls inherited');
},
/* global htmldojomethod */
'HTML5 with method': function () {
// testing data-dojo-event and data-dojo-args support for dojo/method and dojo/connect
assert.isObject(htmldojomethod);
assert.isTrue(htmldojomethod._methodRan, 'plain dojo/method ran');
var x = htmldojomethod.someMethod(2, 2);
assert.equal(x, 14, 'overridden dojo/method');
htmldojomethod.diffMethod(2);
assert.isTrue(htmldojomethod._ran, 'ensures original was called first');
assert.equal(htmldojomethod._fromvalue, 2, 'ensures connected was executed in scope');
},
/* global objOnWatch */
'test watch': function () {
// testing script-type dojo/watch and dojo/on
assert.isObject(objOnWatch);
objOnWatch.set('strProp1', 'newValue1');
assert.equal(objOnWatch.arrProp.newValue, 'newValue1', 'ensures watch executed');
objOnWatch.onclick();
assert.isTrue(objOnWatch.prototypeOnclick, 'ensures original was called');
assert.isTrue(objOnWatch.boolProp1, 'ensure on executed in scope');
},
/* global on_form */
'on': function () {
/*jshint camelcase:false*/
// testing script-type dojo/on, when script comes after another element
parser.parse('on');
assert.property(window, 'on_form', 'widget created');
on_form.emit('click');
assert.isTrue(on_form.clicked, 'on callback fired');
},
/* global objAspect */
'aspect': function () {
// testing script-type dojo/aspect
assert.isObject(objAspect);
assert.isFalse(objAspect.method1ran, 'ensures method unfired');
assert.isFalse(objAspect.method2ran, 'ensures method unfired');
assert.equal(objAspect.method3result, '', 'ensures method unfired');
assert.isFalse(objAspect.method4ran, 'ensures method unfired');
objAspect.method1();
objAspect.method2();
objAspect.method3('something');
objAspect.method4();
assert.isTrue(objAspect.method1ran, 'method fired');
assert.isTrue(objAspect.method1after, 'after advice fired');
assert.isTrue(objAspect.method2ran, 'method fired');
assert.isTrue(objAspect.method2before, 'around before advice fired');
assert.isTrue(objAspect.method2after, 'around after advice fired');
assert.equal(objAspect.method3result, 'before', 'before argument passed');
assert.isTrue(objAspect.method4ran, 'method fired');
assert.isTrue(objAspect.method4after, 'after advice fired');
},
/* global objAMDWidget */
'mid': function () {
// testing specifying data-dojo-type as mid
assert.isObject(objAMDWidget);
assert.equal(objAMDWidget.params.value, 'Value1', 'ensure object was properly parsed using MID');
}
});
registerSuite({
name: 'bidi',
setup: setup('main'),
teardown: teardown,
// Test that dir=rtl or dir=ltr setting trickles down from root node
/* global setRtl, inheritRtl, inheritRtl2, inheritLtr, setLtr */
'dir attribute': function () {
parser.parse('dirSection1');
parser.parse('dirSection2');
assert.equal(setRtl.dir, 'rtl', 'direct setting of dir=rtl works');
assert.equal(inheritRtl.dir, 'rtl', 'inherited rtl works');
assert.equal(inheritLtr.dir, 'ltr', 'inherited ltr works (closest ancestor wins)');
assert.equal(inheritRtl2.dir, 'rtl', 'inherited rtl works, from grandparent');
assert.equal(setLtr.dir, 'ltr', 'direct setting of dir=ltr overrides inherited RTL');
},
/* global noLang, inheritedLang, specifiedLang */
'lang attribute': function () {
parser.parse('langSection');
assert.notProperty(noLang.params, 'lang', 'no lang');
assert.equal(inheritedLang.lang, 'it_it', 'inherited lang works');
assert.equal(specifiedLang.lang, 'en_us', 'direct setting of lang overrides inherited');
},
/* global noTextdir, inheritedTextdir, specifiedTextdir */
'textDir attribute': function () {
parser.parse('textDirSection');
assert.notProperty(noTextdir.params, 'textDir', 'no textdir');
assert.equal(inheritedTextdir.textDir, 'rtl', 'inherited textdir works');
assert.equal(specifiedTextdir.textDir, 'ltr', 'direct setting of textdir overrides inherited');
},
'inheritance from HTML': function () {
// Test that calling parser.parse(nodeX) will inherit dir/lang/etc. settings
// even from
var textdirAttr = util.fixScope('data-${dojo}-textdir');
var attrs = { dir: 'rtl', lang: 'ja-jp' };
attrs[textdirAttr] = 'auto';
domAttr.set(win.doc.documentElement, attrs);
parser.parse('bidiInheritanceFromHtml');
/* global inheritedFromHtml */
assert.equal(inheritedFromHtml.params.dir, 'rtl', 'dir');
assert.equal(inheritedFromHtml.params.lang, 'ja-jp', 'lang');
assert.equal(inheritedFromHtml.params.textDir, 'auto', 'textDir');
// teardown
array.forEach(['dir', 'lang', textdirAttr], function (attr) {
win.doc.documentElement.removeAttribute(attr);
});
}
});
registerSuite({
name: 'IE Attribute Detection',
setup: setup('main'),
teardown: teardown,
'input1': function () {
var widgets = parser.instantiate([dom.byId('ieInput1')]);
var params = widgets[0].params;
assert.equal(params.type, 'checkbox', 'type');
assert.isTrue(params.disabled, 'disabled');
assert.isTrue(params.checked, 'checked');
assert.isTrue(params.readonly, 'readonly');
assert.equal(params.foo, 'bar', 'foo');
assert.equal(params.bar, 'zaz', 'bar');
assert.equal(params.bob, 'escaped\"dq', 'bob');
assert.equal(params.frank, 'escaped\'sq', 'frank');
//assert.isFalse('value' in params, 'value not specified'); // fails in IE8, thinks value=='on'
},
'input2': function () {
var widgets = parser.instantiate([dom.byId('ieInput2')]);
var params = widgets[0].params;
assert.notProperty(params, 'type', 'type');
assert.notProperty(params, 'name', 'name');
assert.notProperty(params, 'value', 'value');
assert.notProperty(params, 'data-dojo-type', 'data-dojo-type');
assert.notProperty(params, 'data-dojo-props', 'data-dojo-props');
assert.equal(params.foo, 'hi', 'foo');
assert.notProperty(params, 'value', 'value not specified');
},
'input3': function () {
var widgets = parser.instantiate([dom.byId('ieInput3')]);
var params = widgets[0].params;
assert.equal(params.type, 'password', 'type');
assert.equal(params.name, 'test', 'name');
assert.equal(params.value, '123', 'value');
assert.equal(params['class'], 'myClass', 'class');
assert.equal(params.style.replace(/[ ;]/g, '').toLowerCase(), 'display:block', 'style');
assert.equal(params.tabIndex, '3', 'tabIndex');
},
'textarea': function () {
var widgets = parser.instantiate([dom.byId('ieTextarea')]);
var params = widgets[0].params;
assert.equal(params.value, 'attrVal', 'value');
},
'button1': function () {
var widgets = parser.instantiate([dom.byId('ieButton1')]);
var params = widgets[0].params;
assert.isTrue(params.checked, 'checked');
assert.equal(params.value, 'button1val', 'value');
},
'button2': function () {
var widgets = parser.instantiate([dom.byId('ieButton2')]);
var params = widgets[0].params;
assert.notProperty(params, 'checked', 'checked');
assert.notProperty(params, 'value', 'value');
},
'button3': function () {
var widgets = parser.instantiate([dom.byId('ieButton3')]);
var params = widgets[0].params;
assert.isTrue(params.checked, 'checked');
},
'button4': function () {
var widgets = parser.instantiate([dom.byId('ieButton4')]);
var params = widgets[0].params;
assert.notProperty(params, 'checked');
},
'form1': function () {
var widgets = parser.instantiate([dom.byId('ieForm1')]);
var params = widgets[0].params;
assert.equal(params.encType, 'foo', 'encType is specified');
},
'form2': function () {
var widgets = parser.instantiate([dom.byId('ieForm2')]);
var params = widgets[0].params;
assert.notProperty(params, 'encType', 'encType not specified');
},
'li': function () {
var widgets = parser.instantiate([dom.byId('li')]);
var params = widgets[0].params;
assert.equal(params.value, 'home');
}
});
registerSuite({
name: 'mixed attribute specification',
setup: setup('main'),
teardown: teardown,
/* global mixedObj */
'mixed': function () {
parser.parse(dom.byId('mixedContainer'));
assert.isObject(mixedObj, 'widget created');
assert.equal(mixedObj.value, 'mixedValue', 'native attribute');
assert.equal(mixedObj.custom1, 999, 'data-dojo-props attribute');
assert.equal(mixedObj.title, 'custom title', 'data-dojo-props overrides native');
}
});
registerSuite({
name: 'functions',
setup: setup('main'),
teardown: teardown,
'onclick': function () {
declare('tests.parser.Button', null, {
onClick: function () {
console.log('prototype click');
},
constructor: function (args, node) {
lang.mixin(this, args);
this.domNode = node;
aspect.after(this.domNode, 'onclick', lang.hitch(this, 'onClick'));
}
});
buttonClicked = function () {
console.log('markup click');
}; // markup says onClick='buttonClicked'
// Parse markup inside 'functions' div
parser.parse('functions');
// Should have created an instance called 'button' where button.onClick == buttonClicked
/* global button, buttonClicked */
assert.isObject(button, 'widget created');
assert.isFunction(button.onClick, 'created as function');
assert.isTrue(buttonClicked === button.onClick, 'points to specified function');
}
});
registerSuite({
name: 'parser.construct()',
setup: setup('main'),
teardown: teardown,
/* global objC1, objC2 */
'construct1': function () {
// var nodes = [dom.byId('objC1'), dom.byId('objC2')];
parser.construct(tests.parser.Class1, dom.byId('objC1'));
assert.isObject(objC1, 'widget 1 created');
assert.equal(objC1.intProp, 5, 'objC1.intProp');
parser.construct(tests.parser.Class1, dom.byId('objC2'));
assert.isObject(objC2, 'widget 2 created');
assert.equal(objC2.intProp, 5, 'objC2.intProp');
}
});
registerSuite({
name: 'data-dojo-mixins support',
setup: setup('mixins', true),
teardown: teardown,
'mixins': function () {
/* global resultMixins1, resultMixins2 */
assert.ok(resultMixins1, 'object using data-dojo-mixins created from an already parsed type');
assert.isTrue(resultMixins1.mixin1Done, 'mixin1 correctly mixed in');
assert.isTrue(resultMixins1.mixin2Done, 'mixin2 correctly mixed in');
assert.isTrue(resultMixins1.amdMixinDone, 'amd mixin correctly mixed in');
assert.ok(resultMixins2, 'object using data-dojo-mixins created from a non parsed type');
assert.isTrue(resultMixins2.classDone, 'class correctly created');
assert.isTrue(resultMixins2.mixin1Done, 'mixin1 correctly mixed in');
assert.isTrue(resultMixins2.mixin2Done, 'mixin2 correctly mixed in');
assert.isTrue(resultMixins2.amdMixinDone, 'amd mixin correctly mixed in');
/* global resultNonDojoMixin */
assert.isTrue(resultNonDojoMixin.expectedClass, 'correct class is returned for composeJS mixin');
assert.equal(resultNonDojoMixin.params.length, 2, 'correct # of params were passed to compose JS');
assert.equal(resultNonDojoMixin.params[0], tests.parser.Mixin1, 'correct param 1');
assert.equal(resultNonDojoMixin.params[1], tests.parser.Mixin2, 'correct param 2');
}
});
registerSuite({
name: 'behavorial',
setup: setup('main'),
teardown: teardown,
'doubleConnect': function () {
// Class used in 'behavioral'
/* global Behavioral1:true */
Behavioral1 = declare(null, {
constructor: function (params, node) {
on(node, 'click', lang.hitch(this, 'onClick'));
if (typeof params.onClick !== 'function') {
throw new Error('onClick not passed to constructor');
}
lang.mixin(this, params);
},
onClick: function () {
console.log('original onnClick handler');
},
foo: ''
});
parser.parse('behavioral');
// Setup global accessed by Behavioral1.onclick handler
behavioralClickCounter = 0;
// Trigger click event, and make sure that handler was only called once.
on.emit(dom.byId('bh1'), 'click', {bubbles: true, cancelable: true});
/* global behavioralClickCounter */
assert.equal(behavioralClickCounter, 1, 'one click event processed');
assert.equal(dom.byId('bh1').getAttribute('foo'), 'bar', 'foo attribute not removed from widget DOMNode');
}
});
registerSuite({
name: 'script type=dojo/require support',
setup: setup('main'),
teardown: teardown,
'declarativeRequire': function () {
var td = this.async();
parser.parse('declarativeRequire').then(td.callback(function () {
/* global dr1, dr2, dr3, dr4, dr5 */
assert.isObject(dr1, 'object using MID mapped to return var');
assert.equal(dr1.params.foo, 'bar', 'parameters set on instantiation');
assert.isObject(dr2, 'object using MID mapped to return var');
assert.equal(dr2.params.foo, 'bar', 'parameters set on instantiation');
assert.isObject(dr3, 'object using fully required');
assert.equal(dr3.params.foo, 'bar', 'parameters set on instantiation');
assert.equal(dr4.params.foo, 2, 'module loaded and executed');
assert.equal(dr5.method1(1), 3, 'declarative script has access to parser scope');
}));
},
'contextRequire': function () {
var td = this.async();
parser.parse('contextRequire', {
contextRequire: require
}).then(td.callback(function () {
/* global cr1, cr2, cr3, cr4 */
assert.isObject(cr1, 'object using relative MID mapped to return var');
assert.equal(cr1.params.foo, 'bar', 'parameters set on instantiation');
assert.isObject(cr2, 'object using relative MID mapped to return var');
assert.equal(cr2.params.foo, 'bar', 'parameters set on instantiation');
assert.isObject(cr3, 'object using relative MID mapped to return var');
assert.equal(cr3.params.foo, 'bar', 'parameters set on instantiation');
assert.isObject(cr4, 'object using relative MID mapped to return var');
assert.equal(cr4.params.foo, 'bar', 'parameters set on instantiation');
}));
}
});
registerSuite({
name: 'promise error handling support',
setup: setup('main'),
teardown: teardown,
'asyncError': function () {
var td = this.async();
parser.parse('errorHandling').then(td.rejectOnError(function () {
throw new Error('shouldn\'t get here');
}), td.callback(function (e) {
assert.equal(typeof e, 'object', 'error object returned');
}));
},
'missingCtor': function () {
var td = this.async();
parser.parse('missingCtor').then(td.rejectOnError(function () {
throw new Error('shouldn\'t get here');
}), td.callback(function (e) {
assert.equal(typeof e, 'object', 'error object returned');
assert.equal(e.toString(),
'Error: Unable to resolve constructor for: \'some.type\'', 'proper error value returned');
}));
}
});
});