pdf_ravager 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +2 -4
  6. data/README.md +14 -10
  7. data/Rakefile +2 -2
  8. data/lib/pdf_ravager/field_types/acro_form.rb +0 -8
  9. data/lib/pdf_ravager/kernel.rb +1 -0
  10. data/lib/pdf_ravager/ravager.rb +25 -54
  11. data/lib/pdf_ravager/strategies/acro_form.rb +25 -0
  12. data/lib/pdf_ravager/strategies/smart.rb +22 -0
  13. data/lib/pdf_ravager/strategies/xfa.rb +67 -0
  14. data/lib/pdf_ravager/template.rb +14 -4
  15. data/lib/pdf_ravager/version.rb +1 -1
  16. data/pdf_ravager.gemspec +2 -3
  17. data/spec/integration/checkbox_field/checked.png +0 -0
  18. data/spec/integration/checkbox_field/pdf +0 -0
  19. data/spec/integration/checkbox_field/spec.rb +31 -0
  20. data/spec/integration/checkbox_field/unchecked.png +0 -0
  21. data/spec/integration/checkbox_group/bar.png +0 -0
  22. data/spec/integration/checkbox_group/foo.png +0 -0
  23. data/spec/integration/checkbox_group/pdf +0 -0
  24. data/spec/integration/checkbox_group/spec.rb +49 -0
  25. data/spec/integration/checkbox_group/unchecked.png +0 -0
  26. data/spec/integration/integration_helper.rb +14 -3
  27. data/spec/integration/multiline_text_field/spec.rb +10 -11
  28. data/spec/integration/radio_field/empty.png +0 -0
  29. data/spec/integration/radio_field/no.png +0 -0
  30. data/spec/integration/radio_field/pdf +0 -0
  31. data/spec/integration/radio_field/spec.rb +45 -0
  32. data/spec/integration/radio_field/yes.png +0 -0
  33. data/spec/integration/text_field/spec.rb +11 -12
  34. data/spec/spec_helper.rb +4 -1
  35. data/spec/unit/fields/checkbox_spec.rb +25 -16
  36. data/spec/unit/kernel_spec.rb +14 -8
  37. data/spec/unit/template_spec.rb +91 -41
  38. data/spec/unit/unit_helper.rb +1 -1
  39. metadata +58 -63
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 78b00f06cc54b5f044001f621fc30d284a02410e
4
+ data.tar.gz: b9fac87df32a1e3033d2e73f622b0665e761b3da
5
+ SHA512:
6
+ metadata.gz: 8dc1d7f6bca130cb731862d507463df813775abc7cbff40a7f5313fe28e92b5e327677cc2103718621bbc0ae12687d88e692146428b93863e7bd5cec81ec1043
7
+ data.tar.gz: cba64b43ca4100a42d7b10e77daa5112fcac7ec4df066e2b2cdfe57c42dc1dc349c62c14a1e382d7315039763f29d8d69a2bad39a3618bbafb919604e3ff595c
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ Gemfile.lock
2
2
  pkg/
3
3
  *.gem
4
4
  .bundle
5
+ coverage/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --color
3
+ --profile
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## 0.2.0
2
+
3
+ Features:
4
+
5
+ - Deprecate global `pdf` convenience method
6
+ - Deprecate name option to `PDFRavager::Template.new`
7
+ - Move PDF population methods into strategies
8
+ - Speed up PDF population by default (i.e. :smart strategy) by avoiding XFA
data/Gemfile CHANGED
@@ -5,9 +5,7 @@ gemspec
5
5
  platforms :jruby do
6
6
  # Necessary for `rake release` on JRuby
7
7
  gem "jruby-openssl", "~> 0.7.7"
8
+ gem 'bouncy-castle-java'
8
9
  end
9
10
 
10
- group :test do
11
- # Formats and colorizes test output
12
- gem "turn", "~> 0.9.6", :require => false
13
- end
11
+ gem "simplecov", "~> 0.8", :require => false
data/README.md CHANGED
@@ -1,21 +1,21 @@
1
1
  # PDF Ravager [![Build Status](https://secure.travis-ci.org/abevoelker/pdf_ravager.png)](http://travis-ci.org/abevoelker/pdf_ravager)
2
2
 
3
- Provides a simple DSL for easily filling out AcroForms PDF or XFA documents.
3
+ JRuby-only DSL for filling out AcroForms PDF or XFA documents.
4
4
 
5
5
  ## Description
6
6
 
7
7
  This library uses a combination of a simple DSL and a minimal façade over the
8
- last free version of the iText library to aid in filling out AcroForms PDF or
9
- XFA documents.
8
+ last free version of the Java iText library to aid in filling out AcroForms PDF
9
+ or XFA documents.
10
10
 
11
11
  ## Synopsis
12
12
 
13
13
  ```ruby
14
- require 'pdf_ravager/kernel'
14
+ require 'pdf_ravager'
15
15
 
16
- data = {name: 'Bob', gender: 'm', relation: 'Uncle' }
16
+ data = { name: 'Bob', gender: 'm', relation: 'Uncle' }
17
17
 
18
- template = pdf do |p|
18
+ template = PDFRavager::Template.new do |p|
19
19
  p.text 'name', data[:name]
20
20
  p.rich_text 'name_stylized', "<b>#{data[:name]}</b>"
21
21
  p.radio_group 'sex' do |rg|
@@ -40,20 +40,24 @@ template.ravage '/tmp/info.pdf', out_file: '/tmp/info_filled.pdf'
40
40
  template.ravage '/tmp/info.pdf', out_file: '/tmp/info_filled.pdf', read_only: true
41
41
  ```
