lolsoap 0.1.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.
Files changed (47) hide show
  1. data/.document +5 -0
  2. data/.travis.yml +7 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +22 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +124 -0
  8. data/Rakefile +29 -0
  9. data/VERSION +1 -0
  10. data/lib/lolsoap.rb +11 -0
  11. data/lib/lolsoap/builder.rb +93 -0
  12. data/lib/lolsoap/client.rb +25 -0
  13. data/lib/lolsoap/envelope.rb +94 -0
  14. data/lib/lolsoap/errors.rb +15 -0
  15. data/lib/lolsoap/fault.rb +26 -0
  16. data/lib/lolsoap/hash_builder.rb +48 -0
  17. data/lib/lolsoap/request.rb +54 -0
  18. data/lib/lolsoap/response.rb +50 -0
  19. data/lib/lolsoap/wsdl.rb +98 -0
  20. data/lib/lolsoap/wsdl/element.rb +28 -0
  21. data/lib/lolsoap/wsdl/null_element.rb +15 -0
  22. data/lib/lolsoap/wsdl/null_type.rb +19 -0
  23. data/lib/lolsoap/wsdl/operation.rb +18 -0
  24. data/lib/lolsoap/wsdl/type.rb +38 -0
  25. data/lib/lolsoap/wsdl_parser.rb +121 -0
  26. data/lolsoap.gemspec +97 -0
  27. data/test/fixtures/stock_quote.wsdl +74 -0
  28. data/test/fixtures/stock_quote_fault.xml +16 -0
  29. data/test/fixtures/stock_quote_response.xml +8 -0
  30. data/test/helper.rb +14 -0
  31. data/test/integration/test_client.rb +20 -0
  32. data/test/integration/test_envelope.rb +45 -0
  33. data/test/integration/test_request.rb +19 -0
  34. data/test/integration/test_response.rb +15 -0
  35. data/test/integration/test_wsdl.rb +28 -0
  36. data/test/unit/test_builder.rb +95 -0
  37. data/test/unit/test_client.rb +12 -0
  38. data/test/unit/test_envelope.rb +112 -0
  39. data/test/unit/test_fault.rb +33 -0
  40. data/test/unit/test_hash_builder.rb +127 -0
  41. data/test/unit/test_request.rb +48 -0
  42. data/test/unit/test_response.rb +39 -0
  43. data/test/unit/test_wsdl.rb +143 -0
  44. data/test/unit/test_wsdl_parser.rb +105 -0
  45. data/test/unit/wsdl/test_element.rb +31 -0
  46. data/test/unit/wsdl/test_type.rb +44 -0
  47. metadata +152 -0
