domkey 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4e084e3b9ec1fd8d799b054c5c7621ff614cbe25
4
+ data.tar.gz: cc50953f3c169a28d21346e076681fb7e3dcc099
5
+ SHA512:
6
+ metadata.gz: 708a161af1039a64b5beed49e5b8b3ea354387624ceae4fa810f9c52993aa21fb41b493778f6bd816a75a751a55ba060d2b86c4d743ff75fbdd58e4dece13aa8
7
+ data.tar.gz: 49e6a0ff0391b95355d136dcc44d9fae71acf7413829ea52cf3e0008d16a11de06d002a714071558b0f31a22bfe487a1f11289523e928f3f600c06238c70d095
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in domkey.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 rubytester
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.
@@ -0,0 +1,37 @@
1
+ # Domain Specifc PageObject for Selenium Watir-Webdriver
2
+
3
+ PageObject that models business domain first and browser code second.
4
+
5
+ Watir-Webdriver is the Bee's Knees! Now with Domain Specific PageObject Factory!
6
+
7
+ Watir-Webdriver is the Bee's Knees! Now with Domain Specific PageObject Factory!
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'domkey'
14
+
15
+ or this line to use gem directly from github
16
+
17
+ gem 'domkey', git: "git://github.com/rubytester/domkey.git"
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it from rubygems.org as:
24
+
25
+ $ gem install domkey
26
+
27
+ ## Usage
28
+
29
+ TODO: Write usage instructions here
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it ( http://github.com/<my-github-username>/domkey/fork )
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ # kill browsers dude
9
+ task :pkill do
10
+ `pkill -f firefox`
11
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'domkey/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'domkey'
8
+ spec.version = Domkey::VERSION
9
+ spec.authors = ["rubytester", "marekj"]
10
+ spec.email = ["github@rubytester.com"]
11
+ spec.summary = %q{Domain Specifc PageObject for Selenium Watir-Webdriver}
12
+ spec.description = %q{Domain Specifc PageObject for Selenium Watir-Webdriver. PageObject that models business domain first and browser code second}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '~> 2.0'
22
+
23
+ spec.add_dependency 'watir-webdriver', '~> 0.6.4'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.5'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 2.14'
28
+ spec.add_development_dependency 'simplecov'
29
+
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'domkey/version'
2
+ require 'watir-webdriver'
3
+ require 'domkey/browser_session'
4
+ require 'domkey/view'
5
+ require 'domkey/exception'
6
+
7
+ module Domkey
8
+
9
+ # current browser for testing session
10
+ def self.browser
11
+ BrowserSession.instance.browser
12
+ end
13
+
14
+ # sets current browser for testing session
15
+ def self.browser=(b)
16
+ BrowserSession.instance.browser=b
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'singleton'
2
+
3
+ module Domkey
4
+
5
+ class BrowserSession
6
+ include Singleton
7
+ attr_accessor :browser
8
+
9
+ def browser
10
+ return @browser if (@browser && @browser.exist?)
11
+ @browser = Watir::Browser.new
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ module Domkey
2
+ module Exception
3
+ class Error < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Domkey
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,39 @@
1
+ require 'domkey/view/page_object'
2
+ require 'domkey/view/page_object_collection'
3
+ module Domkey
4
+
5
+ module View
6
+
7
+ module ClassMethods
8
+
9
+ # PageObjectCollection factory
10
+ def doms(key, &watirproc)
11
+ send :define_method, key do
12
+ PageObjectCollection.new watirproc, Proc.new { browser }
13
+ end
14
+ end
15
+
16
+ # PageObject factory
17
+ def dom(key, &watirproc)
18
+ send :define_method, key do
19
+ PageObject.new watirproc, Proc.new { browser }
20
+ end
21
+ end
22
+ end
23
+
24
+ def self.included(klass)
25
+ klass.extend(ClassMethods)
26
+ end
27
+
28
+ attr_accessor :browser
29
+
30
+ def initialize browser=nil
31
+ @browser = browser
32
+ end
33
+
34
+ def browser
35
+ @browser ||= Domkey.browser
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,120 @@
1
+ module Domkey
2
+
3
+ module View
4
+
5
+ class PageObject
6
+
7
+ attr_accessor :watirproc, :container
8
+
9
+ # PageObject represents an semantically essential area in a View
10
+ # It is an object that responds to set and value as the main way of sending data to it.
11
+ # it is composed of one or more watir elements.
12
+ # PageObject encapuslates the widgetry of DOM elements to provide semantic interfact to the user of the widgetry
13
+ #
14
+ # Compose PageObject with watirproc and container
15
+ #
16
+ # What is a container? it's a proc, a callable object that plays a role of a container for watirproc widgetry
17
+ # container can be one of:
18
+ # - browser (default)
19
+ # - a pageobject
20
+ #
21
+ # What is watirproc? it's a proc of DOM elements widgetry that can be found inside the container
22
+ # watirproc can be one of the following:
23
+ # - definition of single watir element i.e. `-> { text_field(:id, 'foo')}`
24
+ # - a pageobject i.e. previously instantiated definition
25
+ # - hash where key defines subelement and value a definition or pageobject
26
+ #
27
+ # Usage:
28
+ # Clients would not usually instantate this class.
29
+ # A client class which acts as a View would use a :dom factory method to create PageObjects
30
+ # Example:
31
+ #
32
+ # class MyView
33
+ # include Domkey::View
34
+ #
35
+ # dom(:headline) { text_field(id:, 'some_desc_text') }
36
+ #
37
+ # def property
38
+ # PropertyPanel.new browser.div(id: 'container')
39
+ # end
40
+ # end
41
+ #
42
+ # class PropertyPanel
43
+ # include Domkey::View
44
+ # dom(:headline) { text_field(class: 'headline_for_house') }
45
+ # end
46
+ #
47
+ # view = MyView.new
48
+ # view.headline.set 'HomeAway Rules!'
49
+ # view.value #=> returns 'HomeAway Rules!'
50
+ # view.property.headline.set 'Awesome Vactaion Home'
51
+ # view.property.headline.value #=> returns 'Awesome Vaction Home'
52
+ #
53
+ def initialize watirproc, container=lambda { Domkey.browser }
54
+ @container = container
55
+ @watirproc = initialize_this watirproc
56
+ end
57
+
58
+ def set value
59
+ return instantiator.set(value) unless value.respond_to?(:each_pair)
60
+ value.each_pair { |k, v| watirproc.fetch(k).set(v) }
61
+ end
62
+
63
+ def value
64
+ return instantiator.value unless watirproc.respond_to?(:each_pair)
65
+ Hash[watirproc.map { |key, pageobject| [key, pageobject.value] }]
66
+ end
67
+
68
+ # access widgetry of watir elements composing this page object
69
+ def element(key=false)
70
+ return instantiator unless watirproc.respond_to?(:each_pair)
71
+ return watirproc.fetch(key).element if key
72
+ Hash[watirproc.map { |key, watirproc| [key, watirproc.element] }]
73
+ end
74
+
75
+ private
76
+
77
+ # recursive
78
+ def initialize_this watirproc
79
+ if watirproc.respond_to?(:each_pair) #hash
80
+ Hash[watirproc.map { |key, watirproc| [key, PageObject.new(watirproc, container)] }]
81
+ else
82
+ if watirproc.respond_to?(:call) #proc
83
+ begin
84
+ # peek inside suitcase that is proc. XXX ouch, ugly
85
+ peeked_inside = watirproc.call
86
+ rescue NoMethodError
87
+ return watirproc #suitecase exploded, proc returned
88
+ end
89
+ if peeked_inside.respond_to?(:each_pair) # hash
90
+ return initialize_this peeked_inside
91
+ elsif peeked_inside.respond_to?(:wd) # watir element
92
+ return lambda { peeked_inside }
93
+ elsif peeked_inside.respond_to?(:watirproc) #pageobject
94
+ return peeked_inside.watirproc
95
+ else
96
+ fail Exception::Error, "watirproc must be kind of hash, watirelement or pageobject but I got this: #{watirproc}"
97
+ end
98
+ elsif watirproc.respond_to?(:watirproc) #pageobject
99
+ return watirproc.watirproc
100
+ else
101
+ fail Exception::Error, "watirproc must be kind of hash, watirelement or pageobject but I got this: #{watirproc}"
102
+ end
103
+ end
104
+ end
105
+
106
+ # talk to the browser executor.
107
+ # returns runtime element in a specified container
108
+ # expects that element to respond to set and value
109
+ def instantiator
110
+ container_instantiator.instance_exec(&watirproc)
111
+ end
112
+
113
+ # talk to the browser
114
+ # returns runtime container element in a browser/driver
115
+ def container_instantiator
116
+ container.respond_to?(:call) ? container.call : container.send(:instantiator)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,78 @@
1
+ module Domkey
2
+
3
+ module View
4
+
5
+ class PageObjectCollection
6
+ include Enumerable
7
+
8
+ attr_accessor :watirproc, :container
9
+
10
+ # PageObjectCollection see PageObject for detailes.
11
+ # Compose PageObjectCollection with watirproc and container
12
+ #
13
+ # What is a container? see PageObject container
14
+ #
15
+ # What is watirproc? see PageObject watirproc except the following:
16
+ # watirproc can be one of the following:
17
+ # - definition of watir elements collection i.e. `-> { text_fields(:class, /^foo/)}`
18
+ # - a pageobject i.e. previously instantiated definition watir elements collection
19
+ # - hash where key defines subelement and value a definition or pageobject
20
+ # Usage:
21
+ # Clients would not usually instantate this class.
22
+ # A client class which acts as a View would use a :doms factory method to create PageObjectCollection
23
+ # Example:
24
+ #
25
+ def initialize watirproc, container=lambda { Domkey.browser }
26
+ @container = container
27
+ @watirproc = initialize_this watirproc
28
+ end
29
+
30
+ def element(key=false)
31
+ return instantiator unless watirproc.respond_to?(:each_pair)
32
+ return watirproc.fetch(key).element if key
33
+ Hash[watirproc.map { |key, watirproc| [key, watirproc.element] }]
34
+ end
35
+
36
+ def each(&blk)
37
+ if watirproc.respond_to?(:each_pair)
38
+ watirproc.map { |k, v| [k, PageObjectCollection.new(lambda { v }, @container)] }.each { |k, v| yield Hash[k, v] }
39
+ else
40
+ instantiator.each { |e| yield PageObject.new(lambda { e }, @container) }
41
+ end
42
+ end
43
+
44
+ def [] idx
45
+ to_a[idx]
46
+ end
47
+
48
+ alias_method :size, :count
49
+
50
+ private
51
+
52
+ # --
53
+ # recursive
54
+ def initialize_this watirproc
55
+ if watirproc.respond_to?(:each_pair) #hash
56
+ Hash[watirproc.map { |key, watirproc| [key, PageObjectCollection.new(watirproc, container)] }]
57
+ else
58
+ if watirproc.respond_to?(:call) #proc
59
+ watirproc
60
+ elsif watirproc.respond_to?(:watirproc)
61
+ watirproc.watirproc
62
+ else
63
+ fail Exception::Error, "watirproc must be kind of hash, watirelement or pageobject but I got this: #{watirproc}"
64
+ end
65
+ end
66
+ end
67
+
68
+ def instantiator
69
+ container_at_runtime.instance_exec(&watirproc)
70
+ end
71
+
72
+ def container_at_runtime
73
+ container.respond_to?(:call) ? container.call : container.send(:instantiator)
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Domkey::BrowserSession do
4
+
5
+ context 'when no browsers present in the system' do
6
+
7
+ it 'browser gives us default browser' do
8
+ #ugly setup with singleton
9
+ Domkey::BrowserSession.instance.browser.close
10
+ Domkey::browser=nil
11
+
12
+ fakebrowser = double('browser')
13
+ fakebrowser.stub(:exist?).and_return(true)
14
+ Watir::Browser.should_receive(:new).once.and_return(fakebrowser)
15
+ b = Domkey.browser
16
+ b.should eq fakebrowser
17
+ b2 = Domkey.browser
18
+ b.should eql b2
19
+ Domkey::BrowserSession.instance.browser=nil
20
+ end
21
+
22
+ end
23
+ end