taza 0.5.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +33 -0
  2. data/Manifest.txt +39 -9
  3. data/README.txt +29 -7
  4. data/Rakefile +72 -13
  5. data/bin/taza +16 -3
  6. data/generators/flow/flow_generator.rb +57 -0
  7. data/generators/flow/templates/flow.rb.erb +12 -0
  8. data/generators/page/page_generator.rb +58 -0
  9. data/generators/page/templates/functional_page_spec.rb.erb +8 -0
  10. data/generators/page/templates/page.rb.erb +8 -0
  11. data/generators/site/site_generator.rb +55 -0
  12. data/generators/site/templates/site.rb.erb +10 -0
  13. data/generators/site/templates/site.yml.erb +3 -0
  14. data/lib/app_generators/taza/taza_generator.rb +76 -0
  15. data/lib/app_generators/taza/templates/config.yml.erb +3 -0
  16. data/lib/{taza/generators → app_generators/taza}/templates/rakefile.rb.erb +0 -0
  17. data/lib/app_generators/taza/templates/spec_helper.rb.erb +11 -0
  18. data/lib/taza.rb +44 -5
  19. data/lib/taza/browser.rb +40 -0
  20. data/lib/taza/browsers/ie_watir.rb +8 -0
  21. data/lib/taza/browsers/safari_watir.rb +8 -0
  22. data/lib/taza/flow.rb +45 -0
  23. data/lib/taza/page.rb +66 -19
  24. data/lib/taza/settings.rb +36 -0
  25. data/lib/taza/site.rb +122 -11
  26. data/lib/taza/tasks.rb +26 -34
  27. data/spec/browser_spec.rb +72 -0
  28. data/spec/flow_generator_spec.rb +70 -0
  29. data/spec/page_generator_spec.rb +57 -0
  30. data/spec/page_spec.rb +82 -0
  31. data/spec/platform/osx/browser_spec.rb +14 -0
  32. data/spec/platform/windows/browser_spec.rb +14 -0
  33. data/spec/project_generator_spec.rb +42 -0
  34. data/spec/sandbox/config.yml +3 -0
  35. data/spec/sandbox/config/config.yml +1 -0
  36. data/spec/sandbox/config/site_name.yml +5 -0
  37. data/spec/sandbox/flows/batman.rb +2 -0
  38. data/spec/sandbox/flows/robin.rb +4 -0
  39. data/spec/sandbox/pages/foo/bar.rb +9 -0
  40. data/spec/settings_spec.rb +88 -0
  41. data/spec/site_generator_spec.rb +53 -0
  42. data/spec/site_spec.rb +239 -0
  43. data/spec/spec_helper.rb +49 -0
  44. data/spec/taza_bin_spec.rb +14 -0
  45. data/spec/taza_spec.rb +12 -0
  46. data/spec/taza_tasks_spec.rb +27 -0
  47. data/spec/unit_helper_spec.rb +14 -0
  48. metadata +103 -13
  49. data/lib/taza/generators.rb +0 -4
  50. data/lib/taza/generators/base.rb +0 -33
  51. data/lib/taza/generators/page.rb +0 -22
  52. data/lib/taza/generators/project.rb +0 -18
  53. data/lib/taza/generators/site.rb +0 -24
  54. data/lib/taza/generators/templates/page.rb.erb +0 -6
  55. data/lib/taza/generators/templates/site.rb.erb +0 -6
@@ -0,0 +1,36 @@
1
+ require 'activesupport'
2
+
3
+ module Taza
4
+ class Settings
5
+ def self.config(site_name)
6
+ env_settings = {}
7
+ env_settings[:browser] = ENV['browser'].to_sym if ENV['browser']
8
+ env_settings[:driver] = ENV['driver'].to_sym if ENV['driver']
9
+ env_settings[:timeout] = ENV['timeout'] if ENV['timeout']
10
+ env_settings[:server_ip] = ENV['server_ip'] if ENV['server_ip']
11
+ env_settings[:server_port] = ENV['server_port'] if ENV['server_port']
12
+ env_settings = {:browser=>:firefox,:driver=>:selenium}.merge(config_file.merge(env_settings))
13
+ site_file(site_name).merge(env_settings)
14
+ end
15
+
16
+ def self.config_file # :nodoc:
17
+ YAML.load_file(config_file_path)
18
+ end
19
+
20
+ def self.config_file_path # :nodoc:
21
+ File.join(config_folder,'config.yml')
22
+ end
23
+
24
+ def self.config_folder # :nodoc:
25
+ File.join(path,'config')
26
+ end
27
+
28
+ def self.site_file(site_name) # :nodoc:
29
+ YAML.load_file(File.join(config_folder,"#{site_name.underscore}.yml"))[ENV['TAZA_ENV']]
30
+ end
31
+
32
+ def self.path # :nodoc:
33
+ '.'
34
+ end
35
+ end
36
+ end
data/lib/taza/site.rb CHANGED
@@ -2,27 +2,138 @@ require 'rubygems'
2
2
  require 'activesupport'
