lolsoap 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3
+ <soap:Body>
4
+ <soap:Fault>
5
+ <soap:faultcode>soap:Sender</soap:faultcode>
6
+ <soap:faultstring>Omg! stock market has crashed!</soap:faultstring>
7
+ <soap:detail><Foo>Some detail</Foo></soap:detail>
8
+ </soap:Fault>
9
+ </soap:Body>
10
+ </soap:Envelope>
@@ -21,6 +21,7 @@ module LolSoap
21
21
  s.name 'LOCOLOCOLOCO'
22
22
  end
23
23
  b.lol
24
+ b.id 42
24
25
  end
25
26
 
26
27
  el = doc.at_xpath('//xsd1:TradePriceRequest/xsd1:tickerSymbol', doc.namespaces)
@@ -30,6 +31,9 @@ module LolSoap
30
31
  el = doc.at_xpath('//xsd1:TradePriceRequest/xsd1:specialTickerSymbol/xsd2:name', doc.namespaces)
31
32
  el.wont_equal nil
32
33
  el.text.to_s.must_equal 'LOCOLOCOLOCO'
34
+
35
+ attr = doc.at_xpath('//xsd1:TradePriceRequest/@id', doc.namespaces)
36
+ attr.to_s.must_equal "42"
33
37
  end
34
38
 
35
39
  it 'creates some header' do
@@ -8,14 +8,13 @@ module LolSoap
8
8
  it 'should successfully parse a WSDL document' do
9
9
  subject.operations.length.must_equal 1
10
10
  subject.operations['GetLastTradePrice'].tap do |o|
11
- o.input.must_equal subject.types['TradePriceRequest']
11
+ o.input.must_equal subject.types['xsd1:TradePriceRequest']
12
12
  o.action.must_equal 'http://example.com/GetLastTradePrice'
13
13
  end
14
14
 
15
15
  subject.types.length.must_equal 3
16
- subject.types['TradePriceRequest'].tap do |t|
17
- t.name.must_equal 'TradePriceRequest'
18
- t.namespace.must_equal 'http://example.com/stockquote.xsd'
16
+ subject.types['xsd1:TradePriceRequest'].tap do |t|
17
+ t.prefix.must_equal 'xsd1'
19
18
  end
20
19
  end
21
20
 
@@ -15,6 +15,7 @@ module LolSoap
15
15
  end
16
16
  let(:type) do
17
17
  type = OpenStruct.new(:prefix => 'a')
18
+ def type.has_attribute?(*); false; end
18
19
  def type.sub_type(name)
19
20
  @sub_types ||= { 'foo' => Object.new, 'bar' => Object.new, 'clone' => Object.new }
20
21
  @sub_types[name]
@@ -3,7 +3,13 @@ require 'lolsoap/envelope'
3
3
 
4
4
  module LolSoap
5
5
  describe Envelope do
6
- let(:wsdl) { OpenStruct.new(:type_namespaces => { 'foo' => 'http://example.com/foo' }) }
6
+ let(:wsdl) do
7
+ OpenStruct.new(
8
+ :type_namespaces => { 'foo' => 'http://example.com/foo' },
9
+ :soap_version => '1.2'
10
+ )
11
+ end
12
+
7
13
  let(:operation) do
8
14
  OpenStruct.new(:input => OpenStruct.new(:prefix => 'foo', :name => 'WashHandsRequest'))
9
15
  end
@@ -16,7 +22,7 @@ module LolSoap
16
22
 
17
23
  it 'has a skeleton SOAP envelope structure when first created' do
18
24
  doc.namespaces.must_equal(
19
- 'xmlns:soap' => Envelope::SOAP_NAMESPACE,
25
+ 'xmlns:soap' => Envelope::SOAP_1_2,
20
26
  'xmlns:foo' => 'http://example.com/foo'
21
27
  )
22
28
 
@@ -84,7 +90,11 @@ module LolSoap
84
90
 
85
91
  describe '#to_xml' do
86
92
  it 'returns the xml of the doc' do
