siesta 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/controllers/siesta/siesta_controller.rb +1 -1
- data/app/helpers/siesta/application_helper.rb +2 -2
- data/config/routes.rb +1 -1
- data/lib/siesta/test_suite.rb +3 -3
- data/lib/siesta/version.rb +1 -1
- data/vendor/assets/images/siesta/resources/images/trigger-groups.gif +0 -0
- data/vendor/assets/images/siesta/resources/images/trigger-leafs.gif +0 -0
- data/vendor/assets/javascripts/siesta/siesta-all.js +2144 -494
- data/vendor/assets/javascripts/siesta/siesta-nodejs-all.js +538 -138
- data/vendor/assets/javascripts/siesta/siesta-touch-all.js +1325 -449
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-all.css +22 -2
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-touch-all.css +1 -1
- metadata +1243 -1241
@@ -10,7 +10,7 @@ module Siesta
|
|
10
10
|
|
11
11
|
def include_test_harness
|
12
12
|
if Siesta.config.auto_organizing
|
13
|
-
content_tag(:script, test_harness, { type
|
13
|
+
content_tag(:script, test_harness, { :type => 'text/javascript' }, false)
|
14
14
|
else
|
15
15
|
javascript_include_tag 'test_harness'
|
16
16
|
end
|
@@ -25,7 +25,7 @@ module Siesta
|
|
25
25
|
@suite ||= TestSuite.new(File.join(Rails.root, Siesta.config.spec_dir))
|
26
26
|
|
27
27
|
groups = @suite.groups.inject([]) do |c, g|
|
28
|
-
c << { group
|
28
|
+
c << { :group => g.name, :items => g.items.map(&:url) }
|
29
29
|
end
|
30
30
|
|
31
31
|
<<-SCRIPTS
|
data/config/routes.rb
CHANGED
data/lib/siesta/test_suite.rb
CHANGED
@@ -14,7 +14,7 @@ module Siesta
|
|
14
14
|
|
15
15
|
def items
|
16
16
|
@items ||= Dir.glob(File.join(path, '*.t.js')).inject([]) do |c, f|
|
17
|
-
c << Item.new(path
|
17
|
+
c << Item.new(:path => f, :group => self, :suite => suite) unless File.directory?(f)
|
18
18
|
|
19
19
|
c
|
20
20
|
end
|
@@ -41,12 +41,12 @@ module Siesta
|
|
41
41
|
|
42
42
|
def groups
|
43
43
|
@groups ||= Dir.glob(File.join(path, '**', '*')).inject([]) do |c, f|
|
44
|
-
c << Group.new(path
|
44
|
+
c << Group.new(:path => f, :suite => self) if File.directory?(f)
|
45
45
|
|
46
46
|
c
|
47
47
|
end
|
48
48
|
|
49
|
-
@groups << Group.new(path
|
49
|
+
@groups << Group.new(:path => path, :suite => self)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
data/lib/siesta/version.rb
CHANGED
Binary file
|
Binary file
|
@@ -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
|
if (typeof JooseX != "undefined" && !JooseX.SimpleRequest) {;
|
18829
19214
|
Class("JooseX.SimpleRequest", {
|
@@ -19048,6 +19433,8 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19048
19433
|
*/
|
19049
19434
|
target : { required : false },
|
19050
19435
|
|
19436
|
+
normalizedTarget : null,
|
19437
|
+
|
19051
19438
|
/**
|
19052
19439
|
* @cfg {Object} el
|
19053
19440
|
*
|
@@ -19055,7 +19442,7 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19055
19442
|
*/
|
19056
19443
|
|
19057
19444
|
/**
|
19058
|
-
* @cfg {Boolean} passTargetToNext Whether to pass
|
19445
|
+
* @cfg {Boolean} passTargetToNext Whether to pass the target further on chain as the first argument
|
19059
19446
|
*/
|
19060
19447
|
passTargetToNext : true
|
19061
19448
|
},
|
@@ -19068,12 +19455,12 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19068
19455
|
var me = this
|
19069
19456
|
var prevNext = this.next
|
19070
19457
|
|
19071
|
-
// Needs to be 'resolved'
|
19072
|
-
// e.g. unchecking a checkbox
|
19073
|
-
var realTarget = me.test.normalizeActionTarget(me.getTarget());
|
19458
|
+
// // Needs to be 'resolved' at action instantiate time since the action may cause the selector not to be found
|
19459
|
+
// // e.g. unchecking a checkbox
|
19460
|
+
// var realTarget = me.test.normalizeActionTarget(me.getTarget());
|
19074
19461
|
|
19075
19462
|
this.next = function () {
|
19076
|
-
prevNext.call(this,
|
19463
|
+
prevNext.call(this, me.normalizedTarget);
|
19077
19464
|
}
|
19078
19465
|
}
|
19079
19466
|
},
|
@@ -19095,11 +19482,11 @@ Role('Siesta.Test.Action.Role.HasTarget', {
|
|
19095
19482
|
var test = this.test;
|
19096
19483
|
var target = this.target || test.getElementAtCursor();
|
19097
19484
|
|
19098
|
-
if (test.typeOf(target) === 'Function')
|
19099
|
-
|
19100
|
-
|
19485
|
+
if (test.typeOf(target) === 'Function') target = target.call(test, this);
|
19486
|
+
|
19487
|
+
this.normalizedTarget = test.normalizeActionTarget(target)
|
19101
19488
|
|
19102
|
-
return this.__cachedTarget__
|
19489
|
+
return this.__cachedTarget__ = target
|
19103
19490
|
}
|
19104
19491
|
}
|
19105
19492
|
});
|
@@ -19191,30 +19578,119 @@ Siesta.Test.ActionRegistry.registerAction('longpress', Siesta.Test.Action.LongPr
|
|
19191
19578
|
;
|
19192
19579
|
/**
|
19193
19580
|
|
19194
|
-
@class Siesta.Test.Action.
|
19581
|
+
@class Siesta.Test.Action.Tap
|
19195
19582
|
@extends Siesta.Test.Action
|
19196
19583
|
@mixin Siesta.Test.Action.Role.HasTarget
|
19197
19584
|
|
19198
|
-
This action can be included in
|
19585
|
+
This action can be included in the `t.chain` call with "tap" shortcut:
|
19199
19586
|
|
19200
19587
|
t.chain(
|
19201
19588
|
{
|
19202
|
-
action : '
|
19589
|
+
action : 'tap',
|
19203
19590
|
target : someDOMElement
|
19204
19591
|
}
|
19205
19592
|
)
|
19206
19593
|
|
19207
|
-
This action will perform a {@link Siesta.Test.Browser#
|
19594
|
+
This action will perform a {@link Siesta.Test.Browser#tap tap} on the provided {@link #target}.
|
19208
19595
|
|
19209
19596
|
*/
|
19210
|
-
Class('Siesta.Test.Action.
|
19597
|
+
Class('Siesta.Test.Action.Tap', {
|
19211
19598
|
|
19212
19599
|
isa : Siesta.Test.Action,
|
19213
19600
|
|
19214
19601
|
does : Siesta.Test.Action.Role.HasTarget,
|
19215
19602
|
|
19216
19603
|
has : {
|
19217
|
-
requiredTestMethod : '
|
19604
|
+
requiredTestMethod : 'tap'
|
19605
|
+
},
|
19606
|
+
|
19607
|
+
|
19608
|
+
methods : {
|
19609
|
+
|
19610
|
+
process : function () {
|
19611
|
+
this.test.tap(this.getTarget(), this.next)
|
19612
|
+
}
|
19613
|
+
}
|
19614
|
+
});
|
19615
|
+
|
19616
|
+
|
19617
|
+
Siesta.Test.ActionRegistry.registerAction('tap', Siesta.Test.Action.Tap);
|
19618
|
+
/**
|
19619
|
+
|
19620
|
+
@class Siesta.Test.Action.DoubleTap
|
19621
|
+
@extends Siesta.Test.Action
|
19622
|
+
@mixin Siesta.Test.Action.Role.HasTarget
|
19623
|
+
|
19624
|
+
This action will perform a {@link Siesta.Test.Browser#doubleClick double tap} on the provided {@link #target}.
|
19625
|
+
|
19626
|
+
This action can be included in the `t.chain` call with "doubletap" or "doubleTap" shortcuts:
|
19627
|
+
|
19628
|
+
t.chain(
|
19629
|
+
{
|
19630
|
+
action : 'doubletap',
|
19631
|
+
target : someDOMElement
|
19632
|
+
}
|
19633
|
+
)
|
19634
|
+
|
19635
|
+
|
19636
|
+
*/
|
19637
|
+
Class('Siesta.Test.Action.DoubleTap', {
|
19638
|
+
|
19639
|
+
isa : Siesta.Test.Action,
|
19640
|
+
|
19641
|
+
does : Siesta.Test.Action.Role.HasTarget,
|
19642
|
+
|
19643
|
+
has : {
|
19644
|
+
requiredTestMethod : 'doubleTap'
|
19645
|
+
},
|
19646
|
+
|
19647
|
+
|
19648
|
+
methods : {
|
19649
|
+
|
19650
|
+
process : function () {
|
19651
|
+
this.test.doubleTap(this.getTarget(), this.next)
|
19652
|
+
}
|
19653
|
+
}
|
19654
|
+
});
|
19655
|
+
|
19656
|
+
|
19657
|
+
Siesta.Test.ActionRegistry.registerAction('doubletap', Siesta.Test.Action.DoubleTap)
|
19658
|
+
;
|
19659
|
+
/**
|
19660
|
+
|
19661
|
+
@class Siesta.Test.Action.MouseDown
|
19662
|
+
@extends Siesta.Test.Action
|
19663
|
+
@mixin Siesta.Test.Action.Role.HasTarget
|
19664
|
+
|
19665
|
+
This action can be included in a `t.chain` call with "mouseDown" shortcut:
|
19666
|
+
|
19667
|
+
t.chain(
|
19668
|
+
{
|
19669
|
+
action : 'mouseDown',
|
19670
|
+
target : someDOMElement,
|
19671
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19672
|
+
}
|
19673
|
+
)
|
19674
|
+
|
19675
|
+
This action will perform a {@link Siesta.Test.Browser#MouseDown MouseDown} on the provided {@link #target}.
|
19676
|
+
|
19677
|
+
*/
|
19678
|
+
Class('Siesta.Test.Action.MouseDown', {
|
19679
|
+
|
19680
|
+
isa : Siesta.Test.Action,
|
19681
|
+
|
19682
|
+
does : Siesta.Test.Action.Role.HasTarget,
|
19683
|
+
|
19684
|
+
has : {
|
19685
|
+
requiredTestMethod : 'mouseDown',
|
19686
|
+
|
19687
|
+
/**
|
19688
|
+
* @cfg {Object} options
|
19689
|
+
*
|
19690
|
+
* Any options that will be used when simulating the event. For information about possible
|
19691
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19692
|
+
*/
|
19693
|
+
options : null
|
19218
19694
|
},
|
19219
19695
|
|
19220
19696
|
|
@@ -19222,7 +19698,7 @@ Class('Siesta.Test.Action.MouseDown', {
|
|
19222
19698
|
|
19223
19699
|
process : function () {
|
19224
19700
|
// This method is synchronous
|
19225
|
-
this.test.mouseDown(this.getTarget());
|
19701
|
+
this.test.mouseDown(this.getTarget(), this.options);
|
19226
19702
|
|
19227
19703
|
setTimeout(this.next, 100);
|
19228
19704
|
}
|
@@ -19244,7 +19720,8 @@ This action can be included in a `t.chain` call with "mouseUp" shortcut:
|
|
19244
19720
|
t.chain(
|
19245
19721
|
{
|
19246
19722
|
action : 'mouseUp',
|
19247
|
-
target : someDOMElement
|
19723
|
+
target : someDOMElement,
|
19724
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19248
19725
|
}
|
19249
19726
|
)
|
19250
19727
|
|
@@ -19258,7 +19735,15 @@ Class('Siesta.Test.Action.MouseUp', {
|
|
19258
19735
|
does : Siesta.Test.Action.Role.HasTarget,
|
19259
19736
|
|
19260
19737
|
has : {
|
19261
|
-
requiredTestMethod : 'mouseUp'
|
19738
|
+
requiredTestMethod : 'mouseUp',
|
19739
|
+
|
19740
|
+
/**
|
19741
|
+
* @cfg {Object} options
|
19742
|
+
*
|
19743
|
+
* Any options that will be used when simulating the event. For information about possible
|
19744
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19745
|
+
*/
|
19746
|
+
options : null
|
19262
19747
|
},
|
19263
19748
|
|
19264
19749
|
|
@@ -19266,7 +19751,7 @@ Class('Siesta.Test.Action.MouseUp', {
|
|
19266
19751
|
|
19267
19752
|
process : function () {
|
19268
19753
|
// This method is synchronous
|
19269
|
-
this.test.mouseUp(this.getTarget());
|
19754
|
+
this.test.mouseUp(this.getTarget(), this.options);
|
19270
19755
|
|
19271
19756
|
setTimeout(this.next, 100);
|
19272
19757
|
}
|
@@ -19288,7 +19773,8 @@ This action can be included in the `t.chain` call with "click" shortcut:
|
|
19288
19773
|
t.chain(
|
19289
19774
|
{
|
19290
19775
|
action : 'click',
|
19291
|
-
target : someDOMElement
|
19776
|
+
target : someDOMElement,
|
19777
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19292
19778
|
}
|
19293
19779
|
)
|
19294
19780
|
|
@@ -19302,21 +19788,29 @@ Class('Siesta.Test.Action.Click', {
|
|
19302
19788
|
does : Siesta.Test.Action.Role.HasTarget,
|
19303
19789
|
|
19304
19790
|
has : {
|
19305
|
-
requiredTestMethod : 'click'
|
19791
|
+
requiredTestMethod : 'click',
|
19792
|
+
|
19793
|
+
/**
|
19794
|
+
* @cfg {Object} options
|
19795
|
+
*
|
19796
|
+
* Any options that will be used when simulating the event. For information about possible
|
19797
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19798
|
+
*/
|
19799
|
+
options : null
|
19306
19800
|
},
|
19307
19801
|
|
19308
19802
|
|
19309
19803
|
methods : {
|
19310
19804
|
|
19311
19805
|
process : function () {
|
19312
|
-
this.test.click(this.getTarget(), this.next)
|
19806
|
+
this.test.click(this.getTarget(), this.next, null, this.options);
|
19313
19807
|
}
|
19314
19808
|
}
|
19315
19809
|
});
|
19316
19810
|
|
19317
19811
|
|
19318
|
-
Siesta.Test.ActionRegistry.registerAction('click', Siesta.Test.Action.Click)
|
19319
|
-
|
19812
|
+
Siesta.Test.ActionRegistry.registerAction('click', Siesta.Test.Action.Click);
|
19813
|
+
;
|
19320
19814
|
/**
|
19321
19815
|
|
19322
19816
|
@class Siesta.Test.Action.DoubleClick
|
@@ -19329,8 +19823,9 @@ This action can be included in the `t.chain` call with "doubleclick" or "doubleC
|
|
19329
19823
|
|
19330
19824
|
t.chain(
|
19331
19825
|
{
|
19332
|
-
action : '
|
19333
|
-
target : someDOMElement
|
19826
|
+
action : 'doubleclick',
|
19827
|
+
target : someDOMElement,
|
19828
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19334
19829
|
}
|
19335
19830
|
)
|
19336
19831
|
|
@@ -19343,21 +19838,28 @@ Class('Siesta.Test.Action.DoubleClick', {
|
|
19343
19838
|
does : Siesta.Test.Action.Role.HasTarget,
|
19344
19839
|
|
19345
19840
|
has : {
|
19346
|
-
requiredTestMethod : 'doubleClick'
|
19841
|
+
requiredTestMethod : 'doubleClick',
|
19842
|
+
|
19843
|
+
/**
|
19844
|
+
* @cfg {Object} options
|
19845
|
+
*
|
19846
|
+
* Any options that will be used when simulating the event. For information about possible
|
19847
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19848
|
+
*/
|
19849
|
+
options : null
|
19347
19850
|
},
|
19348
19851
|
|
19349
19852
|
|
19350
19853
|
methods : {
|
19351
19854
|
|
19352
19855
|
process : function () {
|
19353
|
-
this.test.doubleClick(this.getTarget(), this.next)
|
19856
|
+
this.test.doubleClick(this.getTarget(), this.next, null, this.options)
|
19354
19857
|
}
|
19355
19858
|
}
|
19356
19859
|
});
|
19357
19860
|
|
19358
19861
|
|
19359
19862
|
Siesta.Test.ActionRegistry.registerAction('doubleclick', Siesta.Test.Action.DoubleClick)
|
19360
|
-
Siesta.Test.ActionRegistry.registerAction('doubletap', Siesta.Test.Action.DoubleClick)
|
19361
19863
|
;
|
19362
19864
|
/**
|
19363
19865
|
|
@@ -19372,7 +19874,8 @@ This action can be included in the `t.chain` call with "rightclick" or "rightCli
|
|
19372
19874
|
t.chain(
|
19373
19875
|
{
|
19374
19876
|
action : 'rightclick',
|
19375
|
-
target : someDOMElement
|
19877
|
+
target : someDOMElement,
|
19878
|
+
options : { shiftKey : true } // Optionally hold shiftkey
|
19376
19879
|
}
|
19377
19880
|
)
|
19378
19881
|
|
@@ -19385,7 +19888,15 @@ Class('Siesta.Test.Action.RightClick', {
|
|
19385
19888
|
does : Siesta.Test.Action.Role.HasTarget,
|
19386
19889
|
|
19387
19890
|
has : {
|
19388
|
-
requiredTestMethod : 'rightClick'
|
19891
|
+
requiredTestMethod : 'rightClick',
|
19892
|
+
|
19893
|
+
/**
|
19894
|
+
* @cfg {Object} options
|
19895
|
+
*
|
19896
|
+
* Any options that will be used when simulating the event. For information about possible
|
19897
|
+
* config options, please see: https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent
|
19898
|
+
*/
|
19899
|
+
options : null
|
19389
19900
|
},
|
19390
19901
|
|
19391
19902
|
|
@@ -19445,6 +19956,7 @@ Class('Siesta.Test.Action.Type', {
|
|
19445
19956
|
// By default use the current focused element as target
|
19446
19957
|
this.target = this.target || this.test.global.document.activeElement;
|
19447
19958
|
|
19959
|
+
// additional "getTarget" to allow functions as "target" value
|
19448
19960
|
this.test.type(this.getTarget(), this.text, this.next)
|
19449
19961
|
}
|
19450
19962
|
}
|
@@ -19831,7 +20343,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19831
20343
|
|
19832
20344
|
// Normalize target
|
19833
20345
|
if (!this.isArray(target)) {
|
19834
|
-
target = this.detectCenter(this.normalizeElement(target));
|
20346
|
+
target = this.detectCenter(this.normalizeElement(target), 'moveMouseTo');
|
19835
20347
|
}
|
19836
20348
|
this.moveMouse(this.currentPosition, target, callback, scope);
|
19837
20349
|
},
|
@@ -19943,12 +20455,12 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19943
20455
|
queue.run(function () {
|
19944
20456
|
me.endAsync(a);
|
19945
20457
|
|
19946
|
-
callback &&
|
20458
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
19947
20459
|
})
|
19948
20460
|
},
|
19949
20461
|
|
19950
20462
|
|
19951
|
-
normalizeClickTarget : function (el) {
|
20463
|
+
normalizeClickTarget : function (el, clickMethod) {
|
19952
20464
|
var doc = this.global.document
|
19953
20465
|
var xy
|
19954
20466
|
|
@@ -19957,13 +20469,12 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19957
20469
|
if (this.isArray(el)) {
|
19958
20470
|
xy = el;
|
19959
20471
|
el = doc.elementFromPoint(xy[0], xy[1]) || doc.body;
|
19960
|
-
options = { clientX : xy[0], clientY : xy[1] };
|
19961
20472
|
} else {
|
19962
20473
|
el = this.normalizeElement(el)
|
19963
20474
|
doc = el.ownerDocument
|
19964
|
-
xy = this.detectCenter(el);
|
20475
|
+
xy = this.detectCenter(el, clickMethod);
|
19965
20476
|
el = doc.elementFromPoint(xy[0], xy[1]) || doc.body;
|
19966
|
-
|
20477
|
+
el && this.$(el).is(':visible');
|
19967
20478
|
}
|
19968
20479
|
|
19969
20480
|
if (!el) {
|
@@ -19978,14 +20489,18 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
19978
20489
|
},
|
19979
20490
|
|
19980
20491
|
|
19981
|
-
genericMouseClick : function (el, callback, scope, clickMethod) {
|
20492
|
+
genericMouseClick : function (el, callback, scope, options, clickMethod) {
|
19982
20493
|
if (jQuery.isFunction(el)) {
|
19983
20494
|
scope = callback;
|
19984
20495
|
callback = el;
|
19985
20496
|
el = null;
|
19986
20497
|
}
|
19987
20498
|
|
19988
|
-
var data = this.normalizeClickTarget(el)
|
20499
|
+
var data = this.normalizeClickTarget(el, clickMethod);
|
20500
|
+
|
20501
|
+
data.options = data.options || {};
|
20502
|
+
|
20503
|
+
$.extend(data.options, options);
|
19989
20504
|
|
19990
20505
|
// the asynchronous case
|
19991
20506
|
if (this.moveCursorBetweenPoints && callback) {
|
@@ -20016,10 +20531,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20016
20531
|
*
|
20017
20532
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
20018
20533
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
20019
|
-
* @param {Object} scope (optional) The scope for the callback
|
20534
|
+
* @param {Object} scope (optional) The scope for the callback
|
20535
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
20020
20536
|
*/
|
20021
|
-
click: function (el, callback, scope) {
|
20022
|
-
this.genericMouseClick(el, callback, scope, 'simulateMouseClick')
|
20537
|
+
click: function (el, callback, scope, options) {
|
20538
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateMouseClick')
|
20023
20539
|
},
|
20024
20540
|
|
20025
20541
|
|
@@ -20043,10 +20559,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20043
20559
|
*
|
20044
20560
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
20045
20561
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
20046
|
-
* @param {Object} scope (optional) The scope for the callback
|
20562
|
+
* @param {Object} scope (optional) The scope for the callback
|
20563
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
20047
20564
|
*/
|
20048
|
-
rightClick: function (el, callback, scope) {
|
20049
|
-
this.genericMouseClick(el, callback, scope, 'simulateRightClick')
|
20565
|
+
rightClick: function (el, callback, scope, options) {
|
20566
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateRightClick')
|
20050
20567
|
},
|
20051
20568
|
|
20052
20569
|
|
@@ -20070,10 +20587,11 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20070
20587
|
*
|
20071
20588
|
* @param {Siesta.Test.ActionTarget} (optional) el One of the {@link Siesta.Test.ActionTarget} values to convert to DOM element
|
20072
20589
|
* @param {Function} callback (optional) A function to call when the condition has been met.
|
20073
|
-
* @param {Object} scope (optional) The scope for the callback
|
20590
|
+
* @param {Object} scope (optional) The scope for the callback
|
20591
|
+
* @param {Object} options (optional) Any options to use for the simulated DOM event
|
20074
20592
|
*/
|
20075
|
-
doubleClick: function (el, callback, scope) {
|
20076
|
-
this.genericMouseClick(el, callback, scope, 'simulateDoubleClick')
|
20593
|
+
doubleClick: function (el, callback, scope, options) {
|
20594
|
+
this.genericMouseClick(el, callback, scope, options, 'simulateDoubleClick')
|
20077
20595
|
},
|
20078
20596
|
|
20079
20597
|
/**
|
@@ -20173,7 +20691,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20173
20691
|
queue.run(function () {
|
20174
20692
|
me.endAsync(async);
|
20175
20693
|
|
20176
|
-
callback &&
|
20694
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20177
20695
|
})
|
20178
20696
|
},
|
20179
20697
|
|
@@ -20212,7 +20730,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20212
20730
|
queue.run(function () {
|
20213
20731
|
me.endAsync(async);
|
20214
20732
|
|
20215
|
-
callback &&
|
20733
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20216
20734
|
})
|
20217
20735
|
},
|
20218
20736
|
|
@@ -20255,7 +20773,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20255
20773
|
queue.run(function () {
|
20256
20774
|
me.endAsync(async);
|
20257
20775
|
|
20258
|
-
callback &&
|
20776
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20259
20777
|
})
|
20260
20778
|
},
|
20261
20779
|
|
@@ -20328,7 +20846,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20328
20846
|
if (this.isArray(source)) {
|
20329
20847
|
sourceXY = source;
|
20330
20848
|
} else {
|
20331
|
-
sourceXY = this.detectCenter(this.normalizeElement(source));
|
20849
|
+
sourceXY = this.detectCenter(this.normalizeElement(source), 'dragTo');
|
20332
20850
|
}
|
20333
20851
|
|
20334
20852
|
// Normalize target
|
@@ -20371,7 +20889,7 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20371
20889
|
if (this.isArray(source)) {
|
20372
20890
|
sourceXY = source;
|
20373
20891
|
} else {
|
20374
|
-
sourceXY = this.detectCenter(this.normalizeElement(source));
|
20892
|
+
sourceXY = this.detectCenter(this.normalizeElement(source), 'dragBy');
|
20375
20893
|
}
|
20376
20894
|
targetXY = [ sourceXY[0] + delta[0], sourceXY[1] + delta[1] ];
|
20377
20895
|
|
@@ -20465,16 +20983,21 @@ Role('Siesta.Test.Simulate.Mouse', {
|
|
20465
20983
|
queue.run(function () {
|
20466
20984
|
me.endAsync(async)
|
20467
20985
|
|
20468
|
-
callback &&
|
20986
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20469
20987
|
});
|
20470
20988
|
},
|
20471
20989
|
|
20472
|
-
detectCenter : function(el) {
|
20990
|
+
detectCenter : function (el, actionName, skipWarning) {
|
20473
20991
|
var hidden = !this.isElementVisible(el);
|
20474
20992
|
|
20475
20993
|
// Trigger mouseover in case source is hidden, possibly shown only when hovering over it (its x/y cannot be determined if display:none)
|
20476
20994
|
if (hidden) {
|
20477
|
-
this.simulateEvent(el, "mouseover", { clientX: 0, clientY: 0});
|
20995
|
+
this.simulateEvent(el, "mouseover", { clientX: 0, clientY: 0 });
|
20996
|
+
|
20997
|
+
if (!skipWarning && !this.isElementVisible(el)) this.fail(
|
20998
|
+
(actionName ? "Target element of action [" + actionName + "]" : "Target element of some action") +
|
20999
|
+
" is not visible: " + (el.id ? '#' + el.id : el)
|
21000
|
+
)
|
20478
21001
|
}
|
20479
21002
|
var center = this.findCenter(el);
|
20480
21003
|
if (hidden) {
|
@@ -20817,21 +21340,22 @@ Role('Siesta.Test.Simulate.Keyboard', {
|
|
20817
21340
|
* @param {Object} scope (optional) the scope for the callback
|
20818
21341
|
*/
|
20819
21342
|
type: function (el, text, callback, scope) {
|
20820
|
-
el = this.normalizeElement(el || this.
|
21343
|
+
el = this.normalizeElement(el || this.global.document.activeElement);
|
20821
21344
|
|
20822
21345
|
// Some browsers (IE/FF) do not overwrite selected text, do it manually.
|
20823
21346
|
var selText = this.getSelectedText(el);
|
21347
|
+
|
20824
21348
|
if (selText) {
|
20825
21349
|
el.value = el.value.replace(selText, '');
|
20826
21350
|
}
|
20827
21351
|
|
21352
|
+
var me = this
|
21353
|
+
|
20828
21354
|
if (el.readOnly || el.disabled) {
|
20829
|
-
callback &&
|
21355
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20830
21356
|
|
20831
21357
|
return;
|
20832
21358
|
}
|
20833
|
-
|
20834
|
-
var me = this
|
20835
21359
|
|
20836
21360
|
// Extract normal chars, or special keys in brackets such as [TAB], [RIGHT] or [ENTER]
|
20837
21361
|
var keys = (text + '').match(/\[([^\])]+\])|([^\[])/g) || [];
|
@@ -20881,7 +21405,7 @@ Role('Siesta.Test.Simulate.Keyboard', {
|
|
20881
21405
|
queue.run(function () {
|
20882
21406
|
me.endAsync(async)
|
20883
21407
|
|
20884
|
-
callback &&
|
21408
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
20885
21409
|
})
|
20886
21410
|
},
|
20887
21411
|
|
@@ -21168,6 +21692,37 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21168
21692
|
return {
|
21169
21693
|
ready : true
|
21170
21694
|
}
|
21695
|
+
},
|
21696
|
+
|
21697
|
+
// Overridden to deal with the different event firing mechanisms in Ext JS 3 vs 4
|
21698
|
+
// This code is required because in IE are simulated using fireEvent instead of dispatchEvent and it seems fireEvent will
|
21699
|
+
// will not update a checkbox 'checked' state properly so we're forcing the toggle to solve this situation.
|
21700
|
+
// This issue is only relevant in IE + Ext.
|
21701
|
+
//
|
21702
|
+
// Test case: 507_form_checkbox.t.js
|
21703
|
+
simulateMouseClick: function (el, callback, scope) {
|
21704
|
+
|
21705
|
+
// Force check toggle for input checkboxes
|
21706
|
+
if (this.simulateEventsWith === 'fireEvent' && (el.type === 'checkbox' || el.type === 'radio') && !el.disabled && !el.readOnly) {
|
21707
|
+
var oldState = el.checked;
|
21708
|
+
|
21709
|
+
if (callback) {
|
21710
|
+
this.SUPER(el, function() {
|
21711
|
+
if (el.checked === oldState) {
|
21712
|
+
el.checked = !oldState;
|
21713
|
+
}
|
21714
|
+
callback.call(scope || this);
|
21715
|
+
});
|
21716
|
+
} else {
|
21717
|
+
this.SUPER(el);
|
21718
|
+
|
21719
|
+
if (el.checked === oldState) {
|
21720
|
+
el.checked = !oldState;
|
21721
|
+
}
|
21722
|
+
}
|
21723
|
+
} else {
|
21724
|
+
this.SUPERARG(arguments);
|
21725
|
+
}
|
21171
21726
|
}
|
21172
21727
|
},
|
21173
21728
|
|
@@ -21271,11 +21826,33 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21271
21826
|
|
21272
21827
|
return component;
|
21273
21828
|
},
|
21274
|
-
|
21275
|
-
|
21276
|
-
|
21829
|
+
|
21830
|
+
/**
|
21831
|
+
* @private
|
21832
|
+
* @param {Ext.Component} comp the Ext.Component
|
21833
|
+
* @param {Boolean} locateInputEl For form fields, try to find the inner input element by default.
|
21834
|
+
* If you want to target the containing Component element, pass false instead.
|
21835
|
+
* @return {*}
|
21836
|
+
*/
|
21837
|
+
compToEl : function (comp, locateInputEl) {
|
21838
|
+
var Ext = this.Ext();
|
21839
|
+
|
21277
21840
|
if (!comp) return null
|
21278
|
-
|
21841
|
+
|
21842
|
+
locateInputEl = locateInputEl !== false;
|
21843
|
+
|
21844
|
+
// Ext JS
|
21845
|
+
if (Ext && Ext.form && Ext.form.Field && locateInputEl) {
|
21846
|
+
if (comp instanceof Ext.form.Field && comp.inputEl){
|
21847
|
+
return comp.inputEl;
|
21848
|
+
}
|
21849
|
+
}
|
21850
|
+
|
21851
|
+
// Sencha Touch: Form fields can have a child input component
|
21852
|
+
if (Ext && Ext.field && Ext.field.Field && comp instanceof Ext.field.Field && locateInputEl) {
|
21853
|
+
comp = comp.getComponent();
|
21854
|
+
}
|
21855
|
+
|
21279
21856
|
// Ext JS vs Sencha Touch
|
21280
21857
|
return comp.getEl ? comp.getEl() : (comp.el || comp.element);
|
21281
21858
|
},
|
@@ -21305,17 +21882,14 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21305
21882
|
}
|
21306
21883
|
}
|
21307
21884
|
|
21308
|
-
if (
|
21309
|
-
el = el
|
21310
|
-
|
21311
|
-
|
21312
|
-
|
21313
|
-
|
21314
|
-
|
21315
|
-
|
21316
|
-
}
|
21317
|
-
|
21318
|
-
// ExtJS Element
|
21885
|
+
if (Ext && Ext.Component && el instanceof Ext.Component) {
|
21886
|
+
el = this.compToEl(el);
|
21887
|
+
var center = this.findCenter(el);
|
21888
|
+
|
21889
|
+
el = this.elementFromPoint(center[0], center[1]) || el;
|
21890
|
+
}
|
21891
|
+
|
21892
|
+
// ExtJS Element
|
21319
21893
|
if (el && el.dom) return el.dom
|
21320
21894
|
|
21321
21895
|
// will also handle the case of conversion of array with coordinates to el
|
@@ -21416,7 +21990,7 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21416
21990
|
me.fail("Class: " + className + " was loaded")
|
21417
21991
|
})
|
21418
21992
|
|
21419
|
-
callback && callback
|
21993
|
+
callback && me.processCallbackFromTest(callback)
|
21420
21994
|
}
|
21421
21995
|
|
21422
21996
|
var timeout = Ext.isIE ? 120000 : 30000,
|
@@ -21530,8 +22104,9 @@ Role('Siesta.Test.ExtJSCore', {
|
|
21530
22104
|
cmp = cmp[0];
|
21531
22105
|
|
21532
22106
|
if (!cmp.rendered) throw 'The source component of the composite query: ' + cmp.id + ' is not yet rendered';
|
21533
|
-
|
21534
|
-
|
22107
|
+
|
22108
|
+
|
22109
|
+
return this.compToEl(cmp, false).query(result[1]);
|
21535
22110
|
},
|
21536
22111
|
|
21537
22112
|
/**
|
@@ -21809,7 +22384,7 @@ Role('Siesta.Test.ExtJS.Observable', {
|
|
21809
22384
|
annotation : n + " '" + event + "' events were expected, but " + counter + ' were fired'
|
21810
22385
|
});
|
21811
22386
|
|
21812
|
-
callback && callback
|
22387
|
+
callback && me.processCallbackFromTest(callback);
|
21813
22388
|
|
21814
22389
|
}, timeOut);
|
21815
22390
|
|
@@ -22345,7 +22920,9 @@ Role('Siesta.Test.ExtJS.Component', {
|
|
22345
22920
|
* @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.
|
22346
22921
|
*/
|
22347
22922
|
waitForComponent: function (component, rendered, callback, scope, timeout) {
|
22348
|
-
var Ext
|
22923
|
+
var Ext = this.getExt();
|
22924
|
+
var xtype
|
22925
|
+
|
22349
22926
|
if (Ext.isString(component)) {
|
22350
22927
|
xtype = Ext.ClassManager.get(component).xtype;
|
22351
22928
|
} else {
|
@@ -22383,6 +22960,75 @@ Role('Siesta.Test.ExtJS.Component', {
|
|
22383
22960
|
hasPosition: function (component, x, y, description) {
|
22384
22961
|
component = this.normalizeComponent(component);
|
22385
22962
|
this.isDeeply(component.getPosition(), [x, y], description);
|
22963
|
+
},
|
22964
|
+
|
22965
|
+
|
22966
|
+
/**
|
22967
|
+
* This assertion accepts variable number of Ext.Component instances (can be also provided as component query string).
|
22968
|
+
* Then it calls their "destroy" method and verifies that:
|
22969
|
+
* - there were no exceptions during destroy
|
22970
|
+
* - that each component was actually destoyed (since destroy can be canceled in the "beforedestroy" event listener)
|
22971
|
+
*
|
22972
|
+
* @param {Ext.Component/Array[Ext.Component]/String} components A single instance of Ext.Component, an array of such or a string with component query
|
22973
|
+
* @param {String} description The description of the assertion
|
22974
|
+
*/
|
22975
|
+
destroysOk : function (components, description) {
|
22976
|
+
var Ext = this.Ext();
|
22977
|
+
|
22978
|
+
if (this.typeOf(components) != 'Array') {
|
22979
|
+
if (this.typeOf(components) == 'String')
|
22980
|
+
components = this.Ext().ComponentQuery.query(components);
|
22981
|
+
else
|
22982
|
+
components = [ components ]
|
22983
|
+
}
|
22984
|
+
|
22985
|
+
if (!components.length) {
|
22986
|
+
this.fail(description, {
|
22987
|
+
assertionName : 'destroysOk',
|
22988
|
+
annotation : 'No components provided, or component query returned empty result'
|
22989
|
+
})
|
22990
|
+
|
22991
|
+
return
|
22992
|
+
}
|
22993
|
+
|
22994
|
+
var currentComp
|
22995
|
+
|
22996
|
+
var e = this.getExceptionCatcher()(function () {
|
22997
|
+
Joose.A.each(components, function (component) {
|
22998
|
+
currentComp = component
|
22999
|
+
|
23000
|
+
component.destroy()
|
23001
|
+
})
|
23002
|
+
})
|
23003
|
+
|
23004
|
+
if (e !== undefined) {
|
23005
|
+
this.fail(description, {
|
23006
|
+
assertionName : 'destroysOk',
|
23007
|
+
got : e,
|
23008
|
+
gotDesc : 'Exception',
|
23009
|
+
annotation : 'Exception thrown while calling "destroy" method of ' + currentComp.id
|
23010
|
+
})
|
23011
|
+
|
23012
|
+
return
|
23013
|
+
}
|
23014
|
+
|
23015
|
+
var me = this
|
23016
|
+
|
23017
|
+
var allDestroyed = Joose.A.each(components, function (component) {
|
23018
|
+
// ExtJS ST
|
23019
|
+
if (!(component.isDestroyed || component.destroy == Ext.emptyFn)) {
|
23020
|
+
me.fail(description, {
|
23021
|
+
assertionName : 'destroysOk',
|
23022
|
+
annotation : 'Component [' + component.id + '] was not destroyed (probably destroy was canceled in the `beforedestroy` listener)'
|
23023
|
+
})
|
23024
|
+
|
23025
|
+
return false
|
23026
|
+
}
|
23027
|
+
})
|
23028
|
+
|
23029
|
+
if (allDestroyed === false) return
|
23030
|
+
|
23031
|
+
this.pass(description)
|
22386
23032
|
}
|
22387
23033
|
}
|
22388
23034
|
});
|
@@ -22784,13 +23430,14 @@ Role('Siesta.Test.Element', {
|
|
22784
23430
|
|
22785
23431
|
|
22786
23432
|
/**
|
22787
|
-
* Returns true if the element is visible.
|
23433
|
+
* Returns true if the element is visible, checking jQuery :visible selector + style visibilty value.
|
22788
23434
|
* @param {Siesta.Test.ActionTarget} el The element
|
22789
23435
|
* @return {Boolean}
|
22790
23436
|
*/
|
22791
23437
|
isElementVisible : function(el) {
|
22792
23438
|
el = this.normalizeElement(el);
|
22793
|
-
|
23439
|
+
// Jquery :visible doesn't take visibility into account
|
23440
|
+
return !!el && this.$(el).is(':visible') && el.style.visibility !== 'hidden';
|
22794
23441
|
},
|
22795
23442
|
|
22796
23443
|
/**
|
@@ -22966,7 +23613,7 @@ Role('Siesta.Test.Element', {
|
|
22966
23613
|
assertionChecker()
|
22967
23614
|
}
|
22968
23615
|
|
22969
|
-
callback &&
|
23616
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
22970
23617
|
});
|
22971
23618
|
},
|
22972
23619
|
|
@@ -23386,11 +24033,11 @@ Role('Siesta.Test.Element', {
|
|
23386
24033
|
this.fail(description, {
|
23387
24034
|
assertionName : 'elementIsAt',
|
23388
24035
|
got : { x: xy[0], y : xy[1] },
|
23389
|
-
gotDesc : '
|
24036
|
+
gotDesc : 'Position',
|
23390
24037
|
annotation : 'No element found at the specified position'
|
23391
24038
|
});
|
23392
24039
|
} else if (allowChildren) {
|
23393
|
-
if (foundEl === el || $(foundEl).closest(el)) {
|
24040
|
+
if (foundEl === el || $(foundEl).closest(el).length > 0) {
|
23394
24041
|
this.pass(description);
|
23395
24042
|
} else {
|
23396
24043
|
this.fail(description, {
|
@@ -23488,21 +24135,14 @@ Role('Siesta.Test.Element', {
|
|
23488
24135
|
|
23489
24136
|
var foundEl = this.$(doc.elementFromPoint(xy[0], xy[1]) || doc.body);
|
23490
24137
|
|
23491
|
-
if (!foundEl) {
|
23492
|
-
this.fail(description, {
|
23493
|
-
assertionName : 'selectorIsAt',
|
23494
|
-
got : { x: xy[0], y : xy[1] },
|
23495
|
-
gotDesc : 'Postion',
|
23496
|
-
annotation : 'No element matching the passed selector found at the specified position'
|
23497
|
-
});
|
23498
|
-
}
|
23499
|
-
|
23500
24138
|
if (foundEl.has(selector).length > 0 || foundEl.closest(selector).length > 0) {
|
23501
24139
|
this.pass(description);
|
23502
24140
|
} else {
|
23503
24141
|
this.fail(description, {
|
24142
|
+
got : foundEl[0].outerHTML ? foundEl[0].outerHTML : foundEl[0].innerHTML,
|
24143
|
+
need : 'Element matching ' + selector,
|
23504
24144
|
assertionName : 'selectorIsAt',
|
23505
|
-
annotation : 'Passed selector does not match
|
24145
|
+
annotation : 'Passed selector does not match any selector at [' + xy + ']'
|
23506
24146
|
});
|
23507
24147
|
}
|
23508
24148
|
},
|
@@ -23629,7 +24269,11 @@ Role('Siesta.Test.Element', {
|
|
23629
24269
|
})
|
23630
24270
|
})
|
23631
24271
|
|
23632
|
-
|
24272
|
+
var me = this
|
24273
|
+
|
24274
|
+
if (callback) steps.push(function () {
|
24275
|
+
me.processCallbackFromTest(callback)
|
24276
|
+
})
|
23633
24277
|
|
23634
24278
|
this.chain.apply(this, steps)
|
23635
24279
|
},
|
@@ -23646,7 +24290,7 @@ Role('Siesta.Test.Element', {
|
|
23646
24290
|
*
|
23647
24291
|
* t.clickSelector('.my-grid .x-grid-row', function () {})
|
23648
24292
|
*
|
23649
|
-
* The provided callback will receive
|
24293
|
+
* The provided callback will receive an array with DOM elements - result of query.
|
23650
24294
|
*
|
23651
24295
|
*
|
23652
24296
|
* @param {String} selector The selector/xpath query
|
@@ -23942,7 +24586,7 @@ Class('Siesta.Test.Browser', {
|
|
23942
24586
|
annotation : n + " '" + event + "' events were expected, but " + counter + ' were fired'
|
23943
24587
|
});
|
23944
24588
|
|
23945
|
-
callback && callback
|
24589
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
23946
24590
|
|
23947
24591
|
}, timeOut);
|
23948
24592
|
|
@@ -24077,15 +24721,19 @@ Class('Siesta.Test.ExtJS', {
|
|
24077
24721
|
|
24078
24722
|
getExtBundlePath : function() {
|
24079
24723
|
var path;
|
24080
|
-
|
24081
|
-
|
24082
|
-
|
24083
|
-
|
24084
|
-
|
24085
|
-
|
24086
|
-
|
24724
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24725
|
+
|
24726
|
+
while (testDescriptor && !path) {
|
24727
|
+
if (testDescriptor.preload) {
|
24728
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24729
|
+
if (url.match && url.match(/ext(?:js)?-\d\.\d+(?:\.\d+)?.*?\/ext-all(?:-debug)?\.js/)) {
|
24730
|
+
path = url;
|
24731
|
+
return false;
|
24732
|
+
}
|
24733
|
+
});
|
24087
24734
|
}
|
24088
|
-
|
24735
|
+
testDescriptor = testDescriptor.parent;
|
24736
|
+
}
|
24089
24737
|
|
24090
24738
|
return path;
|
24091
24739
|
},
|
@@ -24093,17 +24741,21 @@ Class('Siesta.Test.ExtJS', {
|
|
24093
24741
|
|
24094
24742
|
getExtBundleFolder : function() {
|
24095
24743
|
var folder;
|
24744
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24096
24745
|
|
24097
|
-
|
24098
|
-
|
24099
|
-
|
24100
|
-
|
24101
|
-
|
24746
|
+
while (testDescriptor && !folder) {
|
24747
|
+
if (testDescriptor.preload) {
|
24748
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24749
|
+
var regex = /(.*ext(?:js)?-\d\.\d+(?:\.\d+)?.*?)\/ext-all(?:-debug)?\.js/;
|
24750
|
+
var match = regex.exec(url);
|
24102
24751
|
|
24103
|
-
|
24104
|
-
|
24752
|
+
if (match) {
|
24753
|
+
folder = match[1];
|
24754
|
+
}
|
24755
|
+
});
|
24105
24756
|
}
|
24106
|
-
|
24757
|
+
testDescriptor = testDescriptor.parent;
|
24758
|
+
}
|
24107
24759
|
|
24108
24760
|
return folder;
|
24109
24761
|
}
|
@@ -24182,7 +24834,47 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24182
24834
|
},
|
24183
24835
|
|
24184
24836
|
methods : {
|
24185
|
-
|
24837
|
+
getTouchBundlePath : function() {
|
24838
|
+
var path;
|
24839
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24840
|
+
|
24841
|
+
while (testDescriptor && !path) {
|
24842
|
+
if (testDescriptor.preload) {
|
24843
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24844
|
+
if (url.match && url.match(/(.*sencha-touch-\d\.\d+\.\d+.*?)\/sencha-touch(.*)\.js/)) {
|
24845
|
+
path = url;
|
24846
|
+
return false;
|
24847
|
+
}
|
24848
|
+
});
|
24849
|
+
}
|
24850
|
+
testDescriptor = testDescriptor.parent;
|
24851
|
+
}
|
24852
|
+
|
24853
|
+
return path;
|
24854
|
+
},
|
24855
|
+
|
24856
|
+
|
24857
|
+
getTouchBundleFolder : function() {
|
24858
|
+
var folder;
|
24859
|
+
var testDescriptor = this.harness.getScriptDescriptor(this.url)
|
24860
|
+
|
24861
|
+
while (testDescriptor && !folder) {
|
24862
|
+
if (testDescriptor.preload) {
|
24863
|
+
Joose.A.each(testDescriptor.preload, function (url) {
|
24864
|
+
var regex = /(.*sencha-touch-\d\.\d+\.\d+.*?)\/sencha-touch(.*)\.js/;
|
24865
|
+
var match = regex.exec(url);
|
24866
|
+
|
24867
|
+
if (match) {
|
24868
|
+
folder = match[1];
|
24869
|
+
}
|
24870
|
+
});
|
24871
|
+
}
|
24872
|
+
testDescriptor = testDescriptor.parent;
|
24873
|
+
}
|
24874
|
+
|
24875
|
+
return folder;
|
24876
|
+
},
|
24877
|
+
|
24186
24878
|
/**
|
24187
24879
|
* This method taps the passed target, which can be of several different types, see {@link Siesta.Test.ActionTarget}
|
24188
24880
|
*
|
@@ -24191,18 +24883,73 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24191
24883
|
* @param {Object} scope (optional) The scope for the callback
|
24192
24884
|
*/
|
24193
24885
|
tap: function (target, callback, scope) {
|
24194
|
-
|
24195
|
-
|
24196
|
-
|
24197
|
-
|
24198
|
-
|
24199
|
-
|
24200
|
-
|
24201
|
-
|
24886
|
+
var me = this;
|
24887
|
+
|
24888
|
+
target = this.normalizeElement(target);
|
24889
|
+
|
24890
|
+
var queue = new Siesta.Util.Queue({
|
24891
|
+
deferer : this.originalSetTimeout,
|
24892
|
+
deferClearer : this.originalClearTimeout,
|
24893
|
+
|
24894
|
+
interval : callback ? 30 : 0,
|
24895
|
+
|
24896
|
+
observeTest : this,
|
24897
|
+
|
24898
|
+
processor : function (data) {
|
24899
|
+
me.simulateEvent.apply(me, data);
|
24900
|
+
}
|
24901
|
+
})
|
24902
|
+
|
24903
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24904
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24905
|
+
|
24906
|
+
var async = me.beginAsync();
|
24907
|
+
|
24908
|
+
queue.run(function () {
|
24909
|
+
me.endAsync(async);
|
24910
|
+
|
24911
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
24912
|
+
})
|
24913
|
+
},
|
24914
|
+
|
24915
|
+
/**
|
24916
|
+
* This method double taps the passed target, which can be of several different types, see {@link Siesta.Test.ActionTarget}
|
24917
|
+
*
|
24918
|
+
* @param {Siesta.Test.ActionTarget} target Target for this action
|
24919
|
+
* @param {Function} callback (optional) A function to call after action
|
24202
24920
|
* @param {Object} scope (optional) The scope for the callback
|
24203
24921
|
*/
|
24204
24922
|
doubleTap: function (target, callback, scope) {
|
24205
|
-
|
24923
|
+
var me = this;
|
24924
|
+
|
24925
|
+
target = this.normalizeElement(target);
|
24926
|
+
|
24927
|
+
var queue = new Siesta.Util.Queue({
|
24928
|
+
deferer : this.originalSetTimeout,
|
24929
|
+
deferClearer : this.originalClearTimeout,
|
24930
|
+
|
24931
|
+
interval : callback ? 30 : 0,
|
24932
|
+
|
24933
|
+
observeTest : this,
|
24934
|
+
|
24935
|
+
processor : function (data) {
|
24936
|
+
me.simulateEvent.apply(me, data);
|
24937
|
+
}
|
24938
|
+
})
|
24939
|
+
|
24940
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24941
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24942
|
+
|
24943
|
+
queue.addStep([ target, "mousedown", {}, false ])
|
24944
|
+
queue.addStep([ target, "mouseup", {}, true ])
|
24945
|
+
|
24946
|
+
var async = me.beginAsync();
|
24947
|
+
|
24948
|
+
queue.run(function () {
|
24949
|
+
me.endAsync(async);
|
24950
|
+
|
24951
|
+
callback && me.processCallbackFromTest(callback, null, scope || me)
|
24952
|
+
})
|
24206
24953
|
},
|
24207
24954
|
|
24208
24955
|
/**
|
@@ -24214,11 +24961,17 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24214
24961
|
*/
|
24215
24962
|
longpress: function (target, callback, scope) {
|
24216
24963
|
var Ext = this.Ext();
|
24964
|
+
var me = this;
|
24217
24965
|
|
24218
24966
|
this.simulateEvent(target, 'mousedown');
|
24219
24967
|
|
24220
24968
|
var amount = Ext.event.recognizer.LongPress.prototype.config.minDuration;
|
24221
|
-
|
24969
|
+
|
24970
|
+
this.waitFor(amount, function() {
|
24971
|
+
me.simulateEvent(target, 'mouseup');
|
24972
|
+
|
24973
|
+
callback.call(scope || me);
|
24974
|
+
});
|
24222
24975
|
},
|
24223
24976
|
|
24224
24977
|
/**
|
@@ -24237,30 +24990,41 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24237
24990
|
start,
|
24238
24991
|
end,
|
24239
24992
|
edgeOffsetRatio = 10;
|
24993
|
+
|
24994
|
+
// Since this method accepts elements as target, we need to assure that we swipe at least about 150px
|
24995
|
+
// using Math.max below etc
|
24240
24996
|
|
24241
24997
|
switch(direction) {
|
24242
24998
|
case 'u':
|
24243
24999
|
case 'up':
|
24244
|
-
start
|
24245
|
-
end
|
25000
|
+
start = [box.x + box.width/2, (box.y + box.height*9/edgeOffsetRatio)];
|
25001
|
+
end = [box.x + box.width/2, box.y + box.height/edgeOffsetRatio];
|
25002
|
+
|
25003
|
+
end[1] = Math.min(start[1] - 100, end[1]);
|
24246
25004
|
break;
|
24247
25005
|
|
24248
25006
|
case 'd':
|
24249
25007
|
case 'down':
|
24250
|
-
start
|
24251
|
-
end
|
24252
|
-
break;
|
25008
|
+
start = [box.x + box.width/2, (box.y + box.height/edgeOffsetRatio)];
|
25009
|
+
end = [box.x + box.width/2, (box.y + box.height*9/edgeOffsetRatio)];
|
24253
25010
|
|
24254
|
-
|
24255
|
-
case 'left':
|
24256
|
-
start = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
24257
|
-
end = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
25011
|
+
end[1] = Math.max(start[1] + 100, end[1]);
|
24258
25012
|
break;
|
24259
25013
|
|
24260
25014
|
case 'r':
|
24261
25015
|
case 'right':
|
24262
|
-
start
|
24263
|
-
end
|
25016
|
+
start = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
25017
|
+
end = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
25018
|
+
|
25019
|
+
end[0] = Math.max(start[0] + 100, end[0]);
|
25020
|
+
break;
|
25021
|
+
|
25022
|
+
case 'l':
|
25023
|
+
case 'left':
|
25024
|
+
start = [box.x + (box.width * 9/edgeOffsetRatio), (box.y + box.height/2)];
|
25025
|
+
end = [box.x + (box.width /edgeOffsetRatio), (box.y + box.height/2)];
|
25026
|
+
|
25027
|
+
end[0] = Math.min(start[0] - 100, end[0]);
|
24264
25028
|
break;
|
24265
25029
|
|
24266
25030
|
default:
|
@@ -24270,6 +25034,42 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24270
25034
|
this.dragTo(start, end, callback, scope);
|
24271
25035
|
},
|
24272
25036
|
|
25037
|
+
/**
|
25038
|
+
* This method will simulate a finger move to an xy-coordinate or an element (the center of it)
|
25039
|
+
*
|
25040
|
+
* @param {Siesta.Test.ActionTarget} target Target point to move the mouse to.
|
25041
|
+
* @param {Function} callback (optional) To run this method async, provide a callback method to be called after the operation is completed.
|
25042
|
+
* @param {Object} scope (optional) the scope for the callback
|
25043
|
+
*/
|
25044
|
+
moveFingerTo : function(target, callback, scope) {
|
25045
|
+
if (!target) {
|
25046
|
+
throw 'Trying to call moveFingerTo without a target';
|
25047
|
+
}
|
25048
|
+
|
25049
|
+
// Normalize target
|
25050
|
+
if (!this.isArray(target)) {
|
25051
|
+
target = this.detectCenter(this.normalizeElement(target), 'moveFingerTo');
|
25052
|
+
}
|
25053
|
+
this.moveMouse(this.currentPosition, target, callback, scope);
|
25054
|
+
},
|
25055
|
+
|
25056
|
+
/**
|
25057
|
+
* This method will simulate a finger move from current position relative by the x and y distances provided.
|
25058
|
+
*
|
25059
|
+
* @param {Siesta.Test.ActionTarget} target Target point to move the mouse to.
|
25060
|
+
* @param {Function} callback (optional) To run this method async, provide a callback method to be called after the operation is completed.
|
25061
|
+
* @param {Object} scope (optional) the scope for the callback
|
25062
|
+
*/
|
25063
|
+
moveFingerBy : function(delta, callback, scope) {
|
25064
|
+
if (!delta) {
|
25065
|
+
throw 'Trying to call moveFingerBy without relative distances';
|
25066
|
+
}
|
25067
|
+
|
25068
|
+
var targetXY = [ this.currentPosition[0] + delta[0], this.currentPosition[1] + delta[1] ];
|
25069
|
+
|
25070
|
+
this.moveMouseTo(targetXY, callback, scope);
|
25071
|
+
},
|
25072
|
+
|
24273
25073
|
// /**
|
24274
25074
|
// * This method will simulate a swipe operation between either two points or on a single DOM element.
|
24275
25075
|
// *
|
@@ -24327,7 +25127,7 @@ Class('Siesta.Test.SenchaTouch', {
|
|
24327
25127
|
var inner = function() {
|
24328
25128
|
if (checkerFn.call(scope || me, target)) {
|
24329
25129
|
// We're done
|
24330
|
-
|
25130
|
+
me.processCallbackFromTest(callback, null, scope || me)
|
24331
25131
|
} else {
|
24332
25132
|
me.swipe(target, direction, function() {
|
24333
25133
|
var as = me.beginAsync();
|
@@ -24732,7 +25532,9 @@ Class('Siesta.Harness.Browser', {
|
|
24732
25532
|
*/
|
24733
25533
|
viewportHeight : 768,
|
24734
25534
|
|
24735
|
-
needUI : true
|
25535
|
+
needUI : true,
|
25536
|
+
|
25537
|
+
isAutomated : false
|
24736
25538
|
},
|
24737
25539
|
|
24738
25540
|
|
@@ -24775,6 +25577,10 @@ Class('Siesta.Harness.Browser', {
|
|
24775
25577
|
|
24776
25578
|
onTestUpdate : function (test, result) {
|
24777
25579
|
if (this.viewport) this.viewport.onTestUpdate(test, result)
|
25580
|
+
|
25581
|
+
if ((result instanceof Siesta.Result.Diagnostic) && result.isWarning && this.needUI) {
|
25582
|
+
if (typeof console != 'undefined' && console.warn) console.warn(result + '')
|
25583
|
+
}
|
24778
25584
|
},
|
24779
25585
|
|
24780
25586
|
|
@@ -24811,11 +25617,6 @@ Class('Siesta.Harness.Browser', {
|
|
24811
25617
|
},
|
24812
25618
|
|
24813
25619
|
|
24814
|
-
isAutomated : function () {
|
24815
|
-
return false
|
24816
|
-
},
|
24817
|
-
|
24818
|
-
|
24819
25620
|
configure : function() {
|
24820
25621
|
this.SUPERARG(arguments);
|
24821
25622
|
|
@@ -24857,7 +25658,7 @@ Class('Siesta.Harness.Browser', {
|
|
24857
25658
|
|
24858
25659
|
// if we here, then we were requested to show the UI for automated launch
|
24859
25660
|
// auto-launch the test suite in this case
|
24860
|
-
if (me.isAutomated
|
25661
|
+
if (me.isAutomated) SUPER.apply(me, args)
|
24861
25662
|
};
|
24862
25663
|
|
24863
25664
|
if (Ext.setup) {
|
@@ -24892,7 +25693,7 @@ Class('Siesta.Harness.Browser', {
|
|
24892
25693
|
var sup = this.SUPER
|
24893
25694
|
|
24894
25695
|
// delay the super setup until dom ready
|
24895
|
-
if (!this.isAutomated
|
25696
|
+
if (!this.isAutomated) {
|
24896
25697
|
Ext.onReady(function () {
|
24897
25698
|
Siesta.supports.init();
|
24898
25699
|
|
@@ -25032,16 +25833,28 @@ Class('Siesta.Harness.Browser', {
|
|
25032
25833
|
|
25033
25834
|
|
25034
25835
|
showForcedIFrame : function (iframe, test) {
|
25035
|
-
|
25036
|
-
|
25836
|
+
$.rebindWindowContext(window);
|
25837
|
+
$(iframe).addClass('tr-iframe-forced')
|
25838
|
+
$(iframe).removeClass('tr-iframe-hidden')
|
25037
25839
|
|
25038
|
-
|
25840
|
+
$(iframe).center()
|
25039
25841
|
},
|
25040
25842
|
|
25041
25843
|
|
25042
25844
|
hideForcedIFrame : function (iframe) {
|
25043
|
-
|
25044
|
-
|
25845
|
+
$.rebindWindowContext(window);
|
25846
|
+
$(iframe).removeClass('tr-iframe-forced')
|
25847
|
+
$(iframe).addClass('tr-iframe-hidden')
|
25848
|
+
},
|
25849
|
+
|
25850
|
+
getQueryParam : function (paramName) {
|
25851
|
+
var regex = new RegExp('(?:\\?|&)' + paramName + '=(.*?)(?:\\?|&|$)', 'i')
|
25852
|
+
|
25853
|
+
var match = regex.exec(window.location.search)
|
25854
|
+
|
25855
|
+
if (!match) return null
|
25856
|
+
|
25857
|
+
return match[ 1 ]
|
25045
25858
|
}
|
25046
25859
|
}
|
25047
25860
|
|
@@ -25220,179 +26033,527 @@ Ext.Container.override({
|
|
25220
26033
|
}
|
25221
26034
|
})
|
25222
26035
|
;
|
25223
|
-
|
25224
|
-
|
26036
|
+
(function () {
|
26037
|
+
var config = {
|
26038
|
+
idProperty : 'id',
|
25225
26039
|
|
25226
|
-
|
25227
|
-
|
25228
|
-
|
25229
|
-
|
25230
|
-
|
25231
|
-
|
25232
|
-
|
25233
|
-
|
25234
|
-
|
25235
|
-
|
25236
|
-
|
25237
|
-
|
25238
|
-
|
25239
|
-
|
25240
|
-
|
25241
|
-
|
26040
|
+
fields : [
|
26041
|
+
'id',
|
26042
|
+
'url',
|
26043
|
+
|
26044
|
+
'title',
|
26045
|
+
|
26046
|
+
{ name : 'passCount', type : 'int', defaultValue : 0 },
|
26047
|
+
{ name : 'failCount', type : 'int', defaultValue : 0 },
|
26048
|
+
{ name : 'todoPassCount', type : 'int', defaultValue : 0 },
|
26049
|
+
{ name : 'todoFailCount', type : 'int', defaultValue : 0 },
|
26050
|
+
|
26051
|
+
{ name : 'time', type : 'int', defaultValue : 0 },
|
26052
|
+
|
26053
|
+
{
|
26054
|
+
name : 'checked',
|
26055
|
+
defaultValue : false
|
26056
|
+
},
|
26057
|
+
|
26058
|
+
{
|
26059
|
+
name : 'folderStatus',
|
26060
|
+
defaultValue : 'yellow'
|
26061
|
+
},
|
26062
|
+
|
26063
|
+
// will be set to true for all tests, once the users clicks "run"
|
26064
|
+
'isStarting',
|
26065
|
+
// will be set to true, right before the scope preload begin
|
26066
|
+
'isStarted',
|
26067
|
+
// will be set to true, after preload ends and tests launch
|
26068
|
+
{ name : 'isRunning', type : 'boolean', defaultValue : false },
|
26069
|
+
{ name : 'isMissing', type : 'boolean', defaultValue : false },
|
26070
|
+
{ name : 'isFailed', type : 'boolean', defaultValue : false },
|
26071
|
+
|
26072
|
+
// composite objects
|
26073
|
+
'assertionsStore',
|
26074
|
+
'test',
|
26075
|
+
'descriptor'
|
26076
|
+
]
|
26077
|
+
};
|
26078
|
+
|
26079
|
+
Ext.define('Siesta.Harness.Browser.Model.TestFile', Ext.apply({
|
26080
|
+
|
26081
|
+
extend : 'Ext.data.Model',
|
26082
|
+
|
26083
|
+
init : function () {
|
26084
|
+
this.internalId = this.getId() || this.internalId
|
25242
26085
|
},
|
25243
|
-
|
25244
|
-
{
|
25245
|
-
name : 'folderStatus',
|
25246
|
-
defaultValue : 'yellow'
|
25247
|
-
},
|
25248
|
-
|
25249
|
-
// will be set to true for all tests, once the users clicks "run"
|
25250
|
-
'isStarting',
|
25251
|
-
// will be set to true, right before the scope preload begin
|
25252
|
-
'isStarted',
|
25253
|
-
// will be set to true, after preload ends and tests launch
|
25254
|
-
{ name : 'isRunning', type : 'boolean', defaultValue : false },
|
25255
|
-
{ name : 'isMissing', type : 'boolean', defaultValue : false },
|
25256
|
-
{ name : 'isFailed', type : 'boolean', defaultValue : false },
|
25257
|
-
|
25258
|
-
// composite objects
|
25259
|
-
'assertionsStore',
|
25260
|
-
'test',
|
25261
|
-
'descriptor'
|
25262
|
-
]
|
25263
|
-
};
|
25264
26086
|
|
25265
|
-
Ext.define('Siesta.Harness.Browser.Model.TestFile', Ext.apply({
|
25266
26087
|
|
25267
|
-
|
26088
|
+
computeFolderStatus : function () {
|
26089
|
+
if (!this.childNodes.length) return 'yellow'
|
25268
26090
|
|
25269
|
-
|
25270
|
-
|
25271
|
-
|
26091
|
+
var isWorking = false
|
26092
|
+
var hasFailed = false
|
26093
|
+
var allGreen = true
|
26094
|
+
|
26095
|
+
Joose.A.each(this.childNodes, function (childNode) {
|
26096
|
+
|
26097
|
+
if (childNode.isLeaf()) {
|
26098
|
+
var test = childNode.get('test')
|
26099
|
+
|
26100
|
+
if (test && test.isFailed()) {
|
26101
|
+
allGreen = false
|
26102
|
+
hasFailed = true
|
26103
|
+
|
26104
|
+
// stop iteration
|
26105
|
+
return false
|
26106
|
+
}
|
26107
|
+
|
26108
|
+
if (!test && childNode.get('isStarting')) isWorking = true
|
26109
|
+
if (test && !test.isFinished()) isWorking = true
|
26110
|
+
if (test && !test.isPassed()) allGreen = false
|
26111
|
+
if (!test) allGreen = false
|
26112
|
+
|
26113
|
+
} else {
|
26114
|
+
var status = childNode.computeFolderStatus()
|
26115
|
+
|
26116
|
+
if (status == 'red') {
|
26117
|
+
allGreen = false
|
26118
|
+
hasFailed = true
|
26119
|
+
|
26120
|
+
// stop iteration
|
26121
|
+
return false
|
26122
|
+
}
|
26123
|
+
|
26124
|
+
if (status == 'working') {
|
26125
|
+
isWorking = true
|
26126
|
+
|
26127
|
+
// stop iteration
|
26128
|
+
return false
|
26129
|
+
}
|
26130
|
+
|
26131
|
+
if (status == 'yellow') allGreen = false
|
26132
|
+
}
|
26133
|
+
})
|
26134
|
+
|
26135
|
+
if (isWorking) return 'working'
|
26136
|
+
if (hasFailed) return 'red'
|
26137
|
+
if (allGreen) return 'green'
|
26138
|
+
|
26139
|
+
return 'yellow'
|
26140
|
+
},
|
26141
|
+
|
26142
|
+
|
26143
|
+
updateFolderStatus : function () {
|
26144
|
+
this.set('folderStatus', this.computeFolderStatus())
|
26145
|
+
|
26146
|
+
var parentNode = this.parentNode
|
26147
|
+
|
26148
|
+
if (parentNode && !parentNode.isRoot()) parentNode.updateFolderStatus()
|
26149
|
+
},
|
25272
26150
|
|
26151
|
+
getFailedAssertions : function () {
|
26152
|
+
var failed = [];
|
26153
|
+
var as = this.get('assertionsStore');
|
25273
26154
|
|
25274
|
-
|
25275
|
-
|
26155
|
+
if (as) {
|
26156
|
+
as.each(function (assertion) {
|
26157
|
+
if (assertion.get('passed') === false) {
|
26158
|
+
failed.push(assertion);
|
26159
|
+
}
|
26160
|
+
});
|
26161
|
+
}
|
26162
|
+
|
26163
|
+
return failed;
|
26164
|
+
}
|
26165
|
+
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config), function () {
|
26166
|
+
var isSenchaTouch = Ext.getVersion && Ext.getVersion('touch')
|
26167
|
+
|
26168
|
+
if (!isSenchaTouch) {
|
26169
|
+
Ext.data.NodeInterface.decorate(this);
|
26170
|
+
|
26171
|
+
this.override({
|
26172
|
+
expand : function () {
|
26173
|
+
Ext.suspendLayouts();
|
26174
|
+
this.callParent(arguments);
|
26175
|
+
Ext.resumeLayouts();
|
26176
|
+
}
|
26177
|
+
});
|
26178
|
+
}
|
26179
|
+
})
|
26180
|
+
})();
|
26181
|
+
;
|
26182
|
+
(function () {
|
26183
|
+
var config = {
|
26184
|
+
idProperty : 'index',
|
26185
|
+
|
26186
|
+
fields : [
|
26187
|
+
'index',
|
26188
|
+
'summaryFailure',
|
26189
|
+
{ name : 'passed', type : 'boolean', defaultValue : false },
|
26190
|
+
{ name : 'isTodo', type : 'boolean', defaultValue : false },
|
26191
|
+
{ name : 'isWaitFor', type : 'boolean', defaultValue : false },
|
26192
|
+
{ name : 'completed', type : 'boolean', defaultValue : false },
|
26193
|
+
'description',
|
26194
|
+
'annotation',
|
26195
|
+
'type',
|
26196
|
+
'sourceLine',
|
26197
|
+
'isWarning',
|
26198
|
+
|
26199
|
+
// For logging simulated events (will also have a type as for diagnostic messages)
|
26200
|
+
{ name : 'isSimulatedEvent', type : 'boolean', defaultValue : false },
|
26201
|
+
'eventType'
|
26202
|
+
]
|
26203
|
+
};
|
26204
|
+
|
26205
|
+
Ext.define('Siesta.Harness.Browser.Model.Assertion', Ext.apply({
|
26206
|
+
extend : 'Ext.data.Model'
|
26207
|
+
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config));
|
26208
|
+
})();
|
26209
|
+
;
|
26210
|
+
Ext.define("Sch.data.FilterableNodeStore", {
|
26211
|
+
extend : 'Ext.data.NodeStore',
|
25276
26212
|
|
25277
|
-
var isWorking = false
|
25278
|
-
var hasFailed = false
|
25279
|
-
var allGreen = true
|
25280
26213
|
|
25281
|
-
|
26214
|
+
onNodeExpand : function (parent, records, suppressEvent) {
|
26215
|
+
var visibleRecords = [];
|
25282
26216
|
|
25283
|
-
|
25284
|
-
|
26217
|
+
for (var i = 0; i < records.length; i++) {
|
26218
|
+
var record = records[ i ];
|
25285
26219
|
|
25286
|
-
|
25287
|
-
|
25288
|
-
|
25289
|
-
|
25290
|
-
|
25291
|
-
|
25292
|
-
|
26220
|
+
if (!(record.isHidden && record.isHidden() || record.hidden || record.data.hidden)) visibleRecords[ visibleRecords.length ] = record;
|
26221
|
+
}
|
26222
|
+
|
26223
|
+
return this.callParent([ parent, visibleRecords, suppressEvent ]);
|
26224
|
+
}
|
26225
|
+
});;
|
26226
|
+
Ext.define("Sch.data.mixin.FilterableTreeStore", {
|
26227
|
+
|
26228
|
+
requires : [
|
26229
|
+
'Sch.data.FilterableNodeStore'
|
26230
|
+
],
|
26231
|
+
|
26232
|
+
|
26233
|
+
nodeStoreClassName : 'Sch.data.FilterableNodeStore',
|
26234
|
+
|
26235
|
+
nodeStore : null,
|
26236
|
+
|
26237
|
+
isFilteredFlag : false,
|
26238
|
+
|
26239
|
+
|
26240
|
+
/**
|
26241
|
+
* Should be called in the constructor of the consuming class, to activate the filteirng functionality.
|
26242
|
+
*/
|
26243
|
+
initTreeFiltering : function () {
|
26244
|
+
if (!this.nodeStore) this.nodeStore = this.createNodeStore(this);
|
26245
|
+
|
26246
|
+
this.addEvents(
|
26247
|
+
'filter-set',
|
26248
|
+
'filter-clear',
|
26249
|
+
'nodestore-datachange-start',
|
26250
|
+
'nodestore-datachange-end'
|
26251
|
+
);
|
26252
|
+
},
|
26253
|
+
|
26254
|
+
|
26255
|
+
createNodeStore : function (treeStore) {
|
26256
|
+
return Ext.create(this.nodeStoreClassName, {
|
26257
|
+
treeStore : treeStore,
|
26258
|
+
recursive : true,
|
26259
|
+
rootVisible : this.rootVisible
|
26260
|
+
});
|
26261
|
+
},
|
26262
|
+
|
26263
|
+
|
26264
|
+
/**
|
26265
|
+
* Clears current filter (if any).
|
26266
|
+
*
|
26267
|
+
* See also {@link Sch.data.mixin.FilterableTreeStore} for additional information.
|
26268
|
+
*/
|
26269
|
+
clearTreeFilter : function () {
|
26270
|
+
if (!this.isTreeFiltered()) return;
|
26271
|
+
|
26272
|
+
this.refreshNodeStoreContent();
|
26273
|
+
|
26274
|
+
this.isFilteredFlag = false;
|
26275
|
+
|
26276
|
+
this.fireEvent('filter-clear', this);
|
26277
|
+
},
|
26278
|
+
|
26279
|
+
|
26280
|
+
refreshNodeStoreContent : function (skipUIRefresh) {
|
26281
|
+
var root = this.getRootNode(),
|
26282
|
+
linearNodes = [];
|
25293
26283
|
|
25294
|
-
|
25295
|
-
|
25296
|
-
|
25297
|
-
|
26284
|
+
var rootVisible = this.rootVisible;
|
26285
|
+
|
26286
|
+
var collectNodes = function (node) {
|
26287
|
+
if (node.isHidden && node.isHidden() || node.hidden || node.data.hidden) return;
|
25298
26288
|
|
25299
|
-
|
25300
|
-
var status = childNode.computeFolderStatus()
|
26289
|
+
if (rootVisible || node != root) linearNodes[ linearNodes.length ] = node;
|
25301
26290
|
|
25302
|
-
|
25303
|
-
|
25304
|
-
|
26291
|
+
if (!node.data.leaf && node.isExpanded()) {
|
26292
|
+
var childNodes = node.childNodes,
|
26293
|
+
length = childNodes.length;
|
25305
26294
|
|
25306
|
-
|
25307
|
-
|
25308
|
-
|
26295
|
+
for (var k = 0; k < length; k++) collectNodes(childNodes[ k ]);
|
26296
|
+
}
|
26297
|
+
};
|
26298
|
+
|
26299
|
+
collectNodes(root);
|
26300
|
+
|
26301
|
+
this.fireEvent('nodestore-datachange-start', this);
|
26302
|
+
|
26303
|
+
var nodeStore = this.nodeStore;
|
26304
|
+
|
26305
|
+
// "loadDataInNodeStore" is a special hook for buffered case
|
26306
|
+
// in buffered case, instead of "loadRecords" we need to use "cachePage"
|
26307
|
+
if (!this.loadDataInNodeStore || !this.loadDataInNodeStore(linearNodes)) nodeStore.loadRecords(linearNodes);
|
26308
|
+
|
26309
|
+
// HACK - forcing view to refresh, the usual "refresh" event is blocked by the tree view (see `blockRefresh` property)
|
26310
|
+
if (!skipUIRefresh) nodeStore.fireEvent('clear', nodeStore);
|
26311
|
+
|
26312
|
+
this.fireEvent('nodestore-datachange-end', this);
|
26313
|
+
},
|
26314
|
+
|
26315
|
+
|
26316
|
+
/**
|
26317
|
+
* Returns the boolean, indicating whether this store is currently filtered
|
26318
|
+
*
|
26319
|
+
* @return {Boolean}
|
26320
|
+
*/
|
26321
|
+
isTreeFiltered : function () {
|
26322
|
+
return this.isFilteredFlag;
|
26323
|
+
},
|
26324
|
+
|
26325
|
+
|
26326
|
+
/**
|
26327
|
+
* This method filters the tree store. It accept an object with following properties:
|
26328
|
+
*
|
26329
|
+
* - `filter` - a function to check if the node should be included in the results. It will be called for each **leaf** node in tree and will receive the current node as the first argument.
|
26330
|
+
* It should return `true` if node should remain visible, `false` otherwise. The results will also contain all parents nodes of all matching leafs. Results will not include
|
26331
|
+
* parent nodes, which do not have at least one matching child.
|
26332
|
+
* To call this method for parent nodes too, pass an additional parameter - `checkParents` (see below).
|
26333
|
+
* - `scope` - a scope to call the filter with (optional)
|
26334
|
+
* - `checkParents` - when set to `true` will also call the `filter` function for each parent node. If function returns `false` for some parent node,
|
26335
|
+
* it still may be included in filter results, if some of its children matches the `filter` (see also "shallow" option below). If function returns `true` for some parent node, it will be
|
26336
|
+
* included in the filtering results even if it does not have any matching child nodes.
|
26337
|
+
* - `shallow` - implies `checkParents`. When set to `true` will stop checking child nodes if the `filter` function return `false` for some parent node. Whole sub-tree, starting
|
26338
|
+
* from non-matching parent, will be excluded from filtering results in such case.
|
26339
|
+
* - `onlyParents` - alternative for `checkParents`. When set to `true` will only call the provided `filter` function for parent tasks. If
|
26340
|
+
* filter returns `true`, parent, and all its direct children leaf will be included in the results. If `filter` returns `false`, parent node still can
|
26341
|
+
* be included in the results (w/o direct children leafs), if some of its child nodes matches the filter.
|
26342
|
+
* - `fullMathchingParents` - implies `onlyParents`. In this mode, if parent node matches the filter, then not only its direct children
|
26343
|
+
* will be included in the results, but a whole sub-tree, starting form matching node.
|
26344
|
+
*
|
26345
|
+
* Repeated calls to this method will clear previous filters.
|
26346
|
+
*
|
26347
|
+
* This function can be also called with 2 arguments, which should be the `filter` function and `scope` in such case.
|
26348
|
+
*
|
26349
|
+
* See also {@link Sch.data.mixin.FilterableTreeStore} for additional information.
|
26350
|
+
*
|
26351
|
+
* @param {Object} params
|
26352
|
+
*/
|
26353
|
+
filterTreeBy : function (params, scope) {
|
26354
|
+
var filter;
|
26355
|
+
|
26356
|
+
if (arguments.length == 1 && Ext.isObject(arguments[ 0 ])) {
|
26357
|
+
scope = params.scope;
|
26358
|
+
filter = params.filter;
|
26359
|
+
} else {
|
26360
|
+
filter = params;
|
26361
|
+
params = {};
|
26362
|
+
}
|
26363
|
+
|
26364
|
+
this.fireEvent('nodestore-datachange-start', this);
|
26365
|
+
|
26366
|
+
params = params || {};
|
26367
|
+
|
26368
|
+
var shallowScan = params.shallow;
|
26369
|
+
var checkParents = params.checkParents || shallowScan;
|
26370
|
+
var fullMathchingParents = params.fullMathchingParents;
|
26371
|
+
var onlyParents = params.onlyParents || fullMathchingParents;
|
26372
|
+
var rootVisible = this.rootVisible;
|
26373
|
+
|
26374
|
+
if (onlyParents && checkParents) throw new Error("Can't combine `onlyParents` and `checkParents` options");
|
26375
|
+
|
26376
|
+
var keepTheseParents = {};
|
26377
|
+
|
26378
|
+
var root = this.getRootNode(),
|
26379
|
+
linearNodes = [];
|
26380
|
+
|
26381
|
+
var includeParentNodesInResults = function (node) {
|
26382
|
+
var parent = node.parentNode;
|
26383
|
+
|
26384
|
+
while (parent && !keepTheseParents[ parent.internalId ]) {
|
26385
|
+
keepTheseParents[ parent.internalId ] = true;
|
25309
26386
|
|
25310
|
-
|
25311
|
-
|
26387
|
+
parent = parent.parentNode;
|
26388
|
+
}
|
26389
|
+
};
|
26390
|
+
|
26391
|
+
var collectNodes = function (node) {
|
26392
|
+
if (node.isHidden && node.isHidden() || node.hidden || node.data.hidden) return;
|
26393
|
+
|
26394
|
+
var nodeMatches, childNodes, length, k;
|
26395
|
+
|
26396
|
+
// `collectNodes` should not be called for leafs at all
|
26397
|
+
if (node.data.leaf) {
|
26398
|
+
if (filter.call(scope, node, keepTheseParents)) {
|
26399
|
+
linearNodes[ linearNodes.length ] = node;
|
26400
|
+
|
26401
|
+
includeParentNodesInResults(node);
|
26402
|
+
}
|
26403
|
+
} else {
|
26404
|
+
// include _all_ parent nodes in intermediate result set originally, except the root one
|
26405
|
+
// intermediate result set will be filtered
|
26406
|
+
if (rootVisible || node != root) linearNodes[ linearNodes.length ] = node;
|
25312
26407
|
|
25313
|
-
|
25314
|
-
|
26408
|
+
if (onlyParents) {
|
26409
|
+
nodeMatches = filter.call(scope, node);
|
26410
|
+
|
26411
|
+
childNodes = node.childNodes;
|
26412
|
+
length = childNodes.length;
|
26413
|
+
|
26414
|
+
if (nodeMatches) {
|
26415
|
+
keepTheseParents[ node.internalId ] = true;
|
26416
|
+
|
26417
|
+
includeParentNodesInResults(node);
|
26418
|
+
|
26419
|
+
if (fullMathchingParents) {
|
26420
|
+
node.cascadeBy(function (node) {
|
26421
|
+
linearNodes[ linearNodes.length ] = node;
|
26422
|
+
|
26423
|
+
if (!node.data.leaf) keepTheseParents[ node.internalId ] = true;
|
26424
|
+
});
|
26425
|
+
|
26426
|
+
return;
|
26427
|
+
}
|
26428
|
+
}
|
26429
|
+
|
26430
|
+
// at this point nodeMatches and fullMathchingParents can't be both true
|
26431
|
+
for (k = 0; k < length; k++)
|
26432
|
+
if (nodeMatches && childNodes[ k ].data.leaf)
|
26433
|
+
linearNodes[ linearNodes.length ] = childNodes[ k ];
|
26434
|
+
else if (!childNodes[ k ].data.leaf)
|
26435
|
+
collectNodes(childNodes[ k ]);
|
26436
|
+
|
26437
|
+
} else {
|
26438
|
+
// mark matching nodes to be kept in results
|
26439
|
+
if (checkParents) {
|
26440
|
+
nodeMatches = filter.call(scope, node, keepTheseParents);
|
26441
|
+
|
26442
|
+
if (nodeMatches) {
|
26443
|
+
keepTheseParents[ node.internalId ] = true;
|
26444
|
+
|
26445
|
+
includeParentNodesInResults(node);
|
26446
|
+
}
|
26447
|
+
}
|
26448
|
+
|
26449
|
+
// recurse if
|
26450
|
+
// - we don't check parents
|
26451
|
+
// - shallow scan is not enabled
|
26452
|
+
// - shallow scan is enabled and parent node matches the filter or it does not, but its and invisible root, so we don't care
|
26453
|
+
if (!checkParents || !shallowScan || shallowScan && (nodeMatches || node == root && !rootVisible)) {
|
26454
|
+
childNodes = node.childNodes;
|
26455
|
+
length = childNodes.length;
|
26456
|
+
|
26457
|
+
for (k = 0; k < length; k++) collectNodes(childNodes[ k ]);
|
26458
|
+
}
|
25315
26459
|
}
|
25316
|
-
|
25317
|
-
if (status == 'yellow') allGreen = false
|
25318
26460
|
}
|
25319
|
-
}
|
26461
|
+
};
|
26462
|
+
|
26463
|
+
collectNodes(root);
|
26464
|
+
|
26465
|
+
// additional filtering of the result set
|
26466
|
+
// removes the parent nodes which do not match filter themselves and have no macthing children
|
26467
|
+
var nodesToKeep = [];
|
26468
|
+
|
26469
|
+
for (var i = 0, len = linearNodes.length; i < len; i++) {
|
26470
|
+
var node = linearNodes[ i ];
|
26471
|
+
|
26472
|
+
if (node.data.leaf || keepTheseParents[ node.internalId ]) nodesToKeep[ nodesToKeep.length ] = node;
|
26473
|
+
}
|
26474
|
+
|
26475
|
+
var nodeStore = this.nodeStore;
|
26476
|
+
|
26477
|
+
nodeStore.loadRecords(nodesToKeep, false);
|
26478
|
+
|
26479
|
+
// HACK - forcing view to refresh, the usual "refresh" event is blocked by the tree view (see `blockRefresh` property)
|
26480
|
+
nodeStore.fireEvent('clear', nodeStore);
|
26481
|
+
|
26482
|
+
this.isFilteredFlag = true;
|
26483
|
+
|
26484
|
+
this.fireEvent('nodestore-datachange-end', this);
|
26485
|
+
|
26486
|
+
this.fireEvent('filter-set', this);
|
26487
|
+
},
|
25320
26488
|
|
25321
|
-
if (isWorking) return 'working'
|
25322
|
-
if (hasFailed) return 'red'
|
25323
|
-
if (allGreen) return 'green'
|
25324
26489
|
|
25325
|
-
|
26490
|
+
/**
|
26491
|
+
* Hide nodes from the tree store rendering presenation (they still remains in the store).
|
26492
|
+
*
|
26493
|
+
* See also {@link Sch.data.mixin.FilterableTreeStore} for additional information.
|
26494
|
+
*
|
26495
|
+
* @param {Function} filter - A filtering function. Will be called for each node in the tree store and receive a current node as 1st argument. Should return `true` to **hide** the node
|
26496
|
+
* and `false`, to **keep it visible**.
|
26497
|
+
* @param {Object} scope (optional).
|
26498
|
+
*/
|
26499
|
+
hideNodesBy : function (filter, scope) {
|
26500
|
+
if (this.isFiltered()) throw new Error("Can't hide nodes of the filtered tree store");
|
26501
|
+
|
26502
|
+
var me = this;
|
26503
|
+
scope = scope || this;
|
26504
|
+
|
26505
|
+
this.getRootNode().cascadeBy(function (node) {
|
26506
|
+
node.hidden = filter.call(scope, node, me);
|
26507
|
+
});
|
26508
|
+
|
26509
|
+
this.refreshNodeStoreContent();
|
25326
26510
|
},
|
25327
|
-
|
25328
|
-
|
25329
|
-
updateFolderStatus : function () {
|
25330
|
-
this.set('folderStatus', this.computeFolderStatus())
|
25331
26511
|
|
25332
|
-
var parentNode = this.parentNode
|
25333
26512
|
|
25334
|
-
|
25335
|
-
|
25336
|
-
|
25337
|
-
|
25338
|
-
|
25339
|
-
|
25340
|
-
|
25341
|
-
|
25342
|
-
|
25343
|
-
|
25344
|
-
|
25345
|
-
|
25346
|
-
|
25347
|
-
|
25348
|
-
|
25349
|
-
|
26513
|
+
/**
|
26514
|
+
* Shows all nodes, previously hidden with {@link #hideNodesBy}
|
26515
|
+
*
|
26516
|
+
* See also {@link Sch.data.mixin.FilterableTreeStore} for additional information.
|
26517
|
+
*/
|
26518
|
+
showAllNodes : function () {
|
26519
|
+
this.getRootNode().cascadeBy(function (node) {
|
26520
|
+
node.hidden = node.data.hidden = false;
|
26521
|
+
});
|
26522
|
+
|
26523
|
+
this.refreshNodeStoreContent();
|
26524
|
+
}
|
26525
|
+
});;
|
26526
|
+
Ext.define('Siesta.Harness.Browser.Model.TestTreeStore', {
|
26527
|
+
extend : 'Ext.data.TreeStore',
|
26528
|
+
|
26529
|
+
mixins : [
|
26530
|
+
'Sch.data.mixin.FilterableTreeStore'
|
26531
|
+
],
|
26532
|
+
|
26533
|
+
|
26534
|
+
constructor : function () {
|
26535
|
+
this.callParent(arguments)
|
26536
|
+
|
26537
|
+
this.initTreeFiltering()
|
25350
26538
|
}
|
25351
|
-
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config ))
|
25352
|
-
;
|
25353
|
-
var config = {
|
25354
|
-
idProperty : 'index',
|
25355
|
-
|
25356
|
-
fields : [
|
25357
|
-
'index',
|
25358
|
-
'summaryFailure',
|
25359
|
-
{ name : 'passed', type : 'boolean', defaultValue : false },
|
25360
|
-
{ name : 'isTodo', type : 'boolean', defaultValue : false },
|
25361
|
-
{ name : 'isWaitFor', type : 'boolean', defaultValue : false },
|
25362
|
-
{ name : 'completed', type : 'boolean', defaultValue : false },
|
25363
|
-
'description',
|
25364
|
-
'annotation',
|
25365
|
-
'type',
|
25366
|
-
'sourceLine',
|
25367
|
-
|
25368
|
-
// For logging simulated events (will also have a type as for diagnostic messages)
|
25369
|
-
{ name : 'isSimulatedEvent', type : 'boolean', defaultValue : false },
|
25370
|
-
'eventType'
|
25371
|
-
]
|
25372
|
-
}
|
25373
26539
|
|
25374
|
-
|
25375
|
-
extend : 'Ext.data.Model'
|
25376
|
-
}, (Ext.getVersion && Ext.getVersion('touch')) ? { config : config } : config ))
|
25377
|
-
;
|
26540
|
+
});
|
25378
26541
|
Ext.define('Siesta.Harness.Browser.UI.VersionField', {
|
25379
26542
|
|
25380
26543
|
extend : 'Ext.form.field.Spinner',
|
25381
26544
|
alias : 'widget.versionfield',
|
25382
|
-
|
25383
|
-
|
26545
|
+
|
25384
26546
|
width : 90,
|
25385
26547
|
|
25386
26548
|
// versions : read from harness?
|
25387
26549
|
versions : [
|
25388
26550
|
'4.0.2a',
|
25389
|
-
'4.0.4',
|
25390
|
-
'4.0.5',
|
25391
|
-
'4.0.6',
|
25392
26551
|
'4.0.7',
|
25393
|
-
'4.1.0
|
25394
|
-
'4.1.
|
25395
|
-
'4.1.
|
26552
|
+
'4.1.0',
|
26553
|
+
'4.1.1',
|
26554
|
+
'4.1.2',
|
26555
|
+
'4.1.3',
|
26556
|
+
'4.1.4'
|
25396
26557
|
],
|
25397
26558
|
|
25398
26559
|
|
@@ -25721,6 +26882,164 @@ Ext.define('Siesta.Harness.Browser.UI.ExtHeader', {
|
|
25721
26882
|
})
|
25722
26883
|
//eof Siesta.Harness.Browser.UI.ExtHeader
|
25723
26884
|
;
|
26885
|
+
// !XXX when adding new methods to this mixing need to also update the
|
26886
|
+
// `setupLockableTree` method in the Sch.mixin.Lockable
|
26887
|
+
Ext.define("Sch.mixin.FilterableTreeView", {
|
26888
|
+
|
26889
|
+
initTreeFiltering : function () {
|
26890
|
+
var doInit = function () {
|
26891
|
+
var treeStore = this.up('tablepanel').store;
|
26892
|
+
|
26893
|
+
this.mon(treeStore, 'nodestore-datachange-start', this.onFilterChangeStart, this);
|
26894
|
+
this.mon(treeStore, 'nodestore-datachange-end', this.onFilterChangeEnd, this);
|
26895
|
+
|
26896
|
+
this.mon(treeStore, 'filter-clear', this.onFilterCleared, this);
|
26897
|
+
this.mon(treeStore, 'filter-set', this.onFilterSet, this);
|
26898
|
+
};
|
26899
|
+
|
26900
|
+
if (this.rendered)
|
26901
|
+
doInit.call(this);
|
26902
|
+
else
|
26903
|
+
this.on('beforerender', doInit, this, { single : true });
|
26904
|
+
},
|
26905
|
+
|
26906
|
+
|
26907
|
+
onFilterChangeStart : function () {
|
26908
|
+
Ext.suspendLayouts();
|
26909
|
+
},
|
26910
|
+
|
26911
|
+
|
26912
|
+
onFilterChangeEnd : function () {
|
26913
|
+
Ext.resumeLayouts();
|
26914
|
+
},
|
26915
|
+
|
26916
|
+
|
26917
|
+
onFilterCleared : function () {
|
26918
|
+
delete this.toggle;
|
26919
|
+
|
26920
|
+
var el = this.getEl();
|
26921
|
+
|
26922
|
+
if (el) el.removeCls('sch-tree-filtered');
|
26923
|
+
},
|
26924
|
+
|
26925
|
+
|
26926
|
+
onFilterSet : function () {
|
26927
|
+
this.toggle = function () {};
|
26928
|
+
|
26929
|
+
var el = this.getEl();
|
26930
|
+
|
26931
|
+
if (el) el.addCls('sch-tree-filtered');
|
26932
|
+
}
|
26933
|
+
});;
|
26934
|
+
Ext.define('Siesta.Harness.Browser.UI.FilterableTreeView', {
|
26935
|
+
extend : 'Ext.tree.View',
|
26936
|
+
alias : 'widget.filterabletreeview',
|
26937
|
+
|
26938
|
+
mixins : [
|
26939
|
+
'Sch.mixin.FilterableTreeView'
|
26940
|
+
],
|
26941
|
+
|
26942
|
+
|
26943
|
+
constructor : function () {
|
26944
|
+
|
26945
|
+
if (!Ext.tree.View.prototype.patched)
|
26946
|
+
// PATCH
|
26947
|
+
Ext.tree.View.addMembers({
|
26948
|
+
patched : true,
|
26949
|
+
|
26950
|
+
initComponent: function() {
|
26951
|
+
var me = this,
|
26952
|
+
treeStore = me.panel.getStore();
|
26953
|
+
|
26954
|
+
if (me.initialConfig.animate === undefined) {
|
26955
|
+
me.animate = Ext.enableFx;
|
26956
|
+
}
|
26957
|
+
|
26958
|
+
// BEGIN OF MODIFICATIONS
|
26959
|
+
me.store = me.store || new Ext.data.NodeStore({
|
26960
|
+
treeStore: treeStore,
|
26961
|
+
recursive: true,
|
26962
|
+
rootVisible: me.rootVisible
|
26963
|
+
});
|
26964
|
+
|
26965
|
+
me.store.on({
|
26966
|
+
beforeexpand: me.onBeforeExpand,
|
26967
|
+
expand: me.onExpand,
|
26968
|
+
beforecollapse: me.onBeforeCollapse,
|
26969
|
+
collapse: me.onCollapse,
|
26970
|
+
write: me.onStoreWrite,
|
26971
|
+
datachanged: me.onStoreDataChanged,
|
26972
|
+
collapsestart: me.beginBulkUpdate,
|
26973
|
+
collapsecomplete: me.endBulkUpdate,
|
26974
|
+
scope: me
|
26975
|
+
});
|
26976
|
+
|
26977
|
+
if (Ext.versions.extjs.isGreaterThanOrEqual('4.1.2')) {
|
26978
|
+
me.mon(treeStore, {
|
26979
|
+
scope: me,
|
26980
|
+
beforefill: me.onBeforeFill,
|
26981
|
+
fillcomplete: me.onFillComplete,
|
26982
|
+
beforebulkremove: me.beginBulkUpdate,
|
26983
|
+
bulkremovecomplete: me.endBulkUpdate
|
26984
|
+
});
|
26985
|
+
|
26986
|
+
if (!treeStore.remoteSort) {
|
26987
|
+
me.mon(treeStore, {
|
26988
|
+
scope: me,
|
26989
|
+
beforesort: me.onBeforeSort,
|
26990
|
+
sort: me.onSort
|
26991
|
+
});
|
26992
|
+
}
|
26993
|
+
}
|
26994
|
+
if (me.node && !me.store.node) {
|
26995
|
+
me.setRootNode(me.node);
|
26996
|
+
}
|
26997
|
+
// EOF MODIFICATIONS
|
26998
|
+
|
26999
|
+
me.animQueue = {};
|
27000
|
+
me.animWraps = {};
|
27001
|
+
me.addEvents(
|
27002
|
+
/**
|
27003
|
+
* @event afteritemexpand
|
27004
|
+
* Fires after an item has been visually expanded and is visible in the tree.
|
27005
|
+
* @param {Ext.data.NodeInterface} node The node that was expanded
|
27006
|
+
* @param {Number} index The index of the node
|
27007
|
+
* @param {HTMLElement} item The HTML element for the node that was expanded
|
27008
|
+
*/
|
27009
|
+
'afteritemexpand',
|
27010
|
+
/**
|
27011
|
+
* @event afteritemcollapse
|
27012
|
+
* Fires after an item has been visually collapsed and is no longer visible in the tree.
|
27013
|
+
* @param {Ext.data.NodeInterface} node The node that was collapsed
|
27014
|
+
* @param {Number} index The index of the node
|
27015
|
+
* @param {HTMLElement} item The HTML element for the node that was collapsed
|
27016
|
+
*/
|
27017
|
+
'afteritemcollapse'
|
27018
|
+
);
|
27019
|
+
me.callParent(arguments);
|
27020
|
+
me.on({
|
27021
|
+
element: 'el',
|
27022
|
+
scope: me,
|
27023
|
+
delegate: me.expanderSelector,
|
27024
|
+
mouseover: me.onExpanderMouseOver,
|
27025
|
+
mouseout: me.onExpanderMouseOut
|
27026
|
+
});
|
27027
|
+
me.on({
|
27028
|
+
element: 'el',
|
27029
|
+
scope: me,
|
27030
|
+
delegate: me.checkboxSelector,
|
27031
|
+
click: me.onCheckboxChange
|
27032
|
+
});
|
27033
|
+
}
|
27034
|
+
});
|
27035
|
+
// EOF PATCH
|
27036
|
+
|
27037
|
+
this.callParent(arguments)
|
27038
|
+
|
27039
|
+
this.initTreeFiltering()
|
27040
|
+
}
|
27041
|
+
})
|
27042
|
+
;
|
25724
27043
|
Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
25725
27044
|
|
25726
27045
|
extend : 'Ext.container.Viewport',
|
@@ -25736,6 +27055,8 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25736
27055
|
// stateful
|
25737
27056
|
selection : null,
|
25738
27057
|
selectedURL : null,
|
27058
|
+
filter : null,
|
27059
|
+
filterGroups : false,
|
25739
27060
|
// eof stateful
|
25740
27061
|
|
25741
27062
|
testsStore : null,
|
@@ -25763,10 +27084,10 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25763
27084
|
|
25764
27085
|
this.selection = {}
|
25765
27086
|
|
25766
|
-
this.applyState(
|
27087
|
+
this.applyState(this.loadState())
|
25767
27088
|
|
25768
27089
|
|
25769
|
-
var testsStore = this.testsStore = new
|
27090
|
+
var testsStore = this.testsStore = new Siesta.Harness.Browser.Model.TestTreeStore({
|
25770
27091
|
model : 'Siesta.Harness.Browser.Model.TestFile',
|
25771
27092
|
|
25772
27093
|
sortOnLoad : false,
|
@@ -25815,7 +27136,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25815
27136
|
Ext.apply(this, {
|
25816
27137
|
plugins : Ext.isIE ? undefined : new Siesta.Harness.Browser.UI.MouseVisualizer(this.harness),
|
25817
27138
|
slots : true,
|
25818
|
-
|
27139
|
+
|
25819
27140
|
contextMenu : this.buildContextMenu(),
|
25820
27141
|
|
25821
27142
|
layout : 'border',
|
@@ -25832,6 +27153,9 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25832
27153
|
|
25833
27154
|
animate : !Ext.isIE,
|
25834
27155
|
split : true,
|
27156
|
+
|
27157
|
+
filter : this.filter,
|
27158
|
+
filterGroups : this.filterGroups,
|
25835
27159
|
|
25836
27160
|
listeners : {
|
25837
27161
|
selectionchange : this.onSelectionChange,
|
@@ -25839,8 +27163,10 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25839
27163
|
|
25840
27164
|
itemcontextmenu : this.onFilesContextMenu,
|
25841
27165
|
itemdblclick : this.onTestFileDoubleClick,
|
27166
|
+
|
27167
|
+
'filter-group-change' : this.saveState,
|
25842
27168
|
|
25843
|
-
scope
|
27169
|
+
scope : this
|
25844
27170
|
},
|
25845
27171
|
|
25846
27172
|
store : testsStore
|
@@ -25879,6 +27205,13 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25879
27205
|
|
25880
27206
|
// delay is required to avoid recursive loop
|
25881
27207
|
this.on('afterlayout', this.onAfterLayout, this, { single : true, delay : 1 })
|
27208
|
+
|
27209
|
+
this.slots.filesTree.store.on({
|
27210
|
+
'filter-set' : this.saveState,
|
27211
|
+
'filter-clear' : this.saveState,
|
27212
|
+
|
27213
|
+
scope : this
|
27214
|
+
})
|
25882
27215
|
},
|
25883
27216
|
|
25884
27217
|
|
@@ -25902,9 +27235,9 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25902
27235
|
})
|
25903
27236
|
|
25904
27237
|
Ext.apply(data, {
|
25905
|
-
expanded : collapsedNodes[ prevId ] != null ? false : true,
|
27238
|
+
expanded : (collapsedNodes[ prevId ] != null || descriptor.expanded === false) ? false : true,
|
25906
27239
|
// || false is required for TreeView - it checks that "checked" field contains Boolean
|
25907
|
-
checked : me.selection
|
27240
|
+
checked : me.selection.hasOwnProperty(prevId) || false,
|
25908
27241
|
|
25909
27242
|
folderStatus : 'yellow',
|
25910
27243
|
|
@@ -25918,7 +27251,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25918
27251
|
|
25919
27252
|
leaf : true,
|
25920
27253
|
// || false is required for TreeView - it checks that "checked" field contains Boolean
|
25921
|
-
checked : me.selection
|
27254
|
+
checked : me.selection.hasOwnProperty(prevId) || false,
|
25922
27255
|
|
25923
27256
|
passCount : 0,
|
25924
27257
|
failCount : 0,
|
@@ -25991,7 +27324,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
25991
27324
|
var id = testFile.getId()
|
25992
27325
|
|
25993
27326
|
if (checked)
|
25994
|
-
this.selection[ id ] =
|
27327
|
+
this.selection[ id ] = 1
|
25995
27328
|
else
|
25996
27329
|
delete this.selection[ id ]
|
25997
27330
|
|
@@ -26042,8 +27375,12 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26042
27375
|
}
|
26043
27376
|
})
|
26044
27377
|
|
27378
|
+
Ext.suspendLayouts();
|
27379
|
+
|
26045
27380
|
filesTree.setIconCls('tr-status-running-small')
|
26046
27381
|
filesTree.setTitle('Running...')
|
27382
|
+
|
27383
|
+
Ext.resumeLayouts();
|
26047
27384
|
},
|
26048
27385
|
|
26049
27386
|
|
@@ -26056,7 +27393,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26056
27393
|
testRecord.get('assertionsStore').removeAll(true)
|
26057
27394
|
testRecord.reject();
|
26058
27395
|
// || false is required for TreeView - it checks that "checked" field contains Boolean
|
26059
|
-
testRecord.set('checked', this.selection
|
27396
|
+
testRecord.set('checked', this.selection.hasOwnProperty(descriptor.id) || false)
|
26060
27397
|
}, this);
|
26061
27398
|
},
|
26062
27399
|
|
@@ -26077,7 +27414,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26077
27414
|
forEachTestFile : function (func, scope) {
|
26078
27415
|
var nodeStore = this.getNodeStore()
|
26079
27416
|
|
26080
|
-
if (
|
27417
|
+
if (this.testsStore.isTreeFiltered())
|
26081
27418
|
nodeStore.each(func, scope)
|
26082
27419
|
else
|
26083
27420
|
Ext.Array.each(this.testsStore.tree.flatten(), func, scope)
|
@@ -26249,6 +27586,8 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26249
27586
|
|
26250
27587
|
type : result.meta.name,
|
26251
27588
|
sourceLine : result.sourceLine,
|
27589
|
+
|
27590
|
+
isWarning : result.isWarning,
|
26252
27591
|
|
26253
27592
|
// For logging simulated events
|
26254
27593
|
isSimulatedEvent : result.isSimulatedEvent,
|
@@ -26332,15 +27671,17 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26332
27671
|
|
26333
27672
|
|
26334
27673
|
setOption : function (name, value) {
|
26335
|
-
|
26336
27674
|
switch (name) {
|
26337
|
-
case 'selection' : return this.selection
|
27675
|
+
case 'selection' : return this.selection = value
|
26338
27676
|
|
26339
|
-
case 'selectedURL' : return this.selectedURL
|
27677
|
+
case 'selectedURL' : return this.selectedURL = value
|
26340
27678
|
|
26341
27679
|
case 'collapsedNodes': return this.collapsedNodes = value
|
26342
27680
|
|
26343
|
-
|
27681
|
+
case 'filter' : return this.filter = value
|
27682
|
+
case 'filterGroups' : return this.filterGroups = value
|
27683
|
+
|
27684
|
+
default : return this.harness[ name ] = value
|
26344
27685
|
}
|
26345
27686
|
},
|
26346
27687
|
|
@@ -26357,19 +27698,33 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26357
27698
|
breakOnFail : this.getOption('breakOnFail'),
|
26358
27699
|
|
26359
27700
|
// UI configs
|
26360
|
-
selection : this.selection,
|
26361
27701
|
selectedURL : this.selectedURL,
|
26362
27702
|
|
26363
|
-
|
27703
|
+
selection : this.getCheckedNodes(),
|
27704
|
+
collapsedNodes : this.getCollapsedFolders(),
|
27705
|
+
|
27706
|
+
filter : this.slots ? this.slots.filesTree.getFilterValue() : this.filter,
|
27707
|
+
filterGroups : this.slots ? this.slots.filesTree.getFilterGroups() : this.filterGroups
|
26364
27708
|
}
|
26365
27709
|
},
|
26366
27710
|
|
26367
27711
|
|
27712
|
+
getCheckedNodes : function () {
|
27713
|
+
var checked = {}
|
27714
|
+
|
27715
|
+
Joose.A.each(this.testsStore.tree.flatten(), function (treeNode) {
|
27716
|
+
if (treeNode.get('checked')) checked[ treeNode.getId() ] = 1
|
27717
|
+
})
|
27718
|
+
|
27719
|
+
return checked
|
27720
|
+
},
|
27721
|
+
|
27722
|
+
|
26368
27723
|
getCollapsedFolders : function () {
|
26369
27724
|
var collapsed = {}
|
26370
27725
|
|
26371
27726
|
Joose.A.each(this.testsStore.tree.flatten(), function (treeNode) {
|
26372
|
-
if (!treeNode.isLeaf() && !treeNode.isExpanded()) collapsed[ treeNode.getId() ] =
|
27727
|
+
if (!treeNode.isLeaf() && !treeNode.isExpanded()) collapsed[ treeNode.getId() ] = 1
|
26373
27728
|
})
|
26374
27729
|
|
26375
27730
|
return collapsed
|
@@ -26401,10 +27756,32 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26401
27756
|
|
26402
27757
|
this.saveState()
|
26403
27758
|
},
|
27759
|
+
|
27760
|
+
|
27761
|
+
loadState : function () {
|
27762
|
+
var stateId = this.getStateId()
|
27763
|
+
var state = Ext.state.Manager.get(stateId)
|
27764
|
+
|
27765
|
+
if (!state) return
|
27766
|
+
|
27767
|
+
if (!state.collapsedNodes) state.collapsedNodes = Ext.state.Manager.get(stateId + '-collapsed')
|
27768
|
+
if (!state.selection) state.selection = Ext.state.Manager.get(stateId + '-selection')
|
27769
|
+
|
27770
|
+
return state
|
27771
|
+
},
|
26404
27772
|
|
26405
27773
|
|
26406
27774
|
saveState : function () {
|
26407
|
-
|
27775
|
+
var stateId = this.getStateId()
|
27776
|
+
var state = this.getState()
|
27777
|
+
|
27778
|
+
Ext.state.Manager.set(stateId + '-collapsed', state.collapsedNodes)
|
27779
|
+
Ext.state.Manager.set(stateId + '-selection', state.selection)
|
27780
|
+
|
27781
|
+
delete state.collapsedNodes
|
27782
|
+
delete state.selection
|
27783
|
+
|
27784
|
+
Ext.state.Manager.set(stateId, state)
|
26408
27785
|
},
|
26409
27786
|
|
26410
27787
|
|
@@ -26494,7 +27871,7 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26494
27871
|
|
26495
27872
|
onTestFileDoubleClick : function (view, testFile) {
|
26496
27873
|
// don't launch groups when filtered - will be confusing for user
|
26497
|
-
if (this.
|
27874
|
+
if (this.testsStore.isTreeFiltered() && !testFile.isLeaf()) return
|
26498
27875
|
|
26499
27876
|
this.launchTest(testFile);
|
26500
27877
|
},
|
@@ -26539,6 +27916,8 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26539
27916
|
|
26540
27917
|
// statusIndicatorEl.removeCls([ 'tr-status-running', 'tr-status-allgreen', 'tr-status-bugs' ])
|
26541
27918
|
|
27919
|
+
Ext.suspendLayouts();
|
27920
|
+
|
26542
27921
|
var filesTree = this.slots.filesTree
|
26543
27922
|
|
26544
27923
|
filesTree.setTitle('Totals: ' + totalPassed + ' / ' + totalFailed)
|
@@ -26551,7 +27930,8 @@ Ext.define('Siesta.Harness.Browser.UI.Viewport', {
|
|
26551
27930
|
if (isNeutral) filesTree.setIconCls('tr-status-neutral-small')
|
26552
27931
|
if (allGreen) filesTree.setIconCls('tr-status-allgreen-small')
|
26553
27932
|
if (hasFailures) filesTree.setIconCls('tr-status-bugs-small')
|
26554
|
-
|
27933
|
+
|
27934
|
+
Ext.resumeLayouts();
|
26555
27935
|
},
|
26556
27936
|
|
26557
27937
|
onSettingsMenuBeforeShow : function(hdr, menu) {
|
@@ -26829,23 +28209,31 @@ Ext.define('Siesta.Harness.Browser.UI.MouseVisualizer', {
|
|
26829
28209
|
});
|
26830
28210
|
;
|
26831
28211
|
Ext.define('Siesta.Harness.Browser.UI.TestGrid', {
|
26832
|
-
|
28212
|
+
extend : 'Ext.tree.Panel',
|
26833
28213
|
alias : 'widget.testgrid',
|
26834
28214
|
|
26835
|
-
extend : 'Ext.tree.Panel',
|
26836
28215
|
stateful : true,
|
26837
28216
|
forceFit : true,
|
26838
28217
|
rootVisible : false,
|
28218
|
+
|
26839
28219
|
cls : 'tr-testgrid',
|
26840
28220
|
width : 300,
|
28221
|
+
|
28222
|
+
filter : null,
|
28223
|
+
|
26841
28224
|
title : 'Double click a test to run it',
|
28225
|
+
|
28226
|
+
filterGroups : false,
|
28227
|
+
|
26842
28228
|
|
26843
28229
|
initComponent : function () {
|
26844
28230
|
var me = this;
|
26845
28231
|
|
26846
28232
|
Ext.apply(this, {
|
26847
28233
|
|
28234
|
+
viewType : 'filterabletreeview',
|
26848
28235
|
viewConfig : {
|
28236
|
+
store : this.store.nodeStore,
|
26849
28237
|
enableTextSelection : true,
|
26850
28238
|
toggleOnDblClick : false
|
26851
28239
|
},
|
@@ -26891,25 +28279,43 @@ Ext.define('Siesta.Harness.Browser.UI.TestGrid', {
|
|
26891
28279
|
|
26892
28280
|
itemId : 'trigger',
|
26893
28281
|
|
26894
|
-
|
28282
|
+
trigger1Cls : 'x-form-clear-trigger',
|
28283
|
+
trigger2Cls : 'tr-filter-trigger-leaf',
|
26895
28284
|
|
26896
|
-
|
26897
|
-
|
26898
|
-
|
26899
|
-
|
26900
|
-
|
28285
|
+
onTrigger1Click : function() {
|
28286
|
+
this.reset()
|
28287
|
+
},
|
28288
|
+
|
28289
|
+
onTrigger2Click : function() {
|
28290
|
+
me.filterGroups = !me.filterGroups
|
28291
|
+
|
28292
|
+
this.triggerEl.item(1).toggleCls('tr-filter-trigger-group')
|
28293
|
+
|
28294
|
+
me.onFilterChange(this, this.getValue())
|
28295
|
+
|
28296
|
+
me.fireEvent('filter-group-change', me)
|
26901
28297
|
},
|
26902
28298
|
|
28299
|
+
|
26903
28300
|
listeners : {
|
26904
|
-
change
|
26905
|
-
specialkey
|
26906
|
-
scope
|
28301
|
+
change : this.onFilterChange,
|
28302
|
+
specialkey : this.onFilterSpecialKey,
|
28303
|
+
scope : this
|
26907
28304
|
}
|
26908
28305
|
}
|
26909
28306
|
]
|
26910
28307
|
})
|
26911
28308
|
|
26912
28309
|
this.callParent(arguments);
|
28310
|
+
|
28311
|
+
var me = this
|
28312
|
+
|
28313
|
+
this.getView().on('refresh', function () {
|
28314
|
+
var trigger = me.down('trigger')
|
28315
|
+
|
28316
|
+
if (me.filterGroups) trigger.triggerEl.item(1).addCls('tr-filter-trigger-group')
|
28317
|
+
if (me.filter) trigger.setValue(me.filter)
|
28318
|
+
}, null, { single : true })
|
26913
28319
|
},
|
26914
28320
|
|
26915
28321
|
onFilterSpecialKey : function(field, e, t) {
|
@@ -26918,46 +28324,45 @@ Ext.define('Siesta.Harness.Browser.UI.TestGrid', {
|
|
26918
28324
|
}
|
26919
28325
|
},
|
26920
28326
|
|
26921
|
-
|
26922
|
-
|
26923
|
-
|
26924
|
-
|
26925
|
-
|
28327
|
+
|
28328
|
+
getFilterValue : function () {
|
28329
|
+
return this.down('trigger').getValue()
|
28330
|
+
},
|
28331
|
+
|
28332
|
+
|
28333
|
+
getFilterGroups : function () {
|
28334
|
+
return this.filterGroups
|
28335
|
+
},
|
28336
|
+
|
28337
|
+
|
28338
|
+
onFilterChange : function (field, newValue) {
|
28339
|
+
var header = this.header
|
28340
|
+
|
26926
28341
|
if (newValue) {
|
26927
28342
|
var regexps = Ext.Array.map(newValue.split(/\s+/), function (token) { return new RegExp(Ext.String.escapeRegex(token), 'i') })
|
26928
28343
|
var length = regexps.length
|
26929
28344
|
|
26930
|
-
|
26931
|
-
|
26932
|
-
|
26933
|
-
var title = testFile.get('title')
|
26934
|
-
|
26935
|
-
// blazing fast "for" loop! :)
|
26936
|
-
for (var i = 0; i < length; i++)
|
26937
|
-
if (!regexps[ i ].test(title)) return
|
26938
|
-
|
26939
|
-
filteredById[ testFile.getId() ] = true
|
26940
|
-
|
26941
|
-
// also include parent nodes for leafs for better user experience
|
26942
|
-
if (testFile.isLeaf()) {
|
26943
|
-
var parent = testFile.parentNode
|
28345
|
+
this.store.filterTreeBy({
|
28346
|
+
filter : function (testFile) {
|
28347
|
+
var title = testFile.get('title')
|
26944
28348
|
|
26945
|
-
|
26946
|
-
|
28349
|
+
// blazing fast "for" loop! :)
|
28350
|
+
for (var i = 0; i < length; i++)
|
28351
|
+
if (!regexps[ i ].test(title)) return false
|
26947
28352
|
|
26948
|
-
|
26949
|
-
|
26950
|
-
|
26951
|
-
})
|
26952
|
-
|
26953
|
-
nodeStore.filterBy(function (testFile) {
|
26954
|
-
return filteredById[ testFile.getId() ]
|
28353
|
+
return true
|
28354
|
+
},
|
28355
|
+
onlyParents : this.filterGroups
|
26955
28356
|
})
|
26956
28357
|
|
28358
|
+
header.down('[type="down"]').disable()
|
28359
|
+
header.down('[type="up"]').disable()
|
26957
28360
|
} else {
|
26958
|
-
|
28361
|
+
this.store.clearTreeFilter()
|
28362
|
+
|
28363
|
+
header.down('[type="down"]').enable()
|
28364
|
+
header.down('[type="up"]').enable()
|
26959
28365
|
}
|
26960
|
-
treeView.blockRefresh = true;
|
26961
28366
|
},
|
26962
28367
|
|
26963
28368
|
|
@@ -27311,7 +28716,6 @@ Ext.define('Siesta.Harness.Browser.UI.ResultPanel', {
|
|
27311
28716
|
|
27312
28717
|
|
27313
28718
|
showTest : function (testFile) {
|
27314
|
-
|
27315
28719
|
if (this.testRecord !== testFile) {
|
27316
28720
|
this.hideIFrame();
|
27317
28721
|
|
@@ -27327,16 +28731,11 @@ Ext.define('Siesta.Harness.Browser.UI.ResultPanel', {
|
|
27327
28731
|
|
27328
28732
|
grid.reconfigure(testFile.get('assertionsStore'));
|
27329
28733
|
|
27330
|
-
|
27331
|
-
Ext.suspendLayouts();
|
27332
|
-
}
|
27333
|
-
|
28734
|
+
Ext.suspendLayouts();
|
27334
28735
|
// This triggers an unnecessary layout recalc
|
27335
|
-
this.setTitle(
|
28736
|
+
this.setTitle(url);
|
28737
|
+
Ext.resumeLayouts();
|
27336
28738
|
|
27337
|
-
if (Ext.resumeLayouts) {
|
27338
|
-
Ext.resumeLayouts();
|
27339
|
-
}
|
27340
28739
|
this.alignIFrame();
|
27341
28740
|
},
|
27342
28741
|
|
@@ -27387,8 +28786,11 @@ Ext.define('Siesta.Harness.Browser.UI.AssertionGrid', {
|
|
27387
28786
|
|
27388
28787
|
Ext.apply(this, {
|
27389
28788
|
resultTpl : new Ext.XTemplate(
|
27390
|
-
'<span class="assertion-index">{index}</span><div class="assertion-status"></div><span class="assertion-text">{
|
28789
|
+
'<span class="assertion-index">{index}</span><div class="assertion-status"></div><span class="assertion-text">{[this.getDescription(values)]}</span>{[this.getAnnotation(values)]}',
|
27391
28790
|
{
|
28791
|
+
getDescription : function (data) {
|
28792
|
+
return data.isWarning ? 'WARN: ' + data.description : data.description
|
28793
|
+
},
|
27392
28794
|
getAnnotation : function(data) {
|
27393
28795
|
if (data.annotation) {
|
27394
28796
|
return '<pre class="tr-assert-row-annontation">' + Ext.String.htmlEncode(data.annotation) + '</pre>';
|
@@ -27416,6 +28818,9 @@ Ext.define('Siesta.Harness.Browser.UI.AssertionGrid', {
|
|
27416
28818
|
disableSelection : true,
|
27417
28819
|
markDirty : false,
|
27418
28820
|
|
28821
|
+
// this should be kept `false` - otherwise assertion grid goes crazy, see #477
|
28822
|
+
deferInitialRefresh : false,
|
28823
|
+
|
27419
28824
|
getRowClass : function(record, rowIndex, rowParams, store){
|
27420
28825
|
switch (record.data.type) {
|
27421
28826
|
case 'Siesta.Result.Diagnostic':
|
@@ -27448,6 +28853,10 @@ Ext.define('Siesta.Harness.Browser.UI.AssertionGrid', {
|
|
27448
28853
|
}
|
27449
28854
|
} else if (record.data.isTodo) {
|
27450
28855
|
metaData.tdCls = value ? 'tr-assert-row-ok-todo-cell' : 'tr-assert-row-bug-todo-cell';
|
28856
|
+
} else if (record.data.isWarning) {
|
28857
|
+
|
28858
|
+
metaData.tdCls = 'tr-warning'
|
28859
|
+
|
27451
28860
|
} else {
|
27452
28861
|
metaData.tdCls = value ? 'tr-assert-row-ok-cell' : 'tr-assert-row-bug-cell';
|
27453
28862
|
}
|
@@ -27657,16 +29066,258 @@ Class('Siesta.Harness.Browser.ExtJS', {
|
|
27657
29066
|
})
|
27658
29067
|
|
27659
29068
|
|
29069
|
+
;
|
29070
|
+
/**
|
29071
|
+
@class Siesta.Harness.Browser.SenchaTouch
|
29072
|
+
@extends Siesta.Harness.Browser
|
29073
|
+
|
29074
|
+
A Class representing the browser harness. This class provides a web-based UI and defines some additional configuration options.
|
29075
|
+
|
29076
|
+
The default value of the `testClass` configuration option in this class is {@link Siesta.Test.SenchaTouch}, which inherits from
|
29077
|
+
{@link Siesta.Test.Browser} and contains various Sencha Touch-specific assertions. Use this harness class when testing Sencha Touch applications.
|
29078
|
+
|
29079
|
+
* **Note** Make sure, you've checked the {@link #performSetup} configuration option.
|
29080
|
+
|
29081
|
+
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>.
|
29082
|
+
|
29083
|
+
Synopsys
|
29084
|
+
========
|
29085
|
+
|
29086
|
+
var Harness = Siesta.Harness.Browser.SenchaTouch;
|
29087
|
+
|
29088
|
+
Harness.configure({
|
29089
|
+
title : 'Awesome Sencha Touch Application Test Suite',
|
29090
|
+
|
29091
|
+
transparentEx : true,
|
29092
|
+
|
29093
|
+
preload : [
|
29094
|
+
"http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js",
|
29095
|
+
"../awesome-project-all.js"
|
29096
|
+
]
|
29097
|
+
})
|
29098
|
+
|
29099
|
+
|
29100
|
+
Harness.start(
|
29101
|
+
// simple string - url relative to harness file
|
29102
|
+
'sanity.t.js',
|
29103
|
+
|
29104
|
+
// test file descriptor with own configuration options
|
29105
|
+
{
|
29106
|
+
url : 'basic.t.js',
|
29107
|
+
|
29108
|
+
// replace `preload` option of harness
|
29109
|
+
preload : [
|
29110
|
+
"http://cdn.sencha.io/ext-4.0.6/ext-all-debug.js",
|
29111
|
+
"../awesome-project-all.js"
|
29112
|
+
]
|
29113
|
+
},
|
29114
|
+
|
29115
|
+
// groups ("folders") of test files (possibly with own options)
|
29116
|
+
{
|
29117
|
+
group : 'Sanity',
|
29118
|
+
|
29119
|
+
autoCheckGlobals : false,
|
29120
|
+
|
29121
|
+
items : [
|
29122
|
+
'data/crud.t.js',
|
29123
|
+
...
|
29124
|
+
]
|
29125
|
+
},
|
29126
|
+
...
|
29127
|
+
)
|
29128
|
+
|
29129
|
+
|
29130
|
+
*/
|
29131
|
+
|
29132
|
+
Class('Siesta.Harness.Browser.SenchaTouch', {
|
29133
|
+
|
29134
|
+
isa: Siesta.Harness.Browser,
|
29135
|
+
|
29136
|
+
// pure static class, no need to instantiate it
|
29137
|
+
my: {
|
29138
|
+
|
29139
|
+
has: {
|
29140
|
+
/**
|
29141
|
+
* @cfg {Class} testClass The test class which will be used for creating test instances, defaults to {@link Siesta.Test.SenchaTouch}.
|
29142
|
+
* You can subclass {@link Siesta.Test.SenchaTouch} and provide a new class.
|
29143
|
+
*
|
29144
|
+
* This option can be also specified in the test file descriptor.
|
29145
|
+
*/
|
29146
|
+
testClass : Siesta.Test.SenchaTouch,
|
29147
|
+
|
29148
|
+
/**
|
29149
|
+
* @cfg {Boolean} transparentEx
|
29150
|
+
*/
|
29151
|
+
transparentEx : true,
|
29152
|
+
keepResults : false,
|
29153
|
+
keepNLastResults : 0,
|
29154
|
+
|
29155
|
+
/**
|
29156
|
+
* @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.
|
29157
|
+
* If, however your test code, performs `Ext.setup()` itself, you need to disable this option.
|
29158
|
+
*
|
29159
|
+
* This option can be also specified in the test file descriptor.
|
29160
|
+
*/
|
29161
|
+
performSetup : true,
|
29162
|
+
|
29163
|
+
/**
|
29164
|
+
* @cfg {String} runCore
|
29165
|
+
*/
|
29166
|
+
runCore : 'sequential',
|
29167
|
+
|
29168
|
+
/**
|
29169
|
+
* @cfg {Object} loaderPath
|
29170
|
+
*
|
29171
|
+
* The path used to configure the Ext.Loader with, for dynamic loading of Ext JS classes.
|
29172
|
+
*
|
29173
|
+
* This option can be also specified in the test file descriptor.
|
29174
|
+
*/
|
29175
|
+
loaderPath : null,
|
29176
|
+
|
29177
|
+
isRunningOnMobile : true,
|
29178
|
+
useExtJSUI : true
|
29179
|
+
},
|
29180
|
+
|
29181
|
+
|
29182
|
+
methods: {
|
29183
|
+
|
29184
|
+
setup : function () {
|
29185
|
+
// TODO fix proper mobile detection, since Ext may be absent in "no-ui" harness
|
29186
|
+
this.isRunningOnMobile = typeof Ext !== 'undefined' && Ext.getVersion && Ext.getVersion('touch')
|
29187
|
+
|
29188
|
+
if (!this.isRunningOnMobile) this.keepNLastResults = 2
|
29189
|
+
|
29190
|
+
this.SUPERARG(arguments)
|
29191
|
+
},
|
29192
|
+
|
29193
|
+
|
29194
|
+
getNewTestConfiguration: function (desc, scopeProvider, contentManager, options, runFunc) {
|
29195
|
+
var config = this.SUPERARG(arguments)
|
29196
|
+
|
29197
|
+
config.performSetup = this.getDescriptorConfig(desc, 'performSetup')
|
29198
|
+
config.loaderPath = this.getDescriptorConfig(desc, 'loaderPath')
|
29199
|
+
|
29200
|
+
return config
|
29201
|
+
},
|
29202
|
+
|
29203
|
+
|
29204
|
+
createViewport: function (config) {
|
29205
|
+
if (!this.isRunningOnMobile && this.useExtJSUI) return Ext.create("Siesta.Harness.Browser.UI.ExtViewport", config);
|
29206
|
+
|
29207
|
+
var mainPanel = Ext.create('Siesta.Harness.Browser.UI_Mobile.MainPanel', config);
|
29208
|
+
|
29209
|
+
Ext.Viewport.add(mainPanel);
|
29210
|
+
|
29211
|
+
return mainPanel;
|
29212
|
+
},
|
29213
|
+
|
29214
|
+
|
29215
|
+
showForcedIFrame : function (iframe, test) {
|
29216
|
+
$.rebindWindowContext(window);
|
29217
|
+
|
29218
|
+
$(iframe).setStyle({
|
29219
|
+
'z-index' : 100000
|
29220
|
+
});
|
29221
|
+
},
|
29222
|
+
|
29223
|
+
|
29224
|
+
onBeforeScopePreload : function (scopeProvider, url) {
|
29225
|
+
var setupEventTranslation = function() {
|
29226
|
+
Ext.event.publisher.TouchGesture.override({
|
29227
|
+
moveEventName: 'mousemove',
|
29228
|
+
|
29229
|
+
map: {
|
29230
|
+
mouseToTouch: {
|
29231
|
+
mousedown: 'touchstart',
|
29232
|
+
mousemove: 'touchmove',
|
29233
|
+
mouseup: 'touchend'
|
29234
|
+
},
|
29235
|
+
|
29236
|
+
touchToMouse: {
|
29237
|
+
touchstart: 'mousedown',
|
29238
|
+
touchmove: 'mousemove',
|
29239
|
+
touchend: 'mouseup'
|
29240
|
+
}
|
29241
|
+
},
|
29242
|
+
|
29243
|
+
attachListener: function(eventName) {
|
29244
|
+
eventName = this.map.touchToMouse[eventName];
|
29245
|
+
|
29246
|
+
if (!eventName) {
|
29247
|
+
return;
|
29248
|
+
}
|
29249
|
+
|
29250
|
+
return this.callOverridden([eventName]);
|
29251
|
+
},
|
29252
|
+
|
29253
|
+
lastEventType: null,
|
29254
|
+
|
29255
|
+
onEvent: function(e) {
|
29256
|
+
if ('button' in e && e.button !== 0) {
|
29257
|
+
return;
|
29258
|
+
}
|
29259
|
+
|
29260
|
+
var type = e.type,
|
29261
|
+
touchList = [e];
|
29262
|
+
|
29263
|
+
// Temporary fix for a recent Chrome bugs where events don't seem to bubble up to document
|
29264
|
+
// when the element is being animated
|
29265
|
+
// with webkit-transition (2 mousedowns without any mouseup)
|
29266
|
+
if (type === 'mousedown' && this.lastEventType && this.lastEventType !== 'mouseup') {
|
29267
|
+
var fixedEvent = document.createEvent("MouseEvent");
|
29268
|
+
fixedEvent.initMouseEvent('mouseup', e.bubbles, e.cancelable,
|
29269
|
+
document.defaultView, e.detail, e.screenX, e.screenY, e.clientX,
|
29270
|
+
e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.metaKey,
|
29271
|
+
e.button, e.relatedTarget);
|
29272
|
+
|
29273
|
+
this.onEvent(fixedEvent);
|
29274
|
+
}
|
29275
|
+
|
29276
|
+
if (type !== 'mousemove') {
|
29277
|
+
this.lastEventType = type;
|
29278
|
+
}
|
29279
|
+
|
29280
|
+
e.identifier = 1;
|
29281
|
+
e.touches = (type !== 'mouseup') ? touchList : [];
|
29282
|
+
e.targetTouches = (type !== 'mouseup') ? touchList : [];
|
29283
|
+
e.changedTouches = touchList;
|
29284
|
+
|
29285
|
+
return this.callOverridden([e]);
|
29286
|
+
},
|
29287
|
+
|
29288
|
+
processEvent: function(e) {
|
29289
|
+
this.eventProcessors[this.map.mouseToTouch[e.type]].call(this, e);
|
29290
|
+
}
|
29291
|
+
});
|
29292
|
+
};
|
29293
|
+
|
29294
|
+
if ("ontouchstart" in window) {
|
29295
|
+
|
29296
|
+
// Need to tell ST to convert mouse events to their touch counterpart
|
29297
|
+
scopeProvider.addPreload({
|
29298
|
+
type : 'js',
|
29299
|
+
content : '(' + setupEventTranslation.toString() + ')();'
|
29300
|
+
})
|
29301
|
+
}
|
29302
|
+
|
29303
|
+
this.SUPERARG(arguments)
|
29304
|
+
}
|
29305
|
+
}
|
29306
|
+
}
|
29307
|
+
})
|
29308
|
+
|
29309
|
+
|
27660
29310
|
;
|
27661
29311
|
;
|
27662
29312
|
Class('Siesta', {
|
27663
|
-
/*PKGVERSION*/VERSION : '1.1.
|
29313
|
+
/*PKGVERSION*/VERSION : '1.1.5',
|
27664
29314
|
|
27665
29315
|
// "my" should been named "static"
|
27666
29316
|
my : {
|
27667
29317
|
|
27668
29318
|
has : {
|
27669
|
-
config
|
29319
|
+
config : null,
|
29320
|
+
activeHarness : null
|
27670
29321
|
},
|
27671
29322
|
|
27672
29323
|
methods : {
|
@@ -27696,4 +29347,3 @@ Class('Siesta', {
|
|
27696
29347
|
|
27697
29348
|
// fake StartTest function to extract test configs
|
27698
29349
|
if (typeof StartTest == 'undefined') StartTest = Siesta.StartTest;
|
27699
|
-
;
|