netzke-testing 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +106 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/netzke/.keep +0 -0
- data/app/assets/javascripts/netzke/testing/helpers/actions.js.coffee +74 -0
- data/app/assets/javascripts/netzke/testing/helpers/expectations.js.coffee +14 -0
- data/app/assets/javascripts/netzke/testing/helpers/form.js.coffee +7 -0
- data/app/assets/javascripts/netzke/testing/helpers/grid.js.coffee +107 -0
- data/app/assets/javascripts/netzke/testing/helpers/queries.js.coffee +88 -0
- data/app/assets/vendor/javascripts/expect/expect.js +1253 -0
- data/app/assets/vendor/javascripts/mocha/mocha.js +5340 -0
- data/app/assets/vendor/stylesheets/mocha/mocha.css +231 -0
- data/app/controllers/.keep +0 -0
- data/app/controllers/netzke/netzke/testing_controller.rb +28 -0
- data/app/helpers/.keep +0 -0
- data/app/helpers/netzke_testing_helper.rb +2 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/views/.keep +0 -0
- data/app/views/layouts/netzke/testing.html.erb +35 -0
- data/app/views/netzke/index.html.erb +2 -0
- data/config/routes.rb +8 -0
- data/lib/netzke/testing/engine.rb +6 -0
- data/lib/netzke/testing/helpers.rb +47 -0
- data/lib/netzke/testing/version.rb +5 -0
- data/lib/netzke/testing.rb +22 -0
- data/lib/netzke-testing.rb +1 -0
- data/netzke-testing.gemspec +23 -0
- data/test/controllers/netzke_testing_controller_test.rb +9 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/components/foo.rb +6 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +24 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +23 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/spec/javascripts/foo.js.coffee +3 -0
- data/test/helpers/netzke_testing_helper_test.rb +4 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/netzke_testing_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f6a8e145a80cbd76fe5872a58d199b5c0c3f6002
|
4
|
+
data.tar.gz: e7bef8a910494ec36fc1d4979f01f990bb1baac7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ecb548ed750a7cdaa03b3a8eb517524c220de8f4a0bc8f845a5a34ad8425773afdb3c8c595633d5d5d240752d2d827b8f3c825ebe06dfe972ed906b622acc3a2
|
7
|
+
data.tar.gz: 8db04d54ff7ebbd9c731297c783dc02ff7a2faea022512bdef617b49b01ef339ea22dc99cd23528c40641e2693db5b4c422a53bfdd105eefafcb1fc6e086d422
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Max Gorin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# Netzke Testing
|
2
|
+
|
3
|
+
This gem helps with development and testing of Netzke components. In parcticular, it helps you with:
|
4
|
+
|
5
|
+
* isolated component development
|
6
|
+
* client-side testing of components with Mocha and Expect.js
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
|
10
|
+
gem 'netzke_testing'
|
11
|
+
|
12
|
+
## Isolated component development
|
13
|
+
|
14
|
+
The gem implements a Rails engine, which (in development and test environments only) adds a route to load your
|
15
|
+
application's Netzke components individually, which can be useful for isolated development. Example (say, we have a
|
16
|
+
UserGrid component defined):
|
17
|
+
|
18
|
+
http://localhost:3000/netzke/components/UserGrid
|
19
|
+
|
20
|
+
This will load a view with UserGrid occupying the available window width, with default height of 400px. You can change
|
21
|
+
the height by providing the `height` parameter in the URL:
|
22
|
+
|
23
|
+
http://localhost:3000/netzke/components/UserGrid?height=600
|
24
|
+
|
25
|
+
## Testing components with Mocha and Expect.js
|
26
|
+
|
27
|
+
Place the Mocha specs (written in Coffeescript) for your components inside `spec/javascripts` folder. An example spec
|
28
|
+
may look like this (in `spec/javascripts/user_grid.js.coffee`):
|
29
|
+
|
30
|
+
describe 'UserGrid', ->
|
31
|
+
it 'shows proper title', ->
|
32
|
+
grid = Ext.ComponentQuery.query('panel[id="user_grid"]')[0]
|
33
|
+
expect(grid.getHeader().title).to.eql 'Test component'
|
34
|
+
|
35
|
+
This spec can be run by appending the `spec` parameter to the url:
|
36
|
+
|
37
|
+
http://localhost:3000/netzke/components/UserGrid?spec=user_grid
|
38
|
+
|
39
|
+
Specs can be structured into directories. For example, let's say we have a namescope for admin components:
|
40
|
+
|
41
|
+
class Admin::UserGrid < Netzke::Basepack::Grid
|
42
|
+
end
|
43
|
+
|
44
|
+
It makes sense to put the corresponding specs in `spec/javascripts/admin/user_grid.js.coffee`. In this case, the URL
|
45
|
+
to run the Mocha specs will be:
|
46
|
+
|
47
|
+
http://localhost:3000/netzke/components/UserGrid?spec=admin/user_grid
|
48
|
+
|
49
|
+
## Mocha spec helpers
|
50
|
+
|
51
|
+
The gem provides a number of helpers that may help you writing less code and make your specs look something like this:
|
52
|
+
|
53
|
+
describe 'UserGrid', ->
|
54
|
+
it 'allows instant removing of all users with a single button click', (done) ->
|
55
|
+
click button 'Remove all'
|
56
|
+
wait ->
|
57
|
+
expectToSee header 'Empty'
|
58
|
+
done()
|
59
|
+
|
60
|
+
Keep in mind the following:
|
61
|
+
|
62
|
+
* the current set of helpers is in flux, and may be drastically changed sooner than you may expect
|
63
|
+
* the helpers directly pollute the `window` namespace; if you decide you're better off without provided helpers,
|
64
|
+
specify 'no-helpers=true' as an extra URL parameter
|
65
|
+
|
66
|
+
See the [source code](TODO) for currently implemented helpers. Also, refer to other Netzke gems source code (like
|
67
|
+
netzke-core and netzke-basepack) to see examples using the helpers.
|
68
|
+
|
69
|
+
## Testing with selenium webdriver
|
70
|
+
|
71
|
+
Generate the `netzke_mocha_spec.rb` file that will automatically run the specs that follow a certain naming convention:
|
72
|
+
|
73
|
+
rails g netzke_testing
|
74
|
+
|
75
|
+
This spec will pick up all the `*_spec.js.coffee` files from `spec/javascripts` folder and generate an `it` clause for
|
76
|
+
each of them. Let's say we want to create the spec for UserGrid. For this we name the spec file
|
77
|
+
`spec/javascripts/user_grid_spec.js.coffee`. And the other way around: when `netzke_mocha_spec.rb` finds a file called
|
78
|
+
`spec/javascripts/order_grid_spec.js.coffee`, it'll assume existance of `OrderGrid` component that should be tested.
|
79
|
+
|
80
|
+
## Mixing client- and server-side testing code
|
81
|
+
|
82
|
+
Often we want to run some Ruby code before running the Mocha spec (e.g. to seed some test data using factories), or
|
83
|
+
after (e.g. to assert changes in the database). In this case you can create a RSpec spec that uses the `run_mocha_spec`
|
84
|
+
helper provided by the `netzke_testing` gem. Here's an example (in `spec/user_grid_spec.rb`):
|
85
|
+
|
86
|
+
require 'spec_helper'
|
87
|
+
feature GridWithDestructiveButton do
|
88
|
+
it 'allows instant removing of all records with a single button click', js: true do
|
89
|
+
10.times { FactoryGirl.create :user }
|
90
|
+
User.count.should == 10
|
91
|
+
run_mocha_spec 'grid_with_destructive_button'
|
92
|
+
User.count.should == 0
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
The `run_mocha_spec` here will run a Mocha spec from `spec/grid_with_destructive_button.js.coffee`.
|
97
|
+
|
98
|
+
You can explicitely specify a component to run the spec on (in order to override the convention):
|
99
|
+
|
100
|
+
run_mocha_spec 'grid_with_destructive_button', component: 'UserGrid'
|
101
|
+
|
102
|
+
---
|
103
|
+
Copyright (c) 2008-2013 [Max Gorin](https://twitter.com/uptomax), released under the MIT license (see LICENSE).
|
104
|
+
|
105
|
+
**Note** that Ext JS is licensed [differently](http://www.sencha.com/products/extjs/license/), and you may need to
|
106
|
+
purchase a commercial license in order to use it in your projects!
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
File without changes
|
@@ -0,0 +1,74 @@
|
|
1
|
+
Ext.Ajax.on 'beforerequest', ->
|
2
|
+
Netzke.ajaxCount = window.ajaxCount || 0
|
3
|
+
Netzke.ajaxCount += 1
|
4
|
+
|
5
|
+
Ext.Ajax.on 'requestcomplete', ->
|
6
|
+
Netzke.ajaxCount -= 1
|
7
|
+
|
8
|
+
Ext.apply window,
|
9
|
+
# Examples:
|
10
|
+
#
|
11
|
+
# wait ->
|
12
|
+
# afterAllAjaxActivityIsStopped()
|
13
|
+
#
|
14
|
+
# wait 2000, ->
|
15
|
+
# afterTwoSeconds()
|
16
|
+
wait: () ->
|
17
|
+
if typeof arguments[0] == 'function'
|
18
|
+
callback = arguments[0]
|
19
|
+
i = 0
|
20
|
+
id = setInterval ->
|
21
|
+
i += 1
|
22
|
+
if i >= 100
|
23
|
+
clearInterval(id)
|
24
|
+
callback.call()
|
25
|
+
|
26
|
+
# this way we ensure another 20ms cycle before we issue a callback
|
27
|
+
i = 100 if Netzke.ajaxCount == 0
|
28
|
+
, 100
|
29
|
+
else
|
30
|
+
delay = arguments[0]
|
31
|
+
callback = arguments[1]
|
32
|
+
setInterval ->
|
33
|
+
callback.call()
|
34
|
+
, delay
|
35
|
+
|
36
|
+
click: (cmp) ->
|
37
|
+
if Ext.isString(cmp)
|
38
|
+
throw "Could not locate " + cmp
|
39
|
+
else if (cmp.isXType) # is Ext component
|
40
|
+
if (cmp.isXType('tool'))
|
41
|
+
# a hack needed for tools
|
42
|
+
el = cmp.toolEl
|
43
|
+
else
|
44
|
+
el = cmp.getEl()
|
45
|
+
|
46
|
+
el.dom.click()
|
47
|
+
else if Ext.isElement(cmp)
|
48
|
+
cmp.click()
|
49
|
+
|
50
|
+
# Closes the first found window
|
51
|
+
closeWindow: ->
|
52
|
+
Ext.ComponentQuery.query("window[hidden=false]")[0].close()
|
53
|
+
|
54
|
+
select: (value, params, callback) ->
|
55
|
+
params ?= params
|
56
|
+
combo = params.in
|
57
|
+
if combo.isExpanded
|
58
|
+
combo.setValue combo.findRecordByDisplay value
|
59
|
+
combo.collapse()
|
60
|
+
else
|
61
|
+
combo.onTriggerClick()
|
62
|
+
if callback
|
63
|
+
wait ->
|
64
|
+
rec = combo.findRecordByDisplay value
|
65
|
+
combo.select rec
|
66
|
+
combo.fireEvent('select', combo, rec )
|
67
|
+
combo.collapse()
|
68
|
+
callback.call()
|
69
|
+
else
|
70
|
+
rec = combo.findRecordByDisplay value
|
71
|
+
combo.select rec
|
72
|
+
combo.fireEvent('select', combo, rec )
|
73
|
+
combo.collapse()
|
74
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Ext.apply window,
|
2
|
+
expectToSee: (el) ->
|
3
|
+
expect(Ext.isObject(el) || Ext.isElement(el)).to.be.ok()
|
4
|
+
|
5
|
+
expectToNotSee: (el) ->
|
6
|
+
expect(Ext.isString(el)).to.be.ok()
|
7
|
+
|
8
|
+
expectDisabled: (cmp) ->
|
9
|
+
throw cmp + " not found" if Ext.isString(cmp)
|
10
|
+
expect(cmp.isDisabled()).to.be(true)
|
11
|
+
|
12
|
+
expectInvisibleBodyOf: (cmp) ->
|
13
|
+
throw cmp + " not found" if Ext.isString(cmp)
|
14
|
+
expect(cmp.body.isVisible()).to.be false
|
@@ -0,0 +1,107 @@
|
|
1
|
+
Ext.apply window,
|
2
|
+
grid: (title) ->
|
3
|
+
if title
|
4
|
+
Ext.ComponentQuery.query('grid[title="'+title+'"]')[0]
|
5
|
+
else
|
6
|
+
Ext.ComponentQuery.query('grid{isVisible(true)}')[0]
|
7
|
+
|
8
|
+
expandRowCombo: (field, params) ->
|
9
|
+
g = g || this.grid()
|
10
|
+
editor = g.getPlugin('celleditor')
|
11
|
+
column = g.headerCt.items.findIndex('name', field) - 1
|
12
|
+
window.editor = editor
|
13
|
+
editor.startEditByPosition({row: g.getSelectionModel().getCurrentPosition().row, column: column})
|
14
|
+
editor.activeEditor.field.onTriggerClick()
|
15
|
+
|
16
|
+
# Example:
|
17
|
+
# addRecords {title: 'Foo'}, {title: 'Bar'}, to: grid('Books'), submit: true
|
18
|
+
addRecords: ->
|
19
|
+
params = arguments[arguments.length - 1]
|
20
|
+
for record in arguments
|
21
|
+
if (record != params)
|
22
|
+
record = params.to.getStore().add(record)[0]
|
23
|
+
record.isNew = true
|
24
|
+
click button 'Apply' if params.submit
|
25
|
+
|
26
|
+
addRecord: (recordData, params) ->
|
27
|
+
params = params || []
|
28
|
+
grid = params.to || this.grid()
|
29
|
+
record = grid.getStore().add(recordData)
|
30
|
+
grid.getSelectionModel().select(grid.getStore().last())
|
31
|
+
|
32
|
+
updateRecord: (recordData, params) ->
|
33
|
+
params = params || []
|
34
|
+
grid = params.to || this.grid()
|
35
|
+
record = grid.getSelectionModel().getSelection()[0]
|
36
|
+
for key,value of recordData
|
37
|
+
record.set(key, value)
|
38
|
+
|
39
|
+
selectAssociation: (attr, value, callback) ->
|
40
|
+
expandRowCombo attr
|
41
|
+
wait ->
|
42
|
+
select value, in: combobox(attr)
|
43
|
+
# wait ->
|
44
|
+
callback.call()
|
45
|
+
|
46
|
+
valuesInColumn: (name, params) ->
|
47
|
+
params ?= {}
|
48
|
+
grid = params.in || this.grid()
|
49
|
+
out = []
|
50
|
+
grid.getStore().each (r) ->
|
51
|
+
assocValue = r.get('meta').associationValues[name]
|
52
|
+
out.push(if assocValue then assocValue else r.get(name))
|
53
|
+
out
|
54
|
+
|
55
|
+
selectAllRows: (params) ->
|
56
|
+
params ?= {}
|
57
|
+
grid = params.in || this.grid()
|
58
|
+
grid.getSelectionModel().selectAll()
|
59
|
+
|
60
|
+
# rowDisplayValues in: grid('Books'), of: grid('Books').getStore().last()
|
61
|
+
# Without parameters, assumes the first found grid and the selected row
|
62
|
+
rowDisplayValues: (params) ->
|
63
|
+
params ?= {}
|
64
|
+
grid = params.in || this.grid()
|
65
|
+
record = params.of || grid.getSelectionModel().getSelection()[0]
|
66
|
+
|
67
|
+
visibleColumns = []
|
68
|
+
Ext.each grid.columns, (c) ->
|
69
|
+
visibleColumns.push(c) if c.isVisible()
|
70
|
+
|
71
|
+
i = -1
|
72
|
+
return Ext.Array.map(Ext.DomQuery.select('tr[data-recordid="'+record.internalId+'"] td div'), (cell) ->
|
73
|
+
i++
|
74
|
+
if visibleColumns[i].attrType == 'boolean'
|
75
|
+
record.get(visibleColumns[i].name)
|
76
|
+
else
|
77
|
+
cell.innerHTML
|
78
|
+
)
|
79
|
+
|
80
|
+
# selectLastRow()
|
81
|
+
# selectLastRow in: grid('Book')
|
82
|
+
selectLastRow: (params) ->
|
83
|
+
params ?= {}
|
84
|
+
grid = params.in || this.grid()
|
85
|
+
grid.getSelectionModel().select(grid.getStore().last())
|
86
|
+
|
87
|
+
# selectFirstRow()
|
88
|
+
# selectFirstRow in: grid('Book')
|
89
|
+
selectFirstRow: (params) ->
|
90
|
+
params ?= {}
|
91
|
+
grid = params.in || this.grid()
|
92
|
+
grid.getSelectionModel().select(grid.getStore().first())
|
93
|
+
|
94
|
+
# Example:
|
95
|
+
# editLastRow {title: 'Foo', exemplars: 10}
|
96
|
+
editLastRow: ->
|
97
|
+
data = arguments[0]
|
98
|
+
grid = Ext.ComponentQuery.query("grid")[0]
|
99
|
+
store = grid.getStore()
|
100
|
+
record = store.last()
|
101
|
+
for key of data
|
102
|
+
record.set(key, data[key])
|
103
|
+
|
104
|
+
completeEditing: (g) ->
|
105
|
+
g = g || this.grid()
|
106
|
+
e = g.getPlugin('celleditor')
|
107
|
+
e.completeEdit()
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Query helpers will return a string denoting what was searched for, when a component/element itself could not be found. This can be used by other helpers to display a more informative error.
|
2
|
+
# KNOWN ISSUE: if the passed parameter contains symbols like "():,.", it results in an invalid query.
|
3
|
+
Ext.apply window,
|
4
|
+
header: (title) ->
|
5
|
+
Ext.ComponentQuery.query('header{isVisible(true)}[title="'+title+'"]')[0] || 'header ' + title
|
6
|
+
|
7
|
+
tab: (title) ->
|
8
|
+
Ext.ComponentQuery.query('tab[text="'+title+'"]')[0] || 'tab ' + title
|
9
|
+
|
10
|
+
panelWithContent: (text) ->
|
11
|
+
Ext.DomQuery.select("div.x-panel-body:contains(" + text + ")")[0] || 'panel with content ' + text
|
12
|
+
|
13
|
+
button: (text) ->
|
14
|
+
Ext.ComponentQuery.query("button{isVisible(true)}[text='"+text+"']")[0] || "button " + text
|
15
|
+
|
16
|
+
tool: (type) ->
|
17
|
+
Ext.ComponentQuery.query("tool{isVisible(true)}[type='"+type+"']")[0] || 'tool ' + type
|
18
|
+
|
19
|
+
component: (id) ->
|
20
|
+
Ext.ComponentQuery.query("panel{isVisible(true)}[id='"+id+"']")[0] || 'component ' + id
|
21
|
+
|
22
|
+
somewhere: (text) ->
|
23
|
+
Ext.DomQuery.select("*:contains(" + text + ")")[0] || 'anywhere ' + text
|
24
|
+
|
25
|
+
# used as work-around for the invalid query problem
|
26
|
+
currentPanelTitle: ->
|
27
|
+
panel = Ext.ComponentQuery.query('panel[hidden=false]')[0]
|
28
|
+
throw "Panel not found" if !panel
|
29
|
+
panel.getHeader().title
|
30
|
+
|
31
|
+
combobox: (name) ->
|
32
|
+
Ext.ComponentQuery.query("combo{isVisible(true)}[name='"+name+"']")[0] ||
|
33
|
+
'combobox ' + name
|
34
|
+
|
35
|
+
icon: (tooltip) ->
|
36
|
+
Ext.DomQuery.select('img[data-qtip="'+tooltip+'"]')[0] || 'icon ' + tooltip
|
37
|
+
|
38
|
+
textfield: (name) ->
|
39
|
+
Ext.ComponentQuery.query("textfield{isVisible(true)}[name='"+name+"']")[0] ||
|
40
|
+
'textfield ' + name
|
41
|
+
|
42
|
+
numberfield: (name) ->
|
43
|
+
Ext.ComponentQuery.query("numberfield{isVisible(true)}[name='"+name+"']")[0] ||
|
44
|
+
'numberfield ' + name
|
45
|
+
|
46
|
+
datefield: (name) ->
|
47
|
+
Ext.ComponentQuery.query("datefield{isVisible(true)}[name='"+name+"']")[0] ||
|
48
|
+
'datefield ' + name
|
49
|
+
|
50
|
+
xdatetime: (name) ->
|
51
|
+
Ext.ComponentQuery.query("xdatetime{isVisible(true)}[name='"+name+"']")[0] ||
|
52
|
+
'xdatetime ' + name
|
53
|
+
|
54
|
+
textFieldWith: (text) ->
|
55
|
+
_componentLike "textfield", "value", text
|
56
|
+
|
57
|
+
comboboxWith: (text) ->
|
58
|
+
_componentLike "combo", "rawValue", text
|
59
|
+
|
60
|
+
textAreaWith: (text) ->
|
61
|
+
_componentLike "textareafield", "value", text
|
62
|
+
|
63
|
+
numberFieldWith: (value) ->
|
64
|
+
_componentLike "numberfield", "value", value
|
65
|
+
|
66
|
+
activeWindow: ->
|
67
|
+
Ext.WindowMgr.getActive()
|
68
|
+
|
69
|
+
dateTimeFieldWith: (value) ->
|
70
|
+
res = 'xdatetime with value ' + value
|
71
|
+
Ext.each Ext.ComponentQuery.query('xdatetime'), (item) ->
|
72
|
+
if item.getValue().toString() == (new Date(value)).toString()
|
73
|
+
res = item
|
74
|
+
return
|
75
|
+
res
|
76
|
+
|
77
|
+
dateFieldWith: (value) ->
|
78
|
+
res = 'datefield with value ' + value
|
79
|
+
Ext.each Ext.ComponentQuery.query('datefield'), (item) ->
|
80
|
+
if item.getValue().toString() == (new Date(value)).toString()
|
81
|
+
res = item
|
82
|
+
return
|
83
|
+
res
|
84
|
+
|
85
|
+
_componentLike:(type,attr,value)->
|
86
|
+
Ext.ComponentQuery.query(type+'['+attr+'='+value+']')[0] || type + " with " + attr + " '" + value + "'"
|
87
|
+
# alias
|
88
|
+
window.anywhere = window.somewhere
|