rutl 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.bundle/config +2 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +37 -10
- data/.travis.yml +1 -0
- data/README.md +75 -38
- data/appveyor.yml +48 -0
- data/bin/ie.reg +0 -0
- data/bin/window_data.rb +27 -0
- data/lib/rspec/default_method_object_to_app.rb +28 -0
- data/lib/rspec/rutl_matchers.rb +7 -5
- data/lib/rutl.rb +26 -6
- data/lib/rutl/appium/appium_extension.rb +27 -0
- data/lib/rutl/appium/appium_server.rb +36 -0
- data/lib/rutl/appium/windows_test_app_wrapper.rb +40 -0
- data/lib/rutl/application.rb +70 -0
- data/lib/rutl/camera.rb +20 -4
- data/lib/rutl/element/click_to_change_state_mixin.rb +1 -1
- data/lib/rutl/element/element.rb +9 -10
- data/lib/rutl/element/element_context.rb +5 -4
- data/lib/rutl/element/string_reader_writer_mixin.rb +11 -7
- data/lib/rutl/interface/base.rb +30 -28
- data/lib/rutl/interface/browser/browser.rb +22 -0
- data/lib/rutl/interface/{chrome.rb → browser/chrome.rb} +3 -10
- data/lib/rutl/interface/{firefox.rb → browser/firefox.rb} +3 -10
- data/lib/rutl/interface/browser/internet_explorer.rb +23 -0
- data/lib/rutl/interface/browser/null.rb +36 -0
- data/lib/rutl/interface/windows/hello.rb +36 -0
- data/lib/rutl/interface/windows/notepad.rb +26 -0
- data/lib/rutl/interface/windows/windows_app.rb +35 -0
- data/lib/rutl/null_driver/null_driver.rb +4 -4
- data/lib/rutl/null_driver/null_element.rb +4 -4
- data/lib/rutl/version.rb +1 -1
- data/lib/rutl/{page.rb → view.rb} +37 -28
- data/lib/utilities/check_view.rb +12 -0
- data/lib/utilities/string.rb +12 -0
- data/lib/utilities/waiter.rb +23 -0
- data/rutl.gemspec +13 -0
- metadata +94 -10
- data/lib/rspec/default_rspec_to_browser.rb +0 -22
- data/lib/rutl/browser.rb +0 -70
- data/lib/rutl/interface/null.rb +0 -35
- data/lib/utilities.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f18aec216e23b12e55da96c52395e8da7521920cf48ab5090038192a034e991b
|
4
|
+
data.tar.gz: 7b3bc290be5e444a4c19952230b2ea1544efda3ab5e76cb16266a952c2f036a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afbebeca0867745a569a658753409a46146d982f859f7967c8d8aa524407dd9534ab3ddcf54b5233002a8cedc33c6501efb813b60f99c38af8647583422cd467
|
7
|
+
data.tar.gz: 2b8cf8f0fc9d31d1caf7ff6bb964be78396a7d127c5268f818018d709470b23e4c10a91619a2f22ec13f6ba5495d5e41b89c7cfd51ec936ae375a50394dfcfcb
|
data/.bundle/config
ADDED
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -33,7 +33,7 @@ Metrics/MethodLength:
|
|
33
33
|
# But should think about this first.
|
34
34
|
Style/BracesAroundHashParameters:
|
35
35
|
Exclude:
|
36
|
-
- 'spec/
|
36
|
+
- 'spec/views/**/*'
|
37
37
|
|
38
38
|
# NullDriverPageElement plays dirty tricks with @@variables to simulate
|
39
39
|
# longer-lived data sources.
|
data/.rubocop_todo.yml
CHANGED
@@ -1,28 +1,48 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2018-
|
3
|
+
# on 2018-07-02 00:08:22 -0700 using RuboCop version 0.56.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
+
# Offense count: 2
|
10
|
+
Lint/EmptyWhen:
|
11
|
+
Exclude:
|
12
|
+
- 'spec/web_browser_spec.rb'
|
13
|
+
|
9
14
|
# Offense count: 1
|
15
|
+
Metrics/AbcSize:
|
16
|
+
Max: 22
|
17
|
+
|
18
|
+
# Offense count: 2
|
10
19
|
# Configuration parameters: CountComments.
|
11
20
|
Metrics/MethodLength:
|
12
|
-
Max:
|
21
|
+
Max: 13
|
13
22
|
|
14
|
-
# Offense count:
|
15
|
-
|
23
|
+
# Offense count: 1
|
24
|
+
# Cop supports --auto-correct.
|
25
|
+
Style/BlockComments:
|
26
|
+
Exclude:
|
27
|
+
- 'spec/windows_spec.rb'
|
28
|
+
|
29
|
+
# Offense count: 9
|
30
|
+
# Cop supports --auto-correct.
|
31
|
+
# Configuration parameters: EnforcedStyle.
|
32
|
+
# SupportedStyles: braces, no_braces, context_dependent
|
33
|
+
Style/BracesAroundHashParameters:
|
16
34
|
Exclude:
|
17
|
-
- '
|
18
|
-
- '
|
19
|
-
- '
|
35
|
+
- 'spec/pages/**/*'
|
36
|
+
- 'spec/views/notepad/notepad.rb'
|
37
|
+
- 'spec/views/web/internet_login_error_view.rb'
|
38
|
+
- 'spec/views/web/internet_login_view.rb'
|
39
|
+
- 'spec/views/web/view1.rb'
|
20
40
|
|
21
41
|
# Offense count: 4
|
22
42
|
# Configuration parameters: AllowedVariables.
|
23
43
|
Style/GlobalVars:
|
24
44
|
Exclude:
|
25
|
-
- 'lib/rutl/
|
45
|
+
- 'lib/rutl/application.rb'
|
26
46
|
- 'lib/rutl/element/element.rb'
|
27
47
|
- 'lib/rutl/element/element_context.rb'
|
28
48
|
- 'lib/rutl/interface/null.rb'
|
@@ -30,7 +50,14 @@ Style/GlobalVars:
|
|
30
50
|
# Offense count: 4
|
31
51
|
Style/MethodMissingSuper:
|
32
52
|
Exclude:
|
33
|
-
- 'lib/rutl/
|
53
|
+
- 'lib/rutl/application.rb'
|
34
54
|
- 'lib/rutl/element/element.rb'
|
35
55
|
- 'lib/rutl/interface/base.rb'
|
36
|
-
- 'lib/rutl/
|
56
|
+
- 'lib/rutl/view.rb'
|
57
|
+
|
58
|
+
# Offense count: 1
|
59
|
+
# Cop supports --auto-correct.
|
60
|
+
# Configuration parameters: AllowAsExpressionSeparator.
|
61
|
+
Style/Semicolon:
|
62
|
+
Exclude:
|
63
|
+
- 'spec/hello.rb'
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[![TravisCI](https://api.travis-ci.org/drewcoo/rutl.svg)](https://travis-ci.org/drewcoo/rutl)
|
4
4
|
[![CircleCI](https://circleci.com/gh/drewcoo/rutl.svg?style=shield)](https://circleci.com/gh/drewcoo/rutl)
|
5
|
+
[![AppVeyor](https://ci.appveyor.com/api/projects/status/09oni14ixl077pr2?svg=true)](https://ci.appveyor.com/project/drewcoo/rutl)
|
5
6
|
[![Coverage Status](https://coveralls.io/repos/github/drewcoo/rutl/badge.svg?branch=master)](https://coveralls.io/github/drewcoo/rutl?branch=master)
|
6
7
|
[![Gem Version](https://badge.fury.io/rb/rutl.svg)](https://badge.fury.io/rb/rutl)
|
7
8
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f95d69f6bdd149e697cf63e842f71600)](https://www.codacy.com/app/drewcoo/rutl?utm_source=github.com&utm_medium=referral&utm_content=drewcoo/rutl&utm_campaign=Badge_Grade)
|
@@ -22,7 +23,7 @@ Framework goals:
|
|
22
23
|
|
23
24
|
Add this line to your application's Gemfile:
|
24
25
|
|
25
|
-
$ gem
|
26
|
+
$ gem rutl
|
26
27
|
|
27
28
|
And then execute:
|
28
29
|
|
@@ -35,28 +36,30 @@ Or install it yourself as:
|
|
35
36
|
|
36
37
|
## Usage
|
37
38
|
|
39
|
+
|
38
40
|
### Page Objects
|
41
|
+
|
39
42
|
Page objects are a common paradigm in browser testing. This framework uses the
|
40
43
|
following convention for page classes:
|
41
|
-
* must inherit from
|
42
|
-
* by default, the class should follow the naming convention ending with
|
43
|
-
* must have
|
44
|
+
* must inherit from `rutl::BasePage` (`require rutl/base_page`)
|
45
|
+
* by default, the class should follow the naming convention ending with `Page` (optional?)
|
46
|
+
* must have `@url` defined per page
|
44
47
|
* must have a layout method such that
|
45
|
-
* field types are defined by methods button
|
48
|
+
* field types are defined by methods `button`, `checkbox`, `link`, and `text` (more tbd?)
|
46
49
|
* field type is followed by name as a symbol (add support for string? tbd)
|
47
50
|
* then a comma
|
48
51
|
* hash of selectors
|
49
|
-
* key is selector type as symbol (currently only
|
52
|
+
* key is selector type as symbol (currently only `:css`)
|
50
53
|
* value is string path
|
51
54
|
* optional comma if there are destinations or error conditions
|
52
55
|
* optional array of destination page or error condition classes if clicking the element causes transition
|
53
56
|
* loaded? method returning boolean to determine when page is loaded
|
54
57
|
* defaults to just checking url; overide as needed
|
55
|
-
* go_to_here (better name?) method to navigate to the page if we can't just go to the url
|
58
|
+
* `go_to_here` (better name?) method to navigate to the page if we can't just go to the url
|
56
59
|
* your own methods because it's a plain ol' Ruby class
|
57
60
|
|
58
61
|
|
59
|
-
|
62
|
+
Example:
|
60
63
|
|
61
64
|
```ruby
|
62
65
|
require 'rutl/base_page'
|
@@ -97,77 +100,87 @@ The framework loads and manages all the pages. You just have to interact with
|
|
97
100
|
what you can see on whatever page you're on. Let's walk through this.
|
98
101
|
* TBD: Does RUTL come with browser drivers? Browsers? What needs to be added?
|
99
102
|
* We're using let! because:
|
100
|
-
* it forces instantiation of
|
101
|
-
* we include DefaultRspecToBrowser
|
103
|
+
* it forces instantiation of `browser` every time
|
104
|
+
* we `include DefaultRspecToBrowser`, defaulting missing methods to "browser"
|
102
105
|
* thus the terse lines that follow
|
103
|
-
* We didn't pass named param rutl_pages
|
104
|
-
* setting environment variable RUTL_PAGES
|
105
|
-
* setting RUTL::PAGES
|
106
|
-
* Browser's type
|
107
|
-
* The first call to the browser is goto because it wasn't on a page.
|
108
|
-
* Auto-created fields are named
|
109
|
-
* Getting and setting text fields is as easy as calling a String
|
106
|
+
* We didn't pass named param `rutl_pages:` to `browser` so we must have done one of:
|
107
|
+
* setting environment variable `RUTL_PAGES`
|
108
|
+
* setting `RUTL::PAGES`
|
109
|
+
* Browser's `type:` parameter currently supports `:chrome`, `:firefox`, and `:null`.
|
110
|
+
* The first call to the browser is `goto` because it wasn't on a page.
|
111
|
+
* Auto-created fields are named `#{friendly_name}_#{field_type}`.
|
112
|
+
* Getting and setting text fields is as easy as calling a `String`.
|
110
113
|
* When we call click, the framework polls for a next state.
|
111
114
|
* We verify that the current page is an instance of the intended page.
|
112
|
-
* Also note here that we have a matcher be_page which matches a page class.
|
115
|
+
* Also note here that we have a matcher `be_page` which matches a page class.
|
116
|
+
|
113
117
|
|
114
118
|
### RSpec Goodies
|
115
119
|
|
116
120
|
The tests here are in RSpec and use some conventions that may be common if your tests are also RSpec.
|
117
121
|
|
122
|
+
|
118
123
|
#### DefaultRspecToBrowser
|
124
|
+
|
119
125
|
This is a module that allows us to skip writing `browser.` in front of everything.
|
120
126
|
1. We assume that `browser` is defined.
|
121
127
|
2. On method_missing, we try to send the method to `browser`.
|
122
128
|
|
123
129
|
It lets us turn this:
|
124
|
-
```
|
125
|
-
|
130
|
+
```ruby
|
131
|
+
message = 'foo'
|
132
|
+
browser.field1_text = message
|
126
133
|
browser.ok_button.click
|
127
|
-
expect(browser.current_page).to
|
134
|
+
expect(browser.current_page).to be_page(NextPage)
|
128
135
|
```
|
129
136
|
into this:
|
130
|
-
```
|
131
|
-
|
137
|
+
```ruby
|
138
|
+
message = 'foo'
|
139
|
+
field1_text = message
|
132
140
|
ok_button.click
|
133
|
-
expect(current_page).to
|
141
|
+
expect(current_page).to be_page(NextPage)
|
134
142
|
```
|
135
|
-
which means less boilerplate
|
143
|
+
which means less boilerplate.
|
144
|
+
Because we insist on adding UI element type as part of the naming convention there's no confusion about which things are UI elements and which aren't. In this case, we don't mistake our variable "message" for a UI element.
|
136
145
|
|
137
146
|
To use it:
|
138
|
-
```
|
147
|
+
```ruby
|
139
148
|
require 'rutl/rspec/default_rspec_to_browser'
|
140
149
|
```
|
141
150
|
|
151
|
+
|
142
152
|
#### RSpec Matcher
|
143
153
|
|
144
154
|
Currently the only has the `be_page` matcher.
|
145
155
|
|
146
156
|
It lets us turn this:
|
147
|
-
```
|
157
|
+
```ruby
|
148
158
|
expect(browser.current_page).to be_instance_of(MyPage)
|
149
159
|
```
|
150
160
|
into this:
|
151
|
-
```
|
161
|
+
```ruby
|
152
162
|
expect(browser.current_page).to be_page(MyPage)
|
153
163
|
```
|
154
164
|
Both are acceptable but the second is more readable.
|
155
165
|
|
156
166
|
To use it:
|
157
|
-
```
|
167
|
+
```ruby
|
158
168
|
require 'rutl/rspec/rutl_matchers'
|
159
169
|
```
|
160
170
|
|
171
|
+
|
161
172
|
### Auto-screenshotting
|
162
173
|
|
163
|
-
If you have RUTL::SCREENSHOTS or ENV['SCREENSHOTS'] set to a directory, RUTL
|
174
|
+
If you have `RUTL::SCREENSHOTS` or `ENV['SCREENSHOTS']` set to a directory, RUTL
|
164
175
|
will automatically take screenshots on page transitions.
|
165
176
|
If you're using RSpec, they'll be automatically named something based on the
|
166
177
|
RSpec description with an auto-incrementing number.
|
167
178
|
If you're not using RSpec, that's not terribly useful but you can always have
|
168
179
|
your tests screenshot anyway, just less magic.
|
169
180
|
|
181
|
+
|
170
182
|
## Roadmap
|
183
|
+
|
171
184
|
Coming up soon in almost no order:
|
172
185
|
* Handle other errors. Auto-screenshot on errors. Navigation errors. Unexpected exceptions?
|
173
186
|
* A test framework should have better tests.
|
@@ -175,17 +188,29 @@ Coming up soon in almost no order:
|
|
175
188
|
* Put more info in this readme.
|
176
189
|
* Move bugs and would-be features to Github Issues instead of this readme and scattered through the code.
|
177
190
|
* Make the framework make it easier to spot bugs in pages. Focus on exception-handling?
|
178
|
-
* The webdriver gem should already include InternetExplorerDriver. Maybe run tests on AppVeyor.
|
179
|
-
* Other browser drivers
|
180
|
-
* Get this working with Appium:
|
181
|
-
* Make TK app to test on desktops and test it.
|
191
|
+
* The webdriver gem should already include [InternetExplorerDriver](https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver). Maybe run tests on [AppVeyor](https://www.appveyor.com/).
|
192
|
+
* [Other browser drivers](https://github.com/fnando/browser)?
|
193
|
+
* Get this working with [Appium](https://appium.io/):
|
194
|
+
* Make [TK app](https://www.tutorialspoint.com/ruby/ruby_tk_guide.htm) to test on desktops and test it.
|
182
195
|
* Can Ruby TK create accesible apps? Not in the simple demos.
|
183
196
|
* Make Android example app and get this to work.
|
184
|
-
*
|
197
|
+
* [Cordova](https://cordova.apache.org/) or [React Native](https://facebook.github.io/react-native/) or maybe even [Flutter](https://flutter.io/)for app?
|
198
|
+
* Choose (default?) emulator. Many choices.
|
185
199
|
* Same with iPhone.
|
186
|
-
*
|
187
|
-
*
|
200
|
+
* Where to build/test? [CircleCI](https://circleci.com/build-environments/#apple-platforms)?
|
201
|
+
* Same test app as Android.
|
202
|
+
* Are there decent alternatives yet to the simulator?
|
203
|
+
* Improve documentation.
|
204
|
+
* Add these things and treat as plugins?
|
205
|
+
* Security testing. See [OWASP](https://github.com/OWASP) stuff.
|
206
|
+
* Also OWASP mobile security testing guide.
|
207
|
+
* Avoid deeper pen testing. Leave it to other toolkits.
|
208
|
+
* Other toolkits? Accessibility?
|
209
|
+
* Support web proxy and integrate out of the box. Browsermob?
|
210
|
+
* Get HARs here for perf stuff.
|
211
|
+
* Also look at browser events and tie to HARs? (Always wanted to do that.)
|
188
212
|
* Auto-screenshot support frameworks other than RSpec.
|
213
|
+
* Or just default them to screenshots at known view changes (links/buttons/other?) or errors.
|
189
214
|
* Others?
|
190
215
|
* Spidering page object maker. Or selector checker/fixer?
|
191
216
|
* Possibly pair the null browser with auto-generated pages for ______?
|
@@ -210,7 +235,19 @@ Rubocop. I still have to tweak what I want it to complain about.
|
|
210
235
|
bundle exec rubocop
|
211
236
|
```
|
212
237
|
|
213
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
238
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
239
|
+
|
240
|
+
To release a new version, update the version number in `version.rb` like so
|
241
|
+
```ruby
|
242
|
+
bundle exec gem bump -v [major|minor|patch|pre|release]
|
243
|
+
```
|
244
|
+
|
245
|
+
and then run
|
246
|
+
```ruby
|
247
|
+
bundle exec rake release
|
248
|
+
```
|
249
|
+
|
250
|
+
which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
214
251
|
|
215
252
|
|
216
253
|
## Contributing
|
data/appveyor.yml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
version: 1.0.{build}-{branch}
|
2
|
+
|
3
|
+
image:
|
4
|
+
# need an image for Win10+ for WinAppDriver
|
5
|
+
- Visual Studio 2017
|
6
|
+
|
7
|
+
cache:
|
8
|
+
- C:\Users\appveyor\AppData\Roaming\npm
|
9
|
+
- vendor/bundle
|
10
|
+
# Chocolatey MSIs - out of luck!
|
11
|
+
|
12
|
+
install:
|
13
|
+
- set PATH=C:\Ruby25-x64\bin;%PATH%
|
14
|
+
# the bundle has stuff for mulitple profiles mixed together
|
15
|
+
- bundle install
|
16
|
+
# Chome, obviously but calling it out in case I make multiple profiles.
|
17
|
+
- choco install googlechrome
|
18
|
+
# This one's for iedriver.
|
19
|
+
- reg import bin\ie.reg
|
20
|
+
- npm install -g appium
|
21
|
+
# Can't choco install WinAppDriver yet.
|
22
|
+
# Also, am currently hardcoding version number. When there's a new Appium/
|
23
|
+
# WinAppDriver pairing available this may break because the Appium will be
|
24
|
+
# too new.
|
25
|
+
- appveyor DownloadFile https://github.com/Microsoft/WinAppDriver/releases/download/v1.0/WindowsApplicationDriver.msi
|
26
|
+
- msiexec /i WindowsApplicationDriver.msi /quiet /qn /norestart /log install.log
|
27
|
+
# allow developer mode for non-UWP-stuffs including WinAppDriver
|
28
|
+
- reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
|
29
|
+
|
30
|
+
build: off
|
31
|
+
|
32
|
+
before_test:
|
33
|
+
- ruby -v
|
34
|
+
- gem -v
|
35
|
+
- bundle -v
|
36
|
+
- bundle info rubocop
|
37
|
+
- npm -v
|
38
|
+
- ver
|
39
|
+
- dir
|
40
|
+
|
41
|
+
test_script:
|
42
|
+
- bundle exec rspec
|
43
|
+
|
44
|
+
artifacts:
|
45
|
+
- path: install.log
|
46
|
+
name: WAD installer log
|
47
|
+
|
48
|
+
- path: tmp\screenshots
|
data/bin/ie.reg
ADDED
Binary file
|
data/bin/window_data.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# gem install win32-window --pre
|
2
|
+
require 'win32/window'
|
3
|
+
|
4
|
+
title = ARGV[0]
|
5
|
+
this_file = File.basename(__FILE__)
|
6
|
+
|
7
|
+
if ARGV.size.zero?
|
8
|
+
STDERR.puts "\n #{this_file.upcase} <window_title_substring>\n\n"
|
9
|
+
STDERR.puts 'Finds full title, pid, and window handle for windows matching'
|
10
|
+
STDERR.puts 'the title substring. For titles with spaces, wrap in quotes.'
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
count = 0
|
15
|
+
Win32::Window.find(title: /#{title}/i).each do |window|
|
16
|
+
next if window.title.match(this_file)
|
17
|
+
puts if count > 0
|
18
|
+
puts "title \"#{window.title}\""
|
19
|
+
puts "pid #{window.pid}"
|
20
|
+
puts format('appTopLevelWindow 0x%08x', window.handle)
|
21
|
+
count += 1
|
22
|
+
end
|
23
|
+
|
24
|
+
if count.zero?
|
25
|
+
STDERR.puts "NO WINDOWS FOUND: \"#{title}\""
|
26
|
+
exit 1
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Tries to send any method to application.method instead.
|
3
|
+
#
|
4
|
+
# Sadly, Ruby doesn't allow this to work work with naked assignments. So
|
5
|
+
# foo_button.click # turns into application.foo_button.click
|
6
|
+
# bar_text == 'baz' # turns into application.bar_text == 'baz'
|
7
|
+
# but
|
8
|
+
# quux = 'quuux' # just stays quux = 'quuux'
|
9
|
+
#
|
10
|
+
module DefaultMethodObjectToApp
|
11
|
+
# rubocop:disable Style/MethodMissingSuper
|
12
|
+
def method_missing(method, *args, &block)
|
13
|
+
super unless respond_to_missing? method
|
14
|
+
if args.empty?
|
15
|
+
app.send(method)
|
16
|
+
else
|
17
|
+
app.send(method, *args, &block)
|
18
|
+
end
|
19
|
+
rescue ArgumentError
|
20
|
+
app.send(method)
|
21
|
+
end
|
22
|
+
# rubocop:enable Style/MethodMissingSuper
|
23
|
+
|
24
|
+
def respond_to_missing?(method, _include_private = false)
|
25
|
+
return false if method =~ /^app$/
|
26
|
+
app.respond_to?(method)
|
27
|
+
end
|
28
|
+
end
|