holoserve 0.3.0 → 0.3.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.
@@ -1,19 +1,15 @@
1
1
 
2
2
  class Holoserve::Fixture::Importer
3
3
 
4
+ attr_accessor :hash
4
5
  attr_accessor :fixtures
5
6
 
6
7
  def initialize(hash, fixtures)
7
- @fixtures = fixtures
8
- self.hash = hash
8
+ @hash, @fixtures = hash, fixtures
9
9
  end
10
10
 
11
- def hash=(value)
12
- @imports = value.respond_to?(:delete) && value.delete(:imports) || [ ]
13
- @hash = value
14
- end
15
-
16
- def hash
11
+ def result
12
+ @result = { }
17
13
  import
18
14
  merge
19
15
  @result
@@ -22,23 +18,30 @@ class Holoserve::Fixture::Importer
22
18
  private
23
19
 
24
20
  def import
25
- @imports.each do |import|
26
- path = import[:path]
27
- as = import[:as] || path
28
- only = import[:only]
21
+ imports.each do |import|
22
+ path, as, only, except = *import.values_at(:path, :as, :only, :except)
29
23
 
30
24
  value = Holoserve::Tool::DataPath.new(path, @fixtures).fetch
31
25
 
32
- value.delete_if do |key, v|
33
- ![ only ].flatten.compact.include?(key.to_s)
34
- end if only.respond_to?(:include?) && value.respond_to?(:delete_if)
26
+ if value.respond_to?(:reject)
27
+ value = value.reject{ |key, v| ![ only ].flatten.compact.include?(key.to_s) } if only
28
+ value = value.reject{ |key, v| [ except ].flatten.compact.include?(key.to_s) } if except
29
+ end
35
30
 
36
31
  @result = Holoserve::Tool::DataPath.new(as, @result || { }).store value
37
32
  end
38
33
  end
39
34
 
40
35
  def merge
41
- @result = Holoserve::Tool::Merger.new(@result, @hash).result if @hash
36
+ @result = Holoserve::Tool::Merger.new(@result, hash_without_imports).result
37
+ end
38
+
39
+ def hash_without_imports
40
+ @hash.reject{ |key, v| key == :imports }
41
+ end
42
+
43
+ def imports
44
+ @hash[:imports] || [ ]
42
45
  end
43
46
 
44
47
  end
@@ -8,13 +8,20 @@ class Holoserve::Interface::Control < Sinatra::Base
8
8
  mime_type :json, "application/json"
9
9
 
10
10
  post "/_control/pairs" do
11
- load_file_into(pairs) ?
12
- acknowledgement :
11
+ if pair_id = load_file_into(pairs)
12
+ logger.info "loaded pair #{pair_id}"
13
+ acknowledgement
14
+ else
13
15
  bad_request
16
+ end
17
+ end
18
+
19
+ get "/_control/pairs.:format" do |format|
20
+ respond_formatted params["evaluate"] ? evaluated_pairs : pairs, format
14
21
  end
15
22
 
16
23
  get "/_control/pairs/:id.:format" do |id, format|
17
- pair = pairs[id.to_sym]
24
+ pair = (params["evaluate"] ? evaluated_pairs : pairs)[id.to_sym]
18
25
  if pair
19
26
  respond_formatted pair, format
20
27
  else
@@ -27,9 +34,12 @@ class Holoserve::Interface::Control < Sinatra::Base
27
34
  end
28
35
 
29
36
  post "/_control/fixtures" do
30
- load_file_into(fixtures) ?
31
- acknowledgement :
37
+ if fixture_id = load_file_into(fixtures)
38
+ logger.info "loaded fixture #{fixture_id}"
39
+ acknowledgement
40
+ else
32
41
  bad_request
42
+ end
33
43
  end
34
44
 
35
45
  get "/_control/fixtures/:id.:format" do |id, format|
@@ -47,6 +57,7 @@ class Holoserve::Interface::Control < Sinatra::Base
47
57
 
48
58
  put "/_control/situation" do
49
59
  configuration[:situation] = params[:name]
60
+ logger.info "set situation to #{params[:name]}"
50
61
  respond_json_acknowledgement
51
62
  end
52
63
 
@@ -111,10 +122,10 @@ class Holoserve::Interface::Control < Sinatra::Base
111
122
 
112
123
  def load_file_into(hash)
113
124
  data = load_file params["file"][:tempfile]
114
- return false unless data
125
+ return nil unless data
115
126
  id = File.basename params["file"][:filename], ".*"
116
127
  hash[id.to_sym] = Holoserve::Tool::Hash::KeySymbolizer.new(data).hash
117
- true
128
+ id.to_sym
118
129
  end
119
130
 
120
131
  def load_file(filename)