42
42
 
43
- If you don't want the global `pdf` method, the default `require 'pdf_ravager'`
44
- actually doesn't add it. You just need to be more wordy in this case:
43
+ Although not recommended due to the pollution of the global namespace, in the
44
+ interest of brevity you can introduce a shorthand `pdf` method that is
45
+ equivalent to `PDFRavager::Template.new` by requiring `pdf_ravager/kernel`
46
+ instead of `pdf_ravager`:
45
47
 
46
48
  ```ruby
47
- require 'pdf_ravager'
49
+ require 'pdf_ravager/kernel'
48
50
 
49
51
  data = {name: 'Bob', gender: 'm', relation: 'Uncle' }
50
52
 
51
- template = PDFRavager::Template.new do |p|
53
+ template = pdf do |p|
52
54
  p.text 'name', data[:name]
53
55
  # ...
54
56
  end
55
57
  ```
56
58
 
59
+ Note: `pdf` has been deprecated and will be removed in a future release.
60
+
57
61
  ## Usage
58
62
 
59
63
  ### Field Names
data/Rakefile CHANGED
@@ -5,13 +5,13 @@ require 'bundler'
5
5
 
6
6
  Rake::TestTask.new('spec:unit') do |t|
7
7
  t.libs << ["lib", "spec"]
8
- t.pattern = "spec/**/*_spec.rb"
8
+ t.pattern = "spec/unit/**/*_spec.rb"
9
9
  end
10
10
 
11
11
  if RUBY_PLATFORM =~ /java/
12
12
  # Integration tests can only run on JRuby
13
13
  RSpec::Core::RakeTask.new('spec:integration') do |spec|
14
- spec.pattern = "spec/**/*spec.rb"
14
+ spec.pattern = "spec/integration/**/*spec.rb"
15
15
  spec.rspec_opts = ['--backtrace']
16
16
  end
17
17
 
@@ -23,14 +23,6 @@ module PDFRavager
23
23
  @value.to_s
24
24
  end
25
25
 
26
- def set_acro_form_value(acro_fields)
27
- begin
28
- acro_fields.setField(SOM.short_name(acro_form_name), acro_form_value)
29
- rescue java.lang.NullPointerException
30
- false
31
- end
32
- end
33
-
34
26
  end
35
27
  end
36
28
  end
@@ -2,6 +2,7 @@ require 'pdf_ravager/template'
2
2
 
3
3
  module Kernel
4
4
  def pdf(*args, &blk)
5
+ warn "[DEPRECATION] Please use `PDFRavager::Template.new` instead of `pdf`"
5
6
  PDFRavager::Template.new(*args, &blk)
6
7
  end
7
8
  end
@@ -1,3 +1,7 @@
1
+ require 'pdf_ravager/strategies/xfa'
2
+ require 'pdf_ravager/strategies/acro_form'
3
+ require 'pdf_ravager/strategies/smart'
4
+
1
5
  unless RUBY_PLATFORM =~ /java/
2
6
  raise "You can only ravage PDFs using JRuby, not #{RUBY_PLATFORM}!"
3
7
  end
@@ -8,71 +12,38 @@ require File.dirname(__FILE__) + '/../../vendor/iText-4.2.0'
8
12
 
9
13
  module PDFRavager
10
14
  class Ravager
11
- private_class_method :new
15
+ def self.ravage(*args, &blk)
16
+ warn "[DEPRECATION] Please use PDFRavager::Ravager's instance " +
17
+ "methods instead of the `::ravage` method"
18
+ new(*args, &blk).ravage
19
+ end
12
20
 
13
- def self.ravage(template, opts={})
21
+ def initialize(template, opts={})
22
+ @opts = opts
14
23
  opts = {:in_file => opts} if opts.is_a? String
15
- out = if opts[:out_file]
24
+ @out = if opts[:out_file]
16
25
  java.io.FileOutputStream.new(opts[:out_file])
17
26
  else
18
27
  java.io.ByteArrayOutputStream.new
19
28
  end
20
- ravager = new(template, opts.merge({:out => out}))
21
- ravager.send(:set_field_values)
22
- ravager.send(:set_read_only) if opts[:read_only]
23
- ravager.send(:destroy)
24
- out
25
- end
26
-
27
- private
28
-
29
- # instantiation is private because there is a lot of state mutation
30
- # and some invariants that need to be cleaned up. therefore, Ravager's
31
- # lifecycle is managed by the public class method `ravage`.
32
- def initialize(template, opts={})
33
- @template, @opts = template, opts
34
- @reader = com.lowagie.text.pdf.PdfReader.new(opts[:in_file])
35
- @stamper = com.lowagie.text.pdf.PdfStamper.new(@reader, opts[:out])
36
- @afields = @stamper.getAcroFields
37
- @xfa = @afields.getXfa
38
- @som = @xfa.getDatasetsSom
39
- @som_template = @xfa.getTemplateSom
40
- @type = @xfa.isXfaPresent ? :xfa : :acro_forms
41
- if @type == :xfa
42
- @xfa_type = @afields.getFields.empty? ? :dynamic : :static
43
- end
44
- end
45
-
46
- def destroy
47
- @stamper.close
48
- end
49
-
50
- def set_field_values
51
- case @type
29
+ @template = template
30
+ reader = com.lowagie.text.pdf.PdfReader.new(opts[:in_file])
31
+ @stamper = com.lowagie.text.pdf.PdfStamper.new(reader, @out)
32
+ @strategy = case template.strategy
52
33
  when :acro_forms