3
3
 
4
4
  module Taza
5
+ # An abstraction of a website, but more really a container for a sites pages.
6
+ #
7
+ # You can generate a site by performing the following command:
8
+ # $ ./script/generate site google
9
+ #
10
+ # This will generate a site file for google, a flows folder, and a pages folder in lib
11
+ #
12
+ # Example:
13
+ #
14
+ # require 'taza'
15
+ #
16
+ # class Google < Taza::Site
17
+ #
18
+ # end
5
19
  class Site
6
- def initialize
20
+ @@before_browser_closes = Proc.new() {}
21
+ # Use this to do something with the browser before it closes, but note that it is a class method which
22
+ # means that this will get called for any instance of a site.
23
+ #
24
+ # Here's an example of how you might use it to print the DOM output of a browser before it closes:
25
+ #
26
+ # Taza::Site.before_browser_closes do |browser|
27
+ # puts browser.html
28
+ # end
29
+ def self.before_browser_closes(&block)
30
+ @@before_browser_closes = block
31
+ end
32
+ attr_accessor :browser
33
+
34
+ # A site can be called a few different ways
35
+ #
36
+ # The following example creates a new browser object and closes it:
37
+ # Google.new do
38
+ # google.search.set "taza"
39
+ # google.submit.click
40
+ # end
41
+ #
42
+ # This example will create a browser object but not close it:
43
+ # Google.new.search.set "taza"
44
+ #
45
+ # Sites can take a couple of parameters in the constructor:
46
+ # :browser => a browser object to act on instead of creating one automatically
47
+ # :url => the url of where to start the site
48
+ def initialize(params={})
49
+ @module_name = self.class.parent.to_s
50
+ @class_name = self.class.to_s.split("::").last
7
51
  define_site_pages
52
+ config = Settings.config(@class_name)
53
+ if params[:browser]
54
+ @browser = params[:browser]
55
+ else
56
+ @browser = Browser.create(config)
57
+ @i_created_browser = true
58
+ end
59
+ @browser.goto(params[:url] || config[:url])
60
+
61
+ if block_given?
62
+ begin
63
+ yield self
64
+ rescue => site_block_exception
65
+ ensure
66
+ begin
67
+ @@before_browser_closes.call(browser)
68
+ rescue => before_browser_closes_block_exception
69
+ end
70
+ close_browser_and_raise_if site_block_exception || before_browser_closes_block_exception
71
+ end
72
+ end
8
73
  end
9
74
 
10
- def define_site_pages
11
- Dir.glob(path) do |file|
12
- require file
75
+ def self.settings # :nodoc:
76
+ Taza::Settings.site_file(self.name.to_s.split("::").last)
77
+ end
78
+
79
+ def close_browser_and_raise_if original_error # :nodoc:
80
+ begin
81
+ if @i_created_browser
82
+ @browser.close
83
+ end
84
+ ensure
85
+ raise original_error if original_error
86
+ end
87
+ end
13
88
 
89
+ def define_site_pages # :nodoc:
90
+ Dir.glob(pages_path) do |file|
91
+ require file
14
92
  page_name = File.basename(file,'.rb')
93
+ page_class = "#{@module_name}::#{page_name.camelize}"
15
94
  self.class.class_eval <<-EOS
16
- def #{page_name}
17
- yield '#{page_name}'.camelcase.constantize.new
18
- end
95
+ def #{page_name}
96
+ page = '#{page_class}'.constantize.new
97
+ page.browser = @browser
98
+ yield page if block_given?
99
+ page
100
+ end
19
101
  EOS
20
102
  end
