siesta 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 : {
|