53
- @template.fields.each{|f| f.set_acro_form_value(@afields) }
34
+ Strategies::AcroForm.new(@stamper)
54
35
  when :xfa
55
- @template.fields.each do |f|
56
- f.set_acro_form_value(@afields) if f.respond_to? :set_acro_form_value
57
- f.set_xfa_value(@xfa) if f.respond_to? :set_xfa_value
58
- end
36
+ Strategies::XFA.new(@stamper)
37
+ when :smart
38
+ Strategies::Smart.new(@stamper)
59
39
  end
60
40
  end
61
41
 
62
- def set_read_only
63
- case @type
64
- when :acro_forms
65
- @stamper.setFormFlattening(true)
66
- when :xfa
67
- doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
68
- doc.xpath("//*[local-name()='field']").each do |node|
69
- node["access"] = "readOnly"
70
- end
71
- @xfa.setDomDocument(doc.to_java)
72
- @xfa.setChanged(true)
73
- end
42
+ def ravage
43
+ @strategy.set_field_values(@template)
44
+ @strategy.set_read_only if @opts[:read_only]
45
+ @stamper.close
46
+ @out
74
47
  end
75
-
76
48
  end
77
-
78
49
  end
@@ -0,0 +1,25 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class AcroForm
4
+ def initialize(stamper)
5
+ @stamper = stamper
6
+ @afields = stamper.getAcroFields
7
+ end
8
+
9
+ def set_field_values(template)
10
+ template.fields.select{|f| f.respond_to?(:acro_form_value)}.select do |f|
11
+ begin
12
+ @afields.setField(FieldTypes::AcroForm::SOM.short_name(f.acro_form_name), f.acro_form_value)
13
+ rescue java.lang.NullPointerException
14
+ false
15
+ end
16
+ end
17
+ end
18
+
19
+ def set_read_only
20
+ @stamper.setFormFlattening(true)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class Smart
4
+ def initialize(stamper)
5
+ @acro_form = Strategies::AcroForm.new(stamper)
6
+ @xfa = Strategies::XFA.new(stamper)
7
+ end
8
+
9
+ def set_field_values(template)
10
+ parsed_fields = @acro_form.set_field_values(template)
11
+ unparsed_fields = template.fields - parsed_fields
12
+ if unparsed_fields.any?
13
+ @xfa.set_field_values(Template.new{|t| t.fields = unparsed_fields })
14
+ end
15
+ end
16
+
17
+ def set_read_only
18
+ [@acro_form, @xfa].each(&:set_read_only)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class XFA
4
+ def initialize(stamper)
5
+ @xfa = stamper.getAcroFields.getXfa
6
+ end
7
+
8
+ def set_field_values(template)
9
+ # the double-load is to work around a Nokogiri bug I found:
10
+ # https://github.com/sparklemotion/nokogiri/issues/781
11
+ doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
12
+ template.fields.select{|f| f.respond_to?(:set_xfa_value)}.each do |f|
13
+ # first, assume the user-provided field name is an xpath and use it directly:
14
+ strict_match =
15
+ begin
16
+ doc.xpath(f.xfa_name)
17
+ rescue Nokogiri::XML::XPath::SyntaxError
18
+ []
19
+ end
20
+ # otherwise, we'll loosely match the field name anywhere in the document:
21
+ loose_match = doc.xpath("//*[local-name()='field'][@name='#{f.xfa_name}']")
22
+ matched_nodes = strict_match.any? ? strict_match : loose_match
23
+ matched_nodes.each do |node|
24
+ value_node = node.at_xpath("*[local-name()='value']")
25
+ if value_node
26
+ text_node = value_node.at_xpath("*[local-name()='#{f.xfa_node_type}']")
27
+ if text_node
28
+ # Complete node structure already exists - just set the value
29
+ text_node.content = f.xfa_value
30
+ else
31
+ # <value> node exists, but without child <text> node
32
+ Nokogiri::XML::Builder.with(value_node) do |xml|
33
+ xml.text_ {
34
+ xml.send("#{f.xfa_node_type}_", f.xfa_value)
35
+ }
36
+ end
37
+ end
38
+ else
39
+ # No <value> node exists - create whole structure
40
+ Nokogiri::XML::Builder.with(node) do |xml|
41
+ xml.value_ {
42
+ xml.send("#{f.xfa_node_type}_") {
43
+ xml.text f.xfa_value
44
+ }
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ @xfa.tap do |x|
51
+ x.setDomDocument(doc.to_java)
52
+ x.setChanged(true)
53
+ end
54
+ end
55
+
56
+ def set_read_only
57
+ doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
58
+ doc.xpath("//*[local-name()='field']").each do |node|
59
+ node["access"] = "readOnly"
60
+ end
61
+ @xfa.setDomDocument(doc.to_java)
62
+ @xfa.setChanged(true)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -8,10 +8,20 @@ require 'pdf_ravager/ravager' if RUBY_PLATFORM =~ /java/
8
8
 
9
9
  module PDFRavager
10
10
  class Template
11
- attr_reader :name, :fields
11
+ attr_reader :name, :strategy
12
+ attr_accessor :fields
12
13
 
13
- def initialize(name=nil)
14
- @name, @fields = name, []
14
+ def initialize(opts={})
15
+ opts = {:name => opts} if opts.respond_to?(:to_sym)
16
+ unless opts[:name].nil?
17
+ warn "[DEPRECATION] Passing a name to `PDFRavager::Template.new` " +
18
+ "is deprecated and will be removed in 1.0.0"
19
+ end
20
+ @name, @strategy = opts[:name], (opts[:strategy] || :smart)
21
+ unless [:smart, :acro_forms, :xfa].include?(@strategy)
22
+ raise "Bad strategy '#{@strategy}'"
23
+ end
24
+ @fields = []
15
25
  yield self if block_given?
16
26
  end
17
27
 
@@ -45,7 +55,7 @@ module PDFRavager
45
55
 
46
56
  if RUBY_PLATFORM =~ /java/
47
57
  def ravage(file, opts={})
48
- PDFRavager::Ravager.ravage(self, opts.merge({:in_file => file}))
58
+ PDFRavager::Ravager.new(self, opts.merge({:in_file => file})).ravage
49
59
  end
50
60
  else
51
61
  def ravage(file, opts={})
@@ -1,3 +1,3 @@
1
1
  module PDFRavager
2
- VERSION = "0.1.0"
2
+ VERSION = '0.2.0'
3
3
  end
data/pdf_ravager.gemspec CHANGED
@@ -7,13 +7,12 @@ Gem::Specification.new do |s|
7
7
  s.authors = ['Abe Voelker']
8
8
  s.email = 'abe@abevoelker.com'
9
9
  s.homepage = 'https://github.com/abevoelker/pdf_ravager'
10
- s.summary = %q{DSL to aid filling out AcroForms PDF and XFA documents}
11
- s.description = %q{DSL to aid filling out AcroForms PDF and XFA documents}
10
+ s.summary = %q{JRuby-only DSL for filling out AcroForms PDF and XFA documents}
11
+ s.description = %q{JRuby-only DSL for filling out AcroForms PDF and XFA documents}
12
12
  s.license = 'MIT'
13
13
 
14
14
  s.add_dependency "nokogiri"
15
15
  s.add_development_dependency "bundler", "~> 1.0"
16
- s.add_development_dependency "minitest", "~> 4.1"
17
16
  s.add_development_dependency "rspec", "~> 2.11"
18
17
  s.add_development_dependency "rake", "~> 0.9"
19
18
  s.add_development_dependency "chunky_png", "~> 1.2"
Binary file
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a checkbox field' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'unchecked' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "unchecked.png") }
11
+
12
+ it 'matches unchecked.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'checked' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.check 'CheckBox1'
22
+ end
23
+ }
24
+ let(:expected) { File.join(File.dirname(__FILE__), "checked.png") }
25
+
26
+ it 'matches checked.png when rendered' do
27
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
28
+ expect(pix_diff).to eq(0)
29
+ end
30
+ end
31
+ end
Binary file
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a checkbox group' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'nothing checked' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "unchecked.png") }
11
+
12
+ it 'matches unchecked.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'CheckBoxGroup.foo checked' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.checkbox_group 'CheckBoxGroup' do |g|
22
+ g.check 'foo'
23
+ end
24
+ end
25
+ }
26
+ let(:expected) { File.join(File.dirname(__FILE__), "foo.png") }
27
+
28
+ it 'matches foo.png when rendered' do
29
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
30
+ expect(pix_diff).to eq(0)
31
+ end
32
+ end
33
+
34
+ context 'CheckBoxGroup.bar checked' do
35
+ let(:template) {
36
+ PDFRavager::Template.new do |t|
37
+ t.checkbox_group 'CheckBoxGroup' do |g|
38
+ g.check 'bar'
39
+ end
40
+ end
41
+ }
42
+ let(:expected) { File.join(File.dirname(__FILE__), "bar.png") }
43
+
44
+ it 'matches bar.png when rendered' do
45
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
46
+ expect(pix_diff).to eq(0)
47
+ end
48
+ end
49
+ end
@@ -1,12 +1,13 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require 'rspec'
3
- require 'pdf_ravager'
4
2
  require 'securerandom'
