domkey 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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