@@ -127,6 +138,19 @@ class Holoserve::Interface::Control < Sinatra::Base
127
138
  end
128
139
  end
129
140
 
141
+ def evaluated_pairs
142
+ result = { }
143
+ pairs.each do |id, pair|
144
+ result[id] = { }
145
+ result[id][:request] = Holoserve::Fixture::Importer.new(pair[:request], fixtures).result
146
+ result[id][:responses] = { }
147
+ pair[:responses].each do |situation, response|
148
+ result[id][:responses][situation] = Holoserve::Fixture::Importer.new(response, fixtures).result
149
+ end
150
+ end
151
+ result
152
+ end
153
+
130
154
  def pairs
131
155
  configuration[:pairs]
132
156
  end
@@ -147,4 +171,8 @@ class Holoserve::Interface::Control < Sinatra::Base
147
171
  Holoserve.instance.configuration
148
172
  end
149
173
 
174
+ def logger
175
+ Holoserve.instance.logger
176
+ end
177
+
150
178
  end
@@ -3,7 +3,7 @@ class Holoserve::Request::Matcher
3
3
 
4
4
  def initialize(request, request_subset, fixtures)
5
5
  @request = request
6
- @request_subset = Holoserve::Fixture::Importer.new(request_subset, fixtures).hash
6
+ @request_subset = Holoserve::Fixture::Importer.new(request_subset, fixtures).result
7
7
  end
8
8
 
9
9
  def match?
@@ -13,13 +13,13 @@ class Holoserve::Response::Combiner
13
13
 
14
14
  def default_response
15
15
  @responses[:default] ?
16
- Holoserve::Fixture::Importer.new(@responses[:default], fixtures).hash :
16
+ Holoserve::Fixture::Importer.new(@responses[:default], fixtures).result :
17
17
  { }
18
18
  end
19
19
 
20
20
  def situation_response
21
21
  situation && @responses[situation.to_sym] ?
22
- Holoserve::Fixture::Importer.new(@responses[situation.to_sym], fixtures).hash :
22
+ Holoserve::Fixture::Importer.new(@responses[situation.to_sym], fixtures).result :
23
23
  { }
24
24
  end
25
25
 
@@ -13,7 +13,7 @@ class Holoserve::Response::Composer
13
13
  private
14
14
 
15
15
  def status
16
- @response[:status]
16
+ @response[:status] || 200
17
17
  end
18
18
 
19
19
  def headers
@@ -65,7 +65,8 @@ class Holoserve::Runner
65
65
 
66
66
  def set_situation
67
67
  Transport::JSON.request :put,
68
- "http://localhost:#{port}/_control/situation/#{@situation}",
68
+ "http://localhost:#{port}/_control/situation",
69
+ :parameters => { :name => @situation },
69
70
  :expected_status_code => 200
70
71
  nil
71
72
  end
@@ -30,9 +30,9 @@ class Holoserve::Tool::DataPath
30
30
 
31
31
  def store(value)
32
32
  path = @path ? @path.split(PATH_SEPARATOR) : [ ]
33
- return value if path.empty?
33
+ return Holoserve::Tool::Merger.new(@data, value).result if path.empty?
34
34
 
35
- selected = @data
35
+ result = selected = clone @data
36
36
  key = parse_key path.shift
37
37
 
38
38
  while path.length > 0
@@ -44,7 +44,7 @@ class Holoserve::Tool::DataPath
44
44
  end
45
45
 
46
46
  selected[key] = value
47
- @data
47
+ result
48
48
  end
49
49
 
50
50
  private
@@ -53,4 +53,8 @@ class Holoserve::Tool::DataPath
53
53
  key =~ /^\d+$/ ? key.to_i : key.to_sym
54
54
  end
55
55
 
56
+ def clone(object)
57
+ Marshal.load Marshal.dump(object)
58
+ end
59
+
56
60
  end
@@ -2,7 +2,13 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "he
2
2
 
3
3
  describe Holoserve::Fixture::Importer do
4
4
 
5
- let(:fixtures) { { :test => { :nested => "value", :second => "value" }, :another => "value" } }
5
+ let(:fixtures) do
6
+ {
7
+ :one => { :first => 1, :second => 2 }.freeze,
8
+ :two => 3,
9
+ :three => { :third => 4 }.freeze
10
+ }.freeze
11
+ end
6
12
 
7
13
  subject { described_class.new nil, fixtures }
8
14
 
@@ -12,66 +18,102 @@ describe Holoserve::Fixture::Importer do
12
18
  subject.hash = {
13
19
  :test => "value"
14
20
  }
15
- subject.hash.should == { :test => "value" }
21
+ subject.result.should == { :test => "value" }
16
22
  end
17
23
 
18
24
  it "should return a hash with imported fixtures" do
