unobtainium 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9921b8f7735c0d00216208fe5ad193525671fd8f
4
- data.tar.gz: 1557e2461fc29570eb97f975d83a4b792b838862
3
+ metadata.gz: 3aa9b74f8f1f3c7d408438a0cff087c268dc89d4
4
+ data.tar.gz: 31f3f35f5ff7b1eccf2fd121c233b62d0056c386
5
5
  SHA512:
6
- metadata.gz: bd7643c1a36ea61aa917629a922cd3535b408f70a4206e18d77cebcd11327e0cb13931589eef0b7367c9c243928fd9c23ea82196397fce2bc756db9edbed1f85
7
- data.tar.gz: f435d50ed4e50e697dbe1b7b1a3c0ddf5ccc50c2148d4d02cb5fea2ac30e7d738e59c47371655a4ccb449bb56c24a66760abebd7838fc22dd0cdecd973c00af6
6
+ metadata.gz: 953d864dd1286c499979044503a8655426f9e14912878d8ebd9300a3ddc9492143c8efe2f014168a44fe7131286107ba318c3c0509591832fda7fd67611dd667
7
+ data.tar.gz: a5bfa05e01c37fd7a8f6a6e15d05227f9552971d708d65fa4a54a290d742d50f0152f95ad55cf9dc51bd6bcf5ee7c44cfc2574caf85cf32069cda8f20ed2fe04
data/.rubocop.yml CHANGED
@@ -64,3 +64,6 @@ Style/TrailingUnderscoreVariable:
64
64
 
65
65
  Style/NumericLiterals:
66
66
  Enabled: false
67
+
68
+ Style/FileName:
69
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unobtainium (0.2.1)
4
+ unobtainium (0.3.1)
5
5
  sys-proctable (~> 1.0)
6
6
 
7
7
  GEM
@@ -37,11 +37,11 @@ GEM
37
37
  gherkin (3.2.0)
38
38
  json (1.8.3)
39
39
  mini_portile2 (2.0.0)
40
- multi_json (1.11.2)
40
+ multi_json (1.11.3)
41
41
  multi_test (0.1.2)
42
42
  nokogiri (1.6.7.2)
43
43
  mini_portile2 (~> 2.0.0.rc2)
44
- parser (2.3.0.7)
44
+ parser (2.3.1.0)
45
45
  ast (~> 2.2)
46
46
  phantomjs (2.1.1.0)
47
47
  powerpack (0.1.1)
@@ -66,7 +66,7 @@ GEM
66
66
  rainbow (>= 1.99.1, < 3.0)
67
67
  ruby-progressbar (~> 1.7)
68
68
  unicode-display_width (~> 1.0, >= 1.0.1)
69
- ruby-progressbar (1.7.5)
69
+ ruby-progressbar (1.8.0)
70
70
  rubyzip (1.2.0)
71
71
  selenium-webdriver (2.53.0)