5
3
  require 'chunky_png'
6
4
  require 'tempfile'
7
5
 
8
6
  def mktemp(ext)
9
- Tempfile.new(['', ext]).path
7
+ f = Tempfile.new(['', ext])
8
+ (@@prevent_gc ||= []) << f # prevents file from getting deleted until all tests are done
9
+ f.close
10
+ f.path
10
11
  end
11
12
 
12
13
  def pdf_to_ps(pdf_file, out_file=nil)
@@ -25,6 +26,16 @@ def pdf_to_png(pdf_file)
25
26
  ps_to_png(pdf_to_ps(pdf_file))
26
27
  end
27
28
 
29
+ def ravage_to_temp_file(template, input_pdf)
30
+ file = mktemp('.pdf')
31
+ template.ravage input_pdf, :out_file => file
32
+ file
33
+ end
34
+
35
+ def compare_pdf_to_png(input_pdf, png)
36
+ png_diff(pdf_to_png(input_pdf), png)
37
+ end
38
+
28
39
  # code taken from http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/
29
40
  def png_diff(img1, img2)
30
41
  images = [
@@ -1,20 +1,19 @@
1
1
  require File.dirname(__FILE__) + '/../integration_helper'
2
2
 
3
3
  describe 'a PDF with a multiline text field' do
4
- describe 'filled with FOO' do
5
- before(:each) do
6
- p = PDFRavager::Template.new do |t|
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'filled with FOO' do
7
+ let(:template) {
8
+ PDFRavager::Template.new do |t|
7
9
  t.text 'multilinetext', 'FOO' * 10000
8
10
  end
9
- pdf_file = File.join(File.dirname(__FILE__), "pdf")
10
- @pdf_file = mktemp('.pdf')
11
- @pdf = p.ravage pdf_file, :out_file => @pdf_file
12
- end
11
+ }
12
+ let(:expected) { File.join(File.dirname(__FILE__), "expected.png") }
13
13
 
14
- it 'should match expected.png when rendered' do
15
- png = pdf_to_png(@pdf_file)
16
- pix_diff, pct_diff = png_diff(png, File.join(File.dirname(__FILE__), "expected.png"))
17
- pix_diff.should == 0
14
+ it 'matches expected.png when rendered' do
15
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
16
+ expect(pix_diff).to eq(0)
18
17
  end
19
18
  end
20
19
  end
Binary file
Binary file
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a radio field' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'with nothing filled in' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "empty.png") }
11
+
12
+ it 'matches empty.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'with "Yes" filled in' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.fill 'RadioButtonList', 'Yes'
22
+ end
23
+ }
24
+ let(:expected) { File.join(File.dirname(__FILE__), "yes.png") }
25
+
26
+ it 'matches yes.png when rendered' do
27
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
28
+ expect(pix_diff).to eq(0)
29
+ end
30
+ end
31
+
32
+ context 'with "No" filled in' do
33
+ let(:template) {
34
+ PDFRavager::Template.new do |t|
35
+ t.fill 'RadioButtonList', 'No'
36
+ end
37
+ }
38
+ let(:expected) { File.join(File.dirname(__FILE__), "no.png") }
39
+
40
+ it 'matches no.png when rendered' do
41
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
42
+ expect(pix_diff).to eq(0)
43
+ end
44
+ end
45
+ end
@@ -1,20 +1,19 @@
1
- require 'integration/integration_helper'
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
2
 
