lolsoap 0.1.0

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