data/lolsoap.gemspec ADDED
@@ -0,0 +1,97 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "lolsoap"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jon Leighton"]
12
+ s.date = "2012-01-17"
13
+ s.description = "A library for dealing with SOAP requests and responses. We tear our hair out so you don't have to."
14
+ s.email = "j@jonathanleighton.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".travis.yml",
22
+ ".yardopts",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/lolsoap.rb",
30
+ "lib/lolsoap/builder.rb",
31
+ "lib/lolsoap/client.rb",
32
+ "lib/lolsoap/envelope.rb",
33
+ "lib/lolsoap/errors.rb",
34
+ "lib/lolsoap/fault.rb",
35
+ "lib/lolsoap/hash_builder.rb",
36
+ "lib/lolsoap/request.rb",
37
+ "lib/lolsoap/response.rb",
38
+ "lib/lolsoap/wsdl.rb",
39
+ "lib/lolsoap/wsdl/element.rb",
40
+ "lib/lolsoap/wsdl/null_element.rb",
41
+ "lib/lolsoap/wsdl/null_type.rb",
42
+ "lib/lolsoap/wsdl/operation.rb",
43
+ "lib/lolsoap/wsdl/type.rb",
44
+ "lib/lolsoap/wsdl_parser.rb",
45
+ "lolsoap.gemspec",
46
+ "test/fixtures/stock_quote.wsdl",
47
+ "test/fixtures/stock_quote_fault.xml",
48
+ "test/fixtures/stock_quote_response.xml",
49
+ "test/helper.rb",
50
+ "test/integration/test_client.rb",
51
+ "test/integration/test_envelope.rb",
52
+ "test/integration/test_request.rb",
53
+ "test/integration/test_response.rb",
54
+ "test/integration/test_wsdl.rb",
55
+ "test/unit/test_builder.rb",
56
+ "test/unit/test_client.rb",
57
+ "test/unit/test_envelope.rb",
58
+ "test/unit/test_fault.rb",
59
+ "test/unit/test_hash_builder.rb",
60
+ "test/unit/test_request.rb",
61
+ "test/unit/test_response.rb",
62
+ "test/unit/test_wsdl.rb",
63
+ "test/unit/test_wsdl_parser.rb",
64
+ "test/unit/wsdl/test_element.rb",
65
+ "test/unit/wsdl/test_type.rb"
66
+ ]
67
+ s.homepage = "http://github.com/jonleighton/lolsoap"
68
+ s.licenses = ["MIT"]
69
+ s.require_paths = ["lib"]
70
+ s.rubygems_version = "1.8.10"
71
+ s.summary = "A library for dealing with SOAP requests and responses."
72
+
73
+ if s.respond_to? :specification_version then
74
+ s.specification_version = 3
75
+
76
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
77
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
78
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
79
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
80
+ s.add_development_dependency(%q<minitest>, [">= 0"])
81
+ s.add_development_dependency(%q<yard>, [">= 0"])
82
+ else
83
+ s.add_dependency(%q<nokogiri>, [">= 0"])
84
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
85
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
86
+ s.add_dependency(%q<minitest>, [">= 0"])
87
+ s.add_dependency(%q<yard>, [">= 0"])
88
+ end
89
+ else
90
+ s.add_dependency(%q<nokogiri>, [">= 0"])
91
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
92
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
93
+ s.add_dependency(%q<minitest>, [">= 0"])
94
+ s.add_dependency(%q<yard>, [">= 0"])
95
+ end
96
+ end
97
+
@@ -0,0 +1,74 @@
1
+ <?xml version="1.0"?>
2
+ <!-- example borrowed and extended from http://cs.au.dk/~amoeller/WWW/webservices/wsdlexample.html -->
3
+ <definitions name="StockQuote"
4
+ targetNamespace="http://example.com/stockquote.wsdl"
5
+ xmlns:tns="http://example.com/stockquote.wsdl"
6
+ xmlns:xsd1="http://example.com/stockquote.xsd"
7
+ xmlns:xsd2="http://example.com/stockquote2.xsd"
8
+ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/"
9
+ xmlns="http://schemas.xmlsoap.org/wsdl/">
10
+
11
+ <types>
12
+ <schema targetNamespace="http://example.com/stockquote.xsd"
13
+ xmlns="http://www.w3.org/2001/XMLSchema">
14
+ <element name="TradePrice">
15
+ <complexType>
16
+ <all>
17
+ <element name="price" type="float"/>
18
+ </all>
19
+ </complexType>
20
+ </element>
21
+ <complexType name="TradePriceRequest">
22
+ <sequence>
23
+ <element name="tickerSymbol" type="string" maxOccurs="5"/>
24
+ <element name="specialTickerSymbol" type="xsd2:TickerSymbol" maxOccurs="unbounded"/>
25
+ </sequence>
26
+ </complexType>
27
+ </schema>
28
+
29
+ <schema targetNamespace="http://example.com/stockquote2.xsd"
30
+ xmlns="http://www.w3.org/2001/XMLSchema">
31
+ <complexType name="TickerSymbol">
32
+ <sequence>
33
+ <element name="name" type="string" maxOccurs="1"/>
34
+ </sequence>
35
+ </complexType>
36
+ </schema>
37
+ </types>
38
+
39
+ <message name="GetLastTradePriceInput">
40
+ <part name="body" element="xsd1:TradePriceRequest"/>
41
+ </message>
42
+
43
+ <message name="GetLastTradePriceOutput">
44
+ <part name="body" element="xsd1:TradePrice"/>
45
+ </message>
46
+
47
+ <portType name="StockQuotePortType">
48
+ <operation name="GetLastTradePrice">
49
+ <input message="tns:GetLastTradePriceInput"/>
50
+ <output message="tns:GetLastTradePriceOutput"/>
51
+ </operation>
52
+ </portType>
53
+
54
+ <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
55
+ <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
56
+ <operation name="GetLastTradePrice">
57
+ <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
58
+ <input>
59
+ <soap:body use="literal"/>
60
+ </input>
61
+ <output>
62
+ <soap:body use="literal"/>
63
+ </output>
64
+ </operation>
65
+ </binding>
66
+
67
+ <service name="StockQuoteService">
68
+ <documentation>My first service</documentation>
69
+ <port name="StockQuotePort" binding="tns:StockQuoteSoapBinding">
70
+ <soap:address location="http://example.com/stockquote"/>
71
+ </port>
72
+ </service>
73
+
74
+ </definitions>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0"?>
2
+ <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
3
+ <soap:Body>
4
+ <soap:Fault>
5
+ <soap:Code>
6
+ <soap:Value>soap:Sender</soap:Value>
7
+ </soap:Code>
8
+ <soap:Reason>
9
+ <soap:Text>Omg! stock market has crashed!</soap:Text>
10
+ </soap:Reason>
11
+ <soap:Detail>
12
+ <Foo>Some detail</Foo>
13
+ </soap:Detail>
14
+ </soap:Fault>
15
+ </soap:Body>
16
+ </soap:Envelope>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0"?>
2
+ <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:m="http://example.com/stockquote.xsd">
3
+ <soap:Body>
4
+ <m:GetStockPriceResponse>
5
+ <m:Price>34.5</m:Price>
6
+ </m:GetStockPriceResponse>
7
+ </soap:Body>
8
+ </soap:Envelope>
data/test/helper.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
5
+ require 'ostruct'
6
+
7
+ TEST_ROOT = File.expand_path('..', __FILE__)
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+
10
+ if RUBY_VERSION == '1.8.7'
11
+ class OpenStruct
12
+ undef_method :type
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+ require 'lolsoap/client'
3
+
4
+ module LolSoap
5
+ describe Client do
6
+ subject { Client.new(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
7
+
8
+ it 'builds a request' do
9
+ request = subject.request('GetLastTradePrice')
10
+ request.body { |foo| foo.bar }
11
+ request.content.empty?.must_equal false
12
+ end
13
+
14
+ it 'builds a response' do
15
+ request = subject.request('GetLastTradePrice')
16
+ response = subject.response(request, File.read(TEST_ROOT + '/fixtures/stock_quote_response.xml'))
17
+ response.body.wont_equal nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ require 'helper'
2
+ require 'lolsoap/envelope'
3
+ require 'lolsoap/wsdl'
4
+
5
+ module LolSoap
6
+ describe Envelope do
7
+ let(:wsdl) { WSDL.parse(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
8
+ subject { Envelope.new(wsdl, wsdl.operations['GetLastTradePrice']) }
9
+
10
+ let(:doc) { subject.doc }
11
+
12
+ it 'creates an empty envelope' do
13
+ body = doc.at_xpath('/soap:Envelope/soap:Body/xsd1:TradePriceRequest', doc.namespaces)
14
+ body.wont_equal nil
15
+ end
16
+
17
+ it 'creates some input' do
18
+ subject.body do |b|
19
+ b.tickerSymbol 'LOCO2'
20
+ b.specialTickerSymbol do |s|
21
+ s.name 'LOCOLOCOLOCO'
22
+ end
23
+ b.lol
24
+ end
25
+
26
+ el = doc.at_xpath('//xsd1:TradePriceRequest/xsd1:tickerSymbol', doc.namespaces)
27
+ el.wont_equal nil
28
+ el.text.to_s.must_equal 'LOCO2'
29
+
30
+ el = doc.at_xpath('//xsd1:TradePriceRequest/xsd1:specialTickerSymbol/xsd2:name', doc.namespaces)
31
+ el.wont_equal nil
32
+ el.text.to_s.must_equal 'LOCOLOCOLOCO'
33
+ end
34
+
35
+ it 'creates some header' do
36
+ subject.header do |h|
37
+ h['xsd1'].verySpecialBoolean true
38
+ end
39
+
40
+ el = doc.at_xpath('/soap:Envelope/soap:Header/xsd1:verySpecialBoolean', doc.namespaces)
41
+ el.wont_equal nil
42
+ el.text.to_s.must_equal 'true'
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+ require 'lolsoap/envelope'
3
+ require 'lolsoap/request'
4
+
5
+ module LolSoap
6
+ describe Request do
7
+ let(:wsdl) { WSDL.parse(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
8
+ let(:operation) { wsdl.operation('GetLastTradePrice') }
9
+ let(:envelope) { Envelope.new(wsdl, operation) }
10
+
11
+ subject { Request.new(envelope) }
12
+
13
+ it 'should put together a HTTP request' do
14
+ subject.url.must_equal "http://example.com/stockquote"
15
+ subject.headers['SOAPAction'].must_equal "http://example.com/GetLastTradePrice"
16
+ subject.content.empty?.must_equal false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ require 'helper'
2
+ require 'lolsoap/client'
3
+
4
+ module LolSoap
5
+ describe Response do
6
+ let(:client) { LolSoap::Client.new File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl') }
7
+ let(:request) { client.request('GetLastTradePrice') }
8
+
9
+ subject { Response.parse(request, File.read(TEST_ROOT + '/fixtures/stock_quote_response.xml')) }
10
+
11
+ it 'should build a hash from the body' do
12
+ subject.body_hash.must_equal({ 'Price' => '34.5' })
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+ require 'lolsoap/wsdl'
3
+
4
+ module LolSoap
5
+ describe WSDL do
6
+ subject { WSDL.parse(File.read(TEST_ROOT + '/fixtures/stock_quote.wsdl')) }
7
+
8
+ it 'should successfully parse a WSDL document' do
9
+ subject.operations.length.must_equal 1
10
+ subject.operations['GetLastTradePrice'].tap do |o|
11
+ o.input.must_equal subject.types['TradePriceRequest']
12
+ o.action.must_equal 'http://example.com/GetLastTradePrice'
13
+ end
14
+
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'
19
+ end
20
+ end
21
+
22
+ describe '#inspect' do
23
+ it 'works' do
24
+ subject.inspect
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,95 @@
1
+ require 'helper'
2
+ require 'lolsoap/builder'
3
+
4
+ module LolSoap
5
+ describe Builder do
6
+ let(:doc) { MiniTest::Mock.new }
7
+ let(:node) do
8
+ node = OpenStruct.new(
9
+ :document => doc,
10
+ :namespace_scopes => [OpenStruct.new(:prefix => 'b'), OpenStruct.new(:prefix => 'a')],
11
+ :children => MiniTest::Mock.new
12
+ )
13
+ def node.<<(child); children << child; end
14
+ node
15
+ end
16
+ let(:type) do
17
+ type = OpenStruct.new(:prefix => 'a')
18
+ def type.sub_type(name)
19
+ @sub_types ||= { 'foo' => Object.new, 'bar' => Object.new, 'clone' => Object.new }
20
+ @sub_types[name]
21
+ end
22
+ type
23
+ end
24
+
25
+ subject { Builder.new(node, type) }
26
+
27
+ def expect_node_added(namespace, *args)
28
+ sub_node = MiniTest::Mock.new
29
+
30
+ doc.expect(:create_element, sub_node, args)
31
+ sub_node.expect(:namespace=, nil, [namespace])
32
+ node.children.expect(:<<, nil, [sub_node])
33
+
34
+ yield sub_node
35
+
36
+ [doc, sub_node, node].each(&:verify)
37
+ end
38
+
39
+ describe '#__tag__' do
40
+ it 'adds an element to the node, using the correct namespace' do
41
+ expect_node_added node.namespace_scopes[1], 'foo', 'bar' do |sub_node|
42
+ sub_builder = subject.__tag__(:foo, 'bar')
43
+ sub_builder.__node__.object_id.must_equal sub_node.object_id
44
+ sub_builder.__type__.must_equal type.sub_type('foo')
45
+ end
46
+ end
47
+
48
+ it 'yields to a block, if given' do
49
+ expect_node_added node.namespace_scopes[1], 'bar' do
50
+ block = nil
51
+ ret = subject.__tag__(:bar) { |b| block = b }
52
+ block.object_id.must_equal ret.object_id
53
+ end
54
+ end
55
+ end
56
+
57
+ describe 'method missing' do
58
+ it 'delegates to __tag__' do
59
+ expect_node_added node.namespace_scopes[1], 'bar', 'baz' do
60
+ subject.bar 'baz'
61
+ end
62
+ end
63
+
64
+ it 'supports standard methods that are usually defined' do
65
+ expect_node_added node.namespace_scopes[1], 'clone' do
66
+ subject.clone
67
+ end
68
+ end
69
+ end
70
+
71
+ it 'responds to anything' do
72
+ subject.respond_to?('omgwtfbbq').must_equal true
73
+ subject['b'].respond_to?('omgwtfbbq').must_equal true
74
+ end
75
+
76
+ it 'can add elements with a custom prefix' do
77
+ expect_node_added node.namespace_scopes[0], 'foo' do
78
+ subject['b'].foo
79
+ end
80
+ end
81
+
82
+ describe '#__node__' do
83
+ it 'returns the node' do
84
+ subject.__node__.must_equal node
85
+ end
86
+ end
87
+
88
+ describe '#__type__' do
89
+ it 'returns the type' do
90
+ subject.__type__.must_equal type
91
+ end
92
+ end
93
+
94
+ end
95
+ end