scudco-taza 0.8.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.
Files changed (63) hide show
  1. data/History.txt +44 -0
  2. data/Manifest.txt +61 -0
  3. data/README +79 -0
  4. data/README.textile +1 -0
  5. data/VERSION.yml +4 -0
  6. data/bin/taza +17 -0
  7. data/generators/flow/flow_generator.rb +57 -0
  8. data/generators/flow/templates/flow.rb.erb +9 -0
  9. data/generators/page/page_generator.rb +58 -0
  10. data/generators/page/templates/functional_page_spec.rb.erb +8 -0
  11. data/generators/page/templates/page.rb.erb +8 -0
  12. data/generators/partial/partial_generator.rb +57 -0
  13. data/generators/partial/templates/partial.rb.erb +7 -0
  14. data/generators/site/site_generator.rb +56 -0
  15. data/generators/site/templates/site.rb.erb +10 -0
  16. data/generators/site/templates/site.yml.erb +3 -0
  17. data/lib/app_generators/taza/taza_generator.rb +72 -0
  18. data/lib/app_generators/taza/templates/config.yml.erb +3 -0
  19. data/lib/app_generators/taza/templates/rakefile.rb.erb +3 -0
  20. data/lib/app_generators/taza/templates/spec_helper.rb.erb +11 -0
  21. data/lib/extensions/array.rb +10 -0
  22. data/lib/extensions/hash.rb +5 -0
  23. data/lib/extensions/object.rb +24 -0
  24. data/lib/extensions/string.rb +11 -0
  25. data/lib/taza/browser.rb +33 -0
  26. data/lib/taza/entity.rb +34 -0
  27. data/lib/taza/fixture.rb +66 -0
  28. data/lib/taza/flow.rb +40 -0
  29. data/lib/taza/page.rb +95 -0
  30. data/lib/taza/settings.rb +47 -0
  31. data/lib/taza/site.rb +145 -0
  32. data/lib/taza/tasks.rb +50 -0
  33. data/lib/taza.rb +35 -0
  34. data/spec/array_spec.rb +16 -0
  35. data/spec/browser_spec.rb +63 -0
  36. data/spec/entity_spec.rb +9 -0
  37. data/spec/fixture_spec.rb +34 -0
  38. data/spec/fixtures_spec.rb +21 -0
  39. data/spec/flow_generator_spec.rb +50 -0
  40. data/spec/hash_spec.rb +12 -0
  41. data/spec/object_spec.rb +29 -0
  42. data/spec/page_generator_spec.rb +56 -0
  43. data/spec/page_spec.rb +82 -0
  44. data/spec/partial_generator_spec.rb +38 -0
  45. data/spec/project_generator_spec.rb +41 -0
  46. data/spec/sandbox/config/config.yml +1 -0
  47. data/spec/sandbox/config/site_name.yml +5 -0
  48. data/spec/sandbox/config.yml +3 -0
  49. data/spec/sandbox/fixtures/examples.yml +8 -0
  50. data/spec/sandbox/fixtures/users.yml +2 -0
  51. data/spec/sandbox/flows/batman.rb +5 -0
  52. data/spec/sandbox/flows/robin.rb +4 -0
  53. data/spec/sandbox/pages/foo/bar.rb +9 -0
  54. data/spec/sandbox/pages/foo/partials/partial_the_reckoning.rb +2 -0
  55. data/spec/settings_spec.rb +88 -0
  56. data/spec/site_generator_spec.rb +57 -0
  57. data/spec/site_spec.rb +229 -0
  58. data/spec/spec_helper.rb +57 -0
  59. data/spec/string_spec.rb +7 -0
  60. data/spec/taza_bin_spec.rb +14 -0
  61. data/spec/taza_spec.rb +12 -0
  62. data/spec/taza_tasks_spec.rb +41 -0
  63. metadata +181 -0