87
- def subject.doc; OpenStruct.new(:to_xml => '<lol>'); end
93
+ def subject.doc
94
+ doc = Object.new
95
+ def doc.to_xml(options); '<lol>'; end
96
+ doc
97
+ end
88
98
  subject.to_xml.must_equal '<lol>'
89
99
  end
90
100
  end
@@ -108,5 +118,15 @@ module LolSoap
108
118
  subject.output_type.must_equal 'lol'
109
119
  end
110
120
  end
121
+
122
+ describe '#soap_namespace' do
123
+ it 'returns the correct envelope namespace according to the SOAP version' do
124
+ wsdl.soap_version = '1.2'
125
+ subject.soap_namespace.must_equal Envelope::SOAP_1_2
126
+
127
+ wsdl.soap_version = '1.1'
128
+ subject.soap_namespace.must_equal Envelope::SOAP_1_1
129
+ end
130
+ end
111
131
  end
112
132
  end
@@ -4,30 +4,48 @@ require 'lolsoap/fault'
4
4
 
5
5
  module LolSoap
6
6
  describe Fault do
7
- let(:request) { OpenStruct.new(:soap_namespace => Envelope::SOAP_NAMESPACE) }
8
- let(:node) do
9
- doc = Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote_fault.xml'))
10
- doc.at_xpath('//soap:Fault', 'soap' => Envelope::SOAP_NAMESPACE)
11
- end
7
+ examples = proc do
8
+ describe '#code' do
9
+ it 'returns the code' do
10
+ subject.code.must_equal 'soap:Sender'
11
+ end
12
+ end
12
13
 
13
- subject { Fault.new(request, node) }
14
+ describe '#reason' do
15
+ it 'returns the reason' do
16
+ subject.reason.must_match(/^Omg.*crashed!$/)
17
+ end
18
+ end
14
19
 
15
- describe '#code' do
16
- it 'returns the code' do
17
- subject.code.must_equal 'soap:Sender'
20
+ describe '#detail' do
21
+ it 'returns the detail' do
22
+ subject.detail.must_equal '<Foo>Some detail</Foo>'
23
+ end
18
24
  end
19
25
  end
20
26
 
21
- describe '#reason' do
22
- it 'returns the reason' do
23
- subject.reason.must_match(/^Omg.*crashed!$/)
27
+ describe 'SOAP 1.1' do
28
+ let(:request) { OpenStruct.new(:soap_version => '1.2', :soap_namespace => Envelope::SOAP_1_2) }
29
+ let(:node) do
30
+ doc = Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote_fault.xml'))
31
+ doc.at_xpath('//soap:Fault', 'soap' => Envelope::SOAP_1_2)
24
32
  end
33
+
34
+ subject { Fault.new(request, node) }
35
+
36
+ instance_eval(&examples)
25
37
  end
26
38
 
27
- describe '#detail' do
28
- it 'returns the detail' do
29
- subject.detail.must_equal '<Foo>Some detail</Foo>'
39
+ describe 'SOAP 1.2' do
40
+ let(:request) { OpenStruct.new(:soap_version => '1.1', :soap_namespace => Envelope::SOAP_1_1) }
41
+ let(:node) do
42
+ doc = Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote_fault_soap_1_1.xml'))
43
+ doc.at_xpath('//soap:Fault', 'soap' => Envelope::SOAP_1_1)
30
44
  end
45
+
46
+ subject { Fault.new(request, node) }
47
+
48
+ instance_eval(&examples)
31
49
  end
32
50
  end
33
51
  end
@@ -6,18 +6,6 @@ module LolSoap
6
6
  let(:envelope) { OpenStruct.new }
7
7
  subject { Request.new(envelope) }
8
8
 
9
- [:header, :body, :soap_namespace, :input_type, :output_type].each do |method|
10
- describe "##{method}" do
11
- let(:envelope) { MiniTest::Mock.new }
12
-
13
- it 'delegates to the envelope' do
14
- ret = Object.new
15
- envelope.expect(method, ret)
16
- subject.send(method).must_equal ret
17
- end
18
- end
19
- end
20
-
21
9
  describe '#url' do
