gaq 0.2.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.
- data/.gitignore +18 -0
- data/Gemfile +15 -0
- data/Guardfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.md +102 -0
- data/Rakefile +1 -0
- data/gaq.gemspec +22 -0
- data/lib/gaq.rb +3 -0
- data/lib/gaq/class_cache.rb +32 -0
- data/lib/gaq/command_language.rb +145 -0
- data/lib/gaq/configuration.rb +159 -0
- data/lib/gaq/controller_facade.rb +15 -0
- data/lib/gaq/controller_handle.rb +93 -0
- data/lib/gaq/dsl_target.rb +51 -0
- data/lib/gaq/dsl_target_factory.rb +64 -0
- data/lib/gaq/flash_commands_adapter.rb +48 -0
- data/lib/gaq/interprets_config.rb +13 -0
- data/lib/gaq/railtie.rb +40 -0
- data/lib/gaq/snippet_renderer.rb +44 -0
- data/lib/gaq/version.rb +3 -0
- data/spec-dummy/.rspec +1 -0
- data/spec-dummy/README.rdoc +261 -0
- data/spec-dummy/Rakefile +7 -0
- data/spec-dummy/app/assets/images/rails.png +0 -0
- data/spec-dummy/app/assets/javascripts/application.js +13 -0
- data/spec-dummy/app/assets/stylesheets/application.css +13 -0
- data/spec-dummy/app/controllers/application_controller.rb +3 -0
- data/spec-dummy/app/controllers/integration_spec_controller.rb +22 -0
- data/spec-dummy/app/helpers/application_helper.rb +2 -0
- data/spec-dummy/app/views/integration_spec/view.erb +0 -0
- data/spec-dummy/app/views/layouts/application.html.erb +16 -0
- data/spec-dummy/config.ru +4 -0
- data/spec-dummy/config/application.rb +64 -0
- data/spec-dummy/config/boot.rb +6 -0
- data/spec-dummy/config/environment.rb +5 -0
- data/spec-dummy/config/environments/development.rb +26 -0
- data/spec-dummy/config/environments/production.rb +51 -0
- data/spec-dummy/config/environments/test_dynamic.rb +39 -0
- data/spec-dummy/config/environments/test_static.rb +38 -0
- data/spec-dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec-dummy/config/initializers/inflections.rb +15 -0
- data/spec-dummy/config/initializers/mime_types.rb +5 -0
- data/spec-dummy/config/initializers/secret_token.rb +7 -0
- data/spec-dummy/config/initializers/session_store.rb +8 -0
- data/spec-dummy/config/initializers/wrap_parameters.rb +10 -0
- data/spec-dummy/config/locales/en.yml +5 -0
- data/spec-dummy/config/routes.rb +8 -0
- data/spec-dummy/db/seeds.rb +7 -0
- data/spec-dummy/public/404.html +26 -0
- data/spec-dummy/public/422.html +26 -0
- data/spec-dummy/public/500.html +25 -0
- data/spec-dummy/public/favicon.ico +0 -0
- data/spec-dummy/public/robots.txt +5 -0
- data/spec-dummy/script/rails +6 -0
- data/spec-dummy/spec/common_spec_methods.rb +88 -0
- data/spec-dummy/spec/features/dynamic_config_spec.rb +21 -0
- data/spec-dummy/spec/features/next_request_spec.rb +27 -0
- data/spec-dummy/spec/features/presence_spec.rb +64 -0
- data/spec-dummy/spec/spec_helper.rb +41 -0
- data/spec/lib/gaq/class_cache_spec.rb +62 -0
- data/spec/lib/gaq/command_language_spec.rb +267 -0
- data/spec/lib/gaq/configuration_spec.rb +233 -0
- data/spec/lib/gaq/controller_facade_spec.rb +29 -0
- data/spec/lib/gaq/controller_handle_spec.rb +510 -0
- data/spec/lib/gaq/dsl_target_factory_spec.rb +163 -0
- data/spec/lib/gaq/dsl_target_spec.rb +87 -0
- data/spec/lib/gaq/flash_commands_adapter_spec.rb +116 -0
- data/spec/lib/gaq/interprets_config_spec.rb +37 -0
- data/spec/lib/gaq/snippet_renderer_spec.rb +60 -0
- 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,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
|