3
3
  describe 'a PDF with a text field' do
4
- describe 'filled with foo' do
5
- before(:each) do
6
- p = PDFRavager::Template.new do |t|
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'filled with foo' do
7
+ let(:template) {
8
+ PDFRavager::Template.new do |t|
7
9
  t.text 'text_field', 'foo'
8
10
  end
9
- pdf_file = File.join(File.dirname(__FILE__), "pdf")
10
- @pdf_file = mktemp('.pdf')
11
- @pdf = p.ravage pdf_file, :out_file => @pdf_file
12
- end
11
+ }
12
+ let(:expected) { File.join(File.dirname(__FILE__), "expected.png") }
13
13
 
14
- it 'should match expected.png when rendered' do
15
- png = pdf_to_png(@pdf_file)
16
- pix_diff, pct_diff = png_diff(png, File.join(File.dirname(__FILE__), "expected.png"))
17
- pix_diff.should be 0
14
+ it 'matches expected.png when rendered' do
15
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
16
+ expect(pix_diff).to eq(0)
18
17
  end
19
18
  end
20
19
  end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,4 @@
1
- require 'turn/autorun'
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+ require 'rspec'
4
+ require 'pdf_ravager'
@@ -1,27 +1,36 @@
1
1
  require File.dirname(__FILE__) + '/fields_helper'
2
- require 'pdf_ravager/template'
3
2
 
4
- class TestCheckbox < MiniTest::Unit::TestCase
3
+ describe PDFRavager::Fields::Checkbox do
5
4
 
6
- def setup
7
- @checked = PDFRavager::Fields::Checkbox.new('checkbox1', true, :true_value => 'foo', :false_value => 'bar')
8
- @unchecked = PDFRavager::Fields::Checkbox.new('checkbox2', false, :true_value => 'foo', :false_value => 'bar')
9
- end
5
+ let(:checked) { PDFRavager::Fields::Checkbox.new('checkbox1', true, :true_value => 'foo', :false_value => 'bar') }
6
+ let(:unchecked) { PDFRavager::Fields::Checkbox.new('checkbox2', false, :true_value => 'foo', :false_value => 'bar') }
10
7
 
11
- def test_that_custom_checked_acro_form_value_is_set
12
- assert_equal @checked.acro_form_value, 'foo'
13
- end
8
+ context 'checked' do
9
+ context 'AcroForm value' do
10
+ it 'sets value properly' do
11
+ expect(checked.xfa_value).to eq('foo')
12
+ end
13
+ end
14
14
 
15
- def test_that_custom_checked_xfa_value_is_set
16
- assert_equal @checked.xfa_value, 'foo'
15
+ context 'XFA value' do
16
+ it 'sets value properly' do
17
+ expect(checked.xfa_value).to eq('foo')
18
+ end
19
+ end
17
20
  end
18
21
 
