gaq 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|