19
25
  subject.hash = {
20
26
  :imports => [
21
- { :path => "test.nested" }
27
+ { :path => "one" }
22
28
  ]
23
29
  }
24
- subject.hash.should == { :test => { :nested => "value" } }
30
+ subject.result.should == { :first => 1, :second => 2 }
25
31
  end
26
32
 
27
33
  it "should return a hash with imported fixtures at a target path" do
28
34
  subject.hash = {
29
35
  :imports => [
30
- { :path => "test.nested", :as => "test" }
36
+ { :path => "one.first", :as => "test" }
31
37
  ]
32
38
  }
33
- subject.hash.should == { :test => "value" }
39
+ subject.result.should == { :test => 1 }
34
40
  end
35
41
 
36
- it "should return a hash with imported and filtered fixtures" do
42
+ it "should return a hash with imported and white-list filtered fixtures" do
37
43
  subject.hash = {
38
44
  :imports => [
39
- { :path => "test", :as => "test", :only => [ "second" ] }
45
+ { :path => "one", :as => "test", :only => "second" }
40
46
  ]
41
47
  }
42
- subject.hash.should == { :test => { :second => "value" } }
48
+ subject.result.should == { :test => { :second => 2 } }
49
+ end
50
+
51
+ it "should return a hash with imported and black-list filtered fixtures" do
52
+ subject.hash = {
53
+ :imports => [
54
+ { :path => "one", :as => "test", :except => [ "second" ] }
55
+ ]
56
+ }
57
+ subject.result.should == { :test => { :first => 1 } }
43
58
  end
44
59
 
45
60
  it "should return a hash where all the imports are imported" do
46
61
  subject.hash = {
47
62
  :imports => [
48
- { :path => "test.nested", :as => "test" },
49
- { :path => "another", :as => "another.test" }
63
+ { :path => "one.first", :as => "test" },
64
+ { :path => "two", :as => "another.test" }
65
+ ]
66
+ }
67
+ subject.result.should == { :test => 1, :another => { :test => 3 } }
68
+ end
69
+
70
+ it "should return a hash where all the imports are merged together" do
71
+ subject.hash = {
72
+ :imports => [
73
+ { :path => "one" },
74
+ { :path => "three" }
50
75
  ]
51
76
  }
52
- subject.hash.should == { :test => "value", :another => { :test => "value" } }
77
+ subject.result.should == { :first => 1, :second => 2, :third => 4 }
53
78
  end
54
79
 
55
80
  it "should return a hash where the data is merged with the imports" do
56
81
  subject.hash = {
57
82
  :imports => [
58
- { :path => "test.nested", :as => "test" }
83
+ { :path => "one.first", :as => "test" }
59
84
  ],
60
85
  :another => "value"
61
86
  }
62
- subject.hash.should == { :test => "value", :another => "value" }
87
+ subject.result.should == { :test => 1, :another => "value" }
63
88
  end
64
89
 
65
90
  it "should return a hash where the data is deep merged with the imports" do
66
91
  subject.hash = {
67
92
  :imports => [
68
- { :path => "test.nested", :as => "test.nested" }
93
+ { :path => "one.first", :as => "test.nested" }
69
94
  ],
70
95
  :test => {
71
96
  :another => "value"
72
97
  }
73
98
  }
74
- subject.hash.should == { :test => { :nested => "value", :another => "value" } }
99
+ subject.result.should == { :test => { :nested => 1, :another => "value" } }
100
+ end
101
+
102
+ it "should not destroy the original hash and stay repeatable" do
103
+ hash = {
104
+ :imports => [
105
+ { :path => "three" },
106
+ { :path => "one.first", :as => "test.nested" }
107
+ ],
108
+ :test => {
109
+ :another => "value"
110
+ }
111
+ }
112
+ subject.hash = hash
113
+ subject.result.should == { :third => 4, :test => { :nested => 1, :another => "value" } }
114
+
115
+ importer = described_class.new hash, fixtures
116
+ importer.result.should == { :third => 4, :test => { :nested => 1, :another => "value" } }
75
117
  end
76
118
 
77
119
  end
@@ -8,37 +8,37 @@ describe Holoserve::Tool::DataPath do
8
8
 
9
9
  it "should return the given data if no path is specified" do
10
10
  subject.path = nil
11
- subject.data = { :test => "value" }
11
+ subject.data = { :test => "value" }.freeze
12
12
  subject.fetch.should == { :test => "value" }
13
13
  end
14
14
 
15
15
  it "should return the value specified by the given path" do
16
16
  subject.path = "test"
17
- subject.data = { :test => "value" }
17
+ subject.data = { :test => "value" }.freeze
18
18
  subject.fetch.should == "value"
19
19
  end
20
20
 
21
21
  it "should return the nested value specified by the given path" do
22
22
  subject.path = "test.nested"