19
- def test_that_custom_unchecked_acro_form_value_is_set
20
- assert_equal @unchecked.acro_form_value, 'bar'
21
- end
22
+ context 'unchecked' do
23
+ context 'AcroForm value' do
24
+ it 'sets value properly' do
25
+ expect(unchecked.xfa_value).to eq('bar')
26
+ end
27
+ end
22
28
 
23
- def test_that_custom_unchecked_xfa_value_is_set
24
- assert_equal @unchecked.xfa_value, 'bar'
29
+ context 'XFA value' do
30
+ it 'sets value properly' do
31
+ expect(unchecked.xfa_value).to eq('bar')
32
+ end
33
+ end
25
34
  end
26
35
 
27
36
  end
@@ -1,27 +1,33 @@
1
1
  require File.dirname(__FILE__) + '/unit_helper'
2
2
  require 'pdf_ravager/kernel'
3
3
 
4
- class TestKernelIntegration < MiniTest::Unit::TestCase
5
-
6
- def setup
7
- @template = pdf do |p|
4
+ describe Kernel do
5
+ let(:template) {
6
+ pdf do |p|
8
7
  p.text 'text', 'foo'
9
8
  p.rich_text 'rich_text', '<b>foo</b>'
10
9
  p.check 'checkbox1'
11
10
  p.uncheck 'checkbox2'
12
11
  p.fill 'radio_group', 'button'
13
12
  end
14
- end
13
+ }
15
14
 
16
- def test_that_dsl_template_equals_longform_template
17
- template = PDFRavager::Template.new do |t|
15
+ let(:longform_template) {
16
+ PDFRavager::Template.new do |t|
18
17
  t.text 'text', 'foo'
19
18
  t.rich_text 'rich_text', '<b>foo</b>'
20
19
  t.check 'checkbox1'
21
20
  t.uncheck 'checkbox2'
22
21
  t.fill 'radio_group', 'button'
23
22
  end
24
- assert_equal @template, template
23
+ }
24
+
25
+ context 'equality' do
26
+ context 'a shorthand and longform template with equal options' do
27
+ it 'is equal' do
28
+ expect(template).to eq(longform_template)
29
+ end
30
+ end
25
31
  end
26
32
 
27
33
  end
@@ -1,61 +1,111 @@
1
1
  require File.dirname(__FILE__) + '/unit_helper'
2
- require 'pdf_ravager/template'
3
2
 
4
- class TestTemplate < MiniTest::Unit::TestCase
3
+ describe PDFRavager::Template do
5
4
 
6
- def setup
7
- @template = PDFRavager::Template.new do |t|
8
- t.text 'text', 'foo'
9
- t.rich_text 'rich_text', '<b>foo</b>'
10
- t.check 'checkbox1'
11
- t.uncheck 'checkbox2'
12
- t.checkbox_group 'cbox_group' do |cb|
13
- cb.check 'checked'
14
- cb.uncheck 'unchecked'
5
+ context 'initialization' do
6
+ context 'template with a name' do
7
+ let(:template) { PDFRavager::Template.new('template') }
8
+
9
+ it 'sets the name' do
10
+ expect(template.name).to eq('template')
15
11
  end
16
- t.fill 'radio_group', 'button'
17
- t.radio_group 'better_radio_group' do |rg|
18
- rg.fill 'button'
12
+ end
13
+
14
+ context 'template without a name' do
15
+ let(:template) { PDFRavager::Template.new }
16
+
17
+ it 'does not set the name' do
18
+ expect(template.name).to be_nil
19
19
  end
20
20
  end
21
21
 
22
- @template_with_name = PDFRavager::Template.new('template'){}
23
- end
22
+ context 'setting strategy' do
23
+ context 'with a valid strategy' do
24
+ let(:template) { PDFRavager::Template.new(:strategy => :xfa) }
24
25
 
25
- def test_that_text_is_set
26
- assert_includes @template.fields, PDFRavager::Fields::Text.new('text', 'foo')
27
- end
26
+ it 'sets the strategy' do
27
+ expect(template.strategy).to eq(:xfa)
28
+ end
29
+ end
28
30
 
29
- def test_that_rich_text_is_set
30
- assert_includes @template.fields, PDFRavager::Fields::RichText.new('rich_text', '<b>foo</b>')
31
+ context 'with an invalid strategy' do
32
+ it 'raises an error' do
33
+ expect { PDFRavager::Template.new(:strategy => :foo) }.to raise_error
34
+ end
35
+ end
36
+ end
31
37
  end
32
38
 
33
- def test_that_checkbox_is_set
34
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('checkbox1', true)
35
- end
39
+ context 'setting template values' do
36
40
 
37
- def test_that_checkbox_is_unset
38
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('checkbox2', false)
39
- end
41
+ let(:template) {
42
+ PDFRavager::Template.new do |t|
43
+ t.text 'text', 'foo'
44
+ t.rich_text 'rich_text', '<b>foo</b>'
45
+ t.check 'checkbox1'
46
+ t.uncheck 'checkbox2'
47
+ t.checkbox_group 'cbox_group' do |cb|
48
+ cb.check 'checked'
49
+ cb.uncheck 'unchecked'
50
+ end
51
+ t.fill 'radio_group', 'button'
52
+ t.radio_group 'better_radio_group' do |rg|
53
+ rg.fill 'button'
54
+ end
55
+ end
56
+ }
40
57
 
