spdocgen 1.1.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA512:
3
+ metadata.gz: c2f64220f543247a047013d39dc6cebee4390b8fcc531b67cd5e8a86073298a4f401b0c7fd6abe97894a736f9449219c04460dc631a99a6f492942c8d5c4acfa
4
+ data.tar.gz: ee878ee4a4a915378cb266ed2b1f0cd0cbd36a4086ced6178a020dc199288a198966da9a96c0285178fb1d5d328e7e084e57dc0211ef0e3328bba69039fdccbf
5
+ SHA1:
6
+ metadata.gz: f084863ea5fc6784ac2bf2a57e800d6cddcf4a1b
7
+ data.tar.gz: 72ba51d7f0976b343ed747a95abcf96751fdf8d7
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spdocgen.gemspec
4
+ gemspec
5
+
6
+ gem 'rspec'
7
+ gem 'rack'
8
+ gem 'thin'
9
+ gem 'uuid'
10
+
11
+ gem 'net-ssh'
12
+ gem 'net-scp'
13
+ gem 'highline'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Software Projects
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # SP Docgen for Ruby
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'spdocgen'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install spdocgen
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require "bundler/gem_tasks"
2
+ require 'net/ssh'
3
+ require 'net/ssh/authentication/methods/password'
4
+ require 'net/scp'
5
+ require 'highline/import'
6
+
7
+ task :push => :build do
8
+ def upload(ssh)
9
+ filename = "spdocgen-#{SPDocgen::VERSION}.gem"
10
+ print "Uploading #{filename}..."
11
+ u = ssh.scp.upload("pkg/#{filename}", "/var/www/rubygems/gems/#{filename}") do
12
+ print '.'
13
+ end
14
+ u.wait
15
+ puts
16
+ ssh.exec! '/usr/local/rvm/bin/gem generate_index --directory=/var/www/rubygems'
17
+ end
18
+
19
+ opts = Net::SSH.configuration_for('sp43.sp.local')
20
+ begin
21
+ Net::SSH.start('sp43.sp.local', 'rubygems', :auth_methods => %w[publickey]) {|o| upload(o)}
22
+ rescue
23
+ password = ask("rubygems@sp43.sp.local's password: ") { |q| q.echo = false }
24
+ Net::SSH.start('sp43.sp.local', 'rubygems', :password => password) {|o| upload(o)}
25
+ end
26
+ end
data/lib/spdocgen.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "spdocgen/version"
2
+
3
+ module SPDocgen
4
+ autoload :Configuration, 'spdocgen/configuration'
5
+ autoload :Document, 'spdocgen/document'
6
+ autoload :DocumentSet, 'spdocgen/document_set'
7
+ autoload :Protocol, 'spdocgen/protocol'
8
+
9
+ autoload :DownloadRequest, 'spdocgen/download_request'
10
+ autoload :DownloadResponse, 'spdocgen/download_response'
11
+ autoload :RenderRequest, 'spdocgen/render_request'
12
+ autoload :RenderResponse, 'spdocgen/render_response'
13
+ autoload :StatusRequest, 'spdocgen/status_request'
14
+ autoload :StatusResponse, 'spdocgen/status_response'
15
+ end
@@ -0,0 +1,31 @@
1
+ module SPDocgen
2
+ class Configuration
3
+ class <<self
4
+ attr_accessor :configuration_file
5
+
6
+ def current
7
+ env = nil
8
+ env = Rails.env if defined? Rails
9
+ env ||= ENV['RAILS_ENV']
10
+ env ||= ENV['RACK_ENV']
11
+ raise 'Unable to determine environment' if env.nil?
12
+
13
+ c = read
14
+ raise "Environment not defined in SPDocgen configuration: #{env}" if c[env].nil?
15
+ (c['global'] || {}).merge(c[env])
16
+ end
17
+
18
+ private
19
+
20
+ def read
21
+ if defined? Rails
22
+ self.configuration_file ||= File.join(Rails.root, 'config', 'spdocgen.yml')
23
+ elsif self.configuration_file.nil?
24
+ raise 'Unable to determine a default location for SPDocgen configuration'
25
+ end
26
+
27
+ @configuration ||= YAML.load_file(self.configuration_file)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module SPDocgen
2
+ class Document
3
+ attr_reader :xmlns, :data_sources
4
+ def initialize
5
+ @xmlns = {}
6
+ @data_sources = []
7
+ end
8
+
9
+ def build(xml)
10
+ raise "#{self.class.name} does not define a 'build' method"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module SPDocgen
2
+ class DocumentSet
3
+ attr_reader :xmlns, :data_sources
4
+ attr_accessor :documents
5
+
6
+ def initialize
7
+ @xmlns = {}
8
+ @data_sources = []
9
+ end
10
+
11
+ def all_data_sources
12
+ mapped = (data_sources + documents.collect(&:data_sources).flatten).inject({}) do |map, ds|
13
+ map[ds.id] = ds
14
+ map
15
+ end
16
+ mapped.values.sort_by(&:id)
17
+ end
18
+
19
+ def all_xmlns
20
+ documents.inject(@xmlns){|map, doc| map.merge(doc.xmlns)}
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ require 'uri'
2
+
3
+ module SPDocgen
4
+ class DownloadRequest
5
+ attr_accessor :uri
6
+
7
+ def initialize(uri)
8
+ self.uri = uri
9
+ end
10
+
11
+ def download
12
+ SPDocgen::Protocol.instance.download(URI.parse(self.uri))
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module SPDocgen
2
+ class DownloadResponse
3
+ attr_accessor :body, :content_type, :content_encoding, :content_disposition
4
+
5
+ def initialize(body, content_type, content_encoding, content_disposition)
6
+ self.body = body
7
+ self.content_type = content_type
8
+ self.content_encoding = content_encoding
9
+ self.content_disposition = content_disposition
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,80 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+
4
+ module SPDocgen
5
+ class Protocol
6
+ def self.instance
7
+ @instance ||= self.new Configuration.current
8
+ end
9
+
10
+ def initialize(config)
11
+ @base_url = config['base_url']
12
+ @render_path = config['render_path']
13
+ @username = config['username']
14
+ @password = config['password']
15
+
16
+ url = URI.parse @base_url
17
+ @http = Net::HTTP.new url.host, url.port
18
+ @http.use_ssl = (url.scheme =~ /https/i)
19
+
20
+ @downloaders = {}
21
+ end
22
+
23
+ def download(parsed_uri)
24
+ with_downloader_for(parsed_uri) do |http|
25
+ req = Net::HTTP::Get.new parsed_uri.request_uri
26
+ req['Accept'] = '*/*'
27
+ req.basic_auth @username, @password
28
+
29
+ response = http.request(req)
30
+
31
+ raise "Unable to download: #{parsed_uri.to_s} .. Response was #{response.code} #{response.message} : #{response.body ? response.body : ''} - request is #{req.to_s}" unless response.is_a? Net::HTTPOK
32
+
33
+ SPDocgen::DownloadResponse.new response.body, response.content_type, response['content-encoding'], response['content-disposition']
34
+ end
35
+ end
36
+
37
+ def submit(xml)
38
+ request = Net::HTTP::Post.new render_url
39
+ request.body = xml
40
+ request['Content-Type'] = 'application/xml'
41
+
42
+ SPDocgen::RenderResponse.new do_request(request).body
43
+ end
44
+
45
+ def poll(uri)
46
+ request = Net::HTTP::Get.new uri
47
+ SPDocgen::StatusResponse.new do_request(request).body
48
+ end
49
+
50
+ private
51
+
52
+ def http
53
+ @http.start unless @http.started?
54
+ @http
55
+ end
56
+
57
+ def render_url
58
+ URI.join(@base_url, @render_path).to_s
59
+ end
60
+
61
+ def with_downloader_for(u, &block)
62
+ host = u.class.new(u.scheme, nil, u.host, u.port, nil, '', nil, nil, nil, false).to_s
63
+
64
+ downloader = Net::HTTP.new(u.host, u.port)
65
+ downloader.use_ssl = (u.scheme =~ /https/i)
66
+
67
+ downloader.start(&block)
68
+ end
69
+
70
+ def do_request(request)
71
+ request['Accept'] = 'application/xml'
72
+ request.basic_auth @username, @password
73
+
74
+ response = http.request request
75
+ raise 'Response did not contain XML' unless response.code == '200' and response['content-type'] =~ /xml/i
76
+
77
+ response
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,76 @@
1
+ require 'nokogiri'
2
+
3
+ module SPDocgen
4
+ class RenderRequest
5
+ attr_accessor :metadata, :xml
6
+
7
+ def initialize(document_set)
8
+ raise "Document set should inherit from #{DocumentSet.name}" unless document_set.is_a? DocumentSet
9
+ raise "Documents should inherit from #{Document.name}" unless document_set.documents.all?{|doc| doc.is_a? Document}
10
+
11
+ @document_set = document_set
12
+ @xmlns = {
13
+ 'xmlns:dgr' => 'http://www.sp.com.au/docgen/schemas/wsh',
14
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
15
+ }.merge(document_set.all_xmlns)
16
+
17
+ raise 'XML namespace definitions should start with xmlns:' unless @xmlns.keys.all?{|k| k.start_with? 'xmlns:'}
18
+
19
+ @metadata = {}
20
+ if document_set.respond_to? :metadata
21
+ @metadata = document_set.metadata
22
+ end
23
+ end
24
+
25
+ def build
26
+ raise 'Already built' if @xml
27
+ raise 'No data sources' if @document_set.nil? or @document_set.documents.nil? or @document_set.documents.empty?
28
+
29
+ builder = Nokogiri::XML::Builder.new :encoding => 'utf-8' do |xml|
30
+ # Clients that treat this as a real builder sometimes need to call 'tag!'
31
+ # That's ok.
32
+ def xml.tag!(*args, &bl)
33
+ # Handle reserved names correctly
34
+ name = args.shift + '_'
35
+ send name, *args, &bl
36
+ end
37
+
38
+ xml.DocGenRequest @xmlns do
39
+ # See http://stackoverflow.com/questions/1829425/creating-an-xml-document-with-a-namespaced-root-element-with-nokogiri-builder
40
+ xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == 'dgr'}
41
+ dgr = xml['dgr']
42
+ dgr.MetaData do
43
+ self.metadata.each do |k,v|
44
+ dgr.MetaDataEntry do
45
+ dgr.Key k
46
+ dgr.Value v
47
+ end
48
+ end
49
+ end
50
+
51
+ dgr.SharedXmlDataSources do
52
+ @document_set.all_data_sources.each do |data_source|
53
+ dgr.SharedXmlDataSource 'sharedXmlDataSourceId' => data_source.id do
54
+ data_source.build(xml)
55
+ end
56
+ end
57
+ end
58
+
59
+ dgr.DocumentRequests do
60
+ @document_set.documents.each do |document|
61
+ document.build(xml)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ @xml = builder.to_xml
68
+ end
69
+
70
+ def submit
71
+ raise 'Request needs to be built first' unless @xml
72
+
73
+ SPDocgen::Protocol.instance.submit @xml
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ require 'nokogiri'
2
+
3
+ module SPDocgen
4
+ class RenderResponse
5
+ attr_reader :uuid, :uri
6
+
7
+ def initialize(xml)
8
+ document = Nokogiri::XML.parse(xml, nil, 'UTF-8')
9
+ raise 'Not a render response' unless document.root.name == 'RenderResponse'
10
+
11
+ @uuid = document.xpath('/RenderResponse/Uuid').text
12
+ @uri = document.xpath('/RenderResponse/StatusUri').text
13
+
14
+ raise "Invalid render response #{xml}" unless !@uuid.blank? && !@uri.blank?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module SPDocgen
2
+ class StatusRequest
3
+ def initialize(uri)
4
+ @uri = uri
5
+ end
6
+
7
+ def poll
8
+ SPDocgen::Protocol.instance.poll @uri
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,74 @@
1
+ require 'nokogiri'
2
+
3
+ module SPDocgen
4
+ class StatusResponse
5
+ #<StatusResponse>
6
+ #<DocGenRequestStatuses>
7
+ #<DocGenRequestStatus>
8
+ #<Uuid>9f576898-8d74-432e-80b8-dacbaf8d7bf6</Uuid>
9
+ #<State>Failed</State>
10
+ #<DocumentRequests>
11
+ #<DocumentRequest ServerId='5614' ClientId='b3b98dc0-449c-012f-238b-0026b92085d1' State='Timeout'>
12
+ #<Documents></Documents>
13
+ #</DocumentRequest>
14
+ #</DocumentRequests>
15
+ #</DocGenRequestStatus>
16
+ #</DocGenRequestStatuses>
17
+ #</StatusResponse>
18
+ def initialize(xml)
19
+ document = Nokogiri::XML.parse(xml, nil, 'UTF-8')
20
+ raise 'Not a render response' unless document.root.name == 'StatusResponse'
21
+
22
+ document.xpath('/StatusResponse/DocGenRequestStatuses/DocGenRequestStatus').each do |node|
23
+ uuid = node.xpath('Uuid').text
24
+ state = node.xpath('State').text
25
+ requests = node.xpath('DocumentRequests/DocumentRequest').collect do |req|
26
+ documents = req.xpath('Documents/Document').collect do |doc|
27
+ name = doc.xpath('Name')
28
+ uri = doc.xpath('Uri')
29
+ metadata = doc.xpath('MetaDataEntries/MetaDataEntry').inject({}) do |map,md|
30
+ map[md.xpath('Key').text] = md.xpath('Value').text
31
+ map
32
+ end
33
+
34
+ {
35
+ :reference => doc['Reference'],
36
+ :num_pages => doc['NumPages'].to_i,
37
+ :name => name.text,
38
+ :uri => uri.text,
39
+ :metadata => metadata
40
+ }
41
+ end
42
+
43
+ {
44
+ :server_id => req['ServerId'],
45
+ :request_guid => req['ClientId'],
46
+ :state => req['State'],
47
+ :documents => documents
48
+ }
49
+ end
50
+
51
+ record_status uuid, state, requests
52
+ end
53
+ end
54
+
55
+ def uuids
56
+ @uuids ||= []
57
+ end
58
+
59
+ def status(uuid)
60
+ @status ||= {}
61
+ @status[uuid] ||= {}
62
+ end
63
+
64
+ private
65
+ def record_status(uuid, state, requests)
66
+ self.uuids << uuid
67
+ self.status(uuid).merge!(
68
+ :uuid => uuid,
69
+ :state => state,
70
+ :requests => requests
71
+ )
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,4 @@
1
+ module SPDocgen
2
+ # Please use Semantic Versioning - http://semver.org/
3
+ VERSION = "1.1.2"
4
+ end
data/spdocgen.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'spdocgen/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "spdocgen"
8
+ gem.version = SPDocgen::VERSION
9
+ gem.authors = ["Shaun Mangelsdorf"]
10
+ gem.email = ["smangelsdorf@sp.com.au"]
11
+ gem.description = %q{Ruby client library for rendering and downloading documents from SP Docgen}
12
+ gem.summary = %q{SP Docgen client library}
13
+ gem.homepage = "http://sp.docgen.net.au"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency 'nokogiri'
21
+ end
data/spec/config.yml ADDED
@@ -0,0 +1,4 @@
1
+ test:
2
+ username: test
3
+ password: test
4
+ render_path: /render
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe SPDocgen::DownloadRequest do
4
+ subject do
5
+ SPDocgen::DownloadRequest.new server.url('/download/file.txt')
6
+ end
7
+
8
+ it 'downloads the file' do
9
+ server.response = [200, {'content-type' => 'text/plain'}, "test file"]
10
+
11
+ response = subject.download
12
+ response.should be_a SPDocgen::DownloadResponse
13
+ response.body.should == "test file"
14
+ response.content_type.should == 'text/plain'
15
+ response.content_encoding.should be_nil
16
+ end
17
+
18
+ it 'includes the content encoding' do
19
+ server.response = [200, {'content-type' => 'text/plain', 'content-encoding' => 'gzip'}, "test file"]
20
+
21
+ response = subject.download
22
+ response.should be_a SPDocgen::DownloadResponse
23
+ response.body.should == "test file"
24
+ response.content_type.should == 'text/plain'
25
+ response.content_encoding.should == 'gzip'
26
+ end
27
+
28
+ it 'includes the content disposition' do
29
+ server.response = [200, {'content-type' => 'text/plain', 'content-disposition' => 'attachment; filename=test.txt'}, 'test file']
30
+ response = subject.download
31
+ response.should be_a SPDocgen::DownloadResponse
32
+ response.content_disposition.should == 'attachment; filename=test.txt'
33
+ end
34
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ require 'uuid'
4
+
5
+ describe SPDocgen::RenderRequest do
6
+ class TestDocumentSet < SPDocgen::DocumentSet
7
+ end
8
+
9
+ class BadTestDocument < SPDocgen::Document
10
+ end
11
+ class TestDocument < SPDocgen::Document
12
+ def build(xml)
13
+ xml.DocumentRequest 'test-xml'
14
+ end
15
+ end
16
+ class NamespaceDocument < SPDocgen::Document
17
+ def initialize
18
+ super
19
+ xmlns['xmlns:test'] = 'http://example.org/test'
20
+ end
21
+
22
+ def build(xml)
23
+ xml.DocumentRequest do
24
+ xml['test'].TestXml
25
+ end
26
+ end
27
+ end
28
+
29
+ before :each do
30
+ @uuid = UUID.generate
31
+ end
32
+
33
+ subject do
34
+ end
35
+
36
+ it 'should reject document sets of the wrong type' do
37
+ lambda {
38
+ set = Object.new
39
+ SPDocgen::RenderRequest.new set
40
+ }.should raise_error(RuntimeError, /should inherit from/)
41
+ end
42
+
43
+ it 'should reject documents of the wrong type' do
44
+ lambda {
45
+ set = TestDocumentSet.new
46
+ set.documents = [Object.new]
47
+ SPDocgen::RenderRequest.new set
48
+ }.should raise_error(RuntimeError, /should inherit from/)
49
+ end
50
+
51
+ it 'should not build a bad implementation' do
52
+ set = TestDocumentSet.new
53
+ set.documents = [BadTestDocument.new]
54
+ req = SPDocgen::RenderRequest.new set
55
+ lambda {
56
+ req.build
57
+ }.should raise_error(RuntimeError, /does not define/)
58
+ end
59
+
60
+ it 'should build' do
61
+ set = TestDocumentSet.new
62
+ set.documents = [TestDocument.new]
63
+ req = SPDocgen::RenderRequest.new set
64
+ req.build
65
+ req.xml.should match /test-xml/
66
+ end
67
+
68
+ it 'should build with namespaces' do
69
+ set = TestDocumentSet.new
70
+ set.documents = [NamespaceDocument.new]
71
+ req = SPDocgen::RenderRequest.new set
72
+ req.build
73
+ req.xml.should match /<test:TestXml\/>/
74
+ end
75
+
76
+ it 'should submit' do
77
+ server.response = [200, {'content-type' => 'application/xml'}, %{
78
+ <RenderResponse>
79
+ <Uuid>#{@uuid}</Uuid>
80
+ <StatusUri>#{server.url("/status/#{@uuid}")}</StatusUri>
81
+ </RenderResponse>
82
+ }]
83
+
84
+ set = TestDocumentSet.new
85
+ set.documents = [TestDocument.new]
86
+ req = SPDocgen::RenderRequest.new set
87
+ req.build
88
+
89
+ response = req.submit
90
+ response.should be_a SPDocgen::RenderResponse
91
+ response.uuid.should == @uuid
92
+ response.uri.should end_with @uuid
93
+ end
94
+ end
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'spdocgen'
5
+ require 'test_server'
6
+
7
+ require 'tempfile'
8
+ require 'yaml'
9
+
10
+ RSpec.configure do |config|
11
+ config.add_setting :server
12
+ config.add_setting :spdocgen_configuration
13
+
14
+ config.server = SPDocgen::TestServer.new
15
+ config.server.start
16
+
17
+ config.include SPDocgen::TestServerHelper
18
+
19
+ config.before :suite do
20
+ ENV['RACK_ENV'] = 'test'
21
+
22
+ yml = Tempfile.new(['spdocgen-config', '.yml'])
23
+ template = YAML.load_file File.join(File.dirname(__FILE__), 'config.yml')
24
+ template['test'].merge!('base_url' => config.server.base_url)
25
+ yml.write YAML.dump(template)
26
+ yml.close
27
+
28
+ config.spdocgen_configuration = yml
29
+ SPDocgen::Configuration.configuration_file = yml.path
30
+ end
31
+
32
+ config.after :suite do
33
+ config.spdocgen_configuration.unlink
34
+ end
35
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ require 'uuid'
4
+
5
+ describe SPDocgen::StatusRequest do
6
+ subject do
7
+ SPDocgen::StatusRequest.new server.url('/download/file.txt')
8
+ end
9
+
10
+ before :each do
11
+ @request = UUID.generate
12
+ @uuid = UUID.generate
13
+ end
14
+
15
+ def status_response(state, request_state, documents)
16
+ doc_xml = documents.collect do |doc|
17
+ %{<Document Reference='#{doc[:reference]}' NumPages='#{doc[:num_pages] || 1}'>
18
+ <Name>#{doc[:name]}</Name>
19
+ <Uri>#{doc[:uri]}</Uri>
20
+ <MetaDataEntries>
21
+ <MetaDataEntry>
22
+ <Key>test</Key>
23
+ <Value>this is a test</Value>
24
+ </MetaDataEntry>
25
+ </MetaDataEntries>
26
+ </Document>}
27
+ end.join('')
28
+
29
+ %{<StatusResponse>
30
+ <DocGenRequestStatuses>
31
+ <DocGenRequestStatus>
32
+ <Uuid>#{@uuid}</Uuid>
33
+ <State>#{state}</State>
34
+ <DocumentRequests>
35
+ <DocumentRequest ServerId='1' ClientId='#{@request}' State='#{request_state}'>
36
+ <Documents>#{doc_xml}</Documents>
37
+ </DocumentRequest>
38
+ </DocumentRequests>
39
+ </DocGenRequestStatus>
40
+ </DocGenRequestStatuses>
41
+ </StatusResponse>
42
+ }
43
+ end
44
+
45
+ it 'polls for status' do
46
+ response_body = status_response('Failed', 'Timeout', [])
47
+ server.response = [200, {'content-type' => 'application/xml'}, response_body]
48
+ response = subject.poll
49
+
50
+ response.should be_a SPDocgen::StatusResponse
51
+ end
52
+
53
+ it 'determines a request has failed' do
54
+ response_body = status_response('Failed', 'Timeout', [])
55
+ server.response = [200, {'content-type' => 'application/xml'}, response_body]
56
+ response = subject.poll
57
+
58
+ response.status(@uuid)[:state].should == 'Failed'
59
+ req_status = response.status(@uuid)[:requests].first
60
+ req_status[:request_guid].should == @request
61
+ req_status[:state].should == 'Timeout'
62
+ req_status[:documents].should be_empty
63
+ end
64
+
65
+ it 'determines a request has succeeded' do
66
+ doc_uuid = UUID.generate
67
+
68
+ documents = []
69
+ documents << {:reference => doc_uuid, :num_pages => 5, :name => 'Test.file', :uri => server.url('/test.file')}
70
+
71
+ response_body = status_response('Completed', 'Completed', documents)
72
+ server.response = [200, {'content-type' => 'application/xml'}, response_body]
73
+ response = subject.poll
74
+
75
+ response.status(@uuid)[:state].should == 'Completed'
76
+ req_status = response.status(@uuid)[:requests].first
77
+ req_status[:request_guid].should == @request
78
+ req_status[:state].should == 'Completed'
79
+ req_status[:documents].should_not be_empty
80
+
81
+ doc_status = req_status[:documents].first
82
+ doc_status[:name].should == 'Test.file'
83
+ doc_status[:uri].should end_with '/test.file'
84
+ doc_status[:reference].should == doc_uuid
85
+ doc_status[:num_pages].should == 5
86
+ doc_status[:metadata].should_not be_empty
87
+ doc_status[:metadata]['test'].should == 'this is a test'
88
+ end
89
+ end
@@ -0,0 +1,52 @@
1
+ require 'net/http'
2
+ require 'rack'
3
+ require 'rack/handler/thin'
4
+
5
+ module SPDocgen
6
+ class TestServer
7
+ attr_accessor :env, :response
8
+
9
+ def initialize
10
+ @host = '127.0.0.1'
11
+ @port = find_available_port
12
+ end
13
+
14
+ def base_url
15
+ "http://#{@host}:#{@port}"
16
+ end
17
+
18
+ def url(path)
19
+ URI.join(base_url, path).to_s
20
+ end
21
+
22
+ def call(env)
23
+ self.env = env
24
+ response.tap{self.response = nil}
25
+ end
26
+
27
+ def start
28
+ @thread = Thread.new do
29
+ Rack::Handler::Thin.run self, :Host => @host, :Port => @port do |server|
30
+ @server = server
31
+ end
32
+ end
33
+ sleep(0.1) until @server and @server.running?
34
+ end
35
+
36
+ private
37
+
38
+ # Stolen from Capybara
39
+ def find_available_port
40
+ server = TCPServer.new(@host, 0)
41
+ server.addr[1]
42
+ ensure
43
+ server.close if server
44
+ end
45
+ end
46
+
47
+ module TestServerHelper
48
+ def server
49
+ RSpec.configuration.server
50
+ end
51
+ end
52
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spdocgen
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Shaun Mangelsdorf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2015-11-20 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - &id002
20
+ - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ type: :runtime
24
+ version_requirements: *id001
25
+ description: Ruby client library for rendering and downloading documents from SP Docgen
26
+ email:
27
+ - smangelsdorf@sp.com.au
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - .gitignore
36
+ - Gemfile
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - lib/spdocgen.rb
41
+ - lib/spdocgen/configuration.rb
42
+ - lib/spdocgen/document.rb
43
+ - lib/spdocgen/document_set.rb
44
+ - lib/spdocgen/download_request.rb
45
+ - lib/spdocgen/download_response.rb
46
+ - lib/spdocgen/protocol.rb
47
+ - lib/spdocgen/render_request.rb
48
+ - lib/spdocgen/render_response.rb
49
+ - lib/spdocgen/status_request.rb
50
+ - lib/spdocgen/status_response.rb
51
+ - lib/spdocgen/version.rb
52
+ - spdocgen.gemspec
53
+ - spec/config.yml
54
+ - spec/download_request_spec.rb
55
+ - spec/render_request_spec.rb
56
+ - spec/spec_helper.rb
57
+ - spec/status_request_spec.rb
58
+ - spec/test_server.rb
59
+ homepage: http://sp.docgen.net.au
60
+ licenses: []
61
+
62
+ metadata: {}
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - *id002
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - *id002
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 2.0.11
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: SP Docgen client library
82
+ test_files:
83
+ - spec/config.yml
84
+ - spec/download_request_spec.rb
85
+ - spec/render_request_spec.rb
86
+ - spec/spec_helper.rb
87
+ - spec/status_request_spec.rb
88
+ - spec/test_server.rb