72
72
  childprocess (~> 0.5)
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) Jens Finkhaeuser (http://finkhaeuser.de/) and other unobtainum
1
+ Copyright (c) Jens Finkhaeuser (http://finkhaeuser.de/) and other unobtainium
2
2
  contributors. All rights not covered below are reserved.
3
3
 
4
4
  The MIT +no-false-attribs License (MITNFA)
data/README.md CHANGED
@@ -24,6 +24,8 @@ also added.
24
24
  You can use unobtainium on its own, or use it as part of a
25
25
  [cucumber](https://cucumber.io/) test suite.
26
26
 
27
+ [![Unobtainium Demonstration](http://img.youtube.com/vi/82pYWG5uTnM/0.jpg)](http://www.youtube.com/watch?v=82pYWG5uTnM)
28
+
27
29
  Unobtainium's functionality is in standalone classes, but it's all combined in
28
30
  the `Unobtainium::World` module.
29
31
 
@@ -36,7 +38,7 @@ the `Unobtainium::World` module.
36
38
 
37
39
  - The `Config` class is a `PathedHash`, but also reads JSON or YAML files to
38
40
  initialize itself with values. See the documentation on [configuration features](docs/CONFIGURATION.md)
39
- for details
41
+ for details.
40
42
  - The `Runtime` class is a singleton and a `Hash`-like container (but simpler),
41
43
  that destroys all of its contents at the end of a script, calling custom
42
44
  destructors if required. That allows for clean teardown and avoids everything
@@ -74,6 +76,13 @@ The configuration file knows two configuration variables:
74
76
  options hash you might otherwise pass to `Driver.create` as the second
75
77
  parameter.
76
78
 
79
+ See the documentation on [configuration features](docs/CONFIGURATION.md) for
80
+ details.
81
+
82
+ ## Development
83
+
84
+ - [driver development](docs/DRIVERS.md)
85
+
77
86
  # Credits
78
87
  This gem is inspired by [LapisLazuli](https://github.com/spriteCloud/lapis-lazuli),
79
88
  but vastly less complex, and aims to stay so.
@@ -170,7 +170,9 @@ drivers:
170
170
  The tests can be run on device/browser farms. Typically you only need to
171
171
  configure drivers, much like for mobile testing. The following example
172
172
  is for [TestingBot](https://testingbot.com). Note that each farm expects
173
- different configuration keys for selecting browsers and for authentication.
173
+ different configuration keys for selecting browsers and for authentication,
174
+ and that `unobtainium` just passes these values through to Selenium and/or
175
+ Appium.
174
176
 
175
177
  ```yaml
176
178
  # config/config.yml
data/docs/DRIVERS.md ADDED
@@ -0,0 +1,102 @@
1
+ # Drivers
2
+
3
+ Drivers are used to access web pages and their content. Since unobtainium is
4
+ designed to be primarily a wrapper for Selenium and Appium, the built-in
5
+ drivers provide roughly the same API, but there is no strict requirement for
6
+ this.
7
+
8
+ Driver implementations are classes which are required to have a number of
9
+ class methods, described below. No requirements on instance methods are made.
10
+
11
+ # Required Class Methods
12
+
13
+ The class methods required by unobtainium are as follows:
14
+
15
+ - `matches?` accepting a String or Symbol label, as passed by the user to
16
+ `Driver#create`. Must return true if the driver implementation matches this
17
+ label, i.e. if this driver implementation is to be used when the user
18
+ specifies this particular label.
19
+ Note that multiple driver implementations can match the same label; the order
20
+ of preference is an implementation detail.
21
+ - *[optional]* `resolve_options` accepting the label and options passed to
22
+ `Driver#create` by the user (defaulting to an empty hash). The function must
23
+ return the label and options again, however should normalize the label (see
24
+ below) and supplement any options with default values, etc.
25
+ - `ensure_preconditions` accepting the label, and options.
26
+ The method should be used to require any necessary code, and raise errors if
27
+ any other preconditions are not met. See the section on dynamic loading as
28
+ well.
29
+ - Finally, `create` accepting the label and options should return an instance
30
+ of a driver class matching both parameters.
31
+
32
+ # Optional Instance Methods
33
+
34
+ - `destroy` gets invoked by `Runtime` at exit, if `World#driver` is used to
35
+ create the instance. It can be used to tear down the driver instance cleanly.
36
+
37
+ # Label Normalization & Configuration Resolution
38
+
39
+ The built-in drivers respond to many different labels, some of which are
40
+ aliases for a *normalized* label. For example, you can specify `:headless`,
41
+ which is an alias for `:phantomjs`.
42
+
43
+ Label normalization should return `:phantomjs` in the example above.
44
+
45
+ The main goal behind configuration resolution is to provide a way for driver
46
+ implementations to translate configuration keys into a form better suited to
47
+ the implementation.
48
+
49
+ For example, the Selenium driver symbolizes keys, because `selenium-webdriver`
50
+ requires symbol keys. On the other hand, the [configuration](./CONFIGURATION.md)
51
+ system produces String keys only.
52
+
53
+ But you can use this step also to expand shortcut options. The Appium implentation
54
+ allows you to more simply specify some mobile browsers, expanding this into
55
+ capabilities required by Appium itself.
56
+
57
+ # Instance Management
58
+
59
+ The `World#driver` function registers driver implementations with `Runtime` to
60
+ be destroyed at exit.
61
+
62
+ In order to allow multiple driver instances for e.g. multi-browser testing, but
63
+ simultaneously manage instances as described above, the normalized label and
64
+ resolved configuration (see above) are used to generate unique keys.
65
+
66
+ The basic principle is that `World#driver` will be called multiple times in a
67
+ test suite. If it is invoked twice with the same parameters, the same instance
68
+ should be returned. Parameterless invocations should always return the same
69
+ instance, as defined by the configuration. For the pattern inclined reader, this
70
+ is an implementation of the [flyweight pattern](https://en.wikipedia.org/wiki/Flyweight_pattern).
71
+
72
+ Therefore, `resolve_options` should return identical results for two invocations
73
+ with *semantically* identical input.
74
+
75
+ # Dynamic Loading
76
+
77
+ In order not to create hard dependencies in unobtainium on specific versions of
78
+ Selenium, Appium and PhantomJS, these dependencies are only required when
79
+ `ensure_preconditions` is being invoked. That lets users decide which versions
80
+ to require, and skip libraries they do not use.
81
+
82
+ Your driver implementation does not have to follow the same pattern, unless you
83
+ want to see it merged into unobtainium itself.
84
+
85
+ # Registering an Implementation
86
+
87
+ When you have written your class to conform to the above API, all that is left
88
+ to do is to register it with unobtainium:
89
+
90
+ ```ruby
91
+ class MyDriver
92
+ # implementatin
93
+ end # class MyDriver
94
+
95
+ ::Unobtainium::Driver.register_implementation(MyDriver, __FILE__)
96
+ ```
97
+
98
+ The second path parameter should always be set to `__FILE__`. It is used to
99
+ ensure that if your library is included multiple times, the driver does not
100
+ get registered more than once. On the other hand, a different implementation
101
+ with the same class name would raise an error when `register_implementation`
102
+ is invoked.
@@ -27,6 +27,17 @@ module Unobtainium
27
27
  class PathedHash
28
28
  include RecursiveMerge
29
29
 
30
+ DEFAULT_PROC = proc do |hash, key|
31
+ case key
32
+ when String
33
+ sym = key.to_sym
34
+ hash[sym] if hash.key?(sym)
35
+ when Symbol
36
+ str = key.to_s
37
+ hash[str] if hash.key?(str)
38
+ end
39
+ end.freeze
40
+
30
41
  ##
31
42
  # Initializer. Accepts `nil`, hashes or pathed hashes.
32
43
  #
@@ -38,6 +49,8 @@ module Unobtainium
38
49
  @data = init.dup
39
50
  end
40
51
  @separator = '.'
52
+
53
+ @data.default_proc = DEFAULT_PROC
41
54
  end
42
55
 
43
56
  # @return [String] the separator is the character or pattern splitting paths.
@@ -106,6 +119,7 @@ module Unobtainium
106
119
  # For write methods, we need to create intermediary hashes.
107
120
  leaf = recursive_fetch(components, @data,
108
121
  create: WRITE_METHODS.include?(method))
122
+ leaf.default_proc = DEFAULT_PROC
109
123
 
110
124
  # If we have a leaf, we want to send the requested method to that
111
125
  # leaf.
@@ -8,5 +8,5 @@
8
8
  #
9
9
  module Unobtainium
10
10
  # The current release version
11
- VERSION = "0.3.0".freeze
11
+ VERSION = "0.3.1".freeze
12
12
  end
@@ -36,7 +36,11 @@ module Unobtainium
36
36
  # Return the global configuration, loaded from `World#config_file`
37
37
  def config
38
38
  return ::Unobtainium::Runtime.instance.store_with_if(:config) do
39
- ::Unobtainium::Config.load_config(::Unobtainium::World.config_file)
39
+ begin
40
+ ::Unobtainium::Config.load_config(::Unobtainium::World.config_file)
41
+ rescue Errno::ENOENT
42
+ {}
43
+ end
40
44
  end
41
45
  end
42
46
 
@@ -54,6 +54,31 @@ describe ::Unobtainium::PathedHash do
54
54
  expect(ph["bar.nope"]).to eql nil
55
55
  end
56
56
 
57
+ it "can be used with indifferent access from string key" do
58
+ sample = {
59
+ "foo" => 42,
60
+ }
61
+ ph = ::Unobtainium::PathedHash.new(sample)
62
+
63
+ expect(ph["foo"]).to eql 42
64
+ expect(ph[:foo]).to eql 42
65
+ end
66
+
67
+ it "can be used with indifferent access from symbol key" do
68
+ sample = {
69
+ foo: 42,
70
+ bar: {
71
+ baz: 'quux',
72
+ }
73
+ }
74
+ ph = ::Unobtainium::PathedHash.new(sample)
75
+
76
+ expect(ph["foo"]).to eql 42
77
+ expect(ph[:foo]).to eql 42
78
+
79
+ expect(ph['bar.baz']).to eql 'quux'
80
+ end
81
+
57
82
  it "treats a single separator as the root" do
58
83
  sample = { "foo" => 42 }
59
84
  ph = ::Unobtainium::PathedHash.new(sample)
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,11 @@
1
+ # Only start CodeClimate from travis
2
+ if ENV['CODECLIMATE_REPO_TOKEN']
3
+ require 'codeclimate-test-reporter'
4
+ CodeClimate::TestReporter.start
5
+ end
6
+
7
+ # Always start SimpleCov
1
8
  require 'simplecov'
2
9
  SimpleCov.start do
3
10
  add_filter 'unobtainium/drivers'
4
11
  end
5
-
6
- require "codeclimate-test-reporter"
7
- CodeClimate::TestReporter.start
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unobtainium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Finkhaeuser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-19 00:00:00.000000000 Z
11
+ date: 2016-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -185,6 +185,7 @@ files:
185
185
  - Rakefile
186
186
  - config/config.yml
187
187
  - docs/CONFIGURATION.md
188
+ - docs/DRIVERS.md
188
189
  - features/step_definitions/steps.rb
189
190
  - features/support/env.rb
190
191
  - features/world.feature