41
- def test_that_radio_button_is_filled
42
- assert_includes @template.fields, PDFRavager::Fields::Radio.new('radio_group', 'button')
43
- end
58
+ context 'text' do
59
+ it 'is set' do
60
+ expect(template.fields).to include(PDFRavager::Fields::Text.new('text', 'foo'))
61
+ end
62
+ end
44
63
 
45
- def test_that_name_is_set
46
- assert_equal @template_with_name.name, 'template'
47
- end
64
+ context 'rich_text' do
65
+ it 'is set' do
66
+ expect(template.fields).to include(PDFRavager::Fields::RichText.new('rich_text', '<b>foo</b>'))
67
+ end
68
+ end
48
69
 
49
- def test_that_checkbox_group_box_is_checked
50
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('cbox_group.checked', true)
51
- end
70
+ context 'checkbox1' do
71
+ it 'is set' do
72
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('checkbox1', true))
73
+ end
74
+ end
52
75
 
53
- def test_that_checkbox_group_box_is_unchecked
54
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('cbox_group.unchecked', false)
55
- end
76
+ context 'checkbox2' do
77
+ it 'is unset' do
78
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('checkbox2', false))
79
+ end
80
+ end
81
+
82
+ context 'cbox_group' do
83
+ context '.checked' do
84
+ it 'is checked' do
85
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('cbox_group.checked', true))
86
+ end
87
+ end
88
+
89
+ context '.unchecked' do
90
+ it 'is unchecked' do
91
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('cbox_group.unchecked', false))
92
+ end
93
+ end
94
+ end
56
95
 
57
- def test_that_radio_group_button_is_filled
58
- assert_includes @template.fields, PDFRavager::Fields::Radio.new('better_radio_group', 'button')
96
+ context 'radio buttons' do
97
+ context 'one-line syntax' do
98
+ it 'fills the radio_group button' do
99
+ expect(template.fields).to include(PDFRavager::Fields::Radio.new('radio_group', 'button'))
100
+ end
101
+ end
102
+
103
+ context 'block syntax' do
104
+ it 'fills the better_radio_group button' do
105
+ expect(template.fields).to include(PDFRavager::Fields::Radio.new('better_radio_group', 'button'))
106
+ end
107
+ end
108
+ end
59
109
  end
60
110
 
61
111
  end
@@ -1,2 +1,2 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require 'minitest/autorun'
2
+ require 'rspec/autorun'
metadata CHANGED
@@ -1,122 +1,95 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdf_ravager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Abe Voelker
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-10 00:00:00.000000000 Z
11
+ date: 2014-03-31 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: nokogiri
16
15
  version_requirements: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - ">="
17
+ - - '>='
19
18
  - !ruby/object:Gem::Version
20
- version: !binary |-
21
- MA==
22
- none: false
19
+ version: '0'
23
20
  requirement: !ruby/object:Gem::Requirement
24
21
  requirements:
25
- - - ">="
22
+ - - '>='
26
23
  - !ruby/object:Gem::Version
27
- version: !binary |-
28
- MA==
29
- none: false
24
+ version: '0'
30
25
  prerelease: false
31
26
  type: :runtime
32
27
  - !ruby/object:Gem::Dependency
33
28
  name: bundler
34
29
  version_requirements: !ruby/object:Gem::Requirement
35
30
  requirements:
36
- - - "~>"
31
+ - - ~>
37
32
  - !ruby/object:Gem::Version
38
33
  version: '1.0'
39
- none: false
40
34
  requirement: !ruby/object:Gem::Requirement
41
35
  requirements:
42
- - - "~>"
36
+ - - ~>
43
37
  - !ruby/object:Gem::Version
44
38
  version: '1.0'
45
- none: false
46
- prerelease: false
47
- type: :development
48
- - !ruby/object:Gem::Dependency
49
- name: minitest
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '4.1'
55
- none: false
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '4.1'
61
- none: false
62
39
  prerelease: false
63
40
  type: :development
64
41
  - !ruby/object:Gem::Dependency
65
42
  name: rspec
66
43
  version_requirements: !ruby/object:Gem::Requirement
67
44
  requirements:
68
- - - "~>"
45
+ - - ~>
69
46
  - !ruby/object:Gem::Version
70
47
  version: '2.11'
71
- none: false
72
48
  requirement: !ruby/object:Gem::Requirement
73
49
  requirements:
74
- - - "~>"
50
+ - - ~>
75
51
  - !ruby/object:Gem::Version
76
52
  version: '2.11'
77
- none: false
78
53
  prerelease: false
79
54
  type: :development
80
55
  - !ruby/object:Gem::Dependency
81
56
  name: rake
82
57
  version_requirements: !ruby/object:Gem::Requirement
83
58
  requirements:
84
- - - "~>"
59
+ - - ~>
85
60
  - !ruby/object:Gem::Version
86
61
  version: '0.9'
87
- none: false
88
62
  requirement: !ruby/object:Gem::Requirement
89
63
  requirements:
90
- - - "~>"
64
+ - - ~>
91
65
  - !ruby/object:Gem::Version
92
66
  version: '0.9'
93
- none: false
94
67
  prerelease: false
95
68
  type: :development
96
69
  - !ruby/object:Gem::Dependency
97
70
  name: chunky_png
98
71
  version_requirements: !ruby/object:Gem::Requirement
99
72
  requirements:
100
- - - "~>"
73
+ - - ~>
101
74
  - !ruby/object:Gem::Version
