lapis_lazuli 0.6.1
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 +18 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +30 -0
- data/README.md +74 -0
- data/Rakefile +1 -0
- data/bin/lapis_lazuli +3 -0
- data/lapis_lazuli.gemspec +32 -0
- data/lib/lapis_lazuli/api.rb +52 -0
- data/lib/lapis_lazuli/argparse.rb +128 -0
- data/lib/lapis_lazuli/ast.rb +160 -0
- data/lib/lapis_lazuli/browser/error.rb +93 -0
- data/lib/lapis_lazuli/browser/find.rb +500 -0
- data/lib/lapis_lazuli/browser/interaction.rb +91 -0
- data/lib/lapis_lazuli/browser/screenshots.rb +70 -0
- data/lib/lapis_lazuli/browser/wait.rb +158 -0
- data/lib/lapis_lazuli/browser.rb +246 -0
- data/lib/lapis_lazuli/cli.rb +110 -0
- data/lib/lapis_lazuli/cucumber.rb +25 -0
- data/lib/lapis_lazuli/generators/cucumber/template/.gitignore +6 -0
- data/lib/lapis_lazuli/generators/cucumber/template/Gemfile +37 -0
- data/lib/lapis_lazuli/generators/cucumber/template/README.md +27 -0
- data/lib/lapis_lazuli/generators/cucumber/template/config/config.yml +29 -0
- data/lib/lapis_lazuli/generators/cucumber/template/config/cucumber.yml +34 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/example.feature +11 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/interaction_steps.rb +20 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/validation_steps.rb +21 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/support/env.rb +12 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/support/transition.rb +12 -0
- data/lib/lapis_lazuli/generators/cucumber.rb +128 -0
- data/lib/lapis_lazuli/generic/xpath.rb +49 -0
- data/lib/lapis_lazuli/options.rb +28 -0
- data/lib/lapis_lazuli/placeholders.rb +36 -0
- data/lib/lapis_lazuli/proxy.rb +179 -0
- data/lib/lapis_lazuli/runtime.rb +88 -0
- data/lib/lapis_lazuli/scenario.rb +88 -0
- data/lib/lapis_lazuli/storage.rb +59 -0
- data/lib/lapis_lazuli/version.rb +10 -0
- data/lib/lapis_lazuli/versions.rb +40 -0
- data/lib/lapis_lazuli/world/annotate.rb +45 -0
- data/lib/lapis_lazuli/world/api.rb +35 -0
- data/lib/lapis_lazuli/world/browser.rb +75 -0
- data/lib/lapis_lazuli/world/config.rb +292 -0
- data/lib/lapis_lazuli/world/error.rb +141 -0
- data/lib/lapis_lazuli/world/hooks.rb +109 -0
- data/lib/lapis_lazuli/world/logging.rb +53 -0
- data/lib/lapis_lazuli/world/proxy.rb +59 -0
- data/lib/lapis_lazuli/world/variable.rb +139 -0
- data/lib/lapis_lazuli.rb +75 -0
- data/test/.gitignore +8 -0
- data/test/Gemfile +42 -0
- data/test/README.md +35 -0
- data/test/config/config.yml +37 -0
- data/test/config/cucumber.yml +37 -0
- data/test/features/annotation.feature +23 -0
- data/test/features/browser.feature +10 -0
- data/test/features/button.feature +38 -0
- data/test/features/click.feature +35 -0
- data/test/features/error.feature +30 -0
- data/test/features/find.feature +92 -0
- data/test/features/har.feature +9 -0
- data/test/features/modules.feature +14 -0
- data/test/features/step_definitions/interaction_steps.rb +154 -0
- data/test/features/step_definitions/validation_steps.rb +350 -0
- data/test/features/support/env.rb +21 -0
- data/test/features/text_field.feature +32 -0
- data/test/features/timing.feature +47 -0
- data/test/features/variable.feature +11 -0
- data/test/features/xpath.feature +41 -0
- data/test/server/start.rb +17 -0
- data/test/server/www/button.html +22 -0
- data/test/server/www/error_html.html +9 -0
- data/test/server/www/find.html +66 -0
- data/test/server/www/javascript_error.html +12 -0
- data/test/server/www/text_fields.html +15 -0
- data/test/server/www/timing.html +32 -0
- data/test/server/www/xpath.html +22 -0
- metadata +295 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
#
|
2
|
+
# LapisLazuli
|
3
|
+
# https://github.com/spriteCloud/lapis-lazuli
|
4
|
+
#
|
5
|
+
# Copyright (c) 2013-2014 spriteCloud B.V. and other LapisLazuli contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
module LapisLazuli
|
10
|
+
module WorldModule
|
11
|
+
##
|
12
|
+
# Module with cucumber hooks
|
13
|
+
#
|
14
|
+
# The module is special in that it does not include other modules. Instead it
|
15
|
+
# always tests whether World responds to a function before calling it.
|
16
|
+
module Hooks
|
17
|
+
##
|
18
|
+
# Add hooks to one of the four queues :before, :after, :start or :end.
|
19
|
+
HOOK_QUEUES = [
|
20
|
+
:before,
|
21
|
+
:after,
|
22
|
+
:start,
|
23
|
+
# :end # FIXME hard to implement. See issue #13
|
24
|
+
]
|
25
|
+
def self.add_hook(queue, hook)
|
26
|
+
if not HOOK_QUEUES.include?(queue)
|
27
|
+
raise "Invalid hook queue #{queue}"
|
28
|
+
end
|
29
|
+
|
30
|
+
@@hooks ||= {}
|
31
|
+
@@hooks[queue] ||= []
|
32
|
+
@@hooks[queue] << hook
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Hook invoked in BeforeScenario
|
37
|
+
def before_scenario_hook(cuke_scenario)
|
38
|
+
# Update the scenario informaton
|
39
|
+
if respond_to? :scenario
|
40
|
+
scenario.running = true
|
41
|
+
scenario.update(cuke_scenario)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Show the name
|
45
|
+
if respond_to? :log
|
46
|
+
log.info("Starting Scenario: #{scenario.id}")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Run 'start' queue once.
|
50
|
+
@@started ||= false
|
51
|
+
if not @@started
|
52
|
+
@@started = true
|
53
|
+
run_queue(:start, cuke_scenario)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Run 'before' queue
|
57
|
+
run_queue(:before, cuke_scenario)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Hook invoked in AfterScenario
|
62
|
+
def after_scenario_hook(cuke_scenario)
|
63
|
+
# Run 'after' queue
|
64
|
+
run_queue(:after, cuke_scenario)
|
65
|
+
|
66
|
+
# Run 'end' queue
|
67
|
+
# FIXME hard to implement; see issue #13
|
68
|
+
|
69
|
+
# The current scenario has finished
|
70
|
+
if respond_to? :scenario
|
71
|
+
scenario.running = false
|
72
|
+
end
|
73
|
+
|
74
|
+
# Sleep if needed
|
75
|
+
if respond_to? :config and has_env_or_config?("step_pause_time")
|
76
|
+
sleep env_or_config("step_pause_time")
|
77
|
+
end
|
78
|
+
|
79
|
+
# Did we fail?
|
80
|
+
if respond_to? :scenario and respond_to? :browser and respond_to? :config
|
81
|
+
if (cuke_scenario.failed? or (scenario.check_browser_errors and browser.has_error?))
|
82
|
+
# Take a screenshot if needed
|
83
|
+
if has_env_or_config?('screenshot_on_failure')
|
84
|
+
fileloc = browser.take_screenshot()
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Close browser if needed
|
90
|
+
if respond_to? :browser
|
91
|
+
browser.close_after_scenario(cuke_scenario)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
def run_queue(queue, cuke_scenario)
|
97
|
+
@@hooks ||= {}
|
98
|
+
|
99
|
+
if @@hooks[queue].nil?
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
103
|
+
@@hooks[queue].each do |hook|
|
104
|
+
self.instance_exec(cuke_scenario, &hook)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end # module Hooks
|
108
|
+
end # module WorldModule
|
109
|
+
end # module LapisLazuli
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# LapisLazuli
|
3
|
+
# https://github.com/spriteCloud/lapis-lazuli
|
4
|
+
#
|
5
|
+
# Copyright (c) 2013-2014 spriteCloud B.V. and other LapisLazuli contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "teelogger"
|
10
|
+
|
11
|
+
require "lapis_lazuli/runtime"
|
12
|
+
|
13
|
+
require "lapis_lazuli/world/config"
|
14
|
+
|
15
|
+
module LapisLazuli
|
16
|
+
module WorldModule
|
17
|
+
##
|
18
|
+
# Module for easy logging
|
19
|
+
#
|
20
|
+
# Manages the following:
|
21
|
+
# @log - TeeLogger instances
|
22
|
+
module Logging
|
23
|
+
include LapisLazuli::WorldModule::Config
|
24
|
+
|
25
|
+
##
|
26
|
+
# Log "singleton"
|
27
|
+
def log
|
28
|
+
return Runtime.instance.set_if(self, :logger) do
|
29
|
+
# Make log directory
|
30
|
+
dir = env_or_config('log_dir')
|
31
|
+
begin
|
32
|
+
Dir.mkdir dir
|
33
|
+
rescue SystemCallError => ex
|
34
|
+
# Swallow this error; it occurs (amongst other situations) when the
|
35
|
+
# directory exists. Checking for an existing directory beforehand is
|
36
|
+
# not concurrency safe.
|
37
|
+
end
|
38
|
+
|
39
|
+
# Start the logger with the config filename
|
40
|
+
log_file = "#{dir}#{File::SEPARATOR}#{File.basename(Config.config_file, ".*")}.log"
|
41
|
+
# Or a filename from the environment
|
42
|
+
if has_env_or_config?("log_file")
|
43
|
+
log_file = env_or_config("log_file")
|
44
|
+
end
|
45
|
+
l = TeeLogger::TeeLogger.new(STDOUT, log_file)
|
46
|
+
l.level = env_or_config("log_level")
|
47
|
+
|
48
|
+
l
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end # module Logging
|
52
|
+
end # module WorldModule
|
53
|
+
end # module LapisLazuli
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#
|
2
|
+
# LapisLazuli
|
3
|
+
# https://github.com/spriteCloud/lapis-lazuli
|
4
|
+
#
|
5
|
+
# Copyright (c) 2013-2014 spriteCloud B.V. and other LapisLazuli contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "lapis_lazuli/proxy"
|
10
|
+
require "lapis_lazuli/runtime"
|
11
|
+
|
12
|
+
require "lapis_lazuli/world/config"
|
13
|
+
require "lapis_lazuli/world/logging"
|
14
|
+
|
15
|
+
module LapisLazuli
|
16
|
+
module WorldModule
|
17
|
+
##
|
18
|
+
# Module managing a proxy instance
|
19
|
+
module Proxy
|
20
|
+
include LapisLazuli::WorldModule::Config
|
21
|
+
include LapisLazuli::WorldModule::Logging
|
22
|
+
|
23
|
+
##
|
24
|
+
# Checks if there is a proxy started
|
25
|
+
def has_proxy?
|
26
|
+
p = Runtime.instance.get :proxy
|
27
|
+
return !p.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Get the current proxy
|
32
|
+
def proxy
|
33
|
+
return Runtime.instance.set_if(self, :proxy) do
|
34
|
+
# Check if we can start a proxy
|
35
|
+
begin
|
36
|
+
# Default proxy settings
|
37
|
+
proxy_ip = "localhost"
|
38
|
+
proxy_port = 10000
|
39
|
+
proxy_master = true
|
40
|
+
|
41
|
+
# Do we have a config?
|
42
|
+
if has_env_or_config?("proxy.ip") and has_env_or_config?("proxy.port")
|
43
|
+
proxy_ip = env_or_config("proxy.ip")
|
44
|
+
proxy_port = env_or_config("proxy.port")
|
45
|
+
proxy_master = env_or_config("proxy.spritecloud", true)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Try to start the proxy
|
49
|
+
p = LapisLazuli::Proxy.new(proxy_ip, proxy_port, proxy_master)
|
50
|
+
|
51
|
+
log.debug("Found proxy: #{proxy_ip}:#{proxy_port}, spritecloud: #{proxy_master}")
|
52
|
+
rescue StandardError => err
|
53
|
+
log.debug("No proxy available: #{err}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end # module Proxy
|
58
|
+
end # module WorldModule
|
59
|
+
end # module LapisLazuli
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#
|
2
|
+
# LapisLazuli
|
3
|
+
# https://github.com/spriteCloud/lapis-lazuli
|
4
|
+
#
|
5
|
+
# Copyright (c) 2013-2014 spriteCloud B.V. and other LapisLazuli contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "securerandom"
|
10
|
+
require 'json'
|
11
|
+
|
12
|
+
require "lapis_lazuli/scenario"
|
13
|
+
require "lapis_lazuli/versions"
|
14
|
+
require "lapis_lazuli/runtime"
|
15
|
+
require "lapis_lazuli/placeholders"
|
16
|
+
|
17
|
+
require "lapis_lazuli/world/config"
|
18
|
+
|
19
|
+
module LapisLazuli
|
20
|
+
module WorldModule
|
21
|
+
##
|
22
|
+
# Module for variable replacement
|
23
|
+
#
|
24
|
+
# Manages the following:
|
25
|
+
# scenario - for per-scenario variables
|
26
|
+
# uuid - for the entire test run
|
27
|
+
# time - for the entire test run
|
28
|
+
# storage - for the entire test run
|
29
|
+
# versions - versions as gathered by e.g. fetch_versions
|
30
|
+
module Variable
|
31
|
+
include LapisLazuli::WorldModule::Config
|
32
|
+
|
33
|
+
##
|
34
|
+
# Scenario "singleton"
|
35
|
+
def scenario
|
36
|
+
return data(:scenario) do
|
37
|
+
Scenario.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Time "singleton"
|
43
|
+
def time
|
44
|
+
return data(:time) do
|
45
|
+
time = Time.now
|
46
|
+
@time = {
|
47
|
+
:timestamp => time.strftime('%y%m%d_%H%M%S'),
|
48
|
+
:iso_timestamp => time.utc.strftime("%FT%TZ"),
|
49
|
+
:iso_short => time.utc.strftime("%y%m%dT%H%M%SZ"),
|
50
|
+
:epoch => time.to_i.to_s
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# UUID "singleton"
|
57
|
+
def uuid
|
58
|
+
return data(:uuid) do
|
59
|
+
SecureRandom.hex
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Storage "singleton"
|
65
|
+
def has_storage?
|
66
|
+
b = Runtime.instance.get :variable_data
|
67
|
+
return !b[:storage].nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
def storage
|
71
|
+
return data(:storage) do
|
72
|
+
storage = Storage.new
|
73
|
+
storage.set("time", time)
|
74
|
+
storage.set("uuid", uuid)
|
75
|
+
|
76
|
+
storage
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
##
|
82
|
+
# Update the variable with timestamps
|
83
|
+
def variable(string)
|
84
|
+
init
|
85
|
+
|
86
|
+
email_domain = "spriteymail.net"
|
87
|
+
if has_env_or_config?("email_domain")
|
88
|
+
email_domain = env_or_config("email_domain")
|
89
|
+
end
|
90
|
+
random_uuid = SecureRandom.hex
|
91
|
+
|
92
|
+
# Prepare current values.
|
93
|
+
values = {}
|
94
|
+
LapisLazuli::PLACEHOLDERS.each do |placeholder, value|
|
95
|
+
values[placeholder] = eval value[0]
|
96
|
+
end
|
97
|
+
|
98
|
+
return string % values
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Same as variable, but modify the string.
|
103
|
+
def variable!(string)
|
104
|
+
string.replace(variable(string))
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def data(name, &block)
|
110
|
+
d = Runtime.instance.get :variable_data
|
111
|
+
if not d.nil?
|
112
|
+
if not d.is_a? Hash
|
113
|
+
raise "Expect a hash for variables managed by the Variable module"
|
114
|
+
end
|
115
|
+
else
|
116
|
+
d = {}
|
117
|
+
end
|
118
|
+
|
119
|
+
if not d.has_key? name
|
120
|
+
value = block.call()
|
121
|
+
d[name] = value
|
122
|
+
|
123
|
+
Runtime.instance.set(self, :variable_data, d, Variable.destroy(self))
|
124
|
+
end
|
125
|
+
|
126
|
+
return d[name]
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def self.destroy(world)
|
131
|
+
Proc.new do |w|
|
132
|
+
if world.has_storage?
|
133
|
+
world.storage.destroy(world)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end # module Variable
|
138
|
+
end # module WorldModule
|
139
|
+
end # module LapisLazuli
|
data/lib/lapis_lazuli.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#
|
2
|
+
# LapisLazuli
|
3
|
+
# https://github.com/spriteCloud/lapis-lazuli
|
4
|
+
#
|
5
|
+
# Copyright (c) 2013-2014 spriteCloud B.V. and other LapisLazuli contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
begin
|
10
|
+
require "simplecov"
|
11
|
+
require "rubygems"
|
12
|
+
spec = Gem::Specification.find_by_name("lapis_lazuli")
|
13
|
+
gem_root = "#{spec.gem_dir}#{File::SEPARATOR}"
|
14
|
+
coverage_root = "#{gem_root}lib"
|
15
|
+
output_dir = "#{Dir.getwd}#{File::SEPARATOR}coverage"
|
16
|
+
template_dir = "#{coverage_root}lib#{File::SEPARATOR}lapis_lazuli#{File::SEPARATOR}generators#{File::SEPARATOR}cucumber"
|
17
|
+
|
18
|
+
if ENV['COVERAGE']
|
19
|
+
puts "Enabling code coverage for files under '#{coverage_root}';"
|
20
|
+
puts "coverage reports get written to '#{output_dir}'."
|
21
|
+
SimpleCov.start do
|
22
|
+
root(coverage_root)
|
23
|
+
coverage_dir(output_dir)
|
24
|
+
add_filter(template_dir)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
rescue LoadError
|
28
|
+
# do nothing
|
29
|
+
end
|
30
|
+
|
31
|
+
require "lapis_lazuli/version"
|
32
|
+
|
33
|
+
require "lapis_lazuli/world/config"
|
34
|
+
require "lapis_lazuli/world/hooks"
|
35
|
+
require "lapis_lazuli/world/variable"
|
36
|
+
require "lapis_lazuli/world/error"
|
37
|
+
require "lapis_lazuli/world/annotate"
|
38
|
+
require "lapis_lazuli/world/logging"
|
39
|
+
require "lapis_lazuli/world/browser"
|
40
|
+
require "lapis_lazuli/world/api"
|
41
|
+
require "lapis_lazuli/generic/xpath"
|
42
|
+
|
43
|
+
|
44
|
+
module LapisLazuli
|
45
|
+
##
|
46
|
+
# Includes all the functionality from the following modules.
|
47
|
+
include LapisLazuli::WorldModule::Config
|
48
|
+
include LapisLazuli::WorldModule::Hooks
|
49
|
+
include LapisLazuli::WorldModule::Variable
|
50
|
+
include LapisLazuli::WorldModule::Error
|
51
|
+
include LapisLazuli::WorldModule::Annotate
|
52
|
+
include LapisLazuli::WorldModule::Logging
|
53
|
+
include LapisLazuli::WorldModule::Browser
|
54
|
+
include LapisLazuli::WorldModule::API
|
55
|
+
include LapisLazuli::GenericModule::XPath
|
56
|
+
|
57
|
+
##
|
58
|
+
# Export equivalents to cucumber's Before/After functions
|
59
|
+
def self.Before(&block)
|
60
|
+
LapisLazuli::WorldModule::Hooks.add_hook(:before, block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.After(&block)
|
64
|
+
LapisLazuli::WorldModule::Hooks.add_hook(:after, block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.Start(&block)
|
68
|
+
LapisLazuli::WorldModule::Hooks.add_hook(:start, block)
|
69
|
+
end
|
70
|
+
|
71
|
+
# FIXME hard to implement; leaving it for now. See issue #13
|
72
|
+
# def self.End(&block)
|
73
|
+
# LapisLazuli::WorldModule::Hooks.add_hook(:end, block)
|
74
|
+
# end
|
75
|
+
end # module LapisLazuli
|
data/test/.gitignore
ADDED
data/test/Gemfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
|
4
|
+
# Add following two lines to your ~/.gemrc or /etc/gemrc:
|
5
|
+
# install: --no-rdoc --no-ri
|
6
|
+
# update: --no-rdoc --no-ri
|
7
|
+
|
8
|
+
# Install helper libraries
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'gherkin'
|
11
|
+
gem 'xml-simple'
|
12
|
+
gem 'mechanize'
|
13
|
+
|
14
|
+
# Debuggers
|
15
|
+
platforms :ruby_18, :ruby_19 do
|
16
|
+
gem 'debugger'
|
17
|
+
end
|
18
|
+
platforms :ruby_20, :ruby_21 do
|
19
|
+
gem 'byebug'
|
20
|
+
gem 'rb-readline'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Windows specific
|
24
|
+
platforms :mswin, :mingw do
|
25
|
+
gem 'win32console'
|
26
|
+
gem 'term-ansicolor'
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# Install all the webdriver gems and cucumber
|
31
|
+
gem 'watir-webdriver'
|
32
|
+
gem 'watir-webdriver-performance'
|
33
|
+
gem 'watir-scroll'
|
34
|
+
# For testing old versions of cucumber, swap the two lines below
|
35
|
+
gem 'cucumber', '>1.3.19'
|
36
|
+
# gem 'cucumber', '=1.3.19'
|
37
|
+
|
38
|
+
# Testing related
|
39
|
+
gem 'simplecov'
|
40
|
+
|
41
|
+
# LapisLazul itself
|
42
|
+
gem 'lapis_lazuli', :github => 'spriteCloud/lapis-lazuli', :branch => 'master'
|
data/test/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Lapis Lazuli Test Suite
|
2
|
+
|
3
|
+
This cucumber project contains a web server with simple test cases to validate Lapis Lazuli behavior.
|
4
|
+
|
5
|
+
Author: "Onno Steenbergen" <onno@spritecloud.com>
|
6
|
+
|
7
|
+
# Setup
|
8
|
+
|
9
|
+
## General
|
10
|
+
|
11
|
+
- Make sure you have ruby 2.1 or later installed.
|
12
|
+
- Make sure you have firefox and/or chrome installed
|
13
|
+
- Install the bundler gem:
|
14
|
+
|
15
|
+
$ gem install bundler
|
16
|
+
|
17
|
+
- Install all of the required gems defined in the gemfile:
|
18
|
+
|
19
|
+
$ bundle install
|
20
|
+
|
21
|
+
- Run cucumber through bundler:
|
22
|
+
|
23
|
+
$ bundle exec cucumber
|
24
|
+
|
25
|
+
# Code Coverage
|
26
|
+
|
27
|
+
Code coverage can be enabled if the `simplecov` gem is installed, by specifying
|
28
|
+
the `COVERAGE` environment variable when running the test suite:
|
29
|
+
|
30
|
+
$ COVERAGE=1 bundle exec cucumber
|
31
|
+
|
32
|
+
# Contributing
|
33
|
+
|
34
|
+
If you create new utility functions and want to contribute them to the Lapis
|
35
|
+
Lazuli project, see https://github.com/spriteCloud/lapis-lazuli
|
@@ -0,0 +1,37 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright 2014 spriteCloud B.V. All rights reserved.
|
3
|
+
# Generated by LapisLazuli, version 0.0.1
|
4
|
+
# Author: "Onno Steenbergen" <onno@steenbe.nl>
|
5
|
+
#
|
6
|
+
# Config file for the test automation
|
7
|
+
# When a config_local.yml exists, that will then be loaded instead of this default config file
|
8
|
+
|
9
|
+
################################################################################
|
10
|
+
# Set the global variables
|
11
|
+
default_env: production # defines the environment
|
12
|
+
screenshots_dir: screenshots # where to save the screenshots
|
13
|
+
step_pause_time: 1 # Waiting time in seconds defined after a step completes
|
14
|
+
make_screenshot_on_failed_scenario: true # make a screenshot after a scenario fails
|
15
|
+
old_portal: true
|
16
|
+
close_browser_after: feature
|
17
|
+
|
18
|
+
|
19
|
+
################################################################################
|
20
|
+
# List of error strings. Step will fail if one of these strings is detected.
|
21
|
+
error_strings:
|
22
|
+
[
|
23
|
+
"Server Error",
|
24
|
+
"Error: Page Not Found"
|
25
|
+
]
|
26
|
+
|
27
|
+
|
28
|
+
################################################################################
|
29
|
+
# Environment specific variables
|
30
|
+
test:
|
31
|
+
|
32
|
+
uat:
|
33
|
+
|
34
|
+
production:
|
35
|
+
close_browser_after: feature
|
36
|
+
server:
|
37
|
+
url: http://localhost:9090/
|
@@ -0,0 +1,37 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright 2014 spriteCloud B.V. All rights reserved.
|
3
|
+
# Generated by LapisLazuli, version 0.0.1
|
4
|
+
# Author: "Onno Steenbergen" <onno@steenbe.nl>
|
5
|
+
#
|
6
|
+
# Ask developer of testsuite to add profiles where desired.
|
7
|
+
# This file defines predefined profiles that can be used.
|
8
|
+
# Example > Cucumber -t @homepage -p default -p localhost
|
9
|
+
|
10
|
+
<% timestamp = Time.now.strftime("%Y%m%d_%H%M") %>
|
11
|
+
|
12
|
+
################################################################################
|
13
|
+
# Type of testrun
|
14
|
+
default: -f pretty -x
|
15
|
+
debug: -f pretty BREAKPOINT_ON_FAILURE=1
|
16
|
+
html_report: -f pretty -f html --out=results/<%=timestamp%>_report.html
|
17
|
+
junit_report: -f pretty -f junit --out=results
|
18
|
+
|
19
|
+
################################################################################
|
20
|
+
# Supported browsers (default = firefox)
|
21
|
+
# TODO: Make it functional on Chrome and IE
|
22
|
+
ff: BROWSER=firefox
|
23
|
+
chrome: BROWSER=chrome
|
24
|
+
ie: BROWSER=ie
|
25
|
+
safari: BROWSER=safari
|
26
|
+
|
27
|
+
|
28
|
+
################################################################################
|
29
|
+
# Listed environments (default is set in config.yml)
|
30
|
+
t: TEST_ENV=test -t @t,@test
|
31
|
+
test: TEST_ENV=test -t @t,@test
|
32
|
+
|
33
|
+
u: TEST_ENV=acceptatie -t @u,@uat
|
34
|
+
uat: TEST_ENV=acceptatie -t @u,@uat
|
35
|
+
|
36
|
+
p: TEST_ENV=production -t @p,@prod
|
37
|
+
production: TEST_ENV=production -t @p,@prod
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@annotation @p
|
2
|
+
Feature: annotiations
|
3
|
+
When I want to test the Lapis Lazuli library
|
4
|
+
I want to run a webserver with some test files
|
5
|
+
And execute the each library function that handles annotations.
|
6
|
+
|
7
|
+
@annotation_01
|
8
|
+
Scenario Outline: annotation_01 - scenario outline
|
9
|
+
Given I annotate a step with <data1>
|
10
|
+
And I annotate a step with <data2>
|
11
|
+
Then the report should include <data1> and <data2> in the correct place
|
12
|
+
|
13
|
+
Examples:
|
14
|
+
| data1 | data2 |
|
15
|
+
| foo | bar |
|
16
|
+
| foo | |
|
17
|
+
| | bar |
|
18
|
+
|
19
|
+
@annotation_02
|
20
|
+
Scenario: annotation_01 - single scenario
|
21
|
+
Given I annotate a step with baz
|
22
|
+
And I annotate a step with quux
|
23
|
+
Then the report should include baz and quux in the correct place
|
@@ -0,0 +1,10 @@
|
|
1
|
+
@browser @p
|
2
|
+
Feature: Browsers
|
3
|
+
When I want to test the Lapis Lazuli library
|
4
|
+
And test if I can start a browser with options
|
5
|
+
|
6
|
+
@browser_01
|
7
|
+
Scenario: browser_01 - Firefox with proxy
|
8
|
+
When I create a firefox browser named "test" with proxy to "localhost:8008"
|
9
|
+
Then the firefox browser named "test" has a profile
|
10
|
+
Then I close the browser named "test"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
@button @p
|
2
|
+
Feature: Buttons
|
3
|
+
When I want to test the Lapis Lazuli library
|
4
|
+
I want to run a webserver with some test files
|
5
|
+
And execute the each library function that handles buttons.
|
6
|
+
|
7
|
+
@button_01
|
8
|
+
Scenario: button_01 - Find First
|
9
|
+
Given I navigate to the button test page
|
10
|
+
Then the first button should be the first element on the page
|
11
|
+
And the 1st button should be the first element on the page
|
12
|
+
And the first button should not be the last element on the page
|
13
|
+
|
14
|
+
@button_02
|
15
|
+
Scenario: button_02 - Find based on index
|
16
|
+
Given I navigate to the button test page
|
17
|
+
Then the 3rd button should be the 3rd element on the page
|
18
|
+
And the 3rd button should not be the 2nd element on the page
|
19
|
+
And the 3rd button should not be the last element on the page
|
20
|
+
And the 3rd button should not be the first element on the page
|
21
|
+
|
22
|
+
@button_03
|
23
|
+
Scenario: button_03 - Hidden elements
|
24
|
+
Given I navigate to the button test page
|
25
|
+
Then the 4th button should not be present
|
26
|
+
And the 5th button should be present
|
27
|
+
|
28
|
+
@button_04
|
29
|
+
Scenario: button_04 - Clicking First
|
30
|
+
Given I navigate to the button test page
|
31
|
+
And I click the first button
|
32
|
+
Then within 1 seconds I should see "first clicked"
|
33
|
+
|
34
|
+
@button_05
|
35
|
+
Scenario: button_05 - Clicking Last
|
36
|
+
Given I navigate to the button test page
|
37
|
+
And I click the last button
|
38
|
+
Then within 1 seconds I should see "last clicked"
|