22
10
  it 'returns the envelope endpoint' do
23
11
  envelope.endpoint = 'lol'
@@ -27,7 +15,7 @@ module LolSoap
27
15
 
28
16
  describe '#headers' do
29
17
  it 'returns the necessary headers' do
30
- envelope.to_xml = '<lol>'
18
+ def envelope.to_xml(options); '<lol>'; end
31
19
  envelope.action = 'http://example.com/LolOutLoud'
32
20
 
33
21
  subject.headers.must_equal({
@@ -40,9 +28,21 @@ module LolSoap
40
28
 
41
29
  describe '#content' do
42
30
  it 'returns the envelope as an xml string' do
43
- envelope.to_xml = '<lol>'
31
+ def envelope.to_xml(options); '<lol>'; end
44
32
  subject.content.must_equal '<lol>'
45
33
  end
46
34
  end
35
+
36
+ describe '#mime' do
37
+ it 'is application/soap+xml for SOAP 1.2' do
38
+ envelope.soap_version = '1.2'
39
+ subject.mime.must_equal 'application/soap+xml'
40
+ end
41
+
42
+ it 'is text/xml for SOAP 1.1' do
43
+ envelope.soap_version = '1.1'
44
+ subject.mime.must_equal 'text/xml'
45
+ end
46
+ end
47
47
  end
48
48
  end
@@ -4,7 +4,7 @@ require 'lolsoap/response'
4
4
 
5
5
  module LolSoap
6
6
  describe Response do
7
- let(:request) { OpenStruct.new(:soap_namespace => Envelope::SOAP_NAMESPACE, :output => Object.new) }
7
+ let(:request) { OpenStruct.new(:soap_namespace => Envelope::SOAP_1_2, :soap_version => '1.2', :output => Object.new) }
8
8
  let(:doc) { Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote_response.xml')) }
9
9
 
10
10
  subject { Response.new(request, doc) }
@@ -5,137 +5,118 @@ module LolSoap
5
5
  describe WSDL do
6
6
  describe 'with a doc that can be parsed' do
7
7
  let(:namespace) { 'http://lolsoap.api/bla' }
8
- let(:parser) { OpenStruct.new(:namespaces => { 'bla' => namespace }) }
9
8
 
10
- subject { WSDL.new(parser) }
11
-
12
- describe 'with operations' do
13
- before do
14
- def subject.type(n)
15
- @types ||= { 'WashHandsRequest' => Object.new, 'WashHandsResponse' => Object.new }
16
- @types[n]
17
- end
18
-
19
- parser.operations = {
9
+ let(:parser) do
10
+ OpenStruct.new(
11
+ :namespaces => { 'bla' => namespace },
12
+ :operations => {
20
13
  'washHands' => {
21
14
  :action => 'urn:washHands',
22
- :input => { :name => 'WashHandsRequest' },
23
- :output => { :name => 'WashHandsResponse' }
15
+ :input => 'bla:Brush',
16
+ :output => 'bla:Color'
24
17
  }
25
- }
26
- end
27
-
28
- describe '#operations' do
29
- it 'returns a hash of operations' do
30
- subject.operations.length.must_equal 1
31
- subject.operations['washHands'].tap do |op|
32
- op.wsdl.must_equal subject
33
- op.action.must_equal "urn:washHands"
34
- op.input.must_equal subject.types['WashHandsRequest']
35
- op.output.must_equal subject.types['WashHandsResponse']
36
- end
37
- end
38
- end
39
-
40
- describe '#operation' do
41
- it 'returns a single operation' do
42
- subject.operation('washHands').must_equal subject.operations['washHands']
43
- end
44
- end
45
- end
46
-
47
- describe '#endpoint' do
48
- it 'returns the endpoint' do
49
- parser.endpoint = 'http://lolsoap.api/v1'
50
- subject.endpoint.must_equal 'http://lolsoap.api/v1'
51
- end
52
- end
53
-
54
- describe '#namespaces' do
55
- it 'returns a namespaces hash' do
56
- subject.namespaces.must_equal({ 'bla' => namespace })
57
- end
58
- end
59
-
60
- describe '#prefixes' do
61
- it 'returns the prefixes-to-namespace mapping' do
62
- subject.prefixes.must_equal({ namespace => 'bla' })
63
- end
64
- end
65
-
66
- describe 'with types' do
67
- before do
68
- parser.types = {
69
- 'Brush' => {
18
+ },
19
+ :types => {
20
+ 'bla:Brush' => {
70
21
  :elements => {
71
22
  'handleColor' => {
72
- :name => 'handleColor',
73
23
  :type => 'bla:Color',
74
24
  :singular => true
75
25
  },
76
26
  'age' => {
77
- :name => 'age',
78
27
  :type => 'xs:int',
79
28
  :singular => false
80
29
  }
81
30
  },
82
- :namespace => namespace
31
+ :attributes => ['id'],
32
+ :prefix => 'bla'
83
33
  },
84
- 'Color' => {
34
+ 'bla:Color' => {
85
35
  :elements => {
86
36
  'name' => {
87
- :name => 'name',
88
37
  :type => 'xs:string',
89
38
  :singular => true
90
39
  },
91
40
  'hex' => {
92
- :name => 'hex',
93
41
  :type => 'xs:string',
94
42
  :singular => true
95
43
  }
96
44
  },
97
- :namespace => namespace
45
+ :attributes => [],
46
+ :prefix => 'bla'
98
47
  }
99
48
  }
49
+ )
50
+ end
51
+
52
+ subject { WSDL.new(parser) }
53
+
54
+ describe '#operations' do
55
+ it 'returns a hash of operations' do
56
+ subject.operations.length.must_equal 1
57
+ subject.operations['washHands'].tap do |op|
58
+ op.wsdl.must_equal subject
59
+ op.action.must_equal "urn:washHands"
60
+ op.input.must_equal subject.types['bla:Brush']
61
+ op.output.must_equal subject.types['bla:Color']
62
+ end
100
63
  end
64
+ end
101
65
 
102
- describe '#types' do
103
- it 'returns a hash of types' do
104
- subject.types.length.must_equal 2
66
+ describe '#operation' do
67
+ it 'returns a single operation' do
68
+ subject.operation('washHands').must_equal subject.operations['washHands']
69
+ end
70
+ end
105
71
 
106
- subject.types['Brush'].tap do |t|
107
- t.namespace.must_equal namespace
108
- t.elements.length.must_equal 2
109
- t.element('handleColor').type.must_equal subject.types['Color']
110
- t.element('handleColor').singular?.must_equal true
111
- t.element('age').type.must_equal WSDL::NullType.new
112
- t.element('age').singular?.must_equal false
113
- end
72
+ describe '#endpoint' do
73
+ it 'returns the endpoint' do
74
+ parser.endpoint = 'http://lolsoap.api/v1'
75
+ subject.endpoint.must_equal 'http://lolsoap.api/v1'
76
+ end
77
+ end
114
78
 
115
- subject.types['Color'].tap do |t|
116
- t.namespace.must_equal namespace
117
- t.elements.length.must_equal 2
118
- t.element('name').type.must_equal WSDL::NullType.new
119
- t.element('hex').type.must_equal WSDL::NullType.new
120
- end
121
- end
79
+ describe '#namespaces' do
80
+ it 'returns a namespaces hash' do
81
+ subject.namespaces.must_equal({ 'bla' => namespace })
122
82
  end
83
+ end
123
84
 
124
- describe '#type' do
125
- it 'returns a single type' do
126
- subject.type('Color').must_equal subject.types['Color']
85
+ describe '#types' do
86
+ it 'returns a hash of types' do
87
+ subject.types.length.must_equal 2
88
+
89
+ subject.types['bla:Brush'].tap do |t|
90
+ t.elements.length.must_equal 2
91
+ t.element('handleColor').type.must_equal subject.types['bla:Color']
92
+ t.element('handleColor').singular?.must_equal true
93
+ t.element('age').type.must_equal WSDL::NullType.new
94
+ t.element('age').singular?.must_equal false
95
+ t.attributes.must_equal ['id']
127
96
  end
128
97
 
129
- it 'returns a null object if a type is missing' do
130
- subject.type('FooBar').must_equal WSDL::NullType.new
98
+ subject.types['bla:Color'].tap do |t|
99
+ t.elements.length.must_equal 2
100
+ t.element('name').type.must_equal WSDL::NullType.new
101
+ t.element('hex').type.must_equal WSDL::NullType.new
131
102
  end
132
103
  end
104
+ end
133
105
 
134
- describe '#type_namespaces' do
135
- it 'returns only the namespaces that used by types' do
136
- parser.namespaces['foo'] = 'bar'
137
- subject.type_namespaces.must_equal 'bla' => namespace
138
- end
106
+ describe '#type' do
107
+ it 'returns a single type' do
108
+ subject.type('bla:Color').must_equal subject.types['bla:Color']
109
+ end
110
+
111
+ it 'returns a null object if a type is missing' do
112
+ subject.type('FooBar').must_equal WSDL::NullType.new
113
+ end
114
+ end
115
+
116
+ describe '#type_namespaces' do
117
+ it 'returns only the namespaces that are used by types' do
118
+ parser.namespaces['foo'] = 'bar'
119
+ subject.type_namespaces.must_equal 'bla' => namespace
139
120
  end
140
121
  end
141
122
  end
@@ -3,7 +3,12 @@ require 'lolsoap/wsdl_parser'
3
3
 
4
4
  module LolSoap
5
5
  describe WSDLParser do
6
- let(:doc) { Nokogiri::XML(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
6
+ def raw_doc
7
+ File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')
8
+ end
9
+
10
+ let(:doc) { Nokogiri::XML(raw_doc) }
11
+
7
12
  subject { WSDLParser.new(doc) }
8
13
 
9
14
  describe '#namespaces' do
@@ -12,7 +17,9 @@ module LolSoap
12
17
  'tns' => 'http://example.com/stockquote.wsdl',
13
18
  'xsd1' => 'http://example.com/stockquote.xsd',
14
19
  'xsd2' => 'http://example.com/stockquote2.xsd',
15
- 'soap' => 'http://schemas.xmlsoap.org/wsdl/soap12/'
20
+ 'xsd3' => 'http://example.com/stockquote.xsd',
21
+ 'soap' => 'http://schemas.xmlsoap.org/wsdl/soap12/',
22
+ 'xs' => 'http://www.w3.org/2001/XMLSchema'
16
23
  })
17
24
  end
18
25
  end
@@ -26,43 +33,42 @@ module LolSoap
26
33
  describe '#types' do
27
34
  it 'returns the types, with attributes and namespace' do
28
35
  subject.types.must_equal({
29
- 'TradePriceRequest' => {
30
- :name => 'TradePriceRequest',
31
- :namespace => 'http://example.com/stockquote.xsd',
32
- :elements => {
36
+ 'xsd1:TradePriceRequest' => {
37
+ :prefix => 'xsd1',
38
+ :name => 'TradePriceRequest',
39
+ :elements => {
33
40
  'tickerSymbol' => {
34
- :name => 'tickerSymbol',
35
- :type => 'string',
41
+ :type => 'xs:string',
36
42
  :singular => false
37
43
  },
38
44
  'specialTickerSymbol' => {
39
- :name => 'specialTickerSymbol',
40
45
  :type => 'xsd2:TickerSymbol',
41
46
  :singular => false
42
47
  }
43
- }
48
+ },
49
+ :attributes => ['id']
44
50
  },
45
- 'TradePrice' => {
46
- :name => 'TradePrice',
47
- :namespace => 'http://example.com/stockquote.xsd',
48
- :elements => {
51
+ 'xsd1:TradePrice' => {
52
+ :prefix => 'xsd1',
53
+ :name => 'TradePrice',
54
+ :elements => {
49
55
  'price' => {
50
- :name => 'price',
51
- :type => 'float',
56
+ :type => 'xs:float',
52
57
  :singular => true
53
58
  }
54
- }
59
+ },
60
+ :attributes => []
55
61
  },
56
- 'TickerSymbol' => {
57
- :name => 'TickerSymbol',
58
- :namespace => 'http://example.com/stockquote2.xsd',
59
- :elements => {
62
+ 'xsd2:TickerSymbol' => {
63
+ :prefix => 'xsd2',
64
+ :name => 'TickerSymbol',
65
+ :elements => {
60
66
  'name' => {
61
- :name => 'name',
62
- :type => 'string',
67
+ :type => 'xs:string',
63
68
  :singular => true
64
69
  }
65
- }
70
+ },
71
+ :attributes => []
66
72
  }
67
73
  })
68
74
  end
@@ -71,8 +77,8 @@ module LolSoap
71
77
  describe '#messages' do
72
78
  it 'maps message names to types' do
73
79
  subject.messages.must_equal({
74
- 'GetLastTradePriceInput' => subject.types['TradePriceRequest'],
75
- 'GetLastTradePriceOutput' => subject.types['TradePrice']
80
+ 'GetLastTradePriceInput' => 'xsd1:TradePriceRequest',
81
+ 'GetLastTradePriceOutput' => 'xsd1:TradePrice'
76
82
  })
77
83
  end
78
84
  end
@@ -81,9 +87,8 @@ module LolSoap
81
87
  it 'is a hash containing input and output types' do
82
88
  subject.port_type_operations.must_equal({
83
89
  'GetLastTradePrice' => {
84
- :name => 'GetLastTradePrice',
85
- :input => subject.types['TradePriceRequest'],
86
- :output => subject.types['TradePrice']
90
+ :input => 'xsd1:TradePriceRequest',
91
+ :output => 'xsd1:TradePrice'
87
92
  }
88
93
  })
89
94
  end
@@ -93,13 +98,22 @@ module LolSoap
93
98
  it 'is a hash of operations with their action and input type' do
94
99
  subject.operations.must_equal({
95
100
  'GetLastTradePrice' => {
96
- :name => 'GetLastTradePrice',
97
101
  :action => 'http://example.com/GetLastTradePrice',
98
- :input => subject.types['TradePriceRequest'],
99
- :output => subject.types['TradePrice']
102
+ :input => 'xsd1:TradePriceRequest',
103
+ :output => 'xsd1:TradePrice'
100
104
  }
101
105
  })
102
106
  end
103
107
  end
108
+
109
+ describe 'soap 1.1' do
110
+ def raw_doc
111
+ super.sub("http://schemas.xmlsoap.org/wsdl/soap12/", "http://schemas.xmlsoap.org/wsdl/soap/")
112
+ end
113
+
114
+ it 'is supported' do
115
+ subject.operations.empty?.must_equal false
116
+ end
117
+ end
104
118
  end
105
119
  end
@@ -3,13 +3,13 @@ require 'lolsoap/wsdl'
3
3
 
4
4
  class LolSoap::WSDL
5
5
  describe Type do
6
- let(:wsdl) { OpenStruct.new(:prefixes => { 'http://example.com/foo' => 'foo' }) }
7
6
  let(:elements) { { 'soapColor' => OpenStruct.new(:type => Object.new) } }
8
- subject { Type.new(wsdl, 'WashHandsRequest', 'http://example.com/foo', elements) }
7
+
8
+ subject { Type.new('WashHandsRequest', 'prfx', elements, {}) }
9
9
 
10
10
  describe '#prefix' do
11
- it 'returns the prefix from the WSDL doc' do
12
- subject.prefix.must_equal 'foo'
11
+ it 'returns the prefix' do
12
+ subject.prefix.must_equal 'prfx'
13
13
  end
14
14
  end
15
15