siesta 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/siesta/siesta_controller.rb +1 -1
- data/app/helpers/siesta/application_helper.rb +2 -2
- data/config/routes.rb +1 -1
- data/lib/siesta/test_suite.rb +3 -3
- data/lib/siesta/version.rb +1 -1
- data/vendor/assets/images/siesta/resources/images/trigger-groups.gif +0 -0
- data/vendor/assets/images/siesta/resources/images/trigger-leafs.gif +0 -0
- data/vendor/assets/javascripts/siesta/siesta-all.js +2144 -494
- data/vendor/assets/javascripts/siesta/siesta-nodejs-all.js +538 -138
- data/vendor/assets/javascripts/siesta/siesta-touch-all.js +1325 -449
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-all.css +22 -2
- data/vendor/assets/stylesheets/siesta/resources/css/siesta-touch-all.css +1 -1
- metadata +1243 -1241
@@ -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
|
-
;
|