23
- subject.data = { :test => { :nested => "value" } }
23
+ subject.data = { :test => { :nested => "value" }.freeze }.freeze
24
24
  subject.fetch.should == "value"
25
25
  end
26
26
 
27
27
  it "should return nil if the path points to nowhere" do
28
28
  subject.path = "test.nested"
29
- subject.data = { :test => true }
29
+ subject.data = { :test => true }.freeze
30
30
  subject.fetch.should be_nil
31
31
  end
32
32
 
33
33
  it "should return nil if the last path element doesn't exists'" do
34
34
  subject.path = "test.nested"
35
- subject.data = { :test => { :another => "value" } }
35
+ subject.data = { :test => { :another => "value" }.freeze }.freeze
36
36
  subject.fetch.should be_nil
37
37
  end
38
38
 
39
39
  it "should return in an array nested value specified by the given path" do
40
40
  subject.path = "test.1.nested"
41
- subject.data = { :test => [ { }, { :nested => "value" } ] }
41
+ subject.data = { :test => [ { }.freeze, { :nested => "value" }.freeze ].freeze }.freeze
42
42
  subject.fetch.should == "value"
43
43
  end
44
44
 
@@ -46,27 +46,33 @@ describe Holoserve::Tool::DataPath do
46
46
 
47
47
  describe "store" do
48
48
 
49
- it "should return the given value if no path is specified" do
49
+ it "should merge the given value with the root element if no path is given" do
50
50
  subject.path = nil
51
- subject.data = { :test => "value" }
51
+ subject.data = { :test => "value" }.freeze
52
+ subject.store(:another => "value").should == { :test => "value", :another => "value" }
53
+ end
54
+
55
+ it "should return the value if no path is given and value is not mergeable" do
56
+ subject.path = nil
57
+ subject.data = { :test => "value" }.freeze
52
58
  subject.store("value").should == "value"
53
59
  end
54
60
 
55
61
  it "should store the given value at the specified path" do
56
62
  subject.path = "another"
57
- subject.data = { :test => "value" }
63
+ subject.data = { :test => "value" }.freeze
58
64
  subject.store("value").should == { :test => "value", :another => "value" }
59
65
  end
60
66
 
61
67
  it "should store the given value in a nested hash" do
62
68
  subject.path = "test.another"
63
- subject.data = { :test => { :nested => "value" } }
69
+ subject.data = { :test => { :nested => "value" }.freeze }.freeze
64
70
  subject.store("value").should == { :test => { :nested => "value", :another => "value" } }
65
71
  end
66
72
 
67
73
  it "should store the given value at the specified path and create it if missing" do
68
74
  subject.path = "another.test"
69
- subject.data = { :test => "value" }
75
+ subject.data = { :test => "value" }.freeze
70
76
  subject.store("value").should == { :test => "value", :another => { :test => "value" } }
71
77
  end
72
78
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: holoserve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000 Z
12
+ date: 2012-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
16
- requirement: &70132546243580 !ruby/object:Gem::Requirement
16
+ requirement: &70159532631360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70132546243580
24
+ version_requirements: *70159532631360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sinatra
27
- requirement: &70132546257040 !ruby/object:Gem::Requirement
27
+ requirement: &70159532629620 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70132546257040
35
+ version_requirements: *70159532629620
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: unicorn
38
- requirement: &70132546255800 !ruby/object:Gem::Requirement
38
+ requirement: &70159532627220 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70132546255800
46
+ version_requirements: *70159532627220
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: transport
49
- requirement: &70132546254300 !ruby/object:Gem::Requirement
49
+ requirement: &70159532638140 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70132546254300
57
+ version_requirements: *70159532638140
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: cucumber
60
- requirement: &70132546252800 !ruby/object:Gem::Requirement
60
+ requirement: &70159532632680 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70132546252800
68
+ version_requirements: *70159532632680
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70132546265600 !ruby/object:Gem::Requirement
71
+ requirement: &70159532646160 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70132546265600
79
+ version_requirements: *70159532646160
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: transport
82
- requirement: &70132546264780 !ruby/object:Gem::Requirement
82
+ requirement: &70159532643660 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70132546264780
90
+ version_requirements: *70159532643660
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: oauth
93
- requirement: &70132546263580 !ruby/object:Gem::Requirement
93
+ requirement: &70159532640540 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70132546263580
101
+ version_requirements: *70159532640540
102
102
  description: This tool can be used to fake webservice APIs for testing proposals.
103
103
  email: philipp.bruell@skrill.com
104
104
  executables:
@@ -150,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
150
150
  version: '0'
151
151
  segments:
152
152
  - 0
153
- hash: 4596962680025174660
153
+ hash: -2968421100355071724
154
154
  required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  none: false
156
156
  requirements: