fluent 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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +14 -0
- data/Gemfile +5 -0
- data/HISTORY.md +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +13 -0
- data/fluent.gemspec +32 -0
- data/lib/fluent.rb +82 -0
- data/lib/fluent/errors.rb +8 -0
- data/lib/fluent/generators.rb +155 -0
- data/lib/fluent/logger.rb +5 -0
- data/lib/fluent/platform_watir.rb +18 -0
- data/lib/fluent/platform_watir/platform_object.rb +112 -0
- data/lib/fluent/platform_watir/platform_web_elements/select_list.rb +30 -0
- data/lib/fluent/platform_watir/platform_web_elements/web_element.rb +21 -0
- data/lib/fluent/platforms.rb +31 -0
- data/lib/fluent/version.rb +3 -0
- data/lib/fluent/web_elements/button.rb +16 -0
- data/lib/fluent/web_elements/checkbox.rb +16 -0
- data/lib/fluent/web_elements/link.rb +16 -0
- data/lib/fluent/web_elements/option.rb +16 -0
- data/lib/fluent/web_elements/paragraph.rb +16 -0
- data/lib/fluent/web_elements/radio.rb +16 -0
- data/lib/fluent/web_elements/select_list.rb +20 -0
- data/lib/fluent/web_elements/text_field.rb +16 -0
- data/lib/fluent/web_elements/web_element.rb +33 -0
- data/spec/fluent_spec.rb +9 -0
- data/spec/generators/button_generators_spec.rb +77 -0
- data/spec/generators/checkbox_generators_spec.rb +88 -0
- data/spec/generators/link_generators_spec.rb +64 -0
- data/spec/generators/paragraph_generators_spec.rb +65 -0
- data/spec/generators/radio_generators_spec.rb +85 -0
- data/spec/generators/select_list_generators_spec.rb +120 -0
- data/spec/generators/text_field_generators_spec.rb +81 -0
- data/spec/generators_spec.rb +42 -0
- data/spec/mock_app.rb +14 -0
- data/spec/platform_object_spec.rb +23 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/web_element_spec.rb +23 -0
- data/spec/web_element_watir_spec.rb +32 -0
- metadata +183 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 517921e222ad7a40ccb585b10e1b951e014a8959
|
4
|
+
data.tar.gz: b4685be3d80ab1d3602f83fcbf0bfca5fde45ebd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a390c6b5f7273ea9c881a52dfb4c357f6e839afdd1988d143979a82fc3e4b3374209a221ce238180c2c6085e6535d540947c1556f64c300f2e4f8973a836a3a9
|
7
|
+
data.tar.gz: e327f85cd71bc75d8364668b3c90d6cb98fb3397057132874f5aa1534e2548d18ebab0fa25f1cbeba11a6eac23745c2df5c4209b79030dac410cdf9dc86aac60
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/HISTORY.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Change Log and History
|
2
|
+
======================
|
3
|
+
|
4
|
+
Version 0.1.0 / 2013-10-18
|
5
|
+
--------------------------
|
6
|
+
|
7
|
+
Initial development release of Fluent. At this point, the basic moving parts have been put in place in order for the framework to be usable.
|
8
|
+
|
9
|
+
Fluent ...
|
10
|
+
|
11
|
+
* ... can be included in page or activity definitions.
|
12
|
+
|
13
|
+
* ... is able to create platform objects based on a driver library.
|
14
|
+
|
15
|
+
* ... allows element definitions to be created.
|
16
|
+
|
17
|
+
* ... uses generators to create actions based on element definitions.
|
18
|
+
|
19
|
+
At this point, the only test library supported is Watir-WebDriver. The web elements that Fluent can recognize are button, checkbox, link, paragraph, radio, select_list, and text_field. The assertions that Fluent allows are url_is and title_is.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Jeff Nyman
|
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,40 @@
|
|
1
|
+
Fluent
|
2
|
+
======
|
3
|
+
|
4
|
+
[](http://travis-ci.org/jnyman/fluent)
|
5
|
+
[](https://gemnasium.com/jnyman/fluent)
|
6
|
+
[](http://badge.fury.io/rb/fluent)
|
7
|
+
[](https://coveralls.io/r/jnyman/fluent)
|
8
|
+
|
9
|
+
Fluent provides a semantic domain-specific language that can be used to construct a fluent interface for test execution libraries.
|
10
|
+
|
11
|
+
See the [Fluent wiki](https://github.com/jnyman/fluent/wiki) for details on how to use the framework.
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
Generally you will just install Fluent as a gem:
|
17
|
+
|
18
|
+
$ gem install fluent
|
19
|
+
|
20
|
+
If your application uses a Gemfile, add the following line to it:
|
21
|
+
|
22
|
+
gem 'fluent'
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Contributing
|
29
|
+
------------
|
30
|
+
|
31
|
+
1. Fork the project.
|
32
|
+
2. Create a branch for your change.
|
33
|
+
3. Make your feature additions or bug fixes in your branch.
|
34
|
+
4. Create unit tests (in spec) for your changes.
|
35
|
+
5. Create acceptance tests (in specs) for your changes.
|
36
|
+
6. Commit your changes.
|
37
|
+
7. Push to the branch.
|
38
|
+
8. Create a new [pull request](https://help.github.com/articles/using-pull-requests).
|
39
|
+
|
40
|
+
Do note that pull requests are very welcome and are considered better than bug reports. Please create a topic branch for every separate change that you make. When you make commits, do not change the rakefile, version or history information.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new do |config|
|
6
|
+
options = %w(--color)
|
7
|
+
options += %w(--format documentation)
|
8
|
+
options += %w(--format nested --out output/fluent-test-report.txt)
|
9
|
+
options += %w(--format html --out output/fluent-test-report.html)
|
10
|
+
config.rspec_opts = options
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
data/fluent.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fluent/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'fluent'
|
8
|
+
spec.version = Fluent::VERSION
|
9
|
+
spec.author = 'Jeff Nyman'
|
10
|
+
spec.email = 'jeffnyman@gmail.com'
|
11
|
+
spec.description = %q{Provides a semantic DSL to construct a fluent interface for test execution libraries.}
|
12
|
+
spec.summary = %q{A Semantically Clean Fluent Interface Test Framework}
|
13
|
+
spec.homepage = 'https://github.com/jnyman/fluent'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.platform = Gem::Platform::RUBY
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = %w(lib)
|
21
|
+
|
22
|
+
spec.required_ruby_version = '>= 1.9.3'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'rspec', '~> 2.0'
|
28
|
+
spec.add_development_dependency 'simplecov', '~> 0.7'
|
29
|
+
|
30
|
+
spec.add_runtime_dependency 'watir-webdriver', '0.6.4'
|
31
|
+
spec.add_runtime_dependency 'selenium-webdriver', '2.37.0'
|
32
|
+
end
|
data/lib/fluent.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'fluent/version'
|
2
|
+
require 'fluent/errors'
|
3
|
+
require 'fluent/logger'
|
4
|
+
require 'fluent/platforms'
|
5
|
+
require 'fluent/generators'
|
6
|
+
|
7
|
+
require 'watir-webdriver'
|
8
|
+
require 'selenium-webdriver'
|
9
|
+
|
10
|
+
module Fluent
|
11
|
+
include Platforms
|
12
|
+
|
13
|
+
# Browser drivers will be:
|
14
|
+
# [Watir::Browser] or [Selenium::WebDriver::Driver]
|
15
|
+
#
|
16
|
+
# @return [Object] browser driver reference
|
17
|
+
attr_reader :browser
|
18
|
+
|
19
|
+
# Platform references will be:
|
20
|
+
# [Fluent::Platforms::WatirWebDriver::PlatformObject]
|
21
|
+
# [Fluent::Platforms::SeleniumWebDriver::PlatformObject]
|
22
|
+
#
|
23
|
+
# @return [Object] platform reference
|
24
|
+
attr_reader :platform
|
25
|
+
|
26
|
+
def self.version
|
27
|
+
"Fluent v#{Fluent::VERSION}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# The included callback is used to provide the core functionality of the
|
31
|
+
# library to any class or module that includes the Fluent library. The
|
32
|
+
# calling class or module is extended with logic that the library makes
|
33
|
+
# available as class methods. Those classes become page definitions or
|
34
|
+
# activity definitions.
|
35
|
+
#
|
36
|
+
# @param caller [Class] the class including the library
|
37
|
+
def self.included(caller)
|
38
|
+
caller.extend Fluent::Generators
|
39
|
+
|
40
|
+
Fluent.trace("#{caller.class} #{caller} is now Fluent.")
|
41
|
+
end
|
42
|
+
|
43
|
+
# The initialize method will be invoked when a definition includes Fluent.
|
44
|
+
# A few key things are happening here that are critical to everything
|
45
|
+
# working properly:
|
46
|
+
# (1) A browser instance is being created.
|
47
|
+
# (2) A platform object is created for that browser.
|
48
|
+
#
|
49
|
+
# @param browser [Object] a browser instance with a tool driver
|
50
|
+
def initialize(browser=nil)
|
51
|
+
@browser = browser
|
52
|
+
@browser = Watir::Browser.new if browser.nil? or browser == :watir
|
53
|
+
@browser = Selenium::WebDriver.for :firefox if browser == :selenium
|
54
|
+
|
55
|
+
Fluent::trace("Fluent attached to browser: #{@browser}")
|
56
|
+
|
57
|
+
establish_platform_object_for @browser
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.can_be_enabled
|
61
|
+
@can_be_enabled ||= [:button, :text_field, :checkbox, :select_list, :radio]
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.can_be_enabled?(method)
|
65
|
+
can_be_enabled.include? method.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# This method is crucial in that it sets up the platform instance that
|
71
|
+
# will be used by just about every module that makes calls to any
|
72
|
+
# platform-specific functionality.
|
73
|
+
#
|
74
|
+
# @param browser [Object] a browser instance with a tool driver
|
75
|
+
# @return [Object] a platform object to execute tests against
|
76
|
+
def establish_platform_object_for(browser)
|
77
|
+
@platform = get_platform_for browser
|
78
|
+
|
79
|
+
Fluent::trace("Fluent platform object: #{@platform}")
|
80
|
+
@platform
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Fluent
|
2
|
+
module Generators
|
3
|
+
|
4
|
+
def url_is(url=nil)
|
5
|
+
msg = "The url_is assertion is empty on the definition #{self}."
|
6
|
+
raise Fluent::Errors::NoUrlForDefinition, msg if url.nil?
|
7
|
+
|
8
|
+
define_method('view') do
|
9
|
+
platform.visit(url)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def title_is(title=nil)
|
14
|
+
msg = "The title_is assertion is empty on the definition #{self}."
|
15
|
+
raise Fluent::Errors::NoTitleForDefinition, msg if title.nil?
|
16
|
+
|
17
|
+
define_method('check_title') do
|
18
|
+
msg = "Expected title: '#{title}'; Actual title: '#{browser.title}'"
|
19
|
+
valid_title = title == browser.title if title.kind_of?(String)
|
20
|
+
valid_title = title =~ browser.title if title.kind_of?(Regexp)
|
21
|
+
raise Fluent::Errors::TitleNotMatched, msg unless valid_title
|
22
|
+
valid_title
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def link(identifier, locator)
|
27
|
+
define_method(identifier) do
|
28
|
+
return platform.link_click(locator)
|
29
|
+
end
|
30
|
+
|
31
|
+
common_definition_methods(identifier, locator, __method__)
|
32
|
+
end
|
33
|
+
|
34
|
+
def paragraph(identifier, locator)
|
35
|
+
define_method(identifier) do
|
36
|
+
return platform.paragraph_text(locator)
|
37
|
+
end
|
38
|
+
|
39
|
+
common_definition_methods(identifier, locator, __method__)
|
40
|
+
end
|
41
|
+
|
42
|
+
def button(identifier, locator)
|
43
|
+
define_method(identifier) do
|
44
|
+
return platform.button_click(locator)
|
45
|
+
end
|
46
|
+
|
47
|
+
common_definition_methods(identifier, locator, __method__)
|
48
|
+
end
|
49
|
+
|
50
|
+
def text_field(identifier, locator)
|
51
|
+
define_method(identifier) do
|
52
|
+
return platform.text_field_get(locator)
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method("#{identifier}=") do |value|
|
56
|
+
return platform.text_field_set(locator, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
common_definition_methods(identifier, locator, __method__)
|
60
|
+
end
|
61
|
+
|
62
|
+
def checkbox(identifier, locator)
|
63
|
+
define_method("#{identifier}_checked?") do
|
64
|
+
return platform.checkbox_check_state(locator)
|
65
|
+
end
|
66
|
+
|
67
|
+
define_method("check_#{identifier}") do
|
68
|
+
return platform.checkbox_check(locator)
|
69
|
+
end
|
70
|
+
|
71
|
+
define_method("uncheck_#{identifier}") do
|
72
|
+
return platform.checkbox_uncheck(locator)
|
73
|
+
end
|
74
|
+
|
75
|
+
common_definition_methods(identifier, locator, __method__)
|
76
|
+
end
|
77
|
+
|
78
|
+
def select_list(identifier, locator)
|
79
|
+
define_method(identifier) do
|
80
|
+
return platform.select_list_get_selected(locator)
|
81
|
+
end
|
82
|
+
|
83
|
+
alias_method "#{identifier}_option?".to_sym, "#{identifier}".to_sym
|
84
|
+
|
85
|
+
define_method("#{identifier}=") do |value|
|
86
|
+
return platform.select_list_set(locator, value)
|
87
|
+
end
|
88
|
+
|
89
|
+
define_method("#{identifier}_options?") do
|
90
|
+
web_object = self.send("#{identifier}_object")
|
91
|
+
(web_object && web_object.options) ? web_object.options.collect(&:text) : []
|
92
|
+
end
|
93
|
+
|
94
|
+
define_method("#{identifier}_value?") do
|
95
|
+
return platform.select_list_get_value(locator)
|
96
|
+
end
|
97
|
+
|
98
|
+
common_definition_methods(identifier, locator, __method__)
|
99
|
+
end
|
100
|
+
|
101
|
+
def radio(identifier, locator)
|
102
|
+
define_method("select_#{identifier}") do
|
103
|
+
return platform.radio_select(locator)
|
104
|
+
end
|
105
|
+
|
106
|
+
define_method("#{identifier}_selected?") do
|
107
|
+
return platform.radio_check_state(locator)
|
108
|
+
end
|
109
|
+
|
110
|
+
alias_method "#{identifier}_set?".to_sym, "#{identifier}_selected?".to_sym
|
111
|
+
alias_method "set_#{identifier}".to_sym, "select_#{identifier}".to_sym
|
112
|
+
|
113
|
+
common_definition_methods(identifier, locator, __method__)
|
114
|
+
end
|
115
|
+
|
116
|
+
alias_method :radio_button, :radio
|
117
|
+
|
118
|
+
def common_definition_methods(identifier, locator, method)
|
119
|
+
define_method("#{identifier}_object") do
|
120
|
+
platform.send(method, locator)
|
121
|
+
end
|
122
|
+
|
123
|
+
define_method("#{identifier}_exists?") do
|
124
|
+
platform.send(method, locator).exists?
|
125
|
+
end
|
126
|
+
|
127
|
+
define_method("#{identifier}_visible?") do
|
128
|
+
platform.send(method, locator).visible?
|
129
|
+
end
|
130
|
+
|
131
|
+
alias_method "#{identifier}_#{method}".to_sym, "#{identifier}_object".to_sym
|
132
|
+
alias_method "#{identifier}_element".to_sym, "#{identifier}_object".to_sym
|
133
|
+
|
134
|
+
alias_method "#{identifier}?".to_sym, "#{identifier}_exists?".to_sym
|
135
|
+
alias_method "#{identifier}_?".to_sym, "#{identifier}_visible?".to_sym
|
136
|
+
|
137
|
+
alias_method "#{identifier}_#{method}_exists?".to_sym, "#{identifier}_exists?".to_sym
|
138
|
+
alias_method "#{identifier}_#{method}_visible?".to_sym, "#{identifier}_visible?".to_sym
|
139
|
+
|
140
|
+
alias_method "#{identifier}_#{method}?".to_sym, "#{identifier}_exists?".to_sym
|
141
|
+
alias_method "#{identifier}_#{method}_?".to_sym, "#{identifier}_visible?".to_sym
|
142
|
+
|
143
|
+
if Fluent.can_be_enabled?(method)
|
144
|
+
define_method("#{identifier}_enabled?") do
|
145
|
+
platform.send(method, locator).enabled?
|
146
|
+
end
|
147
|
+
|
148
|
+
alias_method "#{identifier}!".to_sym, "#{identifier}_enabled?".to_sym
|
149
|
+
alias_method "#{identifier}_#{method}_enabled?".to_sym, "#{identifier}_enabled?".to_sym
|
150
|
+
alias_method "#{identifier}_#{method}!".to_sym, "#{identifier}_exists?".to_sym
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Fluent
|
2
|
+
module Platforms
|
3
|
+
module WatirWebDriver
|
4
|
+
|
5
|
+
def self.create_platform_object_for(browser)
|
6
|
+
require 'fluent/platform_watir/platform_object'
|
7
|
+
return WatirWebDriver::PlatformObject.new(browser)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.works_with?(browser)
|
11
|
+
browser.is_a?(::Watir::Browser)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Fluent::Platforms.register(:watir_webdriver, Fluent::Platforms::WatirWebDriver)
|