gaq 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +15 -0
  3. data/Guardfile +23 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +102 -0
  6. data/Rakefile +1 -0
  7. data/gaq.gemspec +22 -0
  8. data/lib/gaq.rb +3 -0
  9. data/lib/gaq/class_cache.rb +32 -0
  10. data/lib/gaq/command_language.rb +145 -0
  11. data/lib/gaq/configuration.rb +159 -0
  12. data/lib/gaq/controller_facade.rb +15 -0
  13. data/lib/gaq/controller_handle.rb +93 -0
  14. data/lib/gaq/dsl_target.rb +51 -0
  15. data/lib/gaq/dsl_target_factory.rb +64 -0
  16. data/lib/gaq/flash_commands_adapter.rb +48 -0
  17. data/lib/gaq/interprets_config.rb +13 -0
  18. data/lib/gaq/railtie.rb +40 -0
  19. data/lib/gaq/snippet_renderer.rb +44 -0
  20. data/lib/gaq/version.rb +3 -0
  21. data/spec-dummy/.rspec +1 -0
  22. data/spec-dummy/README.rdoc +261 -0
  23. data/spec-dummy/Rakefile +7 -0
  24. data/spec-dummy/app/assets/images/rails.png +0 -0
  25. data/spec-dummy/app/assets/javascripts/application.js +13 -0
  26. data/spec-dummy/app/assets/stylesheets/application.css +13 -0
  27. data/spec-dummy/app/controllers/application_controller.rb +3 -0
  28. data/spec-dummy/app/controllers/integration_spec_controller.rb +22 -0
  29. data/spec-dummy/app/helpers/application_helper.rb +2 -0
  30. data/spec-dummy/app/views/integration_spec/view.erb +0 -0
  31. data/spec-dummy/app/views/layouts/application.html.erb +16 -0
  32. data/spec-dummy/config.ru +4 -0
  33. data/spec-dummy/config/application.rb +64 -0
  34. data/spec-dummy/config/boot.rb +6 -0
  35. data/spec-dummy/config/environment.rb +5 -0
  36. data/spec-dummy/config/environments/development.rb +26 -0
  37. data/spec-dummy/config/environments/production.rb +51 -0
  38. data/spec-dummy/config/environments/test_dynamic.rb +39 -0
  39. data/spec-dummy/config/environments/test_static.rb +38 -0
  40. data/spec-dummy/config/initializers/backtrace_silencers.rb +7 -0
  41. data/spec-dummy/config/initializers/inflections.rb +15 -0
  42. data/spec-dummy/config/initializers/mime_types.rb +5 -0
  43. data/spec-dummy/config/initializers/secret_token.rb +7 -0
  44. data/spec-dummy/config/initializers/session_store.rb +8 -0
  45. data/spec-dummy/config/initializers/wrap_parameters.rb +10 -0
  46. data/spec-dummy/config/locales/en.yml +5 -0
  47. data/spec-dummy/config/routes.rb +8 -0
  48. data/spec-dummy/db/seeds.rb +7 -0
  49. data/spec-dummy/public/404.html +26 -0
  50. data/spec-dummy/public/422.html +26 -0
  51. data/spec-dummy/public/500.html +25 -0
  52. data/spec-dummy/public/favicon.ico +0 -0
  53. data/spec-dummy/public/robots.txt +5 -0
  54. data/spec-dummy/script/rails +6 -0
  55. data/spec-dummy/spec/common_spec_methods.rb +88 -0
  56. data/spec-dummy/spec/features/dynamic_config_spec.rb +21 -0
  57. data/spec-dummy/spec/features/next_request_spec.rb +27 -0
  58. data/spec-dummy/spec/features/presence_spec.rb +64 -0
  59. data/spec-dummy/spec/spec_helper.rb +41 -0
  60. data/spec/lib/gaq/class_cache_spec.rb +62 -0
  61. data/spec/lib/gaq/command_language_spec.rb +267 -0
  62. data/spec/lib/gaq/configuration_spec.rb +233 -0
  63. data/spec/lib/gaq/controller_facade_spec.rb +29 -0
  64. data/spec/lib/gaq/controller_handle_spec.rb +510 -0
  65. data/spec/lib/gaq/dsl_target_factory_spec.rb +163 -0
  66. data/spec/lib/gaq/dsl_target_spec.rb +87 -0
  67. data/spec/lib/gaq/flash_commands_adapter_spec.rb +116 -0
  68. data/spec/lib/gaq/interprets_config_spec.rb +37 -0
  69. data/spec/lib/gaq/snippet_renderer_spec.rb +60 -0
  70. metadata +159 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,88 @@
1
+ require 'nokogiri'
2
+
3
+ module Helpers
4
+ def gaq_cdata
5
+ html = Nokogiri::HTML.parse(page.body)
6
+
7
+ html.css('script[type="text/javascript"]').find do |script|
8
+ cdata = script.children.find(&:cdata?) \
9
+ and cdata.text.include?('_gaq') \
10
+ and break(cdata)
11
+ end
12
+ end
13
+
14
+ def gaq_cdata_content
15
+ /<!\[CDATA\[(.*)\]\]>/m.match(gaq_cdata)[1]
16
+ end
17
+
18
+ def gaq_split_at_snippet_beginning
19
+ text_lines_without_comments = gaq_cdata_content.split("\n").map do |line|
20
+ if me = %r{^(.*?)//}.match(line)
21
+ line = me[1]
22
+ end
23
+
24
+ if me = %r{^\s*(.*)}.match(line)
25
+ line = me[1]
26
+ end
27
+
28
+ line
29
+ end.reject(&:blank?)
30
+
31
+ text_lines_without_comments.join("\n").split(%r{(?=\(function\(\))})
32
+ end
33
+
34
+ def snippet_and_beyond
35
+ gaq_split_at_snippet_beginning[1..-1]
36
+ end
37
+
38
+ def gaq_js_instructions
39
+ gaq_split_at_snippet_beginning.first.split(%r{(?<=;)\n}m)
40
+ end
41
+
42
+ def gaq_pushed_instructions
43
+ lines = %r{\A_gaq.push\((.*)\);\Z}m.match(gaq_js_instructions.second)[1]
44
+ lines.split(",\n").map do |instruction_line|
45
+ instruction_line.should start_with('[')
46
+ instruction_line.should end_with(']')
47
+
48
+ JSON.parse(instruction_line)
49
+ end
50
+ end
51
+
52
+ def track_event_from_before_filter(action)
53
+ be_instruction('_trackEvent').with_args("controller", "action", action)
54
+ end
55
+ end
56
+
57
+ RSpec.configure{ |c| c.include Helpers }
58
+
59
+ RSpec::Matchers.define :be_instruction do |instruction|
60
+ match do |actual|
61
+ (actual.first == instruction) &&
62
+ if defined?(@instruction_args)
63
+ (actual.drop(1) == @instruction_args)
64
+ else
65
+ true
66
+ end
67
+ end
68
+
69
+ chain :with_args do |*args|
70
+ @instruction_args = args
71
+ end
72
+
73
+ chain :without_args do
74
+ @instruction_args = []
75
+ end
76
+
77
+ failure_message_for_should do |actual|
78
+ message = "expected that #{actual} would be instruction #{instruction.inspect}"
79
+ if @instruction_args
80
+ if @instruction_args.empty?
81
+ message << "without args"
82
+ else
83
+ message << " with args #{@instruction_args}"
84
+ end
85
+ end
86
+ message
87
+ end
88
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'common_spec_methods'
3
+
4
+ describe "dynamic config interpretation", dynamic: true do
5
+ it "interprets web property id dynamically" do
6
+ visit '/snippet_presence?wip=UA-OVERRIDE-1'
7
+
8
+ first_instruction = gaq_pushed_instructions.first
9
+ first_instruction.should be_instruction("_setAccount", 'UA-OVERRIDE-1')
10
+ end
11
+
12
+ it "interprets anonymize_ip dynamically" do
13
+ visit '/snippet_presence?anonymize_ip=true'
14
+ gaq_pushed_instructions[1].should be_instruction('_gat._anonymizeIp')
15
+
16
+ visit '/snippet_presence?anonymize_ip=false'
17
+ gaq_pushed_instructions.each do |instruction|
18
+ instruction.should_not be_instruction('_gat._anonymizeIp')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'common_spec_methods'
3
+
4
+ describe "gaq next_request effect" do
5
+ it "renders events after redirect, but not after the request following" do
6
+ visit '/redirecting_action'
7
+
8
+ gaq_pushed_instructions.should have(4).items
9
+
10
+ first_instruction, second_instruction, third_instruction, fourth_instruction = gaq_pushed_instructions
11
+
12
+ first_instruction.should be_instruction("_setAccount")
13
+ second_instruction.should be_instruction("_trackPageview").without_args
14
+ third_instruction.should be_instruction('_trackEvent').with_args('from', 'redirecting', 'action')
15
+ fourth_instruction.should track_event_from_before_filter('target_action')
16
+
17
+ visit '/final_action'
18
+
19
+ gaq_pushed_instructions.should have(3).items
20
+
21
+ first_instruction, second_instruction, third_instruction = gaq_pushed_instructions
22
+
23
+ first_instruction.should be_instruction("_setAccount")
24
+ second_instruction.should be_instruction("_trackPageview").without_args
25
+ third_instruction.should track_event_from_before_filter('final_action')
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'common_spec_methods'
5
+
6
+ describe "gaq snippet presence" do
7
+ it "renders 'gaq' in the page" do
8
+ visit '/snippet_presence'
9
+ expect(page.body).to have_text("_gaq")
10
+ end
11
+
12
+ describe "conditional examples by rails environment" do
13
+ it "renders the configured basic web property id", :static do
14
+ visit '/snippet_presence'
15
+ expect(page.body).to have_text("UA-TESTSTAT-1")
16
+ end
17
+
18
+ it "renders the configured basic web property id", :dynamic do
19
+ visit '/snippet_presence'
20
+ expect(page.body).to have_text("UA-TESTDYNA-1")
21
+ end
22
+ end
23
+
24
+ describe "common spec methods" do
25
+ before { visit '/snippet_presence' }
26
+
27
+ it "renders a CDATA containing _gaq" do
28
+ gaq_cdata.should_not be_nil
29
+ end
30
+
31
+ it "starts by initializing _gaq array" do
32
+ gaq_js_instructions.first.should == "var _gaq = _gaq || [];"
33
+ end
34
+
35
+ it "continues with a _gaq.push line" do
36
+ gaq_js_instructions.second.should match(%r{\A_gaq.push\(.*\);\Z}m)
37
+ end
38
+
39
+ it "does not have more js lines before the snippet" do
40
+ gaq_js_instructions.should have(2).items
41
+ end
42
+
43
+ it "continues with the snippet, and that's the end" do
44
+ snippet_and_beyond.should have(1).item
45
+ snippet_and_beyond.first.should start_with('(function()')
46
+ snippet_and_beyond.first.should end_with('})();')
47
+ end
48
+
49
+ describe "pushed instructions" do
50
+ it "pushed the expected instructions, part 1" do
51
+ gaq_pushed_instructions.should have(3).items
52
+
53
+ first_instruction, second_instruction, third_instruction = gaq_pushed_instructions
54
+ first_instruction.should be_instruction("_setAccount")
55
+ second_instruction.should be_instruction("_trackPageview").without_args
56
+ third_instruction.should track_event_from_before_filter('snippet_presence')
57
+ end
58
+
59
+ it "pushed the expected instructions, part 2", :static do
60
+ gaq_pushed_instructions.first.should be_instruction("_setAccount").with_args('UA-TESTSTAT-1')
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,41 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require File.expand_path("../../config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+ require 'capybara/rails'
7
+
8
+ # Requires supporting ruby files with custom matchers and macros, etc,
9
+ # in spec/support/ and its subdirectories.
10
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+ # ## Mock Framework
14
+ #
15
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
16
+ #
17
+ # config.mock_with :mocha
18
+ # config.mock_with :flexmock
19
+ # config.mock_with :rr
20
+
21
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
22
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
23
+
24
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
25
+ # examples within a transaction, remove the following line or assign false
26
+ # instead of true.
27
+ # config.use_transactional_fixtures = true
28
+
29
+ # If true, the base class of anonymous controllers will be inferred
30
+ # automatically. This will be the default behavior in future versions of
31
+ # rspec-rails.
32
+ config.infer_base_class_for_anonymous_controllers = false
33
+
34
+ # Run specs in random order to surface order dependencies. If you find an
35
+ # order dependency and want to debug it, you can fix the order by providing
36
+ # the seed, which is printed after each run.
37
+ # --seed 1234
38
+ config.order = "random"
39
+
40
+ config.treat_symbols_as_metadata_keys_with_true_values = true
41
+ end
@@ -0,0 +1,62 @@
1
+ require 'gaq/class_cache'
2
+
3
+ module Gaq
4
+ describe ClassCache do
5
+ let(:assertion_double) { double }
6
+
7
+ shared_context silence_double: true do
8
+ before do
9
+ assertion_double.as_null_object
10
+ end
11
+ end
12
+
13
+ before do
14
+ subject.building(:foo, String) do |cls|
15
+ assertion_double.build(:foo)
16
+ cls.class_eval do
17
+ def foo
18
+ "foo"
19
+ end
20
+ end
21
+ end
22
+
23
+ subject.building(:bar, Hash) do |cls|
24
+ assertion_double.build(:bar)
25
+ subject[:foo]
26
+ cls.class_eval do
27
+ def bar
28
+ "bar"
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ context silence_double: true do
35
+ it "builds a class as instructed" do
36
+ built = subject[:foo]
37
+ built.should be < String
38
+ built.new.foo.should be == "foo"
39
+ end
40
+
41
+ it "raises an exception on miss" do
42
+ expect {
43
+ subject[:baz]
44
+ }.to raise_exception ClassCache::Miss
45
+ end
46
+ end
47
+
48
+ it "only builds the class once" do
49
+ assertion_double.should_receive(:build).with(:foo).once
50
+
51
+ subject[:foo]
52
+ subject[:foo]
53
+ end
54
+
55
+ it "implicitly supports dependencies" do
56
+ assertion_double.should_receive(:build).with(:foo)
57
+
58
+ assertion_double.should_receive(:build).with(:bar)
59
+ subject[:bar]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,267 @@
1
+ require 'gaq/command_language'
2
+
3
+ module Gaq
4
+ describe CommandLanguage do
5
+ let(:value_coercer) { double "value coercer" }
6
+
7
+ def null_coercing
8
+ value_coercer.stub(:call) { |type, value| value }
9
+ end
10
+
11
+ subject do
12
+ result = described_class.new
13
+ result.value_coercer = value_coercer
14
+ result
15
+ end
16
+
17
+ let(:descriptors) { {} }
18
+
19
+ before do
20
+ subject.knows_command(:foo) do |desc|
21
+ desc.signature = [String]
22
+ desc.name = "_myFooCommand"
23
+ descriptors[:foo] = desc
24
+ end if example.metadata[:foo_command]
25
+
26
+ subject.knows_command(:bar) do |desc|
27
+ desc.signature = [String, Integer]
28
+ desc.name = "_myBarCommand"
29
+ desc.sort_slot = 1
30
+ descriptors[:bar] = desc
31
+ end if example.metadata[:bar_command]
32
+
33
+ subject.knows_command(:baz) do |desc|
34
+ desc.signature = []
35
+ desc.name = "_myBazCommand"
36
+ desc.sort_slot = 0
37
+ descriptors[:baz] = desc
38
+ end if example.metadata[:baz_command]
39
+ end
40
+
41
+ RSpec::Matchers.define :be_identified_as do |identifier|
42
+ match do |command|
43
+ command.descriptor.identifier.equal? identifier
44
+ end
45
+ end
46
+
47
+ describe ".new_command" do
48
+ it "returns a properly identified and named command", foo_command: true do
49
+ null_coercing
50
+
51
+ command = subject.new_command(:foo, "string")
52
+
53
+ command.should be_identified_as(:foo)
54
+ command.name.should be == "_myFooCommand"
55
+ end
56
+
57
+ it "passes params through value coercer", foo_command: true do
58
+ value_coercer.should_receive(:call).with(String, "string").and_return "coerced string"
59
+
60
+ command = subject.new_command(:foo, "string")
61
+
62
+ command.params.should be == ["coerced string"]
63
+ end
64
+
65
+ it "passes only given params through coercer, even if less than signature length", bar_command: true do
66
+ value_coercer.should_receive(:call).with(String, "string").and_return "coerced string"
67
+
68
+ command = subject.new_command(:bar, "string")
69
+
70
+ command.params.should be == ["coerced string"]
71
+ end
72
+ end
73
+
74
+ shared_examples ".commands_to_flash_items behaves" do
75
+ let(:flash_data_item) do
76
+ flash_items = subject.commands_to_flash_items([command])
77
+ flash_items.should have(1).item
78
+ flash_items.first
79
+ end
80
+
81
+ context "with a command accepting two parameters", bar_command: true do
82
+ let(:command) do
83
+ command = CommandLanguage::Command.new
84
+ command.descriptor = descriptors[:bar]
85
+ command.name = "_myBarCommand"
86
+ command.params = []
87
+ command
88
+ end
89
+
90
+ it "adds params to data items" do
91
+ command.params << "first param" << "second param"
92
+
93
+ flash_data_item.should have(3).items
94
+ flash_data_item[1].should be == "first param"
95
+ flash_data_item[2].should be == "second param"
96
+ end
97
+
98
+ it "adds only as many params as signature length" do
99
+ command.params << "first param"
100
+
101
+ flash_data_item.should have(2).items
102
+ flash_data_item[1].should be == "first param"
103
+ end
104
+ end
105
+
106
+ context "with a command accepting one parameter", foo_command: true do
107
+ let(:command) do
108
+ command = CommandLanguage::Command.new
109
+ command.descriptor = descriptors[:foo]
110
+ command.name = "_myFooCommand"
111
+ command.params = ["param"]
112
+ command
113
+ end
114
+
115
+ it "sets the first flash item's first item to the command name (no target set)" do
116
+ null_coercing
117
+
118
+ flash_data_item.should have(2).items
119
+ flash_data_item.first.should be == "_myFooCommand"
120
+ end
121
+
122
+ it "sets the first flash item's first item to the command name (target set)" do
123
+ null_coercing
124
+
125
+ command.tracker_name = "tracker"
126
+
127
+ flash_data_item.should have(2).items
128
+ flash_data_item.first.should be == "tracker._myFooCommand"
129
+ end
130
+ end
131
+ end
132
+
133
+ describe ".commands_to_flash_items" do
134
+ let(:result) do
135
+ subject.commands_to_flash_items([command])
136
+ end
137
+
138
+ it_should_behave_like ".commands_to_flash_items behaves"
139
+ end
140
+
141
+ describe ".commands_to_segments_for_to_json" do
142
+ let(:result) do
143
+ subject.commands_to_segments_for_to_json([command])
144
+ end
145
+
146
+ it_should_behave_like ".commands_to_flash_items behaves"
147
+ end
148
+
149
+ describe ".sort_commands" do
150
+ def assert_order(commands)
151
+ commands[0].should be_identified_as(:baz)
152
+ commands[1].should be_identified_as(:bar)
153
+ commands[2].should be_identified_as(:foo)
154
+ end
155
+
156
+ it "sorts commands by sort_slot, missing sort_slot values last",
157
+ foo_command: true, bar_command: true, baz_command: true do
158
+ commands = [
159
+ subject.new_command(:foo),
160
+ subject.new_command(:bar),
161
+ subject.new_command(:baz)
162
+ ]
163
+
164
+ subject.sort_commands(commands)
165
+ assert_order(commands)
166
+
167
+ commands = [
168
+ subject.new_command(:bar),
169
+ subject.new_command(:foo),
170
+ subject.new_command(:baz)
171
+ ]
172
+
173
+ subject.sort_commands(commands)
174
+ assert_order(commands)
175
+ end
176
+ end
177
+
178
+ describe ".commands_from_flash_items", foo_command: true, bar_command: true do
179
+ it "correctly detects the command" do
180
+ flash_items = [
181
+ ["_myFooCommand"],
182
+ ["_myBarCommand"]
183
+ ]
184
+ commands = subject.commands_from_flash_items(flash_items)
185
+
186
+ commands.should have(2).items
187
+
188
+ command = commands.first
189
+ command.should be_identified_as(:foo)
190
+ command.name.should be == '_myFooCommand'
191
+
192
+ command = commands.last
193
+ command.should be_identified_as(:bar)
194
+ command.name.should be == '_myBarCommand'
195
+ end
196
+
197
+ it "sets command's params to remaining segments from flash item" do
198
+ flash_item = ["_myBarCommand", "first param", "second param"]
199
+
200
+ commands = subject.commands_from_flash_items([flash_item])
201
+
202
+ commands.should have(1).item
203
+ command = commands.first
204
+
205
+ command.params.should be == ["first param", "second param"]
206
+ end
207
+
208
+ it "sets tracker name to nil when no explicit tracker given" do
209
+ flash_item = ["_myFooCommand"]
210
+ commands = subject.commands_from_flash_items([flash_item])
211
+
212
+ commands.should have(1).item
213
+ command = commands.first
214
+
215
+ command.tracker_name.should be_nil
216
+ end
217
+
218
+ it "correctly sets present tracker name" do
219
+ flash_item = ["my_tracker._myFooCommand"]
220
+ commands = subject.commands_from_flash_items([flash_item])
221
+
222
+ commands.should have(1).item
223
+ command = commands.first
224
+
225
+ command.tracker_name.should be == "my_tracker"
226
+ end
227
+ end
228
+
229
+ describe ".coerce_value" do
230
+ describe "type :Boolean" do
231
+ it "coerces boolish values properly" do
232
+ described_class.coerce_value(:Boolean, true).should be true
233
+ described_class.coerce_value(:Boolean, false).should be false
234
+
235
+ described_class.coerce_value(:Boolean, 1).should be true
236
+ described_class.coerce_value(:Boolean, nil).should be false
237
+ end
238
+ end
239
+
240
+ describe "type :String" do
241
+ it "coerces values like String()" do
242
+ described_class.coerce_value(:String, "str").should be == "str"
243
+ described_class.coerce_value(:String, 1).should be == "1"
244
+
245
+ expect {
246
+ described_class.coerce_value(:String, BasicObject.new)
247
+ }.to raise_exception
248
+ end
249
+ end
250
+
251
+ describe "type :Int" do
252
+ it "coerces values like Integer()" do
253
+ described_class.coerce_value(:Int, 1).should be 1
254
+ described_class.coerce_value(:Int, "5").should be 5
255
+
256
+ expect {
257
+ described_class.coerce_value(:Int, "_")
258
+ }.to raise_exception
259
+
260
+ expect {
261
+ described_class.coerce_value(:Int, "3.14")
262
+ }.to raise_exception
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end