@@ -0,0 +1,47 @@
1
+ require 'activesupport'
2
+
3
+ module Taza
4
+ class Settings
5
+ # The config settings for a site.yml file. ENV variables will override the settings:
6
+ # Can override the browser in config via ENV['BROWSER']
7
+ # Can override the driver in config via ENV['DRIVER']
8
+ # Can override the timeout in config via ENV['TIMEOUT']
9
+ # Can override the server_ip in config via ENV['SERVER_IP']
10
+ # Can override the server_port in config via ENV['SERVER_PORT']
11
+ #
12
+ # Example:
13
+ # Taza::Settings.Config('google')
14
+ def self.config(site_name)
15
+ env_settings = {}
16
+ env_settings[:browser] = ENV['BROWSER'].to_sym if ENV['BROWSER']
17
+ env_settings[:driver] = ENV['DRIVER'].to_sym if ENV['DRIVER']
18
+ env_settings[:timeout] = ENV['TIMEOUT'] if ENV['TIMEOUT']
19
+ env_settings[:server_ip] = ENV['SERVER_IP'] if ENV['SERVER_IP']
20
+ env_settings[:server_port] = ENV['SERVER_PORT'] if ENV['SERVER_PORT']
21
+ env_settings = {:browser=>:firefox,:driver=>:selenium}.merge(config_file.merge(env_settings))
22
+ site_file(site_name).merge(env_settings)
23
+ end
24
+
25
+ # Loads the config file for the entire project and returns the hash.
26
+ # Does not override settings from the ENV variables.
27
+ def self.config_file
28
+ YAML.load_file(config_file_path)
29
+ end
30
+
31
+ def self.config_file_path # :nodoc:
32
+ File.join(config_folder,'config.yml')
33
+ end
34
+
35
+ def self.config_folder # :nodoc:
36
+ File.join(path,'config')
37
+ end
38
+
39
+ def self.site_file(site_name) # :nodoc:
40
+ YAML.load_file(File.join(config_folder,"#{site_name.underscore}.yml"))[ENV['TAZA_ENV']]
41
+ end
42
+
43
+ def self.path # :nodoc:
44
+ '.'
45
+ end
46
+ end
47
+ end
data/lib/taza/site.rb ADDED
@@ -0,0 +1,145 @@
1
+ require 'rubygems'
2
+ require 'activesupport'
3
+
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
19
+ class Site
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={},&block)
49
+ @module_name = self.class.parent.to_s
50
+ @class_name = self.class.to_s.split("::").last
51
+ define_site_pages
52
+ define_flows
53
+ config = Settings.config(@class_name)
54
+ if params[:browser]
55
+ @browser = params[:browser]
56
+ else
57
+ @browser = Browser.create(config)
58
+ @i_created_browser = true
59
+ end
60
+ @browser.goto(params[:url] || config[:url])
61
+ execute_block_and_close_browser(browser,&block) if block_given?
62
+ end
63
+
64
+ def execute_block_and_close_browser(browser)
65
+ begin
66
+ yield self
67
+ rescue => site_block_exception
68
+ ensure
69
+ begin
70
+ @@before_browser_closes.call(browser)
71
+ rescue => before_browser_closes_block_exception
72
+ "" # so basically rcov has a bug where it would insist this block is uncovered when empty
73
+ end
74
+ close_browser_and_raise_if site_block_exception || before_browser_closes_block_exception
75
+ end
76
+ end
77
+
78
+ def self.settings # :nodoc:
79
+ Taza::Settings.site_file(self.name.to_s.split("::").last)
80
+ end
81
+
82
+ def close_browser_and_raise_if original_error # :nodoc:
83
+ begin
84
+ @browser.close if @i_created_browser
85
+ ensure
86
+ raise original_error if original_error
87
+ end
88
+ end
89
+
90
+ def define_site_pages # :nodoc:
91
+ Dir.glob(pages_path) do |file|
92
+ require file
93
+ page_name = File.basename(file,'.rb')
94
+ page_class = "#{@module_name}::#{page_name.camelize}"
95
+ self.class.class_eval <<-EOS
96
+ def #{page_name}
97
+ page = '#{page_class}'.constantize.new
98
+ page.browser = @browser
99
+ yield page if block_given?
100
+ page
101
+ end
102
+ EOS
103
+ end
104
+ end
105
+
106
+ def define_flows # :nodoc:
107
+ Dir.glob(flows_path) do |file|
108
+ require file
109
+ end
110
+ end
111
+
112
+ # This is used to call a flow belonging to the site
113
+ #
114
+ # Example:
115
+ # Google.new do |google|
116
+ # google.flow(:perform_search, :query => "taza")
117
+ # end
118
+ #
119
+ # Where the flow would be defined under lib/sites/google/flows/perform_search.rb and look like:
120
+ # class PerformSearch < Taza::Flow
121
+ # alias :google :site
122
+ #
123
+ # def run(params={})
124
+ # google.search.set params[:query]
125
+ # google.submit.click
126
+ # end
127
+ # end
128
+
129
+ def pages_path # :nodoc:
130
+ File.join(path,'pages','**','*.rb')
131
+ end
132
+
133
+ def flows_path # :nodoc:
134
+ File.join(path,'flows','*.rb')
135
+ end
136
+
137
+ def path # :nodoc:
138
+ File.join(base_path,'lib','sites',@class_name.underscore)
139
+ end
140
+
141
+ def base_path # :nodoc:
142
+ '.'
143
+ end
144
+ end
145
+ end
data/lib/taza/tasks.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rubygems'
4
+ require 'taglob/rake/tasks'
5
+ require 'spec/rake/spectask'
6
+
7
+ def tags
8
+ ENV['TAGS']
9
+ end
10
+
11
+ namespace :spec do
12
+ def format_options(file_name)
13
+ file_name = "artifacts/#{file_name}/index.html"
14
+ dir_name = File.dirname(file_name)
15
+ FileUtils.mkdir_p(dir_name) unless File.directory?(dir_name)
16
+ ["--format","html:#{file_name}","--format","p"]
17
+ end
18
+
19
+ desc "Run all functional specs"
20
+ Spec::Rake::SpecTask.new :functional do |t|
21
+ t.spec_files = Dir.taglob('spec/functional/**/*_spec.rb',tags)
22
+ t.spec_opts << format_options("functional/all")
23
+ end
24
+ desc "Run all integration specs"
25
+ Spec::Rake::SpecTask.new :integration do |t|
26
+ t.spec_files = Dir.taglob('spec/integration/**/*_spec.rb',tags)
27
+ t.spec_opts << format_options("integration/all")
28
+ end
29
+
30
+ namespace :functional do
31
+ Dir.glob('./spec/functional/*/').each do |dir|
32
+ site_name = File.basename(dir)
33
+ desc "Run all functional specs for #{site_name}"
34
+ Spec::Rake::SpecTask.new site_name.to_sym do |t|
35
+ t.spec_files = Dir.taglob("#{dir}**/*_spec.rb",tags)
36
+ t.spec_opts << format_options("functional/#{site_name}/all")
37
+ end
38
+ namespace site_name.to_sym do
39
+ Dir.glob("./spec/functional/#{site_name}/*_spec.rb").each do |page_spec_file|
40
+ page_spec_name = File.basename(page_spec_file)
41
+ page_name = page_spec_name.chomp('_spec.rb')
42
+ Spec::Rake::SpecTask.new page_name.to_sym do |t|
43
+ t.spec_files = page_spec_file
44
+ t.spec_opts << format_options("functional/#{site_name}/#{page_name}")
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/taza.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'taza/page'
2
+ require 'taza/site'
3
+ require 'taza/browser'
4
+ require 'taza/settings'
5
+ require 'taza/flow'
6
+ require 'taza/entity'
7
+ require 'taza/fixture'
8
+ require 'extensions/object'
9
+ require 'extensions/string'
10
+ require 'extensions/hash'
11
+ require 'extensions/array'
12
+
13
+ module Taza
14
+ VERSION = '0.8.1'
15
+
16
+ def self.windows?
17
+ PLATFORM.include?("mswin")
18
+ end
19
+ def self.osx?
20
+ PLATFORM.include?("darwin")
21
+ end
22
+ end
23
+
24
+ module ForwardInitialization
25
+ module ClassMethods
26
+ def new(*args,&block)
27
+ const_get("#{name.split("::").last}").new(*args,&block)
28
+ end
29
+ end
30
+
31
+ def self.included(klass)
32
+ klass.extend(ClassMethods)
33
+ end
34
+ end
35
+
@@ -0,0 +1,16 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe 'Array Extensions' do
4
+ it "should know if elements are not equivilent to a subset of those elements" do
5
+ [1,2,3].should_not be_equivalent([2,3])
6
+ end
7
+ it "should know if elements are not equivilent to a larger set including those elements" do
8
+ [1,2,3].should_not be_equivalent([1,2,3,4])
9
+ end
10
+ it "should know it is equivalent if the same order" do
11
+ [1,2,3].should be_equivalent([1,2,3])
12
+ end
13
+ it "should know it is equivalent if the different orders" do
14
+ [1,2,3].should be_equivalent([2,1,3])
15
+ end
16
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec/spec_helper'
2
+ require 'taza/browser'
3
+ require 'taza/settings'
4
+ require 'selenium'
5
+ require 'watir'
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
+ module Watir
20
+ class Safari
21
+ end
22
+ end
23
+
24
+ it "should raise unknown browser error for unsupported watir browsers" do
25
+ lambda { Taza::Browser.create(:browser => :foo_browser_9000,:driver => :watir) }.should raise_error(StandardError)
26
+ end
27
+
28
+ it "should use params browser type when creating selenium" do
29
+ browser_type = :opera
30
+ Selenium::SeleniumDriver.expects(:new).with(anything,anything,'*opera',anything)
31
+ Taza::Browser.create(:browser => browser_type, :driver => :selenium)
32
+ end
33
+
34
+ it "should raise selenium unsupported browser error" do
35
+ Taza::Browser.create(:browser => :foo, :driver => :selenium)
36
+ end
37
+
38
+ it "should be able to create a selenium instance" do
39
+ browser = Taza::Browser.create(:browser => :firefox, :driver => :selenium)
40
+ browser.should be_a_kind_of(Selenium::SeleniumDriver)
41
+ end
42
+
43
+ it "should use environment settings for server port and ip" do
44
+ Taza::Settings.stubs(:path).returns(File.join('spec','sandbox'))
45
+ ENV['SERVER_PORT'] = 'server_port'
46
+ ENV['SERVER_IP'] = 'server_ip'
47
+ Selenium::SeleniumDriver.expects(:new).with('server_ip','server_port',anything,anything)
48
+ Taza::Browser.create(Taza::Settings.config("SiteName"))
49
+ end
50
+
51
+ it "should use environment settings for timeout" do
52
+ Taza::Settings.stubs(:path).returns(File.join('spec','sandbox'))
53
+ ENV['TIMEOUT'] = 'timeout'
54
+ Selenium::SeleniumDriver.expects(:new).with(anything,anything,anything,'timeout')
55
+ Taza::Browser.create(Taza::Settings.config("SiteName"))
56
+ end
57
+
58
+ it "should be able to give you the class of browser" do
59
+ Taza::Browser.expects(:watir_safari).returns(Object)
60
+ Taza::Browser.browser_class(:browser => :safari, :driver => :watir).should eql(Object)
61
+ end
62
+
63
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec/spec_helper'
2
+ require 'taza'
3
+
4
+ describe Taza::Entity do
5
+ it "should add methods for hash string keys" do
6
+ entity = Taza::Entity.new({'apple' => 'pie'},nil)
7
+ entity.should respond_to(:apple)
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec/spec_helper'
2
+ require 'taza'
3
+
4
+ describe Taza::Fixture do
5
+
6
+ it "should be able to load entries from fixtures" do
7
+ Taza::Fixture.any_instance.stubs(:base_path).returns('./spec/sandbox')
8
+ fixture = Taza::Fixture.new
9
+ fixture.load_all
10
+ example = fixture.get_fixture_entity(:examples,'first_example')
11
+ example.name.should eql("first")
12
+ example.price.should eql(1)
13
+ end
14
+
15
+ it "should use the spec folder as the base path" do
16
+ Taza::Fixture.new.base_path.should eql('./spec')
17
+ end
18
+
19
+ it "should know if a pluralized fixture of that name exists" do
20
+ Taza::Fixture.any_instance.stubs(:base_path).returns('./spec/sandbox')
21
+ fixture = Taza::Fixture.new
22
+ fixture.load_all
23
+ fixture.pluralized_fixture_exists?('example').should be_true
24
+ fixture.pluralized_fixture_exists?('foo').should be_false
25
+ end
26
+
27
+ it "should be able to get all fixtures loaded" do
28
+ Taza::Fixture.any_instance.stubs(:base_path).returns('./spec/sandbox')
29
+ fixture = Taza::Fixture.new
30
+ fixture.load_all
31
+ fixture.fixture_names.should be_equivalent([:examples,:users])
32
+ end
33
+
34
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec/spec_helper'
2
+ require 'taza/fixture'
3
+
4
+ describe Taza::Fixtures do
5
+ Taza::Fixture.any_instance.stubs(:base_path).returns('./spec/sandbox')
6
+ include Taza::Fixtures
7
+
8
+ it "should be able to look up a fixture entity off fixture_methods module" do
9
+ examples(:first_example).name.should eql('first')
10
+ end
11
+
12
+ it "should still raise method missing error" do
13
+ lambda{zomgwtf(:first_example)}.should raise_error(NoMethodError)
14
+ end
15
+
16
+ #TODO: this test tests what is in entity's instance eval not happy with it being here
17
+ it "should be able to look up a fixture entity off fixture_methods module" do
18
+ examples(:first_example).user.name.should eql(users(:shatner).name)
19
+ end
20
+
21
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec/spec_helper'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+ require 'taza'
5
+
6
+ class Taza::Site
7
+ def flows
8
+ flows = []
9
+ Dir.glob(File.join(path,'flows','*.rb')).each do |file|
10
+ require file
11
+
12
+ flows << "#{self.class.parent.to_s}::#{File.basename(file,'.rb').camelize}".constantize
13
+ end
14
+ flows
15
+ end
16
+ end
17
+
18
+ describe "Flow Generation" do
19
+ include RubiGen::GeneratorTestHelper
20
+ include Helpers::Generator
21
+ include Helpers::Taza
22
+
23
+ before :all do
24
+ @site_name = "Foo"
25
+ @site_folder = File.join(PROJECT_FOLDER,'lib','sites',"gap")
26
+ @site_file = File.join(PROJECT_FOLDER,'lib','sites',"gap.rb")
27
+ @flow_name = "CheckOut"
28
+ end
29
+
30
+ before :each do
31
+ run_generator('taza', [APP_ROOT], generator_sources)
32
+ @site_class = generate_site(@site_name)
33
+ end
34
+
35
+ after :each do
36
+ bare_teardown
37
+ end
38
+
39
+ it "should give you usage if you do not give two arguments" do
40
+ FlowGenerator.any_instance.expects(:usage)
41
+ lambda { run_generator('flow', [@flow_name], generator_sources) }.should raise_error
42
+ end
43
+
44
+ it "should give you usage if you give a site that does not exist" do
45
+ FlowGenerator.any_instance.expects(:usage)
46
+ $stderr.expects(:puts).with(regexp_matches(/NoSuchSite/))
47
+ lambda { run_generator('flow', [@flow_name,"NoSuchSite"], generator_sources) }.should raise_error
48
+ end
49
+
50
+ end