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
|
6933
6958
|
|
6934
|
-
|
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
|
+
}
|
6967
|
+
|
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
|
@@ -18824,6 +19200,15 @@ delegate = function (event) {
|
|
18824
19200
|
}
|
18825
19201
|
};
|
18826
19202
|
})(window);
|
19203
|
+
|
19204
|
+
jQuery.fn.center = function () {
|
19205
|
+
this.css("position","absolute");
|
19206
|
+
this.css("top", Math.max(0, (($(window).height() - this.outerHeight()) / 2) +
|
19207
|
+
$(window).scrollTop()) + "px");
|
19208
|
+
this.css("left", Math.max(0, (($(window).width() - this.outerWidth()) / 2) +
|
19209
|
+
$(window).scrollLeft()) + "px");
|
19210
|
+
return this;
|
19211
|
+
}
|
18827
19212
|
;
|
18828
19213
|
Class("JooseX.SimpleRequest", {
|
18829
19214
|
|
@@ -19046,6 +19431,8 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19046
19431
|
*/
|
19047
19432
|
target : { required : false },
|
19048
19433
|
|
19434
|
+
normalizedTarget : null,
|
19435
|
+
|
19049
19436
|
/**
|
19050
19437
|
* @cfg {Object} el
|
19051
19438
|
*
|
@@ -19053,7 +19440,7 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19053
19440
|
*/
|
19054
19441
|
|
19055
19442
|
/**
|
19056
|
-
* @cfg {Boolean} passTargetToNext Whether to pass
|
19443
|
+
* @cfg {Boolean} passTargetToNext Whether to pass the target further on chain as the first argument
|
19057
19444
|
*/
|
19058
19445
|
passTargetToNext : true
|
19059
19446
|
},
|
@@ -19066,12 +19453,12 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19066
19453
|
var me = this
|
19067
19454
|
var prevNext = this.next
|
19068
19455
|
|
19069
|
-
// Needs to be 'resolved'
|
19070
|
-
// e.g. unchecking a checkbox
|
19071
|
-
var realTarget = me.test.normalizeActionTarget(me.getTarget());
|
19456
|
+
// // Needs to be 'resolved' at action instantiate time since the action may cause the selector not to be found
|
19457
|
+
// // e.g. unchecking a checkbox
|
19458
|
+
// var realTarget = me.test.normalizeActionTarget(me.getTarget());
|
19072
19459
|
|
19073
19460
|
this.next = function () {
|
19074
|
-
prevNext.call(this,
|
19461
|
+
prevNext.call(this, me.normalizedTarget);
|
19075
19462
|
}
|
19076
19463
|
}
|
19077
19464
|
},
|
@@ -19093,11 +19480,11 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19093
19480
|
var test = this.test;
|
19094
19481
|
var target = this.target || test.getElementAtCursor();
|
19095
19482
|
|
19096
|
-
if (test.typeOf(target) === 'Function')
|
19097
|
-
|
19098
|
-
|
19483
|
+
if (test.typeOf(target) === 'Function') target = target.call(test, this);
|
19484
|
+
|
19485
|
+
this.normalizedTarget = test.normalizeActionTarget(target)
|
19099
19486
|
|
19100
|
-
return this.__cachedTarget__
|
19487
|
+
return this.__cachedTarget__ = target
|
19101
19488
|
}
|
19102
19489
|
}
|
19103
19490
|
});
|
@@ -19189,19 +19576,100 @@ Siesta.Test.ActionRegistry.registerAction('longpress', Siesta.Test.Action.LongPr
|
|
19189
19576
|
;
|
19190
19577
|
/**
|
19191
19578
|
|
19192
|
-
@class Siesta.Test.Action.
|
19579
|
+
@class Siesta.Test.Action.Tap
|
19193
19580
|
@extends Siesta.Test.Action
|
19194
19581
|
@mixin Siesta.Test.Action.Role.HasTarget
|
19195
19582
|
|
19196
|
-
This action can be included in
|
19583
|
+
This action can be included in the `t.chain` call with "tap" shortcut:
|
19197
19584
|
|
19198
19585
|
t.chain(
|
19199
19586
|
{
|
19200
|
-
action : '
|
19587
|
+
action : 'tap',
|
19201
19588
|
target : someDOMElement
|
19202
19589
|
}
|
19203
19590
|
)
|
19204
19591
|
|
19592
|
+
This action will perform a {@link Siesta.Test.Browser#tap tap} on the provided {@link #target}.
|
19593
|
+
|
19594
|
+
*/
|
19595
|
+
Class('Siesta.Test.Action.Tap', {
|
19596
|
+
|
19597
|
+
isa : Siesta.Test.Action,
|
19598
|
+
|
19599
|
+
does : Siesta.Test.Action.Role.HasTarget,
|
19600
|
+
|
19601
|
+
has : {
|
19602
|
+
requiredTestMethod : 'tap'
|
19603
|
+
},
|
19604
|
+
|
19605
|
+
|
19606
|
+
methods : {
|
19607
|
+
|
19608
|
+
process : function () {
|
19609
|
+
this.test.tap(this.getTarget(), this.next)
|
19610
|
+
}
|
19611
|
+
}
|
19612
|
+
});
|
19613
|
+
|
19614
|
+
|
19615
|
+
Siesta.Test.ActionRegistry.registerAction('tap', Siesta.Test.Action.Tap);
|
19616
|
+
/**
|
19617
|
+
|
19618
|
+
@class Siesta.Test.Action.DoubleTap
|
19619
|
+
@extends Siesta.Test.Action
|
19620
|
+
@mixin Siesta.Test.Action.Role.HasTarget
|
19621
|
+
|
19622
|
+
This action will perform a {@link Siesta.Test.Browser#doubleClick double tap} on the provided {@link #target}.
|
19623
|
+
|
19624
|
+
This action can be included in the `t.chain` call with "doubletap" or "doubleTap" shortcuts:
|
19625
|
+
|
19626
|
+
t.chain(
|
19627
|
+
{
|
19628
|
+
action : 'doubletap',
|
19629
|
+
target : someDOMElement
|
19630
|
+
}
|
19631
|
+
)
|
19632
|
+
|
19633
|
+
|
19634
|
+
*/
|
19635
|
+
Class('Siesta.Test.Action.DoubleTap', {
|
19636
|
+
|
19637
|
+
isa : Siesta.Test.Action,
|
19638
|
+
|
19639
|
+
does : Siesta.Test.Action.Role.HasTarget,
|
19640
|
+
|
19641
|
+
has : {
|
19642
|
+
requiredTestMethod : 'doubleTap'
|
19643
|
+
},
|
19644
|
+
|
19645
|
+
|
19646
|
+
methods : {
|
19647
|
+
|
19648
|
+
process : function () {
|
19649
|
+
this.test.doubleTap(this.getTarget(), this.next)
|
19650
|
+
}
|
19651
|
+
}
|
19652
|
+
});
|
19653
|
+
|
19654
|
+
|
19655
|
+
Siesta.Test.ActionRegistry.registerAction('doubletap', Siesta.Test.Action.DoubleTap)
|
19656
|
+
;
|
19657
|
+
/**
|
19658
|
+
|
19659
|
+
@class Siesta.Test.Action.MouseDown
|
19660
|
+
@extends Siesta.Test.Action
|
19661
|
+
@mixin Siesta.Test.Action.Role.HasTarget
|
19662
|
+
|
19663
|
+
This action can be included in a `t.chain` call with "mouseDown" shortcut:
|
19664
|
+
|
19665
|
+
t.chain(
|
19666
|
+
{
|
19667
|
+
action : 'mouseDown',
|
19668
|
+
target : someDOMElement,
|
19669
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19670
|
+
}
|
19671
|
+
)
|
19672
|
+
|
19205
19673
|
This action will perform a {@link Siesta.Test.Browser#MouseDown MouseDown} on the provided {@link #target}.
|
19206
19674
|
|
19207
19675
|
*/
|
@@ -19212,7 +19680,15 @@ Class('Siesta.Test.Action.MouseDown', {
|
|
19212
19680
|
does : Siesta.Test.Action.Role.HasTarget,
|
19213
19681
|
|
19214
19682
|
has : {
|
19215
|
-
requiredTestMethod : 'mouseDown'
|
19683
|
+
requiredTestMethod : 'mouseDown',
|
19684
|
+
|
19685
|
+
/**
|
19686
|
+
* @cfg {Object} options
|
19687
|
+
*
|
19688
|
+
* Any options that will be used when simulating the event. For information about possible
|
19689
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19690
|
+
*/
|
19691
|
+
options : null
|
19216
19692
|
},
|
19217
19693
|
|
19218
19694
|
|
@@ -19220,7 +19696,7 @@ Class('Siesta.Test.Action.MouseDown', {
|
|
19220
19696
|
|
19221
19697
|
process : function () {
|
19222
19698
|
// This method is synchronous
|
19223
|
-
this.test.mouseDown(this.getTarget());
|
19699
|
+
this.test.mouseDown(this.getTarget(), this.options);
|
19224
19700
|
|
19225
19701
|
setTimeout(this.next, 100);
|
19226
19702
|
}
|
@@ -19242,7 +19718,8 @@ This action can be included in a `t.chain` call with "mouseUp" shortcut:
|
|
19242
19718
|
t.chain(
|
19243
19719
|
{
|
19244
19720
|
action : 'mouseUp',
|
19245
|
-
target : someDOMElement
|
19721
|
+
target : someDOMElement,
|
19722
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19246
19723
|
}
|
19247
19724
|
)
|
19248
19725
|
|
@@ -19256,7 +19733,15 @@ Class('Siesta.Test.Action.MouseUp', {
|
|
19256
19733
|
does : Siesta.Test.Action.Role.HasTarget,
|
19257
19734
|
|
19258
19735
|
has : {
|
19259
|
-
requiredTestMethod : 'mouseUp'
|
19736
|
+
requiredTestMethod : 'mouseUp',
|
19737
|
+
|
19738
|
+
/**
|
19739
|
+
* @cfg {Object} options
|
19740
|
+
*
|
19741
|
+
* Any options that will be used when simulating the event. For information about possible
|
19742
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19743
|
+
*/
|
19744
|
+
options : null
|
19260
19745
|
},
|
19261
19746
|
|
19262
19747
|
|
@@ -19264,7 +19749,7 @@ Class('Siesta.Test.Action.MouseUp', {
|
|
19264
19749
|
|
19265
19750
|
process : function () {
|
19266
19751
|
// This method is synchronous
|
19267
|
-
this.test.mouseUp(this.getTarget());
|
19752
|
+
this.test.mouseUp(this.getTarget(), this.options);
|
19268
19753
|
|
19269
19754
|
setTimeout(this.next, 100);
|
19270
19755
|
}
|
@@ -19286,7 +19771,8 @@ This action can be included in the `t.chain` call with "click" shortcut:
|
|
19286
19771
|
t.chain(
|
19287
19772
|
{
|
19288
19773
|
action : 'click',
|
19289
|
-
target : someDOMElement
|
19774
|
+
target : someDOMElement,
|
19775
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19290
19776
|
}
|
19291
19777
|
)
|
19292
19778
|
|
@@ -19300,21 +19786,29 @@ Class('Siesta.Test.Action.Click', {
|
|
19300
19786
|
does : Siesta.Test.Action.Role.HasTarget,
|
19301
19787
|
|
19302
19788
|
has : {
|
19303
|
-
requiredTestMethod : 'click'
|
19789
|
+
requiredTestMethod : 'click',
|
19790
|
+
|
19791
|
+
/**
|
19792
|
+
* @cfg {Object} options
|
19793
|
+
*
|
19794
|
+
* Any options that will be used when simulating the event. For information about possible
|
19795
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19796
|
+
*/
|
19797
|
+
options : null
|
19304
19798
|
},
|
19305
19799
|
|
19306
19800
|
|
19307
19801
|
methods : {
|
19308
19802
|
|
19309
19803
|
process : function () {
|
19310
|
-
this.test.click(this.getTarget(), this.next)
|
19804
|
+
this.test.click(this.getTarget(), this.next, null, this.options);
|
19311
19805
|
}
|
19312
19806
|
}
|
19313
19807
|
});
|
19314
19808
|
|
19315
19809
|
|
19316
|
-
Siesta.Test.ActionRegistry.registerAction('click', Siesta.Test.Action.Click)
|
19317
|
-
|
19810
|
+
Siesta.Test.ActionRegistry.registerAction('click', Siesta.Test.Action.Click);
|
19811
|
+
;
|
19318
19812
|
/**
|
19319
19813
|
|
19320
19814
|
@class Siesta.Test.Action.DoubleClick
|
@@ -19327,8 +19821,9 @@ This action can be included in the `t.chain` call with "doubleclick" or "doubleC
|
|
19327
19821
|
|
19328
19822
|
t.chain(
|
19329
19823
|
{
|
19330
|
-
action : '
|
19331
|
-
target : someDOMElement
|
19824
|
+
action : 'doubleclick',
|
19825
|
+
target : someDOMElement,
|
19826
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19332
19827
|
}
|
19333
19828
|
)
|
19334
19829
|
|
@@ -19341,21 +19836,28 @@ Class('Siesta.Test.Action.DoubleClick', {
|
|
19341
19836
|
does : Siesta.Test.Action.Role.HasTarget,
|
19342
19837
|
|
19343
19838
|
has : {
|
19344
|
-
requiredTestMethod : 'doubleClick'
|
19839
|
+
requiredTestMethod : 'doubleClick',
|
19840
|
+
|
19841
|
+
/**
|
19842
|
+
* @cfg {Object} options
|
19843
|
+
*
|
19844
|
+
* Any options that will be used when simulating the event. For information about possible
|
19845
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19846
|
+
*/
|
19847
|
+
options : null
|
19345
19848
|
},
|
19346
19849
|
|
19347
19850
|
|
19348
19851
|
methods : {
|
19349
19852
|
|
19350
19853
|
process : function () {
|
19351
|
-
this.test.doubleClick(this.getTarget(), this.next)
|
19854
|
+
this.test.doubleClick(this.getTarget(), this.next, null, this.options)
|
19352
19855
|
}
|
19353
19856
|
}
|
19354
19857
|
});
|
19355
19858
|
|
19356
19859
|
|
19357
19860
|
Siesta.Test.ActionRegistry.registerAction('doubleclick', Siesta.Test.Action.DoubleClick)
|
19358
|
-
Siesta.Test.ActionRegistry.registerAction('doubletap', Siesta.Test.Action.DoubleClick)
|
19359
19861
|
;
|
19360
19862
|
/**
|
19361
19863
|
|
@@ -19402,6 +19904,7 @@ Class('Siesta.Test.Action.Type', {
|
|
19402
19904
|
// By default use the current focused element as target
|
19403
19905
|
this.target = this.target || this.test.global.document.activeElement;
|
19404
19906
|
|
19907
|
+
// additional "getTarget" to allow functions as "target" value
|
19405
19908
|
this.test.type(this.getTarget(), this.text, this.next)
|
19406
19909
|
}
|
19407
19910
|
}
|
@@ -19788,7 +20291,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19788
20291
|
|
19789
20292
|
// Normalize target
|
19790
20293
|
if (!this.isArray(target)) {
|
19791
|
-
target = this.detectCenter(this.normalizeElement(target));
|
20294
|
+
target = this.detectCenter(this.normalizeElement(target), 'moveMouseTo');
|
19792
20295
|
}
|
19793
20296
|
this.moveMouse(this.currentPosition, target, callback, scope);
|
19794
20297
|
},
|
@@ -19900,12 +20403,12 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19900
20403
|
queue.run(function () {
|
19901
20404
|
me.endAsync(a);
|
19902
20405
|
|
19903
|
-
callback &&
|
20406
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
19904
20407
|
})
|
19905
20408
|
},
|
19906
20409
|
|
19907
20410
|
|
19908
|
-
normalizeClickTarget : function (el) {
|
20411
|
+
normalizeClickTarget : function (el, clickMethod) {
|
19909
20412
|
var doc = this.global.document
|
19910
20413
|
var xy
|
19911
20414
|
|
@@ -19914,13 +20417,12 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19914
20417
|
if (this.isArray(el)) {
|
19915
20418
|
xy = el;
|
19916
20419
|
el = doc.elementFromPoint(xy[0], xy[1]) || doc.body;
|
19917
|
-
options = { clientX : xy[0], clientY : xy[1] };
|
19918
20420
|
} else {
|
19919
20421
|
el = this.normalizeElement(el)
|
19920
20422
|
doc = el.ownerDocument
|
19921
|
-
xy = this.detectCenter(el);
|
20423
|
+
xy = this.detectCenter(el, clickMethod);
|
19922
20424
|
el = doc.elementFromPoint(xy[0], xy[1]) || doc.body;
|
19923
|
-
|
20425
|
+
el && this.$(el).is(':visible');
|
19924
20426
|
}
|
19925
20427
|
|
19926
20428
|
if (!el) {
|
@@ -19935,14 +20437,18 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19935
20437
|
},
|
19936
20438
|
|
19937
20439
|
|
19938
|
-
genericMouseClick : function (el, callback, scope, clickMethod) {
|
20440
|
+
genericMouseClick : function (el, callback, scope, options, clickMethod) {
|
19939
20441
|
if (jQuery.isFunction(el)) {
|
19940
20442
|
scope = callback;
|
19941
20443
|
callback = el;
|
19942
20444
|
el = null;
|
19943
20445
|
}
|
19944
20446
|
|
19945
|
-
var data = this.normalizeClickTarget(el)
|
20447
|
+
var data = this.normalizeClickTarget(el, clickMethod);
|
20448
|
+
|
20449
|
+
data.options = data.options || {};
|
20450
|
+
|
20451
|
+
$.extend(data.options, options);
|
19946
20452
|
|
19947
20453
|
// the asynchronous case
|
19948
20454
|
if (this.moveCursorBetweenPoints && callback) {
|
@@ -19973,10 +20479,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19973
20479
|
*
|
19974
20480
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
19975
20481
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
19976
|
-
* @param {Object} scope (optional) The scope for the callback
|
20482
|
+
* @param {Object} scope (optional) The scope for the callback
|
20483
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
19977
20484
|
*/
|
19978
|
-
click: function (el, callback, scope) {
|
19979
|
-
this.genericMouseClick(el, callback, scope, 'simulateMouseClick')
|
20485
|
+
click: function (el, callback, scope, options) {
|
20486
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateMouseClick')
|
19980
20487
|
},
|
19981
20488
|
|
19982
20489
|
|
@@ -20000,10 +20507,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20000
20507
|
*
|
20001
20508
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
20002
20509
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
20003
|
-
* @param {Object} scope (optional) The scope for the callback
|
20510
|
+
* @param {Object} scope (optional) The scope for the callback
|
20511
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
20004
20512
|
*/
|
20005
|
-
rightClick: function (el, callback, scope) {
|
20006
|
-
this.genericMouseClick(el, callback, scope, 'simulateRightClick')
|
20513
|
+
rightClick: function (el, callback, scope, options) {
|
20514
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateRightClick')
|
20007
20515
|
},
|
20008
20516
|
|
20009
20517
|
|
@@ -20027,10 +20535,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20027
20535
|
*
|
20028
20536
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
20029
20537
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
20030
|
-
* @param {Object} scope (optional) The scope for the callback
|
20538
|
+
* @param {Object} scope (optional) The scope for the callback
|
20539
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
20031
20540
|
*/
|
20032
|
-
doubleClick: function (el, callback, scope) {
|
20033
|
-
this.genericMouseClick(el, callback, scope, 'simulateDoubleClick')
|
20541
|
+
doubleClick: function (el, callback, scope, options) {
|
20542
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateDoubleClick')
|
20034
20543
|
},
|
20035
20544
|
|
20036
20545
|
/**
|
@@ -20130,7 +20639,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20130
20639
|
queue.run(function () {
|
20131
20640
|
me.endAsync(async);
|
20132
20641
|
|
20133
|
-
callback &&
|
20642
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20134
20643
|
})
|
20135
20644
|
},
|
20136
20645
|
|
@@ -20169,7 +20678,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20169
20678
|
queue.run(function () {
|
20170
20679
|
me.endAsync(async);
|
20171
20680
|
|
20172
|
-
callback &&
|
20681
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20173
20682
|
})
|
20174
20683
|
},
|
20175
20684
|
|
@@ -20212,7 +20721,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20212
20721
|
queue.run(function () {
|
20213
20722
|
me.endAsync(async);
|
20214
20723
|
|
20215
|
-
callback &&
|
20724
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20216
20725
|
})
|
20217
20726
|
},
|
20218
20727
|
|
@@ -20285,7 +20794,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20285
20794
|
if (this.isArray(source)) {
|
20286
20795
|
sourceXY = source;
|
20287
20796
|
} else {
|
20288
|
-
sourceXY = this.detectCenter(this.normalizeElement(source));
|
20797
|
+
sourceXY = this.detectCenter(this.normalizeElement(source), 'dragTo');
|
20289
20798
|
}
|
20290
20799
|
|
20291
20800
|
// Normalize target
|
@@ -20328,7 +20837,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20328
20837
|
if (this.isArray(source)) {
|
20329
20838
|
sourceXY = source;
|
20330
20839
|
} else {
|
20331
|
-
sourceXY = this.detectCenter(this.normalizeElement(source));
|
20840
|
+
sourceXY = this.detectCenter(this.normalizeElement(source), 'dragBy');
|
20332
20841
|
}
|
20333
20842
|
targetXY = [ sourceXY[0] + delta[0], sourceXY[1] + delta[1] ];
|
20334
20843
|
|
@@ -20422,16 +20931,21 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20422
20931
|
queue.run(function () {
|
20423
20932
|
me.endAsync(async)
|
20424
20933
|
|
20425
|
-
callback &&
|
20934
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20426
20935
|
});
|
20427
20936
|
},
|
20428
20937
|
|
20429
|
-
detectCenter : function(el) {
|
20938
|
+
detectCenter : function (el, actionName, skipWarning) {
|
20430
20939
|
var hidden = !this.isElementVisible(el);
|
20431
20940
|
|
20432
20941
|
// Trigger mouseover in case source is hidden, possibly shown only when hovering over it (its x/y cannot be determined if display:none)
|
20433
20942
|
if (hidden) {
|
20434
|
-
this.simulateEvent(el, "mouseover", { clientX: 0, clientY: 0});
|
20943
|
+
this.simulateEvent(el, "mouseover", { clientX: 0, clientY: 0 });
|
20944
|
+
|
20945
|
+
if (!skipWarning && !this.isElementVisible(el)) this.fail(
|
20946
|
+
(actionName ? "Target element of action [" + actionName + "]" : "Target element of some action") +
|
20947
|
+
" is not visible: " + (el.id ? '#' + el.id : el)
|
20948
|
+
)
|
20435
20949
|
}
|
20436
20950
|
var center = this.findCenter(el);
|
20437
20951
|
if (hidden) {
|
@@ -20774,21 +21288,22 @@ Role('Siesta.Test.Simulate.Keyboard', {
|
|
20774
21288
|
* @param {Object} scope (optional) the scope for the callback
|
20775
21289
|
*/
|
20776
21290
|
type: function (el, text, callback, scope) {
|
20777
|
-
el = this.normalizeElement(el || this.
|
21291
|
+
el = this.normalizeElement(el || this.global.document.activeElement);
|
20778
21292
|
|
20779
21293
|
// Some browsers (IE/FF) do not overwrite selected text, do it manually.
|
20780
21294
|
var selText = this.getSelectedText(el);
|
21295
|
+
|
20781
21296
|
if (selText) {
|
20782
21297
|
el.value = el.value.replace(selText, '');
|
20783
21298
|
}
|
20784
21299
|
|
21300
|
+
var me = this
|
21301
|
+
|
20785
21302
|
if (el.readOnly || el.disabled) {
|
20786
|
-
callback &&
|
21303
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20787
21304
|
|
20788
21305
|
return;
|
20789
21306
|
}
|
20790
|
-
|
20791
|
-
var me = this
|
20792
21307
|
|
20793
21308
|
// Extract normal chars, or special keys in brackets such as [TAB], [RIGHT] or [ENTER]
|
20794
21309
|
var keys = (text + '').match(/\[([^\])]+\])|([^\[])/g) || [];
|
@@ -20838,7 +21353,7 @@ Role('Siesta.Test.Simulate.Keyboard', {
|
|
20838
21353
|
queue.run(function () {
|
20839
21354
|
me.endAsync(async)
|
20840
21355
|
|
20841
|
-
callback &&
|
21356
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20842
21357
|
})
|
20843
21358
|
},
|
20844
21359
|
|
@@ -21125,6 +21640,37 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21125
21640
|
return {
|
21126
21641
|
ready : true
|
21127
21642
|
}
|
21643
|
+
},
|
21644
|
+
|
21645
|
+
// Overridden to deal with the different event firing mechanisms in Ext JS 3 vs 4
|
21646
|
+
// This code is required because in IE are simulated using fireEvent instead of dispatchEvent and it seems fireEvent will
|
21647
|
+
// will not update a checkbox 'checked' state properly so we're forcing the toggle to solve this situation.
|
21648
|
+
// This issue is only relevant in IE + Ext.
|
21649
|
+
//
|
21650
|
+
// Test case: 507_form_checkbox.t.js
|
21651
|
+
simulateMouseClick: function (el, callback, scope) {
|
21652
|
+
|
21653
|
+
// Force check toggle for input checkboxes
|
21654
|
+
if (this.simulateEventsWith === 'fireEvent' && (el.type === 'checkbox' || el.type === 'radio') && !el.disabled && !el.readOnly) {
|
21655
|
+
var oldState = el.checked;
|
21656
|
+
|
21657
|
+
if (callback) {
|
21658
|
+
this.SUPER(el, function() {
|
21659
|
+
if (el.checked === oldState) {
|
21660
|
+
el.checked = !oldState;
|
21661
|
+
}
|
21662
|
+
callback.call(scope || this);
|
21663
|
+
});
|
21664
|
+
} else {
|
21665
|
+
this.SUPER(el);
|
21666
|
+
|
21667
|
+
if (el.checked === oldState) {
|
21668
|
+
el.checked = !oldState;
|
21669
|
+
}
|
21670
|
+
}
|
21671
|
+
} else {
|
21672
|
+
this.SUPERARG(arguments);
|
21673
|
+
}
|
21128
21674
|
}
|
21129
21675
|
},
|
21130
21676
|
|
@@ -21228,11 +21774,33 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21228
21774
|
|
21229
21775
|
return component;
|
21230
21776
|
},
|
21231
|
-
|
21232
|
-
|
21233
|
-
|
21777
|
+
|
21778
|
+
/**
|
21779
|
+
* @private
|
21780
|
+
* @param {Ext.Component} comp the Ext.Component
|
21781
|
+
* @param {Boolean} locateInputEl For form fields, try to find the inner input element by default.
|
21782
|
+
* If you want to target the containing Component element, pass false instead.
|
21783
|
+
* @return {*}
|
21784
|
+
*/
|
21785
|
+
compToEl : function (comp, locateInputEl) {
|
21786
|
+
var Ext = this.Ext();
|
21787
|
+
|
21234
21788
|
if (!comp) return null
|
21235
|
-
|
21789
|
+
|
21790
|
+
locateInputEl = locateInputEl !== false;
|
21791
|
+
|
21792
|
+
// Ext JS
|
21793
|
+
if (Ext && Ext.form && Ext.form.Field && locateInputEl) {
|
21794
|
+
if (comp instanceof Ext.form.Field && comp.inputEl){
|
21795
|
+
return comp.inputEl;
|
21796
|
+
}
|
21797
|
+
}
|
21798
|
+
|
21799
|
+
// Sencha Touch: Form fields can have a child input component
|
21800
|
+
if (Ext && Ext.field && Ext.field.Field && comp instanceof Ext.field.Field && locateInputEl) {
|
21801
|
+
comp = comp.getComponent();
|
21802
|
+
}
|
21803
|
+
|
21236
21804
|
// Ext JS vs Sencha Touch
|
21237
21805
|
return comp.getEl ? comp.getEl() : (comp.el || comp.element);
|
21238
21806
|
},
|
@@ -21262,17 +21830,14 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21262
21830
|
}
|
21263
21831
|
}
|
21264
21832
|
|
21265
|
-
if (
|
21266
|
-
el = el
|
21267
|
-
|
21268
|
-
|
21269
|
-
|
21270
|
-
|
21271
|
-
|
21272
|
-
|
21273
|
-
}
|
21274
|
-
|
21275
|
-
// ExtJS Element
|
21833
|
+
if (Ext && Ext.Component && el instanceof Ext.Component) {
|
21834
|
+
el = this.compToEl(el);
|
21835
|
+
var center = this.findCenter(el);
|
21836
|
+
|
21837
|
+
el = this.elementFromPoint(center[0], center[1]) || el;
|
21838
|
+
}
|
21839
|
+
|
21840
|
+
// ExtJS Element
|
21276
21841
|
if (el && el.dom) return el.dom
|
21277
21842
|
|
21278
21843
|
// will also handle the case of conversion of array with coordinates to el
|
@@ -21373,7 +21938,7 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21373
21938
|
me.fail("Class: " + className + " was loaded")
|
21374
21939
|
})
|
21375
21940
|
|
21376
|
-
callback && callback
|
21941
|
+
callback && me.processCallbackFromTest(callback)
|
21377
21942
|
}
|
21378
21943
|
|
21379
21944
|
var timeout = Ext.isIE ? 120000 : 30000,
|
@@ -21487,8 +22052,9 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21487
22052
|
cmp = cmp[0];
|
21488
22053
|
|
21489
22054
|
if (!cmp.rendered) throw 'The source component of the composite query: ' + cmp.id + ' is not yet rendered';
|
21490
|
-
|
21491
|
-
|
22055
|
+
|
22056
|
+
|
22057
|
+
return this.compToEl(cmp, false).query(result[1]);
|
21492
22058
|
},
|
21493
22059
|
|
21494
22060
|
/**
|
@@ -21766,7 +22332,7 @@ Role('Siesta.Test.ExtJS.Observable', {
|
|
21766
22332
|
annotation : n + " '" + event + "' events were expected, but " + counter + ' were fired'
|
21767
22333
|
});
|
21768
22334
|
|
21769
|
-
callback && callback
|
22335
|
+
callback && me.processCallbackFromTest(callback);
|
21770
22336
|
|
21771
22337
|
}, timeOut);
|
21772
22338
|
|
@@ -22302,7 +22868,9 @@ Role('Siesta.Test.ExtJS.Component', {
|
|
22302
22868
|
* @param {Int} timeout The maximum amount of time to wait for the condition to be fulfilled. Defaults to the {@link Siesta.Test.ExtJS#waitForTimeout} value.
|
22303
22869
|
*/
|
22304
22870
|
waitForComponent: function (component, rendered, callback, scope, timeout) {
|
22305
|
-
var Ext
|
22871
|
+
var Ext = this.getExt();
|
22872
|
+
var xtype
|
22873
|
+
|
22306
22874
|
if (Ext.isString(component)) {
|
22307
22875
|
xtype = Ext.ClassManager.get(component).xtype;
|
22308
22876
|
} else {
|
@@ -22340,6 +22908,75 @@ Role('Siesta.Test.ExtJS.Component', {
|
|
22340
22908
|
hasPosition: function (component, x, y, description) {
|
22341
22909
|
component = this.normalizeComponent(component);
|
22342
22910
|
this.isDeeply(component.getPosition(), [x, y], description);
|
22911
|
+
},
|
22912
|
+
|
22913
|
+
|
22914
|
+
/**
|
22915
|
+
* This assertion accepts variable number of Ext.Component instances (can be also provided as component query string).
|
22916
|
+
* Then it calls their "destroy" method and verifies that:
|
22917
|
+
* - there were no exceptions during destroy
|
22918
|
+
* - that each component was actually destoyed (since destroy can be canceled in the "beforedestroy" event listener)
|
22919
|
+
*
|
22920
|
+
* @param {Ext.Component/Array[Ext.Component]/String} components A single instance of Ext.Component, an array of such or a string with component query
|
22921
|
+
* @param {String} description The description of the assertion
|
22922
|
+
*/
|
22923
|
+
destroysOk : function (components, description) {
|
22924
|
+
var Ext = this.Ext();
|
22925
|
+
|
22926
|
+
if (this.typeOf(components) != 'Array') {
|
22927
|
+
if (this.typeOf(components) == 'String')
|
22928
|
+
components = this.Ext().ComponentQuery.query(components);
|
22929
|
+
else
|
22930
|
+
components = [ components ]
|
22931
|
+
}
|
22932
|
+
|
22933
|
+
if (!components.length) {
|
22934
|
+
this.fail(description, {
|
22935
|
+
assertionName : 'destroysOk',
|
22936
|
+
annotation : 'No components provided, or component query returned empty result'
|
22937
|
+
})
|
22938
|
+
|
22939
|
+
return
|
22940
|
+
}
|
22941
|
+
|
22942
|
+
var currentComp
|
22943
|
+
|
22944
|
+
var e = this.getExceptionCatcher()(function () {
|
22945
|
+
Joose.A.each(components, function (component) {
|
22946
|
+
currentComp = component
|
22947
|
+
|
22948
|
+
component.destroy()
|
22949
|
+
})
|
22950
|
+
})
|
22951
|
+
|
22952
|
+
if (e !== undefined) {
|
22953
|
+
this.fail(description, {
|
22954
|
+
assertionName : 'destroysOk',
|
22955
|
+
got : e,
|
22956
|
+
gotDesc : 'Exception',
|
22957
|
+
annotation : 'Exception thrown while calling "destroy" method of ' + currentComp.id
|
22958
|
+
})
|
22959
|
+
|
22960
|
+
return
|
22961
|
+
}
|
22962
|
+
|
22963
|
+
var me = this
|
22964
|
+
|
22965
|
+
var allDestroyed = Joose.A.each(components, function (component) {
|
22966
|
+
// ExtJS ST
|
22967
|
+
if (!(component.isDestroyed || component.destroy == Ext.emptyFn)) {
|
22968
|
+
me.fail(description, {
|
22969
|
+
assertionName : 'destroysOk',
|
22970
|
+
annotation : 'Component [' + component.id + '] was not destroyed (probably destroy was canceled in the `beforedestroy` listener)'
|
22971
|
+
})
|
22972
|
+
|
22973
|
+
return false
|
22974
|
+
}
|
22975
|
+
})
|
22976
|
+
|
22977
|
+
if (allDestroyed === false) return
|
22978
|
+
|
22979
|
+
this.pass(description)
|
22343
22980
|
}
|
22344
22981
|
}
|
22345
22982
|
});
|
@@ -22568,13 +23205,14 @@ Role('Siesta.Test.Element', {
|
|
22568
23205
|
|
22569
23206
|
|
22570
23207
|
/**
|
22571
|
-
* Returns true if the element is visible.
|
23208
|
+
* Returns true if the element is visible, checking jQuery :visible selector + style visibilty value.
|
22572
23209
|
* @param {Siesta.Test.ActionTarget} el The element
|
22573
23210
|
* @return {Boolean}
|
22574
23211
|
*/
|
22575
23212
|
isElementVisible : function(el) {
|
22576
23213
|
el = this.normalizeElement(el);
|
22577
|
-
|
23214
|
+
// Jquery :visible doesn't take visibility into account
|
23215
|
+
return !!el && this.$(el).is(':visible') && el.style.visibility !== 'hidden';
|
22578
23216
|
},
|
22579
23217
|
|
22580
23218
|
/**
|
@@ -22750,7 +23388,7 @@ Role('Siesta.Test.Element', {
|
|
22750
23388
|
assertionChecker()
|
22751
23389
|
}
|
22752
23390
|
|
22753
|
-
callback &&
|
23391
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
22754
23392
|
});
|
22755
23393
|
},
|
22756
23394
|
|
@@ -23170,11 +23808,11 @@ Role('Siesta.Test.Element', {
|
|
23170
23808
|
this.fail(description, {
|
23171
23809
|
assertionName : 'elementIsAt',
|
23172
23810
|
got : { x: xy[0], y : xy[1] },
|
23173
|
-
gotDesc : '
|
23811
|
+
gotDesc : 'Position',
|
23174
23812
|
annotation : 'No element found at the specified position'
|
23175
23813
|
});
|
23176
23814
|
} else if (allowChildren) {
|
23177
|
-
if (foundEl === el || $(foundEl).closest(el)) {
|
23815
|
+
if (foundEl === el || $(foundEl).closest(el).length > 0) {
|
23178
23816
|
this.pass(description);
|
23179
23817
|
} else {
|
23180
23818
|
this.fail(description, {
|
@@ -23272,21 +23910,14 @@ Role('Siesta.Test.Element', {
|
|
23272
23910
|
|
23273
23911
|
var foundEl = this.$(doc.elementFromPoint(xy[0], xy[1]) || doc.body);
|
23274
23912
|
|
23275
|
-
if (!foundEl) {
|
23276
|
-
this.fail(description, {
|
23277
|
-
assertionName : 'selectorIsAt',
|
23278
|
-
got : { x: xy[0], y : xy[1] },
|
23279
|
-
gotDesc : 'Postion',
|
23280
|
-
annotation : 'No element matching the passed selector found at the specified position'
|
23281
|
-
});
|
23282
|
-
}
|
23283
|
-
|
23284
23913
|
if (foundEl.has(selector).length > 0 || foundEl.closest(selector).length > 0) {
|
23285
23914
|
this.pass(description);
|
23286
23915
|
} else {
|
23287
23916
|
this.fail(description, {
|
23917
|
+
got : foundEl[0].outerHTML ? foundEl[0].outerHTML : foundEl[0].innerHTML,
|
23918
|
+
need : 'Element matching ' + selector,
|
23288
23919
|
assertionName : 'selectorIsAt',
|
23289
|
-
annotation : 'Passed selector does not match
|
23920
|
+
annotation : 'Passed selector does not match any selector at [' + xy + ']'
|
23290
23921
|
});
|
23291
23922
|
}
|
23292
23923
|
},
|
@@ -23413,7 +24044,11 @@ Role('Siesta.Test.Element', {
|
|
23413
24044
|
})
|
23414
24045
|
})
|
23415
24046
|
|
23416
|
-
|
24047
|
+
var me = this
|
24048
|
+
|
24049
|
+
if (callback) steps.push(function () {
|
24050
|
+
me.processCallbackFromTest(callback)
|
24051
|
+
})
|
23417
24052
|
|
23418
24053
|
this.chain.apply(this, steps)
|
23419
24054
|
},
|
@@ -23430,7 +24065,7 @@ Role('Siesta.Test.Element', {
|
|
23430
24065
|
*
|
23431
24066
|
* t.clickSelector('.my-grid .x-grid-row', function () {})
|
23432
24067
|
*
|
23433
|
-
* The provided callback will receive
|
24068
|
+
* The provided callback will receive an array with DOM elements - result of query.
|
23434
24069
|
*
|
23435
24070
|
*
|
23436
24071
|
* @param {String} selector The selector/xpath query
|
@@ -23726,7 +24361,7 @@ Class('Siesta.Test.Browser', {
|
|
23726
24361
|
annotation : n + " '" + event + "' events were expected, but " + counter + ' were fired'
|
23727
24362
|
});
|
23728
24363
|
|
23729
|
-
callback && callback
|
24364
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
23730
24365
|
|
23731
24366
|
}, timeOut);
|
23732
24367
|
|
@@ -23893,7 +24528,47 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23893
24528
|
},
|
23894
24529
|
|
23895
24530
|
methods : {
|
23896
|
-
|
24531
|
+
getTouchBundlePath : function() {
|
24532
|
+
var path;
|
24533
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24534
|
+
|
24535
|
+
while (testDescriptor && !path) {
|
24536
|
+
if (testDescriptor.preload) {
|
24537
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24538
|
+
if (url.match && url.match(/(.*sencha-touch-\d\.\d+\.\d+.*?)\/sencha-touch(.*)\.js/)) {
|
24539
|
+
path = url;
|
24540
|
+
return false;
|
24541
|
+
}
|
24542
|
+
});
|
24543
|
+
}
|
24544
|
+
testDescriptor = testDescriptor.parent;
|
24545
|
+
}
|
24546
|
+
|
24547
|
+
return path;
|
24548
|
+
},
|
24549
|
+
|
24550
|
+
|
24551
|
+
getTouchBundleFolder : function() {
|
24552
|
+
var folder;
|
24553
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24554
|
+
|
24555
|
+
while (testDescriptor && !folder) {
|
24556
|
+
if (testDescriptor.preload) {
|
24557
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24558
|
+
var regex = /(.*sencha-touch-\d\.\d+\.\d+.*?)\/sencha-touch(.*)\.js/;
|
24559
|
+
var match = regex.exec(url);
|
24560
|
+
|
24561
|
+
if (match) {
|
24562
|
+
folder = match[1];
|
24563
|
+
}
|
24564
|
+
});
|
24565
|
+
}
|
24566
|
+
testDescriptor = testDescriptor.parent;
|
24567
|
+
}
|
24568
|
+
|
24569
|
+
return folder;
|
24570
|
+
},
|
24571
|
+
|
23897
24572
|
/**
|
23898
24573
|
* This method taps the passed target, which can be of several different types, see {@link Siesta.Test.ActionTarget}
|
23899
24574
|
*
|
@@ -23902,7 +24577,33 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23902
24577
|
* @param {Object} scope (optional) The scope for the callback
|
23903
24578
|
*/
|
23904
24579
|
tap: function (target, callback, scope) {
|
23905
|
-
|
24580
|
+
var me = this;
|
24581
|
+
|
24582
|
+
target = this.normalizeElement(target);
|
24583
|
+
|
24584
|
+
var queue = new Siesta.Util.Queue({
|
24585
|
+
deferer : this.originalSetTimeout,
|
24586
|
+
deferClearer : this.originalClearTimeout,
|
24587
|
+
|
24588
|
+
interval : callback ? 30 : 0,
|
24589
|
+
|
24590
|
+
observeTest : this,
|
24591
|
+
|
24592
|
+
processor : function (data) {
|
24593
|
+
me.simulateEvent.apply(me, data);
|
24594
|
+
}
|
24595
|
+
})
|
24596
|
+
|
24597
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24598
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24599
|
+
|
24600
|
+
var async = me.beginAsync();
|
24601
|
+
|
24602
|
+
queue.run(function () {
|
24603
|
+
me.endAsync(async);
|
24604
|
+
|
24605
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
24606
|
+
})
|
23906
24607
|
},
|
23907
24608
|
|
23908
24609
|
/**
|
@@ -23913,7 +24614,36 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23913
24614
|
* @param {Object} scope (optional) The scope for the callback
|
23914
24615
|
*/
|
23915
24616
|
doubleTap: function (target, callback, scope) {
|
23916
|
-
|
24617
|
+
var me = this;
|
24618
|
+
|
24619
|
+
target = this.normalizeElement(target);
|
24620
|
+
|
24621
|
+
var queue = new Siesta.Util.Queue({
|
24622
|
+
deferer : this.originalSetTimeout,
|
24623
|
+
deferClearer : this.originalClearTimeout,
|
24624
|
+
|
24625
|
+
interval : callback ? 30 : 0,
|
24626
|
+
|
24627
|
+
observeTest : this,
|
24628
|
+
|
24629
|
+
processor : function (data) {
|
24630
|
+
me.simulateEvent.apply(me, data);
|
24631
|
+
}
|
24632
|
+
})
|
24633
|
+
|
24634
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24635
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24636
|
+
|
24637
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24638
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24639
|
+
|
24640
|
+
var async = me.beginAsync();
|
24641
|
+
|
24642
|
+
queue.run(function () {
|
24643
|
+
me.endAsync(async);
|
24644
|
+
|
24645
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
24646
|
+
})
|
23917
24647
|
},
|
23918
24648
|
|
23919
24649
|
/**
|
@@ -23925,11 +24655,17 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23925
24655
|
*/
|
23926
24656
|
longpress: function (target, callback, scope) {
|
23927
24657
|
var Ext = this.Ext();
|
24658
|
+
var me = this;
|
23928
24659
|
|
23929
24660
|
this.simulateEvent(target, 'mousedown');
|
23930
24661
|
|
23931
24662
|
var amount = Ext.event.recognizer.LongPress.prototype.config.minDuration;
|
23932
|
-
|
24663
|
+
|
24664
|
+
this.waitFor(amount, function() {
|
24665
|
+
me.simulateEvent(target, 'mouseup');
|
24666
|
+
|
24667
|
+
callback.call(scope || me);
|
24668
|
+
});
|
23933
24669
|
},
|
23934
24670
|
|
23935
24671
|
/**
|
@@ -23948,30 +24684,41 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23948
24684
|
start,
|
23949
24685
|
end,
|
23950
24686
|
edgeOffsetRatio = 10;
|
24687
|
+
|
24688
|
+
// Since this method accepts elements as target, we need to assure that we swipe at least about 150px
|
24689
|
+
// using Math.max below etc
|
23951
24690
|
|
23952
24691
|
switch(direction) {
|
23953
24692
|
case 'u':
|
23954
24693
|
case 'up':
|
23955
|
-
start
|
23956
|
-
end
|
24694
|
+
start = [box.x + box.width/2, (box.y + box.height*9/edgeOffsetRatio)];
|
24695
|
+
end = [box.x + box.width/2, box.y + box.height/edgeOffsetRatio];
|
24696
|
+
|
24697
|
+
end[1] = Math.min(start[1] - 100, end[1]);
|
23957
24698
|
break;
|
23958
24699
|
|
23959
24700
|
case 'd':
|
23960
24701
|
case 'down':
|
23961
|
-
start
|
23962
|
-
end
|
23963
|
-
break;
|
24702
|
+
start = [box.x + box.width/2, (box.y + box.height/edgeOffsetRatio)];
|
24703
|
+
end = [box.x + box.width/2, (box.y + box.height*9/edgeOffsetRatio)];
|
23964
24704
|
|
23965
|
-
|
23966
|
-
case 'left':
|
23967
|
-
start = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
23968
|
-
end = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
24705
|
+
end[1] = Math.max(start[1] + 100, end[1]);
|
23969
24706
|
break;
|
23970
24707
|
|
23971
24708
|
case 'r':
|
23972
24709
|
case 'right':
|
23973
|
-
start
|
23974
|
-
end
|
24710
|
+
start = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
24711
|
+
end = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
24712
|
+
|
24713
|
+
end[0] = Math.max(start[0] + 100, end[0]);
|
24714
|
+
break;
|
24715
|
+
|
24716
|
+
case 'l':
|
24717
|
+
case 'left':
|
24718
|
+
start = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
24719
|
+
end = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
24720
|
+
|
24721
|
+
end[0] = Math.min(start[0] - 100, end[0]);
|
23975
24722
|
break;
|
23976
24723
|
|
23977
24724
|
default:
|
@@ -23981,6 +24728,42 @@ Class('Siesta.Test.SenchaTouch', {
|
|
23981
24728
|
this.dragTo(start, end, callback, scope);
|
23982
24729
|
},
|
23983
24730
|
|
24731
|
+
/**
|
24732
|
+
* This method will simulate a finger move to an xy-coordinate or an element (the center of it)
|
24733
|
+
*
|
24734
|
+
* @param {Siesta.Test.ActionTarget} target Target point to move the mouse to.
|
24735
|
+
* @param {Function} callback (optional) To run this method async, provide a callback method to be called after the operation is completed.
|
24736
|
+
* @param {Object} scope (optional) the scope for the callback
|
24737
|
+
*/
|
24738
|
+
moveFingerTo : function(target, callback, scope) {
|
24739
|
+
if (!target) {
|
24740
|
+
throw 'Trying to call moveFingerTo without a target';
|
24741
|
+
}
|
24742
|
+
|
24743
|
+
// Normalize target
|
24744
|
+
if (!this.isArray(target)) {
|
24745
|
+
target = this.detectCenter(this.normalizeElement(target), 'moveFingerTo');
|
24746
|
+
}
|
24747
|
+
this.moveMouse(this.currentPosition, target, callback, scope);
|
24748
|
+
},
|
24749
|
+
|
24750
|
+
/**
|
24751
|
+
* This method will simulate a finger move from current position relative by the x and y distances provided.
|
24752
|
+
*
|
24753
|
+
* @param {Siesta.Test.ActionTarget} target Target point to move the mouse to.
|
24754
|
+
* @param {Function} callback (optional) To run this method async, provide a callback method to be called after the operation is completed.
|
24755
|
+
* @param {Object} scope (optional) the scope for the callback
|
24756
|
+
*/
|
24757
|
+
moveFingerBy : function(delta, callback, scope) {
|
24758
|
+
if (!delta) {
|
24759
|
+
throw 'Trying to call moveFingerBy without relative distances';
|
24760
|
+
}
|
24761
|
+
|
24762
|
+
var targetXY = [ this.currentPosition[0] + delta[0], this.currentPosition[1] + delta[1] ];
|
24763
|
+
|
24764
|
+
this.moveMouseTo(targetXY, callback, scope);
|
24765
|
+
},
|
24766
|
+
|
23984
24767
|
// /**
|
23985
24768
|
// * This method will simulate a swipe operation between either two points or on a single DOM element.
|
23986
24769
|
// *
|
@@ -24038,7 +24821,7 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24038
24821
|
var inner = function() {
|
24039
24822
|
if (checkerFn.call(scope || me, target)) {
|
24040
24823
|
// We're done
|
24041
|
-
|
24824
|
+
me.processCallbackFromTest(callback, null, scope || me)
|
24042
24825
|
} else {
|
24043
24826
|
me.swipe(target, direction, function() {
|
24044
24827
|
var as = me.beginAsync();
|
@@ -24443,7 +25226,9 @@ Class('Siesta.Harness.Browser', {
|
|
24443
25226
|
*/
|
24444
25227
|
viewportHeight : 768,
|
24445
25228
|
|
24446
|
-
needUI : true
|
25229
|
+
needUI : true,
|
25230
|
+
|
25231
|
+
isAutomated : false
|
24447
25232
|
},
|
24448
25233
|
|
24449
25234
|
|
@@ -24486,6 +25271,10 @@ Class('Siesta.Harness.Browser', {
|
|
24486
25271
|
|
24487
25272
|
onTestUpdate : function (test, result) {
|
24488
25273
|
if (this.viewport) this.viewport.onTestUpdate(test, result)
|
25274
|
+
|
25275
|
+
if ((result instanceof Siesta.Result.Diagnostic) && result.isWarning && this.needUI) {
|
25276
|
+
if (typeof console != 'undefined' && console.warn) console.warn(result + '')
|
25277
|
+
}
|
24489
25278
|
},
|
24490
25279
|
|
24491
25280
|
|
@@ -24522,11 +25311,6 @@ Class('Siesta.Harness.Browser', {
|
|
24522
25311
|
},
|
24523
25312
|
|
24524
25313
|
|
24525
|
-
isAutomated : function () {
|
24526
|
-
return false
|
24527
|
-
},
|
24528
|
-
|
24529
|
-
|
24530
25314
|
configure : function() {
|
24531
25315
|
this.SUPERARG(arguments);
|
24532
25316
|
|
@@ -24568,7 +25352,7 @@ Class('Siesta.Harness.Browser', {
|
|
24568
25352
|
|
24569
25353
|
// if we here, then we were requested to show the UI for automated launch
|
24570
25354
|
// auto-launch the test suite in this case
|
24571
|
-
if (me.isAutomated
|
25355
|
+
if (me.isAutomated) SUPER.apply(me, args)
|
24572
25356
|
};
|
24573
25357
|
|
24574
25358
|
if (Ext.setup) {
|
@@ -24603,7 +25387,7 @@ Class('Siesta.Harness.Browser', {
|
|
24603
25387
|
var sup = this.SUPER
|
24604
25388
|
|
24605
25389
|
// delay the super setup until dom ready
|
24606
|
-
if (!this.isAutomated
|
25390
|
+
if (!this.isAutomated) {
|
24607
25391
|
Ext.onReady(function () {
|
24608
25392
|
Siesta.supports.init();
|
24609
25393
|
|
@@ -24743,16 +25527,28 @@ Class('Siesta.Harness.Browser', {
|
|
24743
25527
|
|
24744
25528
|
|
24745
25529
|
showForcedIFrame : function (iframe, test) {
|
24746
|
-
|
24747
|
-
|
25530
|
+
$.rebindWindowContext(window);
|
25531
|
+
$(iframe).addClass('tr-iframe-forced')
|
25532
|
+
$(iframe).removeClass('tr-iframe-hidden')
|
24748
25533
|
|
24749
|
-
|
25534
|
+
$(iframe).center()
|
24750
25535
|
},
|
24751
25536
|
|
24752
25537
|
|
24753
25538
|
hideForcedIFrame : function (iframe) {
|
24754
|
-
|
24755
|
-
|
25539
|
+
$.rebindWindowContext(window);
|
25540
|
+
$(iframe).removeClass('tr-iframe-forced')
|
25541
|
+
$(iframe).addClass('tr-iframe-hidden')
|
25542
|
+
},
|
25543
|
+
|
25544
|
+
getQueryParam : function (paramName) {
|
25545
|
+
var regex = new RegExp('(?:\\?|&)' + paramName + '=(.*?)(?:\\?|&|$)', 'i')
|
25546
|
+
|
25547
|
+
var match = regex.exec(window.location.search)
|
25548
|
+
|
25549
|
+
if (!match) return null
|
25550
|
+
|
25551
|
+
return match[ 1 ]
|
24756
25552
|
}
|
24757
25553
|
}
|
24758
25554
|
|
@@ -24931,160 +25727,179 @@ Ext.Container.override({
|
|
24931
25727
|
}
|
24932
25728
|
})
|
24933
25729
|
;
|
24934
|
-
|
24935
|
-
|
25730
|
+
(function () {
|
25731
|
+
var config = {
|
25732
|
+
idProperty : 'id',
|
24936
25733
|
|
24937
|
-
|
24938
|
-
|
24939
|
-
|
24940
|
-
|
24941
|
-
|
24942
|
-
|
24943
|
-
|
24944
|
-
|
24945
|
-
|
24946
|
-
|
24947
|
-
|
24948
|
-
|
24949
|
-
|
24950
|
-
|
24951
|
-
|
24952
|
-
|
25734
|
+
fields : [
|
25735
|
+
'id',
|
25736
|
+
'url',
|
25737
|
+
|
25738
|
+
'title',
|
25739
|
+
|
25740
|
+
{ name : 'passCount', type : 'int', defaultValue : 0 },
|
25741
|
+
{ name : 'failCount', type : 'int', defaultValue : 0 },
|
25742
|
+
{ name : 'todoPassCount', type : 'int', defaultValue : 0 },
|
25743
|
+
{ name : 'todoFailCount', type : 'int', defaultValue : 0 },
|
25744
|
+
|
25745
|
+
{ name : 'time', type : 'int', defaultValue : 0 },
|
25746
|
+
|
25747
|
+
{
|
25748
|
+
name : 'checked',
|
25749
|
+
defaultValue : false
|
25750
|
+
},
|
25751
|
+
|
25752
|
+
{
|
25753
|
+
name : 'folderStatus',
|
25754
|
+
defaultValue : 'yellow'
|
25755
|
+
},
|
25756
|
+
|
25757
|
+
// will be set to true for all tests, once the users clicks "run"
|
25758
|
+
'isStarting',
|
25759
|
+
// will be set to true, right before the scope preload begin
|
25760
|
+
'isStarted',
|
25761
|
+
// will be set to true, after preload ends and tests launch
|
25762
|
+
{ name : 'isRunning', type : 'boolean', defaultValue : false },
|
25763
|
+
{ name : 'isMissing', type : 'boolean', defaultValue : false },
|
25764
|
+
{ name : 'isFailed', type : 'boolean', defaultValue : false },
|
25765
|
+
|
25766
|
+
// composite objects
|
25767
|
+
'assertionsStore',
|
25768
|
+
'test',
|
25769
|
+
'descriptor'
|
25770
|
+
]
|
25771
|
+
};
|
25772
|
+
|
25773
|
+
Ext.define('Siesta.Harness.Browser.Model.TestFile', Ext.apply({
|
25774
|
+
|
25775
|
+
extend : 'Ext.data.Model',
|
25776
|
+
|
25777
|
+
init : function () {
|
25778
|
+
this.internalId = this.getId() || this.internalId
|
24953
25779
|
},
|
24954
|
-
|
24955
|
-
{
|
24956
|
-
name : 'folderStatus',
|
24957
|
-
defaultValue : 'yellow'
|
24958
|
-
},
|
24959
|
-
|
24960
|
-
// will be set to true for all tests, once the users clicks "run"
|
24961
|
-
'isStarting',
|
24962
|
-
// will be set to true, right before the scope preload begin
|
24963
|
-
'isStarted',
|
24964
|
-
// will be set to true, after preload ends and tests launch
|
24965
|
-
{ name : 'isRunning', type : 'boolean', defaultValue : false },
|
24966
|
-
{ name : 'isMissing', type : 'boolean', defaultValue : false },
|
24967
|
-
{ name : 'isFailed', type : 'boolean', defaultValue : false },
|
24968
|
-
|
24969
|
-
// composite objects
|
24970
|
-
'assertionsStore',
|
24971
|
-
'test',
|
24972
|
-
'descriptor'
|
24973
|
-
]
|
24974
|
-
};
|
24975
25780
|
|
24976
|
-
Ext.define('Siesta.Harness.Browser.Model.TestFile', Ext.apply({
|
24977
25781
|
|
24978
|
-
|
25782
|
+
computeFolderStatus : function () {
|
25783
|
+
if (!this.childNodes.length) return 'yellow'
|
24979
25784
|
|
24980
|
-
|
24981
|
-
|
24982
|
-
|
25785
|
+
var isWorking = false
|
25786
|
+
var hasFailed = false
|
25787
|
+
var allGreen = true
|
24983
25788
|
|
25789
|
+
Joose.A.each(this.childNodes, function (childNode) {
|
24984
25790
|
|
24985
|
-
|
24986
|
-
|
24987
|
-
|
24988
|
-
|
24989
|
-
|
24990
|
-
|
24991
|
-
|
24992
|
-
|
24993
|
-
|
24994
|
-
|
24995
|
-
|
24996
|
-
|
24997
|
-
|
24998
|
-
allGreen
|
24999
|
-
|
25000
|
-
|
25001
|
-
|
25002
|
-
|
25003
|
-
|
25004
|
-
|
25005
|
-
|
25006
|
-
|
25007
|
-
|
25008
|
-
|
25009
|
-
|
25010
|
-
|
25011
|
-
|
25012
|
-
|
25013
|
-
|
25014
|
-
|
25015
|
-
|
25016
|
-
|
25017
|
-
|
25018
|
-
|
25019
|
-
|
25020
|
-
|
25021
|
-
if (status == 'working') {
|
25022
|
-
isWorking = true
|
25023
|
-
|
25024
|
-
// stop iteration
|
25025
|
-
return false
|
25791
|
+
if (childNode.isLeaf()) {
|
25792
|
+
var test = childNode.get('test')
|
25793
|
+
|
25794
|
+
if (test && test.isFailed()) {
|
25795
|
+
allGreen = false
|
25796
|
+
hasFailed = true
|
25797
|
+
|
25798
|
+
// stop iteration
|
25799
|
+
return false
|
25800
|
+
}
|
25801
|
+
|
25802
|
+
if (!test && childNode.get('isStarting')) isWorking = true
|
25803
|
+
if (test && !test.isFinished()) isWorking = true
|
25804
|
+
if (test && !test.isPassed()) allGreen = false
|
25805
|
+
if (!test) allGreen = false
|
25806
|
+
|
25807
|
+
} else {
|
25808
|
+
var status = childNode.computeFolderStatus()
|
25809
|
+
|
25810
|
+
if (status == 'red') {
|
25811
|
+
allGreen = false
|
25812
|
+
hasFailed = true
|
25813
|
+
|
25814
|
+
// stop iteration
|
25815
|
+
return false
|
25816
|
+
}
|
25817
|
+
|
25818
|
+
if (status == 'working') {
|
25819
|
+
isWorking = true
|
25820
|
+
|
25821
|
+
// stop iteration
|
25822
|
+
return false
|
25823
|
+
}
|
25824
|
+
|
25825
|
+
if (status == 'yellow') allGreen = false
|
25026
25826
|
}
|
25027
|
-
|
25028
|
-
if (status == 'yellow') allGreen = false
|
25029
|
-
}
|
25030
|
-
})
|
25031
|
-
|
25032
|
-
if (isWorking) return 'working'
|
25033
|
-
if (hasFailed) return 'red'
|
25034
|
-
if (allGreen) return 'green'
|
25035
|
-
|
25036
|
-
return 'yellow'
|
25037
|
-
},
|
25827
|
+
})
|
25038
25828
|
|
25829
|
+
if (isWorking) return 'working'
|
25830
|
+
if (hasFailed) return 'red'
|
25831
|
+
if (allGreen) return 'green'
|
25039
25832
|
|
25040
|
-
|
25041
|
-
|
25042
|
-
|
25043
|
-
|
25044
|
-
|
25045
|
-
|
25046
|
-
},
|
25833
|
+
return 'yellow'
|
25834
|
+
},
|
25835
|
+
|
25836
|
+
|
25837
|
+
updateFolderStatus : function () {
|
25838
|
+
this.set('folderStatus', this.computeFolderStatus())
|
25047
25839
|
|
25048
|
-
|
25049
|
-
var failed = [];
|
25050
|
-
var as = this.get('assertionsStore');
|
25840
|
+
var parentNode = this.parentNode
|
25051
25841
|
|
25052
|
-
|
25053
|
-
|
25054
|
-
|
25055
|
-
|
25842
|
+
if (parentNode && !parentNode.isRoot()) parentNode.updateFolderStatus()
|
25843
|
+
},
|
25844
|
+
|
25845
|
+
getFailedAssertions : function () {
|
25846
|
+
var failed = [];
|
25847
|
+
var as = this.get('assertionsStore');
|
25848
|
+
|
25849
|
+
if (as) {
|
25850
|
+
as.each(function (assertion) {
|
25851
|
+
if (assertion.get('passed') === false) {
|
25852
|
+
failed.push(assertion);
|
25853
|
+
}
|
25854
|
+
});
|
25855
|
+
}
|
25856
|
+
|
25857
|
+
return failed;
|
25858
|
+
}
|
25859
|
+
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config), function () {
|
25860
|
+
var isSenchaTouch = Ext.getVersion && Ext.getVersion('touch')
|
25861
|
+
|
25862
|
+
if (!isSenchaTouch) {
|
25863
|
+
Ext.data.NodeInterface.decorate(this);
|
25864
|
+
|
25865
|
+
this.override({
|
25866
|
+
expand : function () {
|
25867
|
+
Ext.suspendLayouts();
|
25868
|
+
this.callParent(arguments);
|
25869
|
+
Ext.resumeLayouts();
|
25056
25870
|
}
|
25057
25871
|
});
|
25058
25872
|
}
|
25059
|
-
|
25060
|
-
|
25061
|
-
}
|
25062
|
-
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config ))
|
25873
|
+
})
|
25874
|
+
})();
|
25063
25875
|
;
|
25064
|
-
|
25065
|
-
|
25066
|
-
|
25067
|
-
|
25068
|
-
|
25069
|
-
|
25070
|
-
|
25071
|
-
|
25072
|
-
|
25073
|
-
|
25074
|
-
|
25075
|
-
|
25076
|
-
|
25077
|
-
|
25078
|
-
|
25079
|
-
|
25080
|
-
|
25081
|
-
|
25082
|
-
|
25083
|
-
|
25876
|
+
(function () {
|
25877
|
+
var config = {
|
25878
|
+
idProperty : 'index',
|
25879
|
+
|
25880
|
+
fields : [
|
25881
|
+
'index',
|
25882
|
+
'summaryFailure',
|
25883
|
+
{ name : 'passed', type : 'boolean', defaultValue : false },
|
25884
|
+
{ name : 'isTodo', type : 'boolean', defaultValue : false },
|
25885
|
+
{ name : 'isWaitFor', type : 'boolean', defaultValue : false },
|
25886
|
+
{ name : 'completed', type : 'boolean', defaultValue : false },
|
25887
|
+
'description',
|
25888
|
+
'annotation',
|
25889
|
+
'type',
|
25890
|
+
'sourceLine',
|
25891
|
+
'isWarning',
|
25892
|
+
|
25893
|
+
// For logging simulated events (will also have a type as for diagnostic messages)
|
25894
|
+
{ name : 'isSimulatedEvent', type : 'boolean', defaultValue : false },
|
25895
|
+
'eventType'
|
25896
|
+
]
|
25897
|
+
};
|
25084
25898
|
|
25085
|
-
Ext.define('Siesta.Harness.Browser.Model.Assertion', Ext.apply({
|
25086
|
-
|
25087
|
-
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config
|
25899
|
+
Ext.define('Siesta.Harness.Browser.Model.Assertion', Ext.apply({
|
25900
|
+
extend : 'Ext.data.Model'
|
25901
|
+
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config));
|
25902
|
+
})();
|
25088
25903
|
;
|
25089
25904
|
Ext.define('Siesta.Harness.Browser.UI.MouseVisualizer', {
|
25090
25905
|
|
@@ -25494,6 +26309,7 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25494
26309
|
|
25495
26310
|
Joose.A.each(harness.flattenDescriptors(descriptors), function (descriptor) {
|
25496
26311
|
var test = flatStore.getById(descriptor.id);
|
26312
|
+
|
25497
26313
|
me.lastTests.push(test);
|
25498
26314
|
|
25499
26315
|
test.set({
|
@@ -25533,7 +26349,11 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25533
26349
|
var testRecord = flatStore.getById(descriptor.id);
|
25534
26350
|
|
25535
26351
|
if (testRecord.isLeaf()) testRecord.get('assertionsStore').removeAll(true)
|
26352
|
+
|
25536
26353
|
testRecord.reject(true);
|
26354
|
+
|
26355
|
+
// HACK mark record as not having any test results
|
26356
|
+
testRecord.isCleared = true
|
25537
26357
|
});
|
25538
26358
|
},
|
25539
26359
|
|
@@ -25545,6 +26365,7 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25545
26365
|
Ext.select('.ghost-cursor-click-indicator').each(function(el) { el.destroy(); });
|
25546
26366
|
},
|
25547
26367
|
|
26368
|
+
|
25548
26369
|
toggleResults : function() {
|
25549
26370
|
if (this.lastTests.length > 1) {
|
25550
26371
|
var store = this.createFailedAssertionsStore(this.lastTests);
|
@@ -25559,6 +26380,7 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25559
26380
|
}
|
25560
26381
|
},
|
25561
26382
|
|
26383
|
+
|
25562
26384
|
createFailedAssertionsStore : function(tests) {
|
25563
26385
|
var store = new Ext.data.Store({
|
25564
26386
|
model : 'Siesta.Harness.Browser.Model.Assertion'
|
@@ -25667,6 +26489,8 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25667
26489
|
|
25668
26490
|
onTestStart : function (test) {
|
25669
26491
|
var testRecord = this.flatStore.getById(test.url)
|
26492
|
+
|
26493
|
+
testRecord.isCleared = false
|
25670
26494
|
|
25671
26495
|
testRecord.beginEdit()
|
25672
26496
|
|
@@ -25781,18 +26605,22 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.MainPanel', {
|
|
25781
26605
|
|
25782
26606
|
|
25783
26607
|
onItemDisclose : function (list, testModel, target, index) {
|
25784
|
-
if (testModel.
|
26608
|
+
if (testModel.isCleared) this.launchTest(testModel);
|
25785
26609
|
|
25786
26610
|
this.showResultPanel(testModel);
|
25787
26611
|
},
|
25788
26612
|
|
25789
26613
|
|
25790
|
-
showResultPanel : function() {
|
26614
|
+
showResultPanel : function (testModel) {
|
26615
|
+
var resultList = this.getResultList()
|
26616
|
+
|
26617
|
+
if (testModel) resultList.showTest(testModel);
|
26618
|
+
|
25791
26619
|
this.suiteBar.down("button[ui='back']").enable()
|
25792
26620
|
|
25793
26621
|
this.getLayout().getAnimation().setReverse(false)
|
25794
26622
|
|
25795
|
-
this.setActiveItem(
|
26623
|
+
this.setActiveItem(resultList);
|
25796
26624
|
},
|
25797
26625
|
|
25798
26626
|
|
@@ -25958,7 +26786,7 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
25958
26786
|
|
25959
26787
|
config : {
|
25960
26788
|
itemTpl : new Ext.XTemplate(
|
25961
|
-
'<div class="{[this.getRowClass(values)]}">{description} {[values.annotation ? ("<br/>" + values.annotation) : ""]}</div>',
|
26789
|
+
'<div class="{[this.getRowClass(values)]}">{description} {[values.annotation ? ("<br/>" + Ext.String.htmlEncode(values.annotation)) : ""]}</div>',
|
25962
26790
|
{
|
25963
26791
|
getRowClass: function(data){
|
25964
26792
|
if (data.type === 'Siesta.Result.Diagnostic') {
|
@@ -25977,10 +26805,12 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
25977
26805
|
testRecord : null
|
25978
26806
|
},
|
25979
26807
|
|
26808
|
+
|
25980
26809
|
constructor : function() {
|
25981
26810
|
this.callParent(arguments);
|
25982
26811
|
},
|
25983
26812
|
|
26813
|
+
|
25984
26814
|
getIFrame : function () {
|
25985
26815
|
if (this.testRecord) {
|
25986
26816
|
var test = this.testRecord.get('test');
|
@@ -25990,10 +26820,11 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
25990
26820
|
return null;
|
25991
26821
|
},
|
25992
26822
|
|
26823
|
+
|
25993
26824
|
alignIFrame : function () {
|
25994
26825
|
var iframe = this.getIFrame();
|
25995
26826
|
|
25996
|
-
Ext.fly(iframe).addCls('active')
|
26827
|
+
iframe && Ext.fly(iframe).addCls('active')
|
25997
26828
|
|
25998
26829
|
var test = this.testRecord && this.testRecord.get('test')
|
25999
26830
|
|
@@ -26002,6 +26833,7 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
26002
26833
|
}
|
26003
26834
|
},
|
26004
26835
|
|
26836
|
+
|
26005
26837
|
hideIFrame : function () {
|
26006
26838
|
var iframe = this.getIFrame()
|
26007
26839
|
|
@@ -26014,15 +26846,20 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
26014
26846
|
}
|
26015
26847
|
},
|
26016
26848
|
|
26849
|
+
|
26017
26850
|
toggleFrameVisible : function() {
|
26018
26851
|
var iframe = this.getIFrame()
|
26019
26852
|
iframe && Ext.fly(iframe).toggleCls('active');
|
26020
26853
|
},
|
26021
26854
|
|
26855
|
+
|
26022
26856
|
isFrameVisible : function () {
|
26023
|
-
|
26857
|
+
var iframe = this.getIFrame()
|
26858
|
+
|
26859
|
+
return iframe && Ext.fly(iframe).hasCls('active') || false;
|
26024
26860
|
},
|
26025
26861
|
|
26862
|
+
|
26026
26863
|
showTest : function (testFile) {
|
26027
26864
|
this.addCls('result-list-running');
|
26028
26865
|
|
@@ -26032,8 +26869,9 @@ Ext.define('Siesta.Harness.Browser.UI_Mobile.ResultList', {
|
|
26032
26869
|
}
|
26033
26870
|
|
26034
26871
|
var url = testFile.get('url');
|
26035
|
-
|
26036
|
-
this
|
26872
|
+
|
26873
|
+
// Nickolay: Had to disable this line, do we need it?
|
26874
|
+
// this.container.innerElement.setHtml('');
|
26037
26875
|
this.setStore(testFile.get('assertionsStore'));
|
26038
26876
|
|
26039
26877
|
this.testUrl = url;
|
@@ -26083,53 +26921,55 @@ A Class representing the browser harness. This class provides a web-based UI and
|
|
26083
26921
|
The default value of the `testClass` configuration option in this class is {@link Siesta.Test.SenchaTouch}, which inherits from
|
26084
26922
|
{@link Siesta.Test.Browser} and contains various Sencha Touch-specific assertions. Use this harness class when testing Sencha Touch applications.
|
26085
26923
|
|
26924
|
+
* **Note** Make sure, you've checked the {@link #performSetup} configuration option.
|
26925
|
+
|
26086
26926
|
This file is for reference only, for a getting start guide and manual, please refer to <a href="#!/guide/siesta_getting_started">Getting Started Guide</a>.
|
26087
26927
|
|
26088
26928
|
Synopsys
|
26089
26929
|
========
|
26090
26930
|
|
26091
|
-
var Harness = Siesta.Harness.Browser.SenchaTouch;
|
26092
|
-
|
26093
|
-
Harness.configure({
|
26094
|
-
title : 'Awesome Sencha Touch Application Test Suite',
|
26931
|
+
var Harness = Siesta.Harness.Browser.SenchaTouch;
|
26095
26932
|
|
26096
|
-
|
26097
|
-
|
26098
|
-
|
26099
|
-
|
26100
|
-
|
26101
|
-
|
26102
|
-
|
26103
|
-
|
26104
|
-
|
26105
|
-
|
26106
|
-
// simple string - url relative to harness file
|
26107
|
-
'sanity.t.js',
|
26933
|
+
Harness.configure({
|
26934
|
+
title : 'Awesome Sencha Touch Application Test Suite',
|
26935
|
+
|
26936
|
+
transparentEx : true,
|
26937
|
+
|
26938
|
+
preload : [
|
26939
|
+
"http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js",
|
26940
|
+
"../awesome-project-all.js"
|
26941
|
+
]
|
26942
|
+
})
|
26108
26943
|
|
26109
|
-
// test file descriptor with own configuration options
|
26110
|
-
{
|
26111
|
-
url : 'basic.t.js',
|
26112
|
-
|
26113
|
-
// replace `preload` option of harness
|
26114
|
-
preload : [
|
26115
|
-
"http://cdn.sencha.io/ext-4.0.6/ext-all-debug.js",
|
26116
|
-
"../awesome-project-all.js"
|
26117
|
-
]
|
26118
|
-
},
|
26119
26944
|
|
26120
|
-
|
26121
|
-
|
26122
|
-
|
26123
|
-
|
26124
|
-
|
26125
|
-
|
26126
|
-
|
26127
|
-
|
26128
|
-
|
26129
|
-
|
26130
|
-
|
26131
|
-
|
26132
|
-
|
26945
|
+
Harness.start(
|
26946
|
+
// simple string - url relative to harness file
|
26947
|
+
'sanity.t.js',
|
26948
|
+
|
26949
|
+
// test file descriptor with own configuration options
|
26950
|
+
{
|
26951
|
+
url : 'basic.t.js',
|
26952
|
+
|
26953
|
+
// replace `preload` option of harness
|
26954
|
+
preload : [
|
26955
|
+
"http://cdn.sencha.io/ext-4.0.6/ext-all-debug.js",
|
26956
|
+
"../awesome-project-all.js"
|
26957
|
+
]
|
26958
|
+
},
|
26959
|
+
|
26960
|
+
// groups ("folders") of test files (possibly with own options)
|
26961
|
+
{
|
26962
|
+
group : 'Sanity',
|
26963
|
+
|
26964
|
+
autoCheckGlobals : false,
|
26965
|
+
|
26966
|
+
items : [
|
26967
|
+
'data/crud.t.js',
|
26968
|
+
...
|
26969
|
+
]
|
26970
|
+
},
|
26971
|
+
...
|
26972
|
+
)
|
26133
26973
|
|
26134
26974
|
|
26135
26975
|
*/
|
@@ -26143,17 +26983,31 @@ Class('Siesta.Harness.Browser.SenchaTouch', {
|
|
26143
26983
|
|
26144
26984
|
has: {
|
26145
26985
|
/**
|
26146
|
-
* @cfg {Class} testClass The test class which will be used for creating test instances, defaults to {@link Siesta.Test.
|
26147
|
-
* You can subclass {@link Siesta.Test.
|
26986
|
+
* @cfg {Class} testClass The test class which will be used for creating test instances, defaults to {@link Siesta.Test.SenchaTouch}.
|
26987
|
+
* You can subclass {@link Siesta.Test.SenchaTouch} and provide a new class.
|
26148
26988
|
*
|
26149
26989
|
* This option can be also specified in the test file descriptor.
|
26150
26990
|
*/
|
26151
|
-
testClass: Siesta.Test.SenchaTouch,
|
26991
|
+
testClass : Siesta.Test.SenchaTouch,
|
26152
26992
|
|
26993
|
+
/**
|
26994
|
+
* @cfg {Boolean} transparentEx
|
26995
|
+
*/
|
26153
26996
|
transparentEx : true,
|
26154
26997
|
keepResults : false,
|
26998
|
+
keepNLastResults : 0,
|
26999
|
+
|
27000
|
+
/**
|
27001
|
+
* @cfg {Boolean} performSetup When set to `true`, Siesta will perform a `Ext.setup()` call, so you can safely assume there's a viewport for example.
|
27002
|
+
* If, however your test code, performs `Ext.setup()` itself, you need to disable this option.
|
27003
|
+
*
|
27004
|
+
* This option can be also specified in the test file descriptor.
|
27005
|
+
*/
|
26155
27006
|
performSetup : true,
|
26156
27007
|
|
27008
|
+
/**
|
27009
|
+
* @cfg {String} runCore
|
27010
|
+
*/
|
26157
27011
|
runCore : 'sequential',
|
26158
27012
|
|
26159
27013
|
/**
|
@@ -26163,34 +27017,55 @@ Class('Siesta.Harness.Browser.SenchaTouch', {
|
|
26163
27017
|
*
|
26164
27018
|
* This option can be also specified in the test file descriptor.
|
26165
27019
|
*/
|
26166
|
-
loaderPath: null
|
27020
|
+
loaderPath : null,
|
27021
|
+
|
27022
|
+
isRunningOnMobile : true,
|
27023
|
+
useExtJSUI : true
|
26167
27024
|
},
|
26168
27025
|
|
26169
27026
|
|
26170
27027
|
methods: {
|
27028
|
+
|
27029
|
+
setup : function () {
|
27030
|
+
// TODO fix proper mobile detection, since Ext may be absent in "no-ui" harness
|
27031
|
+
this.isRunningOnMobile = typeof Ext !== 'undefined' && Ext.getVersion && Ext.getVersion('touch')
|
27032
|
+
|
27033
|
+
if (!this.isRunningOnMobile) this.keepNLastResults = 2
|
27034
|
+
|
27035
|
+
this.SUPERARG(arguments)
|
27036
|
+
},
|
27037
|
+
|
26171
27038
|
|
26172
27039
|
getNewTestConfiguration: function (desc, scopeProvider, contentManager, options, runFunc) {
|
26173
27040
|
var config = this.SUPERARG(arguments)
|
26174
27041
|
|
26175
|
-
config.performSetup
|
26176
|
-
config.loaderPath
|
27042
|
+
config.performSetup = this.getDescriptorConfig(desc, 'performSetup')
|
27043
|
+
config.loaderPath = this.getDescriptorConfig(desc, 'loaderPath')
|
26177
27044
|
|
26178
27045
|
return config
|
26179
27046
|
},
|
26180
27047
|
|
27048
|
+
|
26181
27049
|
createViewport: function (config) {
|
27050
|
+
if (!this.isRunningOnMobile && this.useExtJSUI) return Ext.create("Siesta.Harness.Browser.UI.ExtViewport", config);
|
27051
|
+
|
26182
27052
|
var mainPanel = Ext.create('Siesta.Harness.Browser.UI_Mobile.MainPanel', config);
|
27053
|
+
|
26183
27054
|
Ext.Viewport.add(mainPanel);
|
26184
27055
|
|
26185
27056
|
return mainPanel;
|
26186
27057
|
},
|
26187
27058
|
|
27059
|
+
|
26188
27060
|
showForcedIFrame : function (iframe, test) {
|
26189
|
-
|
27061
|
+
$.rebindWindowContext(window);
|
27062
|
+
|
27063
|
+
$(iframe).setStyle({
|
26190
27064
|
'z-index' : 100000
|
26191
27065
|
});
|
26192
27066
|
},
|
26193
27067
|
|
27068
|
+
|
26194
27069
|
onBeforeScopePreload : function (scopeProvider, url) {
|
26195
27070
|
var setupEventTranslation = function() {
|
26196
27071
|
Ext.event.publisher.TouchGesture.override({
|
@@ -26280,13 +27155,14 @@ Class('Siesta.Harness.Browser.SenchaTouch', {
|
|
26280
27155
|
;
|
26281
27156
|
;
|
26282
27157
|
Class('Siesta', {
|
26283
|
-
/*PKGVERSION*/VERSION : '1.1.
|
27158
|
+
/*PKGVERSION*/VERSION : '1.1.5',
|
26284
27159
|
|
26285
27160
|
// "my" should been named "static"
|
26286
27161
|
my : {
|
26287
27162
|
|
26288
27163
|
has : {
|
26289
|
-
config
|
27164
|
+
config : null,
|
27165
|
+
activeHarness : null
|
26290
27166
|
},
|
26291
27167
|
|
26292
27168
|
methods : {
|