21
103
  end
22
104
 
23
- def path
24
- File.join('pages',self.class.to_s.underscore,'*.rb')
105
+ # This is used to call a flow belonging to the site
106
+ #
107
+ # Example:
108
+ # Google.new do |google|
109
+ # google.flow(:perform_search, :query => "taza")
110
+ # end
111
+ #
112
+ # Where the flow would be defined under lib/sites/google/flows/perform_search.rb and look like:
113
+ # class PerformSearch < Taza::Flow
114
+ # alias :google :site
115
+ #
116
+ # def run(params={})
117
+ # google.search.set params[:query]
118
+ # google.submit.click
119
+ # end
120
+ # end
121
+ def flow(name,params={})
122
+ require File.join(path,'flows',name.to_s.underscore)
123
+ flow_class = "#{@module_name}::#{name.to_s.camelize}".constantize
124
+ flow_class.new(self).run(params)
125
+ end
126
+
127
+ def pages_path # :nodoc:
128
+ File.join(path,'pages','*.rb')
129
+ end
130
+
131
+ def path # :nodoc:
132
+ File.join(base_path,'lib','sites',@class_name.underscore)
25
133
  end
26
- end
27
- end
28
134
 
135
+ def base_path # :nodoc:
136
+ '.'
137
+ end
138
+ end
139
+ end
data/lib/taza/tasks.rb CHANGED
@@ -1,46 +1,38 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rubygems'
4
- require 'taglob'
4
+ require 'taglob/rake/tasks'
5
5
  require 'spec/rake/spectask'
6
- require 'taza/generators'
7
6
 
8
- private
9
- def get_tagged_files(test_file_pattern)
10
- Dir.taglob(test_file_pattern,ENV['tags'])
11
- end
12
-
13
- def validate_required_environment_input_present(error_message, *environment_variable_keys)
14
- environment_variable_keys.each do |environment_variable_key|
15
- if ENV[environment_variable_key].nil?
16
- STDERR.puts error_message
17
- exit 1
18
- end
7
+ namespace :spec do
8
+ def format_options(file_name)
9
+ file_name = "artifacts/#{file_name}/index.html"
10
+ dir_name = File.dirname(file_name)
11
+ FileUtils.mkdir_p(dir_name) unless File.directory?(dir_name)
12
+ ["--format","html:#{file_name}","--format","p"]
19
13
  end
20
- end
21
-
22
- public
23
14
 
24
- desc "invoke tests by tag"
25
- Rake::TestTask.new :test_tag do |t|
26
- t.test_files = get_tagged_files('test/**/test_*.rb')
27
- end
15
+ desc "Run all functional specs"
16
+ Spec::Rake::SpecTask.new :functional do |t|
17
+ t.spec_files = 'spec/functional/**/*_spec.rb'
18
+ t.spec_opts << format_options("functional/all")
19
+ end
20
+ desc "Run all integration specs"
21
+ Spec::Rake::SpecTask.new :integration do |t|
22
+ t.spec_files = 'spec/integration/**/*_spec.rb'
23
+ t.spec_opts << format_options("integration/all")
24
+ end
28
25
 
29
- desc "invoke specs by tag"
30
- Spec::Rake::SpecTask.new :spec_tag do |t|
31
- t.spec_files = get_tagged_files('spec/**/*_spec.rb')
32
- end
26
+ namespace :functional do
27
+ Dir.glob('./spec/functional/*/').each do |dir|
28
+ site_name = File.basename(dir)
33
29
 
34
- namespace :generate do
35
- desc "generate a site(rake generate:site name=foo)"
36
- task :site do
37
- validate_required_environment_input_present("Usage: rake generate:site name=the_site_name",'name')
38
- Taza::Generators::Site.new(ENV['name']).generate
39
- end
30
+ desc "Run all functional specs for #{site_name}"
31
+ Spec::Rake::SpecTask.new site_name.to_sym do |t|
32
+ t.spec_files = "#{dir}**/*_spec.rb"
33
+ t.spec_opts << format_options("functional/#{site_name}/all")
34
+ end
40
35
 
41
- desc "generate a page(rake generate:page site=foo page=bar)"
42
- task :page do
43
- validate_required_environment_input_present("Usage: rake generate:page name=the_page_name site=the_site_name",'name','site')
44
- Taza::Generators::Page.new(ENV['name'],ENV['site']).generate
36
+ end
45
37
  end
