siesta 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/siesta/siesta_controller.rb +1 -1
- data/app/helpers/siesta/application_helper.rb +2 -2
- data/config/routes.rb +1 -1
- data/lib/siesta/test_suite.rb +3 -3
- data/lib/siesta/version.rb +1 -1
- data/vendor/assets/images/siesta/resources/images/trigger-groups.gif +0 -0
- data/vendor/assets/images/siesta/resources/images/trigger-leafs.gif +0 -0
- data/vendor/assets/javascripts/siesta/siesta-all.js +2144 -494
- data/vendor/assets/javascripts/siesta/siesta-nodejs-all.js +538 -138
- data/vendor/assets/javascripts/siesta/siesta-touch-all.js +1325 -449
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-all.css +22 -2
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-touch-all.css +1 -1
- metadata +1243 -1241
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
|
3
|
-
Siesta 1.1.
|
3
|
+
Siesta 1.1.5
|
4
4
|
Copyright(c) 2009-2012 Bryntum AB
|
5
5
|
http://bryntum.com/contact
|
6
6
|
http://bryntum.com/products/siesta/license
|
@@ -6114,7 +6114,9 @@ Class('Siesta.Content.Manager', {
|
|
6114
6114
|
require : true
|
6115
6115
|
},
|
6116
6116
|
|
6117
|
-
urls : Joose.I.Object
|
6117
|
+
urls : Joose.I.Object,
|
6118
|
+
|
6119
|
+
maxLoads : 5
|
6118
6120
|
},
|
6119
6121
|
|
6120
6122
|
|
@@ -6142,29 +6144,42 @@ Class('Siesta.Content.Manager', {
|
|
6142
6144
|
var errorCount = 0
|
6143
6145
|
|
6144
6146
|
var total = 0
|
6145
|
-
|
6147
|
+
var urlsArray = []
|
6148
|
+
Joose.O.each(urls, function (value, url) { total++; urlsArray.push(url) })
|
6146
6149
|
|
6147
|
-
if (total)
|
6148
|
-
|
6150
|
+
if (total) {
|
6151
|
+
|
6152
|
+
var loadSingle = function (url) {
|
6153
|
+
if (!url) return
|
6149
6154
|
|
6150
6155
|
me.load(url, function (content) {
|
6151
6156
|
if (errorCount) return
|
6152
6157
|
|
6153
6158
|
urls[ url ] = content
|
6154
6159
|
|
6155
|
-
if (++loadCount == total)
|
6160
|
+
if (++loadCount == total)
|
6161
|
+
callback && callback()
|
6162
|
+
else
|
6163
|
+
loadSingle(urlsArray.shift())
|
6156
6164
|
|
6157
6165
|
}, ignoreErrors ? function () {
|
6158
6166
|
|
6159
|
-
if (++loadCount == total)
|
6167
|
+
if (++loadCount == total)
|
6168
|
+
callback && callback()
|
6169
|
+
else
|
6170
|
+
loadSingle(urlsArray.shift())
|
6160
6171
|
|
6161
6172
|
} : function () {
|
6162
6173
|
errorCount++
|
6163
6174
|
|
6164
6175
|
errback && errback(url)
|
6165
6176
|
})
|
6166
|
-
}
|
6167
|
-
|
6177
|
+
}
|
6178
|
+
|
6179
|
+
// running only `maxLoads` "loading threads" at the same time
|
6180
|
+
for (var i = 0; i < this.maxLoads; i++) loadSingle(urlsArray.shift())
|
6181
|
+
|
6182
|
+
} else
|
6168
6183
|
callback && callback()
|
6169
6184
|
},
|
6170
6185
|
|
@@ -6206,6 +6221,8 @@ Class('Siesta.Result.Diagnostic', {
|
|
6206
6221
|
isa : Siesta.Result,
|
6207
6222
|
|
6208
6223
|
has : {
|
6224
|
+
isWarning : false,
|
6225
|
+
|
6209
6226
|
isSimulatedEvent : false,
|
6210
6227
|
|
6211
6228
|
// Used by simulated events
|
@@ -6217,8 +6234,7 @@ Class('Siesta.Result.Diagnostic', {
|
|
6217
6234
|
methods : {
|
6218
6235
|
|
6219
6236
|
toString : function () {
|
6220
|
-
|
6221
|
-
return message;
|
6237
|
+
return '# ' + this.description
|
6222
6238
|
}
|
6223
6239
|
}
|
6224
6240
|
});
|
@@ -6400,6 +6416,7 @@ Role('Siesta.Test.More', {
|
|
6400
6416
|
'onload',
|
6401
6417
|
'onerror',
|
6402
6418
|
'StartTest',
|
6419
|
+
'startTest',
|
6403
6420
|
// will be reported in IE8 after overriding
|
6404
6421
|
'setTimeout',
|
6405
6422
|
'clearTimeout'
|
@@ -6636,7 +6653,7 @@ Role('Siesta.Test.More', {
|
|
6636
6653
|
|
6637
6654
|
desc = desc || 'throwsOk';
|
6638
6655
|
|
6639
|
-
var e = this.
|
6656
|
+
var e = this.getExceptionCatcher()(func)
|
6640
6657
|
|
6641
6658
|
// assuming no one will throw undefined exception..
|
6642
6659
|
if (e === undefined) {
|
@@ -6648,7 +6665,7 @@ Role('Siesta.Test.More', {
|
|
6648
6665
|
return
|
6649
6666
|
}
|
6650
6667
|
|
6651
|
-
if (e instanceof this.
|
6668
|
+
if (e instanceof this.getTestErrorClass())
|
6652
6669
|
//IE uses non-standard 'description' property for error msg
|
6653
6670
|
e = e.message || e.description
|
6654
6671
|
|
@@ -6703,7 +6720,7 @@ Role('Siesta.Test.More', {
|
|
6703
6720
|
func = [ desc, desc = func][ 0 ]
|
6704
6721
|
}
|
6705
6722
|
|
6706
|
-
var e = this.
|
6723
|
+
var e = this.getExceptionCatcher()(func)
|
6707
6724
|
|
6708
6725
|
if (e === undefined)
|
6709
6726
|
this.pass(desc)
|
@@ -6892,9 +6909,9 @@ Role('Siesta.Test.More', {
|
|
6892
6909
|
*
|
6893
6910
|
* This method has a synonym with singular name: `expectGlobal`
|
6894
6911
|
*
|
6895
|
-
* @param {String} name1 The name of global property
|
6896
|
-
* @param {String} name2 The name of global property
|
6897
|
-
* @param {String} nameN The name of global property
|
6912
|
+
* @param {String/RegExp} name1 The name of global property or the regular expression to match several properties
|
6913
|
+
* @param {String/RegExp} name2 The name of global property or the regular expression to match several properties
|
6914
|
+
* @param {String/RegExp} nameN The name of global property or the regular expression to match several properties
|
6898
6915
|
*/
|
6899
6916
|
expectGlobals : function () {
|
6900
6917
|
this.expectedGlobals.push.apply(this.expectedGlobals, arguments)
|
@@ -6908,9 +6925,9 @@ Role('Siesta.Test.More', {
|
|
6908
6925
|
*
|
6909
6926
|
* You can enable this assertion to automatically happen at the end of each test, using {@link Siesta.Harness#autoCheckGlobals autoCheckGlobals} option of the harness.
|
6910
6927
|
*
|
6911
|
-
* @param {String} name1 The name of global property
|
6912
|
-
* @param {String} name2 The name of global property
|
6913
|
-
* @param {String} nameN The name of global property
|
6928
|
+
* @param {String/RegExp} name1 The name of global property or the regular expression to match several properties
|
6929
|
+
* @param {String/RegExp} name2 The name of global property or the regular expression to match several properties
|
6930
|
+
* @param {String/RegExp} nameN The name of global property or the regular expression to match several properties
|
6914
6931
|
*/
|
6915
6932
|
verifyGlobals : function () {
|
6916
6933
|
if (this.disableGlobalsCheck) {
|
@@ -6922,16 +6939,33 @@ Role('Siesta.Test.More', {
|
|
6922
6939
|
this.expectGlobals.apply(this, arguments)
|
6923
6940
|
|
6924
6941
|
var me = this
|
6925
|
-
var
|
6926
|
-
var
|
6942
|
+
var expectedStrings = {}
|
6943
|
+
var expectedRegExps = []
|
6927
6944
|
|
6928
|
-
Joose.A.each(this.expectedGlobals.concat(this.browserGlobals), function (
|
6945
|
+
Joose.A.each(this.expectedGlobals.concat(this.browserGlobals), function (value) {
|
6946
|
+
if (me.typeOf(value) == 'RegExp')
|
6947
|
+
expectedRegExps.push(value)
|
6948
|
+
else
|
6949
|
+
expectedStrings[ value ] = true
|
6950
|
+
})
|
6929
6951
|
|
6930
6952
|
this.diag('Global variables')
|
6931
6953
|
|
6954
|
+
var failed = false
|
6955
|
+
|
6932
6956
|
for (var name in this.global) {
|
6957
|
+
if (expectedStrings[ name ]) continue
|
6958
|
+
|
6959
|
+
var isExpected = false
|
6960
|
+
|
6961
|
+
for (var i = 0; i < expectedRegExps.length; i++) {
|
6962
|
+
if (expectedRegExps[ i ].test(name)) {
|
6963
|
+
isExpected = true
|
6964
|
+
break
|
6965
|
+
}
|
6966
|
+
}
|
6933
6967
|
|
6934
|
-
if (!
|
6968
|
+
if (!isExpected) {
|
6935
6969
|
me.fail('Unexpected global found', 'Global name: ' + name + ', value: ' + Siesta.Util.Serializer.stringify(this.global[name]))
|
6936
6970
|
|
6937
6971
|
failed = true
|
@@ -6968,7 +7002,7 @@ Role('Siesta.Test.More', {
|
|
6968
7002
|
else
|
6969
7003
|
this.fail(desc, annotation, result);
|
6970
7004
|
},
|
6971
|
-
|
7005
|
+
|
6972
7006
|
|
6973
7007
|
/**
|
6974
7008
|
* Waits for passed checker method to return true (or any non-false value, like for example DOM element or array), and calls the callback when this happens.
|
@@ -6980,8 +7014,9 @@ Role('Siesta.Test.More', {
|
|
6980
7014
|
* @param {Function} callback A function to call when the condition has been met. Will receive a result from checker function.
|
6981
7015
|
* @param {Object} scope The scope for the callback
|
6982
7016
|
* @param {Int} timeout The maximum amount of time (in milliseconds) to wait for the condition to be fulfilled. Defaults to the {@link Siesta.Test.ExtJS#waitForTimeout} value.
|
7017
|
+
* @param {Int} interval The polling interval (in milliseconds)
|
6983
7018
|
*/
|
6984
|
-
waitFor : function (method, callback, scope, timeout) {
|
7019
|
+
waitFor : function (method, callback, scope, timeout, interval) {
|
6985
7020
|
var description = this.typeOf(method) == 'Number' ? (method + ' ms') : ' condition to be fullfilled';
|
6986
7021
|
var assertionName = 'waitFor';
|
6987
7022
|
|
@@ -6992,11 +7027,17 @@ Role('Siesta.Test.More', {
|
|
6992
7027
|
callback = options.callback;
|
6993
7028
|
scope = options.scope;
|
6994
7029
|
timeout = options.timeout;
|
7030
|
+
interval = options.interval
|
7031
|
+
|
6995
7032
|
description = options.description;
|
6996
7033
|
assertionName = options.assertionName || assertionName;
|
7034
|
+
|
6997
7035
|
}
|
6998
7036
|
|
6999
|
-
|
7037
|
+
interval = interval || this.waitForPollInterval
|
7038
|
+
timeout = timeout || this.waitForTimeout
|
7039
|
+
|
7040
|
+
var async = this.beginAsync(timeout + 2 * interval),
|
7000
7041
|
me = this;
|
7001
7042
|
|
7002
7043
|
var sourceLine = me.getSourceLine();
|
@@ -7015,13 +7056,12 @@ Role('Siesta.Test.More', {
|
|
7015
7056
|
if (this.typeOf(method) == 'Number') {
|
7016
7057
|
pollTimeout = originalSetTimeout(function() {
|
7017
7058
|
me.endAsync(async);
|
7018
|
-
|
7059
|
+
me.processCallbackFromTest(callback, [], scope || me)
|
7060
|
+
|
7019
7061
|
}, method);
|
7020
7062
|
|
7021
7063
|
me.finalizeWaiting(waitAssertion, true, 'Waited ' + method + ' ms');
|
7022
7064
|
} else {
|
7023
|
-
|
7024
|
-
timeout = timeout || this.waitForTimeout
|
7025
7065
|
|
7026
7066
|
var startDate = new Date()
|
7027
7067
|
|
@@ -7058,9 +7098,10 @@ Role('Siesta.Test.More', {
|
|
7058
7098
|
me.endAsync(async);
|
7059
7099
|
|
7060
7100
|
me.finalizeWaiting(waitAssertion, true, 'Waited ' + time + ' ms for ' + description);
|
7061
|
-
|
7101
|
+
|
7102
|
+
me.processCallbackFromTest(callback, [ result ], scope || me)
|
7062
7103
|
} else
|
7063
|
-
pollTimeout = originalSetTimeout(pollFunc,
|
7104
|
+
pollTimeout = originalSetTimeout(pollFunc, interval)
|
7064
7105
|
}
|
7065
7106
|
|
7066
7107
|
pollFunc()
|
@@ -7072,8 +7113,8 @@ Role('Siesta.Test.More', {
|
|
7072
7113
|
// returns "true" if "next" is used,
|
7073
7114
|
analyzeChainStep : function (func) {
|
7074
7115
|
var sources = func.toString()
|
7075
|
-
var firstArg = sources.match(/function\s*[^(]*\((.*?)(?:,|\))/)[ 1 ]
|
7076
|
-
|
7116
|
+
var firstArg = sources.match(/function\s*[^(]*\(\s*(.*?)\s*(?:,|\))/)[ 1 ]
|
7117
|
+
|
7077
7118
|
if (!firstArg) return false
|
7078
7119
|
|
7079
7120
|
var body = sources.match(/\{([\s\S]*)\}/)[ 1 ]
|
@@ -7158,11 +7199,13 @@ Role('Siesta.Test.More', {
|
|
7158
7199
|
observeTest : this
|
7159
7200
|
})
|
7160
7201
|
|
7202
|
+
var sourceLine = me.getSourceLine();
|
7203
|
+
|
7161
7204
|
// inline any arrays in the arguments into one array
|
7162
|
-
var steps
|
7205
|
+
var steps = Array.prototype.concat.apply([], arguments)
|
7163
7206
|
|
7164
|
-
var len
|
7165
|
-
var args
|
7207
|
+
var len = steps.length
|
7208
|
+
var args = []
|
7166
7209
|
|
7167
7210
|
Joose.A.each(steps, function (step, index) {
|
7168
7211
|
|
@@ -7170,10 +7213,29 @@ Role('Siesta.Test.More', {
|
|
7170
7213
|
|
7171
7214
|
queue.addAsyncStep({
|
7172
7215
|
processor : function (data) {
|
7173
|
-
var
|
7216
|
+
var isWaitStep = step.action == 'wait' || step.waitFor
|
7217
|
+
|
7218
|
+
if (!isWaitStep) {
|
7219
|
+
var timeout = step.timeout || me.defaultTimeout
|
7220
|
+
|
7221
|
+
// + 100 to allow `waitFor` steps (which will be waiting the `timeout` time) to
|
7222
|
+
// generate their own failures
|
7223
|
+
var async = me.beginAsync(timeout + 100, function () {
|
7224
|
+
me.fail(
|
7225
|
+
'The step in `t.chain()` call did not complete within required timeframe, chain can not proceed',
|
7226
|
+
{
|
7227
|
+
sourceLine : sourceLine,
|
7228
|
+
annotation : 'Step number: ' + (index + 1) + ' (1-based)' + (sourceLine ? '\nAt line : ' + sourceLine : ''),
|
7229
|
+
ownTextOnly : true
|
7230
|
+
}
|
7231
|
+
)
|
7232
|
+
|
7233
|
+
return true
|
7234
|
+
})
|
7235
|
+
}
|
7174
7236
|
|
7175
7237
|
var nextFunc = function () {
|
7176
|
-
me.endAsync(async)
|
7238
|
+
if (!isWaitStep) me.endAsync(async)
|
7177
7239
|
|
7178
7240
|
args = Array.prototype.slice.call(arguments);
|
7179
7241
|
|
@@ -7194,9 +7256,23 @@ Role('Siesta.Test.More', {
|
|
7194
7256
|
// and finalize the async frame manually, as the "nextFunc" for last step will never be called
|
7195
7257
|
isLast && me.endAsync(async)
|
7196
7258
|
|
7259
|
+
} else if (me.typeOf(step) == 'String') {
|
7260
|
+
var action = new Siesta.Test.Action.Eval({
|
7261
|
+
actionString : step,
|
7262
|
+
next : nextFunc,
|
7263
|
+
test : me
|
7264
|
+
})
|
7265
|
+
|
7266
|
+
action.process()
|
7267
|
+
|
7197
7268
|
} else {
|
7198
7269
|
if (!step.args) step.args = args
|
7199
7270
|
|
7271
|
+
// Don't pass target to next step if it is a waitFor action, it does not make sense and messes up the arguments
|
7272
|
+
if (!isLast && (steps[ index + 1 ].waitFor || steps[ index + 1 ].action == 'wait')) {
|
7273
|
+
step.passTargetToNext = false;
|
7274
|
+
}
|
7275
|
+
|
7200
7276
|
step.next = nextFunc
|
7201
7277
|
step.test = me
|
7202
7278
|
|
@@ -7303,6 +7379,9 @@ Class('Siesta.Test', {
|
|
7303
7379
|
results : Joose.I.Array,
|
7304
7380
|
|
7305
7381
|
run : { required : true },
|
7382
|
+
startTestAnchor : null,
|
7383
|
+
exceptionCatcher : null,
|
7384
|
+
testErrorClass : null,
|
7306
7385
|
|
7307
7386
|
harness : { required : true },
|
7308
7387
|
|
@@ -7428,9 +7507,16 @@ Class('Siesta.Test', {
|
|
7428
7507
|
* @return {Object} Object with properties `{ ready : true/false, reason : 'description' }`
|
7429
7508
|
*/
|
7430
7509
|
isReady: function() {
|
7510
|
+
// this should allow us to wait until the presense of "run" function
|
7511
|
+
// it will become available after call to StartTest method
|
7512
|
+
// which some users may call asynchronously, after some delay
|
7513
|
+
// see https://www.assembla.com/spaces/bryntum/tickets/379
|
7514
|
+
// in this case test can not be configured using object as 1st argument for StartTest
|
7515
|
+
this.run = this.run || this.getStartTestAnchor().args && this.getStartTestAnchor().args[ 0 ]
|
7516
|
+
|
7431
7517
|
return {
|
7432
|
-
ready :
|
7433
|
-
reason : ''
|
7518
|
+
ready : this.typeOf(this.run) == 'Function',
|
7519
|
+
reason : 'No code provided to test'
|
7434
7520
|
}
|
7435
7521
|
},
|
7436
7522
|
|
@@ -7561,7 +7647,7 @@ Class('Siesta.Test', {
|
|
7561
7647
|
var gotDesc = params.gotDesc || 'Got'
|
7562
7648
|
var needDesc = params.needDesc || 'Need'
|
7563
7649
|
|
7564
|
-
if (assertionName || sourceLine) strings.push(
|
7650
|
+
if (!params.ownTextOnly && (assertionName || sourceLine)) strings.push(
|
7565
7651
|
'Failed assertion ' + (assertionName ? '[' + assertionName + '] ' : '') + this.formatSourceLine(sourceLine)
|
7566
7652
|
)
|
7567
7653
|
|
@@ -7630,23 +7716,83 @@ Class('Siesta.Test', {
|
|
7630
7716
|
},
|
7631
7717
|
|
7632
7718
|
|
7719
|
+
getStartTestAnchor : function () {
|
7720
|
+
return this.startTestAnchor
|
7721
|
+
},
|
7722
|
+
|
7723
|
+
|
7724
|
+
getExceptionCatcher : function () {
|
7725
|
+
return this.exceptionCatcher
|
7726
|
+
},
|
7727
|
+
|
7728
|
+
|
7729
|
+
getTestErrorClass : function () {
|
7730
|
+
return this.testErrorClass
|
7731
|
+
},
|
7732
|
+
|
7733
|
+
|
7734
|
+
processCallbackFromTest : function (callback, args, scope) {
|
7735
|
+
var me = this
|
7736
|
+
|
7737
|
+
if (this.transparentEx) {
|
7738
|
+
callback.apply(scope || this.global, args || [])
|
7739
|
+
} else {
|
7740
|
+
var e = this.getExceptionCatcher()(function(){
|
7741
|
+
callback.apply(scope || me.global, args || [])
|
7742
|
+
})
|
7743
|
+
|
7744
|
+
if (e) {
|
7745
|
+
this.failWithException(e)
|
7746
|
+
|
7747
|
+
// flow should be interrupted - exception detected
|
7748
|
+
return false
|
7749
|
+
}
|
7750
|
+
}
|
7751
|
+
|
7752
|
+
// flow can be continued
|
7753
|
+
return true
|
7754
|
+
},
|
7755
|
+
|
7756
|
+
|
7633
7757
|
getStackTrace : function (e) {
|
7634
7758
|
if (Object(e) !== e) return null
|
7635
7759
|
if (!e.stack) return null
|
7636
7760
|
|
7637
|
-
var text = e.stack
|
7638
|
-
var
|
7761
|
+
var text = e.stack + '';
|
7762
|
+
var isFirefox = /^@/.test(text)
|
7763
|
+
var lines = text.split('\n')
|
7764
|
+
|
7765
|
+
var result = []
|
7639
7766
|
var match
|
7640
7767
|
|
7641
|
-
var
|
7768
|
+
for (var i = 0; i < lines.length; i++) {
|
7769
|
+
if (!lines[ i ]) continue
|
7770
|
+
|
7771
|
+
if (!i) {
|
7772
|
+
if (isFirefox)
|
7773
|
+
result.push(e + '')
|
7774
|
+
else {
|
7775
|
+
result.push(lines[ i ])
|
7776
|
+
continue;
|
7777
|
+
}
|
7778
|
+
}
|
7642
7779
|
|
7643
|
-
|
7644
|
-
|
7645
|
-
|
7646
|
-
|
7647
|
-
|
7648
|
-
|
7649
|
-
result.push(
|
7780
|
+
if (isFirefox) {
|
7781
|
+
match = /@(.*?):(\d+)/.exec(lines[ i ]);
|
7782
|
+
|
7783
|
+
// the format of stack trace in Firefox has changed, 080_exception_parsing should fail
|
7784
|
+
if (!match) return null
|
7785
|
+
|
7786
|
+
result.push(' at line ' + match[ 2 ] + ' of ' + match[ 1 ])
|
7787
|
+
} else {
|
7788
|
+
match = /\s*at\s(.*?):(\d+):(\d+)/.exec(lines[ i ]);
|
7789
|
+
|
7790
|
+
// the format of stack trace in Chrome has changed, 080_exception_parsing should fail
|
7791
|
+
if (!match) return null
|
7792
|
+
|
7793
|
+
result.push(' at line ' + match[ 2 ] + ', character ' + match[ 3 ] + ', of ' + match[ 1 ])
|
7794
|
+
}
|
7795
|
+
}
|
7650
7796
|
|
7651
7797
|
if (!result.length) return null
|
7652
7798
|
|
@@ -7730,7 +7876,7 @@ Class('Siesta.Test', {
|
|
7730
7876
|
* @param {String} desc The description of the assertion
|
7731
7877
|
*/
|
7732
7878
|
is : function (got, expected, desc) {
|
7733
|
-
if (got instanceof this.global.Date) {
|
7879
|
+
if (expected && got instanceof this.global.Date) {
|
7734
7880
|
this.isDateEqual(got, expected, desc);
|
7735
7881
|
} else if (got == expected)
|
7736
7882
|
this.pass(desc)
|
@@ -7863,7 +8009,7 @@ Class('Siesta.Test', {
|
|
7863
8009
|
|
7864
8010
|
/**
|
7865
8011
|
* This method starts the "asynchronous frame". The test will wait for all asynchronous frames to complete before it will finalize.
|
7866
|
-
* The frame
|
8012
|
+
* The frame should be finished with the {@link #endAsync} call within the provided `time`, otherwise a failure will be reported.
|
7867
8013
|
*
|
7868
8014
|
* For example:
|
7869
8015
|
*
|
@@ -7878,27 +8024,42 @@ Class('Siesta.Test', {
|
|
7878
8024
|
*
|
7879
8025
|
*
|
7880
8026
|
* @param {Number} time The maximum time (in ms) to wait until force the finalization of this async frame. Optional. Default time is 15000 ms.
|
8027
|
+
* @param {Function} errback Optional. The function to call in case the call to {@link #endAsync} was not detected withing `time`. If function
|
8028
|
+
* will return any "truthy" value, the failure will not be reported (you can report own failure with this errback).
|
8029
|
+
*
|
7881
8030
|
* @return {Object} The frame object, which can be used in {@link #endAsync} call
|
7882
8031
|
*/
|
7883
|
-
beginAsync : function (time) {
|
8032
|
+
beginAsync : function (time, errback) {
|
8033
|
+
time = time || this.defaultTimeout
|
8034
|
+
|
7884
8035
|
var me = this
|
7885
8036
|
var originalSetTimeout = this.originalSetTimeout
|
7886
8037
|
|
8038
|
+
var index = this.timeoutsCount++
|
8039
|
+
|
7887
8040
|
// in NodeJS `setTimeout` returns an object and not a simple ID, so we try hard to store that object under unique index
|
7888
8041
|
// also using `setTimeout` from the scope of test - as timeouts in different scopes in browsers are mis-synchronized
|
7889
8042
|
// can't just use `this.originalSetTimeout` because of scoping issues
|
7890
|
-
var timeoutId
|
7891
|
-
|
7892
|
-
|
7893
|
-
|
7894
|
-
|
8043
|
+
var timeoutId = originalSetTimeout(function () {
|
8044
|
+
|
8045
|
+
if (me.hasAsyncFrame(index)) {
|
8046
|
+
if (!errback || !errback.call(me, me)) me.fail('No matching `endAsync` call within ' + time + 'ms')
|
8047
|
+
|
8048
|
+
me.endAsync(index)
|
8049
|
+
}
|
8050
|
+
}, time)
|
7895
8051
|
|
7896
|
-
this.timeoutIds[ index ]
|
8052
|
+
this.timeoutIds[ index ] = timeoutId
|
7897
8053
|
|
7898
8054
|
return index
|
7899
8055
|
},
|
7900
8056
|
|
7901
8057
|
|
8058
|
+
hasAsyncFrame : function (index) {
|
8059
|
+
return this.timeoutIds.hasOwnProperty(index)
|
8060
|
+
},
|
8061
|
+
|
8062
|
+
|
7902
8063
|
/**
|
7903
8064
|
* This method finalize the "asynchronous frame" started with {@link #beginAsync}.
|
7904
8065
|
*
|
@@ -7931,7 +8092,6 @@ Class('Siesta.Test', {
|
|
7931
8092
|
|
7932
8093
|
|
7933
8094
|
clearTimeouts : function () {
|
7934
|
-
var me = this
|
7935
8095
|
var originalClearTimeout = this.originalClearTimeout
|
7936
8096
|
|
7937
8097
|
Joose.O.each(this.timeoutIds, function (value, id) {
|
@@ -8008,10 +8168,14 @@ Class('Siesta.Test', {
|
|
8008
8168
|
originalClearTimeout : this.originalClearTimeout
|
8009
8169
|
})
|
8010
8170
|
|
8011
|
-
var exception = this.
|
8171
|
+
var exception = this.getExceptionCatcher()(function(){
|
8012
8172
|
code(todo)
|
8013
8173
|
})
|
8014
8174
|
|
8175
|
+
todo.global = null
|
8176
|
+
todo.originalSetTimeout = null
|
8177
|
+
todo.originalClearTimeout = null
|
8178
|
+
|
8015
8179
|
if (exception !== undefined) this.diag("TODO section threw an exception: [" + exception + "]")
|
8016
8180
|
},
|
8017
8181
|
|
@@ -8049,7 +8213,8 @@ Class('Siesta.Test', {
|
|
8049
8213
|
this.harness.onTestStart(this)
|
8050
8214
|
|
8051
8215
|
/**
|
8052
|
-
* This event is fired when the individual test case starts. When started
|
8216
|
+
* This event is fired when the individual test case starts. When *started*, test may still be waiting for the {@link #isReady} conditions
|
8217
|
+
* to be fullfilled. Once all conditions will be fullfilled, test will be *launched*.
|
8053
8218
|
*
|
8054
8219
|
* This event bubbles up to the {@link Siesta.Harness harness}, you can observe it on harness as well.
|
8055
8220
|
*
|
@@ -8061,7 +8226,7 @@ Class('Siesta.Test', {
|
|
8061
8226
|
this.fireEvent('teststart', this);
|
8062
8227
|
|
8063
8228
|
if (alreadyFailedWithException) {
|
8064
|
-
this.failWithException(alreadyFailedWithException)
|
8229
|
+
this.failWithException(alreadyFailedWithException)
|
8065
8230
|
|
8066
8231
|
return
|
8067
8232
|
}
|
@@ -8141,7 +8306,7 @@ Class('Siesta.Test', {
|
|
8141
8306
|
else
|
8142
8307
|
// in browser (where `timeoutId` is a number) - to the `idsToIndex` hash
|
8143
8308
|
me.idsToIndex[ timeoutId ] = index
|
8144
|
-
|
8309
|
+
|
8145
8310
|
return me.timeoutIds[ index ] = timeoutId
|
8146
8311
|
}
|
8147
8312
|
|
@@ -8181,10 +8346,13 @@ Class('Siesta.Test', {
|
|
8181
8346
|
global.clearTimeout = originalClearTimeout
|
8182
8347
|
}
|
8183
8348
|
|
8184
|
-
originalSetTimeout = me.originalSetTimeout
|
8185
|
-
originalClearTimeout = me.originalClearTimeout
|
8349
|
+
originalSetTimeout = me.originalSetTimeout = null
|
8350
|
+
originalClearTimeout = me.originalClearTimeout = null
|
8186
8351
|
|
8187
|
-
me.global = global
|
8352
|
+
me.global = global = null
|
8353
|
+
me.run = run = null
|
8354
|
+
me.exceptionCatcher = me.testErrorClass = null
|
8355
|
+
me.startTestAnchor = null
|
8188
8356
|
}
|
8189
8357
|
|
8190
8358
|
var run = this.run
|
@@ -8192,7 +8360,7 @@ Class('Siesta.Test', {
|
|
8192
8360
|
if (this.transparentEx)
|
8193
8361
|
run(me)
|
8194
8362
|
else
|
8195
|
-
var e =
|
8363
|
+
var e = this.getExceptionCatcher()(function(){
|
8196
8364
|
run(me)
|
8197
8365
|
})
|
8198
8366
|
|
@@ -8214,11 +8382,12 @@ Class('Siesta.Test', {
|
|
8214
8382
|
if (force) this.clearTimeouts()
|
8215
8383
|
|
8216
8384
|
if (!Joose.O.isEmpty(this.timeoutIds)) {
|
8217
|
-
if (
|
8218
|
-
|
8219
|
-
|
8385
|
+
if (
|
8386
|
+
!this.__timeoutWarning && this.overrideSetTimeout && this.lastActivityDate &&
|
8387
|
+
new Date() - this.lastActivityDate > this.defaultTimeout * 2
|
8388
|
+
) {
|
8220
8389
|
this.diag('Your test is still considered to be running, if this is unexpected please see console for more information');
|
8221
|
-
this.warn('
|
8390
|
+
this.warn('Your test [' + this.url + '] has not finalized, most likely since a timer (setTimeout) is still active. ' +
|
8222
8391
|
'If this is the expected behavior, try setting "overrideSetTimeout : false" on your Harness configuration.');
|
8223
8392
|
this.__timeoutWarning = true;
|
8224
8393
|
}
|
@@ -8259,25 +8428,6 @@ Class('Siesta.Test', {
|
|
8259
8428
|
this.fireEvent('testfinalize', this);
|
8260
8429
|
|
8261
8430
|
this.callback && this.callback()
|
8262
|
-
|
8263
|
-
// // attempting to clear all references to scope, but with delay, to allow
|
8264
|
-
// // other potentially delayed actions to access `global`
|
8265
|
-
// var me = this
|
8266
|
-
//
|
8267
|
-
// var originalSetTimeout = me.originalSetTimeout
|
8268
|
-
//
|
8269
|
-
// // setTimeout from the scope of harness
|
8270
|
-
// originalSetTimeout(function () {
|
8271
|
-
// if (me.overrideSetTimeout) {
|
8272
|
-
// me.global.setTimeout = me.originalSetTimeout
|
8273
|
-
// me.global.clearTimeout = me.originalClearTimeout
|
8274
|
-
// }
|
8275
|
-
//
|
8276
|
-
// originalSetTimeout = me.originalSetTimeout = null
|
8277
|
-
// me.originalClearTimeout = null
|
8278
|
-
//
|
8279
|
-
// me.global = null
|
8280
|
-
// }, 700)
|
8281
8431
|
},
|
8282
8432
|
|
8283
8433
|
|
@@ -8454,9 +8604,10 @@ Class('Siesta.Test', {
|
|
8454
8604
|
|
8455
8605
|
|
8456
8606
|
warn : function (message) {
|
8457
|
-
|
8458
|
-
|
8459
|
-
|
8607
|
+
this.addResult(new Siesta.Result.Diagnostic({
|
8608
|
+
description : message,
|
8609
|
+
isWarning : true
|
8610
|
+
}))
|
8460
8611
|
}
|
8461
8612
|
}
|
8462
8613
|
|
@@ -8471,6 +8622,21 @@ Role('Siesta.Test.Todo', {
|
|
8471
8622
|
|
8472
8623
|
methods : {
|
8473
8624
|
|
8625
|
+
getExceptionCatcher : function () {
|
8626
|
+
return this.parent.getExceptionCatcher()
|
8627
|
+
},
|
8628
|
+
|
8629
|
+
|
8630
|
+
getTestErrorClass : function () {
|
8631
|
+
return this.parent.getTestErrorClass()
|
8632
|
+
},
|
8633
|
+
|
8634
|
+
|
8635
|
+
getStartTestAnchor : function () {
|
8636
|
+
return this.parent.getStartTestAnchor()
|
8637
|
+
},
|
8638
|
+
|
8639
|
+
|
8474
8640
|
addResult : function (result) {
|
8475
8641
|
if (result instanceof Siesta.Result.Assertion) result.isTodo = true
|
8476
8642
|
|
@@ -8539,6 +8705,10 @@ Class('Siesta.Test.Action', {
|
|
8539
8705
|
has : {
|
8540
8706
|
args : null,
|
8541
8707
|
|
8708
|
+
/**
|
8709
|
+
* @cfg {String} desc When provided, once step is completed, a passing assertion with this text will be added to a test.
|
8710
|
+
* This configuration option can be useful to indicate the progress of "wait" steps
|
8711
|
+
*/
|
8542
8712
|
desc : null,
|
8543
8713
|
test : { required : true },
|
8544
8714
|
next : { required : true },
|
@@ -8598,6 +8768,8 @@ Class('Siesta.Test.Action.Done', {
|
|
8598
8768
|
|
8599
8769
|
process : function () {
|
8600
8770
|
this.test.done(this.delay)
|
8771
|
+
|
8772
|
+
this.next()
|
8601
8773
|
}
|
8602
8774
|
}
|
8603
8775
|
});
|
@@ -8673,14 +8845,14 @@ Class('Siesta.Test.Action.Wait', {
|
|
8673
8845
|
*
|
8674
8846
|
* A number of milliseconds to wait before continuing.
|
8675
8847
|
*/
|
8676
|
-
delay
|
8848
|
+
delay : 1000,
|
8677
8849
|
|
8678
8850
|
/**
|
8679
8851
|
* @cfg {Number} timeout
|
8680
8852
|
*
|
8681
8853
|
* The maximum amount of time to wait for the condition to be fulfilled. Defaults to the {@link Siesta.Test.ExtJS#waitForTimeout} value.
|
8682
8854
|
*/
|
8683
|
-
timeout
|
8855
|
+
timeout : null,
|
8684
8856
|
|
8685
8857
|
/**
|
8686
8858
|
* @cfg {Array} args
|
@@ -8725,25 +8897,24 @@ Class('Siesta.Test.Action.Wait', {
|
|
8725
8897
|
this.args = [ waitFor ];
|
8726
8898
|
waitFor = '';
|
8727
8899
|
}
|
8728
|
-
|
8900
|
+
|
8901
|
+
if (waitFor == null) {
|
8902
|
+
this.args = [ this.delay ];
|
8903
|
+
waitFor = '';
|
8904
|
+
}
|
8905
|
+
|
8729
8906
|
if (this.test.typeOf(this.args) !== "Array") {
|
8730
8907
|
this.args = [ this.args ];
|
8731
8908
|
}
|
8732
8909
|
|
8733
|
-
|
8734
|
-
|
8735
|
-
|
8736
|
-
var methodName = 'waitFor' + Joose.S.uppercaseFirst(waitFor);
|
8737
|
-
|
8738
|
-
if (!test[methodName]){
|
8739
|
-
throw 'Could not find a waitFor method named ' + methodName;
|
8740
|
-
}
|
8741
|
-
test[methodName].apply(test, this.args.concat(this.next, test, this.timeout || test.waitForTimeout));
|
8742
|
-
} else {
|
8743
|
-
var originalSetTimeout = test.originalSetTimeout;
|
8910
|
+
// also allow full method names
|
8911
|
+
waitFor = waitFor.replace(/^waitFor/, '')
|
8912
|
+
var methodName = 'waitFor' + Joose.S.uppercaseFirst(waitFor);
|
8744
8913
|
|
8745
|
-
|
8914
|
+
if (!test[methodName]){
|
8915
|
+
throw 'Could not find a waitFor method named ' + methodName;
|
8746
8916
|
}
|
8917
|
+
test[methodName].apply(test, this.args.concat(this.next, test, this.timeout || test.waitForTimeout));
|
8747
8918
|
}
|
8748
8919
|
}
|
8749
8920
|
});
|
@@ -8753,6 +8924,115 @@ Joose.A.each(['wait', 'delay'], function(name) {
|
|
8753
8924
|
});;
|
8754
8925
|
/**
|
8755
8926
|
|
8927
|
+
@class Siesta.Test.Action.Eval
|
8928
|
+
@extends Siesta.Test.Action
|
8929
|
+
|
8930
|
+
This action can be included in the `t.chain` steps only with a plain string. Siesta will examine the passed string,
|
8931
|
+
and call an apropriate method of the test class. String should have the following format:
|
8932
|
+
|
8933
|
+
methodName(params)
|
8934
|
+
|
8935
|
+
Method name is anything until the first parenthes. Method name may have an optional prefix `t.`.
|
8936
|
+
Everything in between of outermost parentheses will be treated as parameters for method call. For example:
|
8937
|
+
|
8938
|
+
t.chain(
|
8939
|
+
// string should look like a usual method call,
|
8940
|
+
// but arguments can't reference any variables
|
8941
|
+
// strings should be quoted, to include quoting symbol in string use double slash: \\
|
8942
|
+
't.click("combo[type=some\\"Type] => .x-form-trigger")',
|
8943
|
+
|
8944
|
+
// leading "t." is optional, but quoting is not
|
8945
|
+
'waitForComponent("combo[type=someType]")',
|
8946
|
+
|
8947
|
+
// JSON objects are ok, but they should be a valid JSON - ie object properties should be quoted
|
8948
|
+
'myClick([ 10, 10 ], { "foo" : "bar" })',
|
8949
|
+
)
|
8950
|
+
|
8951
|
+
* **Note** You can pass the JSON objects as arguments, but they should be serialized as valid JSON - ie object properties should be quoted.
|
8952
|
+
|
8953
|
+
* **Note** A callback for next step in chain will be always appended to provided parameters. Make sure it is placed in a correct spot!
|
8954
|
+
For example if method signature is `t.someMethod(param1, param2, callback)` and you are calling this method as:
|
8955
|
+
|
8956
|
+
t.chain(
|
8957
|
+
`t.someMethod("text")`
|
8958
|
+
)
|
8959
|
+
it will fail - callback will be provided in place of `param2`. Instead call it as:
|
8960
|
+
|
8961
|
+
t.chain(
|
8962
|
+
`t.someMethod("text", null)`
|
8963
|
+
)
|
8964
|
+
|
8965
|
+
This action may save you few keystrokes, when you need to perform some action with static arguments (known prior the action).
|
8966
|
+
|
8967
|
+
*/
|
8968
|
+
Class('Siesta.Test.Action.Eval', {
|
8969
|
+
|
8970
|
+
isa : Siesta.Test.Action,
|
8971
|
+
|
8972
|
+
has : {
|
8973
|
+
/**
|
8974
|
+
* @cfg {Object} options
|
8975
|
+
*
|
8976
|
+
* Any options that will be used when simulating the event. For information about possible
|
8977
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
8978
|
+
*/
|
8979
|
+
actionString : null
|
8980
|
+
},
|
8981
|
+
|
8982
|
+
|
8983
|
+
methods : {
|
8984
|
+
|
8985
|
+
process : function () {
|
8986
|
+
var test = this.test
|
8987
|
+
var parsed = this.parseActionString(this.actionString)
|
8988
|
+
|
8989
|
+
if (parsed.error) {
|
8990
|
+
test.fail(parsed.error)
|
8991
|
+
this.next()
|
8992
|
+
return
|
8993
|
+
}
|
8994
|
+
|
8995
|
+
var methodName = parsed.methodName
|
8996
|
+
|
8997
|
+
if (!methodName || test.typeOf(test[ methodName ]) != 'Function') {
|
8998
|
+
test.fail("Invalid method name: " + methodName)
|
8999
|
+
this.next()
|
9000
|
+
return
|
9001
|
+
}
|
9002
|
+
|
9003
|
+
parsed.params.push(this.next)
|
9004
|
+
|
9005
|
+
test[ methodName ].apply(test, parsed.params)
|
9006
|
+
},
|
9007
|
+
|
9008
|
+
|
9009
|
+
parseActionString : function (actionString) {
|
9010
|
+
var match = /^\s*(.+?)\(\s*(.*)\s*\)\s*$/.exec(actionString)
|
9011
|
+
|
9012
|
+
if (!match) return {
|
9013
|
+
error : "Wrong format of the action string: " + actionString
|
9014
|
+
}
|
9015
|
+
|
9016
|
+
var methodName = match[ 1 ].replace(/^t\./, '')
|
9017
|
+
|
9018
|
+
try {
|
9019
|
+
var params = JSON.parse('[' + match[ 2 ] + ']')
|
9020
|
+
} catch (e) {
|
9021
|
+
return {
|
9022
|
+
error : "Can't parse arguments: " + match[ 2 ]
|
9023
|
+
}
|
9024
|
+
}
|
9025
|
+
|
9026
|
+
return {
|
9027
|
+
methodName : methodName,
|
9028
|
+
params : params
|
9029
|
+
}
|
9030
|
+
}
|
9031
|
+
}
|
9032
|
+
});
|
9033
|
+
;
|
9034
|
+
/**
|
9035
|
+
|
8756
9036
|
@class Siesta.Harness
|
8757
9037
|
|
8758
9038
|
`Siesta.Harness` is an abstract base harness class in Siesta hierarchy. This class provides no UI,
|
@@ -8836,7 +9116,7 @@ Class('Siesta.Harness', {
|
|
8836
9116
|
|
8837
9117
|
has : {
|
8838
9118
|
/**
|
8839
|
-
* @cfg {String} title The title of the test suite. Can contain HTML.
|
9119
|
+
* @cfg {String} title The title of the test suite. Can contain HTML. When provided in the test file descriptor - will change the name of test in the harness UI.
|
8840
9120
|
*/
|
8841
9121
|
title : null,
|
8842
9122
|
|
@@ -8849,8 +9129,6 @@ Class('Siesta.Harness', {
|
|
8849
9129
|
testClass : Siesta.Test,
|
8850
9130
|
contentManagerClass : Siesta.Content.Manager,
|
8851
9131
|
|
8852
|
-
testsByURL : Joose.I.Object,
|
8853
|
-
|
8854
9132
|
// fields of test descriptor:
|
8855
9133
|
// - id - either `url` or wbs + group - computed
|
8856
9134
|
// - url
|
@@ -8872,7 +9150,12 @@ Class('Siesta.Harness', {
|
|
8872
9150
|
descriptors : Joose.I.Array,
|
8873
9151
|
descriptorsById : Joose.I.Object,
|
8874
9152
|
|
9153
|
+
launchCounter : 0,
|
9154
|
+
|
9155
|
+
launches : Joose.I.Object,
|
9156
|
+
|
8875
9157
|
scopesByURL : Joose.I.Object,
|
9158
|
+
testsByURL : Joose.I.Object,
|
8876
9159
|
|
8877
9160
|
/**
|
8878
9161
|
* @cfg {Boolean} transparentEx When set to `true` harness will not try to catch any exception, thrown from the test code.
|
@@ -8935,7 +9218,7 @@ Class('Siesta.Harness', {
|
|
8935
9218
|
* This option can be also specified in the test file descriptor.
|
8936
9219
|
*/
|
8937
9220
|
expectedGlobals : Joose.I.Array,
|
8938
|
-
// will be populated by `
|
9221
|
+
// will be populated by `populateCleanScopeGlobals`
|
8939
9222
|
cleanScopeGlobals : Joose.I.Array,
|
8940
9223
|
|
8941
9224
|
/**
|
@@ -9035,6 +9318,17 @@ Class('Siesta.Harness', {
|
|
9035
9318
|
*/
|
9036
9319
|
keepResults : true,
|
9037
9320
|
|
9321
|
+
/**
|
9322
|
+
* @cfg {Number} keepNLastResults
|
9323
|
+
*
|
9324
|
+
* Only meaningful when {@link #keepResults} is set to `false`. Indicates the number of the test results which still should be kept, for user examination.
|
9325
|
+
* Results are cleared when their total number exceed this value, based on FIFO order.
|
9326
|
+
*/
|
9327
|
+
keepNLastResults : 2,
|
9328
|
+
|
9329
|
+
lastResultsURLs : Joose.I.Array,
|
9330
|
+
lastResultsByURL : Joose.I.Object,
|
9331
|
+
|
9038
9332
|
/**
|
9039
9333
|
* @cfg {Boolean} overrideSetTimeout When set to `false`, the tests will not override "setTimeout" from the context of each test
|
9040
9334
|
* for asynchronous code tracking. User will need to use `beginAsync/endAsync` calls to indicate that test is still running.
|
@@ -9225,13 +9519,14 @@ Class('Siesta.Harness', {
|
|
9225
9519
|
},
|
9226
9520
|
|
9227
9521
|
/**
|
9228
|
-
* This method will launch a test suite. It accepts a variable number of *test file descriptors
|
9522
|
+
* This method will launch a test suite. It accepts a variable number of *test file descriptors* or an array of such. A test file descritor is one of the following:
|
9229
9523
|
*
|
9230
9524
|
* - a string, containing a test file url
|
9231
9525
|
* - an object containing the `url` property `{ url : '...', option1 : 'value1', option2 : 'value2' }`. The `url` property should point to the test file.
|
9232
9526
|
* Other properties can contain values of some configuration options of the harness (marked accordingly). In this case, they will **override** the corresponding values,
|
9233
9527
|
* provided to harness or parent descriptor.
|
9234
|
-
* - an object `{ group : 'groupName', items : [], expanded : true, option1 : 'value1' }` specifying the folder of test files. The `
|
9528
|
+
* - an object `{ group : 'groupName', items : [], expanded : true, option1 : 'value1' }` specifying the folder of test files. The `expanded` property
|
9529
|
+
* sets the initial state of the folder - "collapsed/expanded". The `items` property can contain an array of test file descriptors.
|
9235
9530
|
* Other properties will override the applicable harness options **for all child descriptors**.
|
9236
9531
|
*
|
9237
9532
|
* Groups (folder) may contain nested groups. Number of nesting levels is not limited.
|
@@ -9294,19 +9589,19 @@ Class('Siesta.Harness', {
|
|
9294
9589
|
*
|
9295
9590
|
* Values from this object takes the highest priority and will override any other configuration.
|
9296
9591
|
*
|
9297
|
-
* @param {Mixed} descriptor1
|
9592
|
+
* @param {Array/Mixed} descriptor1 or an array of descriptors
|
9298
9593
|
* @param {Mixed} descriptor2
|
9299
9594
|
* @param {Mixed} descriptorN
|
9300
9595
|
*/
|
9301
9596
|
start : function () {
|
9302
9597
|
// a bit hackish - used by Selenium reporter..
|
9303
|
-
var me =
|
9598
|
+
var me = Siesta.my.activeHarness = this
|
9304
9599
|
|
9305
9600
|
this.mainPreset = new Siesta.Content.Preset({
|
9306
9601
|
preload : this.processPreloadArray(this.preload)
|
9307
9602
|
})
|
9308
9603
|
|
9309
|
-
var descriptors = this.descriptors = Joose.A.map(arguments, function (desc, index) {
|
9604
|
+
var descriptors = this.descriptors = Joose.A.map(Array.prototype.concat.apply([], arguments), function (desc, index) {
|
9310
9605
|
return me.normalizeDescriptor(desc, me, index)
|
9311
9606
|
})
|
9312
9607
|
|
@@ -9334,6 +9629,8 @@ Class('Siesta.Harness', {
|
|
9334
9629
|
if (desc.preset != me.mainPreset) presets.push(desc.preset)
|
9335
9630
|
|
9336
9631
|
testScriptsPreset.addResource(desc.url)
|
9632
|
+
|
9633
|
+
me.deleteTestByURL(desc.url)
|
9337
9634
|
})
|
9338
9635
|
|
9339
9636
|
// cache either everything (this.cachePreload) or only the test files (to be able to show missing files / show content)
|
@@ -9359,8 +9656,9 @@ Class('Siesta.Harness', {
|
|
9359
9656
|
|
9360
9657
|
// if testConfig contains the "preload" or "alsoPreload" key - then we need to update the preset of the descriptor
|
9361
9658
|
if (testConfig && (testConfig.preload || testConfig.alsoPreload)) desc.preset = me.getDescriptorPreset(desc)
|
9362
|
-
} else
|
9363
|
-
|
9659
|
+
} else
|
9660
|
+
// allow subclasses to define there own logic when found missing test file
|
9661
|
+
me.markMissingFile(desc)
|
9364
9662
|
|
9365
9663
|
me.normalizeScopeProvider(desc)
|
9366
9664
|
})
|
@@ -9377,6 +9675,11 @@ Class('Siesta.Harness', {
|
|
9377
9675
|
},
|
9378
9676
|
|
9379
9677
|
|
9678
|
+
markMissingFile : function (desc) {
|
9679
|
+
desc.isMissing = true
|
9680
|
+
},
|
9681
|
+
|
9682
|
+
|
9380
9683
|
flattenDescriptors : function (descriptors, includeFolders) {
|
9381
9684
|
var flatten = []
|
9382
9685
|
var me = this
|
@@ -9568,10 +9871,10 @@ Class('Siesta.Harness', {
|
|
9568
9871
|
|
9569
9872
|
|
9570
9873
|
getSeedingCode : function (desc) {
|
9571
|
-
return 'StartTest = function () { StartTest.args = arguments };' +
|
9874
|
+
return 'StartTest = startTest = function () { StartTest.args = arguments };' +
|
9572
9875
|
// for older IE - the try/catch should be from the same context as the exception
|
9573
9876
|
'StartTest.exceptionCatcher = function (func) { var ex; try { func() } catch (e) { ex = e; }; return ex; };' +
|
9574
|
-
'StartTest.
|
9877
|
+
'StartTest.testErrorClass = Error;'
|
9575
9878
|
},
|
9576
9879
|
|
9577
9880
|
|
@@ -9584,12 +9887,54 @@ Class('Siesta.Harness', {
|
|
9584
9887
|
},
|
9585
9888
|
|
9586
9889
|
|
9890
|
+
keepTestResult : function (url) {
|
9891
|
+
// already keeping
|
9892
|
+
if (this.lastResultsByURL[ url ]) {
|
9893
|
+
var indexOf = -1
|
9894
|
+
|
9895
|
+
Joose.A.each(this.lastResultsURLs, function (resultUrl, i) {
|
9896
|
+
if (resultUrl == url) { indexOf = i; return false }
|
9897
|
+
})
|
9898
|
+
|
9899
|
+
this.lastResultsURLs.splice(indexOf, 1)
|
9900
|
+
this.lastResultsURLs.push(url)
|
9901
|
+
|
9902
|
+
return
|
9903
|
+
}
|
9904
|
+
|
9905
|
+
this.lastResultsURLs.push(url)
|
9906
|
+
this.lastResultsByURL[ url ] = true
|
9907
|
+
|
9908
|
+
if (this.lastResultsURLs.length > this.keepNLastResults) this.releaseTestResult()
|
9909
|
+
},
|
9910
|
+
|
9911
|
+
|
9912
|
+
releaseTestResult : function () {
|
9913
|
+
if (this.lastResultsURLs.length <= this.keepNLastResults) return
|
9914
|
+
|
9915
|
+
var url = this.lastResultsURLs.shift()
|
9916
|
+
|
9917
|
+
delete this.lastResultsByURL[ url ]
|
9918
|
+
|
9919
|
+
var test = this.getTestByURL(url)
|
9920
|
+
|
9921
|
+
if (test && test.isFinished()) this.cleanupScopeForURL(url)
|
9922
|
+
},
|
9923
|
+
|
9924
|
+
|
9925
|
+
isKeepingResultForURL : function (url) {
|
9926
|
+
return this.lastResultsByURL[ url ]
|
9927
|
+
},
|
9928
|
+
|
9929
|
+
|
9587
9930
|
setupScope : function (desc) {
|
9588
9931
|
var url = desc.url
|
9589
9932
|
var scopeProvideClass = eval(desc.scopeProvider)
|
9590
9933
|
|
9591
9934
|
this.cleanupScopeForURL(url)
|
9592
9935
|
|
9936
|
+
this.keepTestResult(url)
|
9937
|
+
|
9593
9938
|
return this.scopesByURL[ url ] = new scopeProvideClass(this.getScopeProviderConfigFor(desc))
|
9594
9939
|
},
|
9595
9940
|
|
@@ -9705,7 +10050,7 @@ Class('Siesta.Harness', {
|
|
9705
10050
|
var args = startTestAnchor && startTestAnchor.args
|
9706
10051
|
|
9707
10052
|
// pick either 1st or 2nd argument depending which one is a function
|
9708
|
-
var runFunc = args && (typeof args[ 0 ] == 'function'
|
10053
|
+
var runFunc = args && (typeof args[ 0 ] == 'function' ? args[ 0 ] : args[ 1 ])
|
9709
10054
|
|
9710
10055
|
me.launchTest({
|
9711
10056
|
testHolder : testHolder,
|
@@ -9716,6 +10061,8 @@ Class('Siesta.Harness', {
|
|
9716
10061
|
preloadErrors : preloadErrors,
|
9717
10062
|
onErrorHandler : onErrorHandler,
|
9718
10063
|
|
10064
|
+
startTestAnchor : startTestAnchor,
|
10065
|
+
|
9719
10066
|
runFunc : runFunc
|
9720
10067
|
}, callback)
|
9721
10068
|
});
|
@@ -9736,15 +10083,18 @@ Class('Siesta.Harness', {
|
|
9736
10083
|
// after the scope setup, the `onerror` handler might be cleared - installing it again
|
9737
10084
|
if (!this.getDescriptorConfig(desc, 'transparentEx')) scopeProvider.addOnErrorHandler(options.onErrorHandler)
|
9738
10085
|
|
9739
|
-
var testConfig = me.getNewTestConfiguration(desc, scopeProvider, options.contentManager, options.urlOptions, options.runFunc)
|
10086
|
+
var testConfig = me.getNewTestConfiguration(desc, scopeProvider, options.contentManager, options.urlOptions, options.runFunc, options.startTestAnchor)
|
9740
10087
|
|
9741
10088
|
testConfig.callback = function () {
|
9742
|
-
if (!me.keepResults)
|
10089
|
+
if (!me.keepResults) {
|
10090
|
+
if (!me.isKeepingResultForURL(url)) me.cleanupScopeForURL(url)
|
10091
|
+
}
|
9743
10092
|
|
9744
10093
|
callback && callback()
|
9745
10094
|
}
|
9746
10095
|
|
9747
|
-
var test = options.testHolder.test =
|
10096
|
+
var test = options.testHolder.test = new testClass(testConfig)
|
10097
|
+
this.saveTestWithURL(url, test)
|
9748
10098
|
|
9749
10099
|
scopeProvider.scope.setTimeout(function() {
|
9750
10100
|
//console.timeEnd('launch')
|
@@ -9755,7 +10105,7 @@ Class('Siesta.Harness', {
|
|
9755
10105
|
},
|
9756
10106
|
|
9757
10107
|
|
9758
|
-
getNewTestConfiguration : function (desc, scopeProvider, contentManager, options, runFunc) {
|
10108
|
+
getNewTestConfiguration : function (desc, scopeProvider, contentManager, options, runFunc, startTestAnchor) {
|
9759
10109
|
var scope = scopeProvider.scope
|
9760
10110
|
|
9761
10111
|
var config = {
|
@@ -9763,6 +10113,11 @@ Class('Siesta.Harness', {
|
|
9763
10113
|
|
9764
10114
|
harness : this,
|
9765
10115
|
run : runFunc,
|
10116
|
+
|
10117
|
+
startTestAnchor : startTestAnchor,
|
10118
|
+
|
10119
|
+
exceptionCatcher : startTestAnchor.exceptionCatcher,
|
10120
|
+
testErrorClass : startTestAnchor.testErrorClass,
|
9766
10121
|
|
9767
10122
|
expectedGlobals : this.cleanScopeGlobals.concat(this.getDescriptorConfig(desc, 'expectedGlobals')),
|
9768
10123
|
autoCheckGlobals : this.getDescriptorConfig(desc, 'autoCheckGlobals'),
|
@@ -9797,18 +10152,34 @@ Class('Siesta.Harness', {
|
|
9797
10152
|
},
|
9798
10153
|
|
9799
10154
|
|
10155
|
+
getTestByURL : function (url) {
|
10156
|
+
return this.testsByURL[ url ]
|
10157
|
+
},
|
10158
|
+
|
10159
|
+
|
10160
|
+
saveTestWithURL : function (url, test) {
|
10161
|
+
this.testsByURL[ url ] = test
|
10162
|
+
},
|
10163
|
+
|
10164
|
+
|
10165
|
+
deleteTestByURL : function (url) {
|
10166
|
+
delete this.testsByURL[ url ]
|
10167
|
+
},
|
10168
|
+
|
10169
|
+
|
9800
10170
|
allPassed : function () {
|
9801
10171
|
var allPassed = true
|
9802
10172
|
var me = this
|
9803
10173
|
|
9804
10174
|
Joose.A.each(this.flattenDescriptors(this.descriptors), function (descriptor) {
|
9805
|
-
|
10175
|
+
// if at least one test is missing then something is wrong
|
10176
|
+
if (descriptor.isMissing) { allPassed = false; return false }
|
10177
|
+
|
10178
|
+
var test = me.getTestByURL(descriptor.url)
|
9806
10179
|
|
9807
10180
|
// ignore missing tests (could be skipped by test filtering
|
9808
10181
|
if (!test) return
|
9809
10182
|
|
9810
|
-
if (descriptor.isMissing) { allPassed = false; return false }
|
9811
|
-
|
9812
10183
|
allPassed = allPassed && test.isPassed()
|
9813
10184
|
})
|
9814
10185
|
|
@@ -9825,6 +10196,11 @@ Class('Siesta.Harness', {
|
|
9825
10196
|
if (!this[ methodName ]) throw "Can't generate report - missing the `" + methodName + "` method"
|
9826
10197
|
|
9827
10198
|
return this[ methodName ](options)
|
10199
|
+
},
|
10200
|
+
|
10201
|
+
|
10202
|
+
typeOf : function (object) {
|
10203
|
+
return Object.prototype.toString.call(object).replace(/^\[object /, '').replace(/\]$/, '')
|
9828
10204
|
}
|
9829
10205
|
}
|
9830
10206
|
// eof methods
|
@@ -9904,15 +10280,26 @@ Role('Siesta.Role.ConsoleReporter', {
|
|
9904
10280
|
|
9905
10281
|
does : Siesta.Role.CanStyleOutput,
|
9906
10282
|
|
10283
|
+
has : {
|
10284
|
+
// special flag which will be used by automation launchers to prevent the summary message
|
10285
|
+
// after every page
|
10286
|
+
needSummaryMessage : true
|
10287
|
+
},
|
10288
|
+
|
9907
10289
|
|
9908
10290
|
after : {
|
9909
10291
|
|
10292
|
+
markMissingFile : function (desc) {
|
10293
|
+
this.warn("Test file [" + desc.url + "] not found.")
|
10294
|
+
},
|
10295
|
+
|
10296
|
+
|
9910
10297
|
onTestSuiteStart : function () {
|
9911
10298
|
},
|
9912
10299
|
|
9913
10300
|
|
9914
10301
|
onTestSuiteEnd : function () {
|
9915
|
-
this.log(this.getSummaryMessage())
|
10302
|
+
if (this.needSummaryMessage) this.log(this.getSummaryMessage())
|
9916
10303
|
|
9917
10304
|
this.exit(this.getExitCode())
|
9918
10305
|
},
|
@@ -9949,7 +10336,14 @@ Role('Siesta.Role.ConsoleReporter', {
|
|
9949
10336
|
}
|
9950
10337
|
}
|
9951
10338
|
|
9952
|
-
if (result instanceof Siesta.Result.Diagnostic)
|
10339
|
+
if (result instanceof Siesta.Result.Diagnostic) {
|
10340
|
+
text = this.styled(text, 'bold')
|
10341
|
+
|
10342
|
+
if (result.isWarning) {
|
10343
|
+
this.warn(text)
|
10344
|
+
return
|
10345
|
+
}
|
10346
|
+
}
|
9953
10347
|
|
9954
10348
|
if (needToShow) this.log(text)
|
9955
10349
|
}
|
@@ -9958,8 +10352,13 @@ Role('Siesta.Role.ConsoleReporter', {
|
|
9958
10352
|
|
9959
10353
|
methods : {
|
9960
10354
|
|
9961
|
-
|
9962
|
-
|
10355
|
+
warn : function (text) {
|
10356
|
+
this.log(this.styled('[WARN] ', 'red') + text)
|
10357
|
+
},
|
10358
|
+
|
10359
|
+
|
10360
|
+
getSummaryMessage : function (allPassed) {
|
10361
|
+
allPassed = allPassed != null ? allPassed : this.allPassed()
|
9963
10362
|
|
9964
10363
|
return allPassed ? this.style().bold(this.style().green('All tests passed')) : this.style().bold(this.style().red('There are failures'))
|
9965
10364
|
},
|
@@ -10144,13 +10543,14 @@ Class('Siesta.Harness.NodeJS', {
|
|
10144
10543
|
;
|
10145
10544
|
;
|
10146
10545
|
Class('Siesta', {
|
10147
|
-
/*PKGVERSION*/VERSION : '1.1.
|
10546
|
+
/*PKGVERSION*/VERSION : '1.1.5',
|
10148
10547
|
|
10149
10548
|
// "my" should been named "static"
|
10150
10549
|
my : {
|
10151
10550
|
|
10152
10551
|
has : {
|
10153
|
-
config
|
10552
|
+
config : null,
|
10553
|
+
activeHarness : null
|
10154
10554
|
},
|
10155
10555
|
|
10156
10556
|
methods : {
|