102
75
  version: '1.2'
103
- none: false
104
76
  requirement: !ruby/object:Gem::Requirement
105
77
  requirements:
106
- - - "~>"
78
+ - - ~>
107
79
  - !ruby/object:Gem::Version
108
80
  version: '1.2'
109
- none: false
110
81
  prerelease: false
111
82
  type: :development
112
- description: DSL to aid filling out AcroForms PDF and XFA documents
83
+ description: JRuby-only DSL for filling out AcroForms PDF and XFA documents
113
84
  email: abe@abevoelker.com
114
85
  executables: []
115
86
  extensions: []
116
87
  extra_rdoc_files: []
117
88
  files:
118
- - ".gitignore"
119
- - ".travis.yml"
89
+ - .gitignore
90
+ - .rspec
91
+ - .travis.yml
92
+ - CHANGELOG.md
120
93
  - Gemfile
121
94
  - LICENSE
122
95
  - README.md
@@ -132,13 +105,30 @@ files:
132
105
  - lib/pdf_ravager/fieldsets/radio_group.rb
133
106
  - lib/pdf_ravager/kernel.rb
134
107
  - lib/pdf_ravager/ravager.rb
108
+ - lib/pdf_ravager/strategies/acro_form.rb
109
+ - lib/pdf_ravager/strategies/smart.rb
110
+ - lib/pdf_ravager/strategies/xfa.rb
135
111
  - lib/pdf_ravager/template.rb
136
112
  - lib/pdf_ravager/version.rb
137
113
  - pdf_ravager.gemspec
114
+ - spec/integration/checkbox_field/checked.png
115
+ - spec/integration/checkbox_field/pdf
116
+ - spec/integration/checkbox_field/spec.rb
117
+ - spec/integration/checkbox_field/unchecked.png
118
+ - spec/integration/checkbox_group/bar.png
119
+ - spec/integration/checkbox_group/foo.png
120
+ - spec/integration/checkbox_group/pdf
121
+ - spec/integration/checkbox_group/spec.rb
122
+ - spec/integration/checkbox_group/unchecked.png
138
123
  - spec/integration/integration_helper.rb
139
124
  - spec/integration/multiline_text_field/expected.png
140
125
  - spec/integration/multiline_text_field/pdf
141
126
  - spec/integration/multiline_text_field/spec.rb
127
+ - spec/integration/radio_field/empty.png
128
+ - spec/integration/radio_field/no.png
129
+ - spec/integration/radio_field/pdf
130
+ - spec/integration/radio_field/spec.rb
131
+ - spec/integration/radio_field/yes.png
142
132
  - spec/integration/text_field/expected.png
143
133
  - spec/integration/text_field/pdf
144
134
  - spec/integration/text_field/spec.rb
@@ -152,41 +142,46 @@ files:
152
142
  homepage: https://github.com/abevoelker/pdf_ravager
153
143
  licenses:
154
144
  - MIT
145
+ metadata: {}
155
146
  post_install_message:
156
147
  rdoc_options: []
157
148
  require_paths:
158
149
  - lib
159
150
  required_ruby_version: !ruby/object:Gem::Requirement
160
151
  requirements:
161
- - - ">="
152
+ - - '>='
162
153
  - !ruby/object:Gem::Version
163
- segments:
164
- - 0
165
- version: !binary |-
166
- MA==
167
- hash: 2
168
- none: false
154
+ version: '0'
169
155
  required_rubygems_version: !ruby/object:Gem::Requirement
170
156
  requirements:
171
- - - ">="
157
+ - - '>='
172
158
  - !ruby/object:Gem::Version
173
- segments:
174
- - 0
175
- version: !binary |-
176
- MA==
177
- hash: 2
178
- none: false
159
+ version: '0'
179
160
  requirements: []
180
161
  rubyforge_project:
181
- rubygems_version: 1.8.24
162
+ rubygems_version: 2.1.9
182
163
  signing_key:
183
- specification_version: 3
184
- summary: DSL to aid filling out AcroForms PDF and XFA documents
164
+ specification_version: 4
165
+ summary: JRuby-only DSL for filling out AcroForms PDF and XFA documents
185
166
  test_files:
167
+ - spec/integration/checkbox_field/checked.png
168
+ - spec/integration/checkbox_field/pdf
169
+ - spec/integration/checkbox_field/spec.rb
170
+ - spec/integration/checkbox_field/unchecked.png
171
+ - spec/integration/checkbox_group/bar.png
172
+ - spec/integration/checkbox_group/foo.png
173
+ - spec/integration/checkbox_group/pdf
174
+ - spec/integration/checkbox_group/spec.rb
175
+ - spec/integration/checkbox_group/unchecked.png
186
176
  - spec/integration/integration_helper.rb
187
177
  - spec/integration/multiline_text_field/expected.png
188
178
  - spec/integration/multiline_text_field/pdf
189
179
  - spec/integration/multiline_text_field/spec.rb
180
+ - spec/integration/radio_field/empty.png
181
+ - spec/integration/radio_field/no.png
182
+ - spec/integration/radio_field/pdf
183
+ - spec/integration/radio_field/spec.rb
184
+ - spec/integration/radio_field/yes.png
190
185
  - spec/integration/text_field/expected.png
191
186
  - spec/integration/text_field/pdf
192
187
  - spec/integration/text_field/spec.rb