46
38
  end
@@ -0,0 +1,72 @@
1
+ require 'spec/spec_helper'
2
+ require 'taza/browser'
3
+ require 'taza/settings'
4
+ require 'selenium'
5
+ require 'firewatir'
6
+
7
+ describe Taza::Browser do
8
+
9
+ before :each do
10
+ Taza::Settings.stubs(:config_file).returns({})
11
+ ENV['TAZA_ENV'] = 'isolation'
12
+ ENV['server_port'] = nil
13
+ ENV['server_ip'] = nil
14
+ ENV['browser'] = nil
15
+ ENV['driver'] = nil
16
+ ENV['timeout'] = nil
17
+ end
18
+
19
+ it "should be able to create a watir driver" do
20
+ Taza::Browser.expects(:create_watir_ie)
21
+ Taza::Browser.create(:browser => :ie, :driver => :watir)
22
+ end
23
+
24
+ it "should be able to create a firewatir driver" do
25
+ Taza::Browser.expects(:create_watir_firefox)
26
+ Taza::Browser.create(:browser => :firefox,:driver => :watir)
27
+ end
28
+
29
+ it "should be able to create a safariwatir driver" do
30
+ Taza::Browser.expects(:create_watir_safari)
31
+ Taza::Browser.create(:browser => :safari,:driver => :watir)
32
+ end
33
+
34
+ it "should raise unknown browser error for unsupported watir browsers" do
35
+ lambda { Taza::Browser.create(:browser => :foo_browser_9000,:driver => :watir) }.should raise_error(BrowserUnsupportedError)
36
+ end
37
+
38
+ it "should use params browser type when creating selenium" do
39
+ browser_type = :opera
40
+ Selenium::SeleniumDriver.expects(:new).with(anything,anything,'*opera',anything)
41
+ Taza::Browser.create(:browser => browser_type, :driver => :selenium)
42
+ end
43
+
44
+ it "should raise selenium unsupported browser error" do
45
+ Taza::Browser.create(:browser => :foo, :driver => :selenium)
46
+ end
47
+
48
+ it "should be able to create a selenium instance" do
49
+ browser = Taza::Browser.create(:browser => :firefox, :driver => :selenium)
50
+ browser.should be_a_kind_of(Selenium::SeleniumDriver)
51
+ end
52
+
53
+ it "should use environment settings for server port and ip" do
54
+ Taza::Settings.stubs(:path).returns(File.join('spec','sandbox'))
55
+ ENV['server_port'] = 'server_port'
56
+ ENV['server_ip'] = 'server_ip'
57
+ Selenium::SeleniumDriver.expects(:new).with('server_ip','server_port',anything,anything)
58
+ Taza::Browser.create(Taza::Settings.config("SiteName"))
59
+ end
60
+
61
+ it "should use environment settings for timeout" do
62
+ Taza::Settings.stubs(:path).returns(File.join('spec','sandbox'))
63
+ ENV['timeout'] = 'timeout'
64
+ Selenium::SeleniumDriver.expects(:new).with(anything,anything,anything,'timeout')
65
+ Taza::Browser.create(Taza::Settings.config("SiteName"))
66
+ end
67
+
68
+ it "should create firewatir instance" do
69
+ FireWatir::Firefox.expects(:new)
70
+ Taza::Browser.create(:browser => :firefox, :driver => :watir)
71
+ end
72
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec/spec_helper'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+ require 'taza'
5
+ require 'vendor/gems/gems/rubigen-1.3.2/test/test_generator_helper'
6
+
7
+ class Taza::Site
8
+ def flows
9
+ flows = []
10
+ Dir.glob(File.join(path,'flows','*.rb')).each do |file|
11
+ require file
12
+
13
+ flows << "#{self.class.parent.to_s}::#{File.basename(file,'.rb').camelize}".constantize
14
+ end
15
+ flows
16
+ end
17
+ end
18
+
19
+ describe "Flow Generation" do
20
+ include RubiGen::GeneratorTestHelper
21
+ include Helpers::Generator
22
+ include Helpers::Taza
23
+
24
+ before :all do
25
+ @site_name = "Foo"
26
+ @site_folder = File.join(PROJECT_FOLDER,'lib','sites',"gap")
27
+ @site_file = File.join(PROJECT_FOLDER,'lib','sites',"gap.rb")
28
+ @flow_name = "CheckOut"
29
+ end
30
+
31
+ before :each do
32
+ run_generator('taza', [APP_ROOT], generator_sources)
33
+ @site_class = generate_site(@site_name)
34
+ end
35
+
36
+ after :each do
37
+ bare_teardown
38
+ end
39
+
40
+ it "should give you usage if you do not give two arguments" do
41
+ FlowGenerator.any_instance.expects(:usage)
42
+ lambda { run_generator('flow', [@flow_name], generator_sources) }.should raise_error
43
+ end
44
+
45
+ it "should give you usage if you give a site that does not exist" do
46
+ FlowGenerator.any_instance.expects(:usage)
47
+ $stderr.expects(:puts).with(regexp_matches(/NoSuchSite/))
48
+ lambda { run_generator('flow', [@flow_name,"NoSuchSite"], generator_sources) }.should raise_error
49
+ end
50
+
51
+ it "should generate flows that will not have namespace collisions with pages" do
52
+ flow_name = "SignIn"
53
+ run_generator('flow', [flow_name,@site_class.to_s], generator_sources)
54
+ run_generator('page', [flow_name,@site_class.to_s], generator_sources)
55
+ stub_settings
56
+ stub_browser
57
+ site = @site_class.new
58
+ site.flow(:sign_in)
59
+ site.sign_in_page
60
+ end
61
+
62
+ it "should generate flows that will not have namespace collisions with other sites' flows" do
63
+ new_site_class = generate_site('Pag')
64
+ run_generator('flow', [@flow_name,@site_class.to_s], generator_sources)
65
+ run_generator('flow', [@flow_name,new_site_class.to_s], generator_sources)
66
+ stub_settings
67
+ stub_browser
68
+ (@site_class.new.flows & new_site_class.new.flows).should be_empty
69
+ end
70
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec/spec_helper'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+ require 'taza'
5
+ require 'vendor/gems/gems/rubigen-1.3.2/test/test_generator_helper'
6
+
7
+ describe "Page Generation" do
8
+ include RubiGen::GeneratorTestHelper
9
+ include Helpers::Generator
10
+ include Helpers::Taza
11
+
12
+ before :all do
13
+ @page_name = "CheckOut"
14
+ end
15
+
16
+ before :each do
17
+ run_generator('taza', [APP_ROOT], generator_sources)
18
+ @site_class = generate_site('Gap')
19
+ end
20
+
21
+ after :each do
22
+ bare_teardown
23
+ end
24
+
25
+ it "should give you usage if you do not give two arguments" do
26
+ PageGenerator.any_instance.expects(:usage)
27
+ lambda { run_generator('page', [@page_name], generator_sources) }.should raise_error
28
+ end
29
+
30
+ it "should give you usage if you give a site that does not exist" do
31
+ PageGenerator.any_instance.expects(:usage)
32
+ $stderr.expects(:puts).with(regexp_matches(/NoSuchSite/))
33
+ lambda { run_generator('page', [@page_name,"NoSuchSite"], generator_sources) }.should raise_error
34
+ end
35
+
36
+ it "should generate a page spec that can be required" do
37
+ run_generator('page', [@page_name,@site_class.to_s], generator_sources)
38
+ page_functional_spec = File.join(PROJECT_FOLDER,'spec','functional',@site_class.to_s.underscore,'check_out_page_spec.rb')
39
+ system("ruby -c #{page_functional_spec} > #{null_device}").should be_true
40
+ end
41
+
42
+ it "should be able to access the generated page from the site" do
43
+ run_generator('page', [@page_name,@site_class.to_s], generator_sources)
44
+ stub_settings
45
+ stub_browser
46
+ @site_class.new.check_out_page
47
+ end
48
+
49
+ it "should be able to access the generated page for its site" do
50
+ stub_browser
51
+ stub_settings
52
+ new_site_class = generate_site('Pag')
53
+ run_generator('page', [@page_name,@site_class.to_s], generator_sources)
54
+ run_generator('page', [@page_name,new_site_class.to_s], generator_sources)
55
+ new_site_class.new.check_out_page.class.should_not eql(@site_class.new.check_out_page.class)
56
+ end
57
+ end