roo 2.6.0 → 2.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +16 -0
  4. data/.github/pull_request_template.md +14 -0
  5. data/.rubocop.yml +186 -0
  6. data/.travis.yml +14 -11
  7. data/CHANGELOG.md +64 -2
  8. data/Gemfile +2 -4
  9. data/LICENSE +2 -0
  10. data/README.md +36 -10
  11. data/lib/roo/base.rb +82 -225
  12. data/lib/roo/constants.rb +5 -3
  13. data/lib/roo/csv.rb +100 -97
  14. data/lib/roo/excelx/cell/base.rb +26 -12
  15. data/lib/roo/excelx/cell/boolean.rb +9 -6
  16. data/lib/roo/excelx/cell/date.rb +7 -7
  17. data/lib/roo/excelx/cell/datetime.rb +50 -44
  18. data/lib/roo/excelx/cell/empty.rb +3 -2
  19. data/lib/roo/excelx/cell/number.rb +44 -47
  20. data/lib/roo/excelx/cell/string.rb +3 -3
  21. data/lib/roo/excelx/cell/time.rb +17 -16
  22. data/lib/roo/excelx/cell.rb +10 -6
  23. data/lib/roo/excelx/comments.rb +3 -3
  24. data/lib/roo/excelx/coordinate.rb +11 -4
  25. data/lib/roo/excelx/extractor.rb +21 -3
  26. data/lib/roo/excelx/format.rb +38 -31
  27. data/lib/roo/excelx/images.rb +26 -0
  28. data/lib/roo/excelx/relationships.rb +12 -4
  29. data/lib/roo/excelx/shared.rb +10 -3
  30. data/lib/roo/excelx/shared_strings.rb +9 -15
  31. data/lib/roo/excelx/sheet.rb +49 -10
  32. data/lib/roo/excelx/sheet_doc.rb +89 -48
  33. data/lib/roo/excelx/styles.rb +3 -3
  34. data/lib/roo/excelx/workbook.rb +7 -3
  35. data/lib/roo/excelx.rb +50 -19
  36. data/lib/roo/formatters/base.rb +15 -0
  37. data/lib/roo/formatters/csv.rb +84 -0
  38. data/lib/roo/formatters/matrix.rb +23 -0
  39. data/lib/roo/formatters/xml.rb +31 -0
  40. data/lib/roo/formatters/yaml.rb +40 -0
  41. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  42. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  43. data/lib/roo/open_office.rb +17 -9
  44. data/lib/roo/spreadsheet.rb +1 -1
  45. data/lib/roo/tempdir.rb +5 -10
  46. data/lib/roo/utils.rb +70 -20
  47. data/lib/roo/version.rb +1 -1
  48. data/lib/roo.rb +4 -1
  49. data/roo.gemspec +14 -11
  50. data/spec/lib/roo/base_spec.rb +45 -3
  51. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  52. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  53. data/spec/lib/roo/excelx_spec.rb +150 -31
  54. data/spec/lib/roo/strict_spec.rb +43 -0
  55. data/spec/lib/roo/utils_spec.rb +25 -3
  56. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  57. data/spec/lib/roo_spec.rb +0 -0
  58. data/spec/spec_helper.rb +2 -6
  59. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  60. data/test/excelx/cell/test_base.rb +5 -0
  61. data/test/excelx/cell/test_datetime.rb +6 -6
  62. data/test/excelx/cell/test_empty.rb +11 -0
  63. data/test/excelx/cell/test_number.rb +9 -0
  64. data/test/excelx/cell/test_string.rb +20 -0
  65. data/test/excelx/cell/test_time.rb +5 -5
  66. data/test/excelx/test_coordinate.rb +51 -0
  67. data/test/formatters/test_csv.rb +136 -0
  68. data/test/formatters/test_matrix.rb +76 -0
  69. data/test/formatters/test_xml.rb +78 -0
  70. data/test/formatters/test_yaml.rb +20 -0
  71. data/test/helpers/test_accessing_files.rb +60 -0
  72. data/test/helpers/test_comments.rb +43 -0
  73. data/test/helpers/test_formulas.rb +9 -0
  74. data/test/helpers/test_labels.rb +103 -0
  75. data/test/helpers/test_sheets.rb +55 -0
  76. data/test/helpers/test_styles.rb +62 -0
  77. data/test/roo/test_base.rb +182 -0
  78. data/test/roo/test_csv.rb +88 -0
  79. data/test/roo/test_excelx.rb +330 -0
  80. data/test/roo/test_libre_office.rb +9 -0
  81. data/test/roo/test_open_office.rb +289 -0
  82. data/test/test_helper.rb +129 -14
  83. data/test/test_roo.rb +32 -1787
  84. metadata +81 -29
  85. data/.github/ISSUE_TEMPLATE +0 -10
  86. data/Gemfile_ruby2 +0 -29
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "weakref"
4
+
5
+ module Roo
6
+ module Helpers
7
+ module WeakInstanceCache
8
+ private
9
+
10
+ def instance_cache(key)
11
+ object = nil
12
+
13
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && ref.weakref_alive?
14
+ begin
15
+ object = ref.__getobj__
16
+ rescue => e
17
+ unless (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError)) || (defined?(RefError) && e.is_a?(RefError))
18
+ raise e
19
+ end
20
+ end
21
+ end
22
+
23
+ unless object
24
+ object = yield
25
+ ObjectSpace.define_finalizer(object, instance_cache_finalizer(key))
26
+ instance_variable_set(key, WeakRef.new(object))
27
+ end
28
+
29
+ object
30
+ end
31
+
32
+ def instance_cache_finalizer(key)
33
+ proc do |object_id|
34
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && (!ref.weakref_alive? || ref.__getobj__.object_id == object_id)
35
+ remove_instance_variable(key)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
  require 'nokogiri'
3
5
  require 'cgi'
@@ -5,14 +7,15 @@ require 'zip/filesystem'
5
7
  require 'roo/font'
6
8
  require 'roo/tempdir'
7
9
  require 'base64'
10
+ require 'openssl'
8
11
 
9
12
  module Roo
10
13
  class OpenOffice < Roo::Base
11
14
  extend Roo::Tempdir
12
15
 
13
- ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'.freeze
14
- XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']".freeze
15
- XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']".freeze
16
+ ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'
17
+ XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']"
18
+ XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']"
16
19
 
17
20
  # initialization and opening of a spreadsheet file
18
21
  # values for packed: :zip
@@ -22,7 +25,12 @@ module Roo
22
25
 
23
26
  @only_visible_sheets = options[:only_visible_sheets]
24
27
  file_type_check(filename, '.ods', 'an Roo::OpenOffice', file_warning, packed)
25
- @tmpdir = self.class.make_tempdir(self, find_basename(filename), options[:tmpdir_root])
28
+ # NOTE: Create temp directory and allow Ruby to cleanup the temp directory
29
+ # when the object is garbage collected. Initially, the finalizer was
30
+ # created in the Roo::Tempdir module, but that led to a segfault
31
+ # when testing in Ruby 2.4.0.
32
+ @tmpdir = self.class.make_tempdir(self, find_basename(filename), options[:tmpdir_root])
33
+ ObjectSpace.define_finalizer(self, self.class.finalize(object_id))
26
34
  @filename = local_filename(filename, @tmpdir, packed)
27
35
  # TODO: @cells_read[:default] = false
28
36
  open_oo_file(options)
@@ -340,7 +348,7 @@ module Roo
340
348
  def find_cipher(*args)
341
349
  fail ArgumentError, 'Unknown algorithm ' + algorithm unless args[0] == 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
342
350
 
343
- cipher = OpenSSL::Cipher.new('AES-256-CBC')
351
+ cipher = ::OpenSSL::Cipher.new('AES-256-CBC')
344
352
  cipher.decrypt
345
353
  cipher.padding = 0
346
354
  cipher.key = find_cipher_key(cipher, *args[1..4])
@@ -353,7 +361,7 @@ module Roo
353
361
  def find_cipher_key(*args)
354
362
  fail ArgumentError, 'Unknown key derivation name ', args[1] unless args[1] == 'PBKDF2'
355
363
 
356
- OpenSSL::PKCS5.pbkdf2_hmac_sha1(args[2], args[3], args[4], args[0].key_len)
364
+ ::OpenSSL::PKCS5.pbkdf2_hmac_sha1(args[2], args[3], args[4], args[0].key_len)
357
365
  end
358
366
 
359
367
  # Block decrypt raw bytes from the zip file based on the cipher
@@ -555,7 +563,7 @@ module Roo
555
563
  end
556
564
 
557
565
  def read_labels
558
- @label ||= Hash[doc.xpath('//table:named-range').map do |ne|
566
+ @label ||= doc.xpath('//table:named-range').each_with_object({}) do |ne, hash|
559
567
  #-
560
568
  # $Sheet1.$C$5
561
569
  #+
@@ -563,8 +571,8 @@ module Roo
563
571
  sheetname, coords = attribute(ne, 'cell-range-address').to_s.split('.$')
564
572
  col, row = coords.split('$')
565
573
  sheetname = sheetname[1..-1] if sheetname[0, 1] == '$'
566
- [name, [sheetname, row, col]]
567
- end]
574
+ hash[name] = [sheetname, row, col]
575
+ end
568
576
  end
569
577
 
570
578
  def read_styles(style_elements)
@@ -24,7 +24,7 @@ module Roo
24
24
  options[:file_warning] = :ignore
25
25
  extension.tr('.', '').downcase.to_sym
26
26
  else
27
- res = ::File.extname((path =~ /\A#{::URI.regexp}\z/) ? ::URI.parse(::URI.encode(path)).path : path)
27
+ res = ::File.extname((path =~ /\A#{::URI::DEFAULT_PARSER.make_regexp}\z/) ? ::URI.parse(::URI.encode(path)).path : path)
28
28
  res.tr('.', '').downcase.to_sym
29
29
  end
30
30
  end
data/lib/roo/tempdir.rb CHANGED
@@ -2,7 +2,7 @@ module Roo
2
2
  module Tempdir
3
3
  def finalize_tempdirs(object_id)
4
4
  if @tempdirs && (dirs_to_remove = @tempdirs[object_id])
5
- @tempdirs[object_id] = nil
5
+ @tempdirs.delete(object_id)
6
6
  dirs_to_remove.each do |dir|
7
7
  ::FileUtils.remove_entry(dir)
8
8
  end
@@ -10,16 +10,11 @@ module Roo
10
10
  end
11
11
 
12
12
  def make_tempdir(object, prefix, root)
13
- root ||= ENV['ROO_TMP']
14
- # folder is cleaned up in .finalize_tempdirs
13
+ root ||= ENV["ROO_TMP"]
14
+ # NOTE: This folder is cleaned up by finalize_tempdirs.
15
15
  ::Dir.mktmpdir("#{Roo::TEMP_PREFIX}#{prefix}", root).tap do |tmpdir|
16
- @tempdirs ||= {}
17
- if @tempdirs[object.object_id]
18
- @tempdirs[object.object_id] << tmpdir
19
- else
20
- @tempdirs[object.object_id] = [tmpdir]
21
- ObjectSpace.define_finalizer(object, method(:finalize_tempdirs))
22
- end
16
+ @tempdirs ||= Hash.new { |h, k| h[k] = [] }
17
+ @tempdirs[object.object_id] << tmpdir
23
18
  end
24
19
  end
25
20
  end
data/lib/roo/utils.rb CHANGED
@@ -1,35 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Roo
2
4
  module Utils
3
5
  extend self
4
6
 
5
7
  LETTERS = ('A'..'Z').to_a
6
8
 
7
- def split_coordinate(str)
8
- @split_coordinate ||= {}
9
+ def extract_coordinate(s)
10
+ num = letter_num = 0
11
+ num_only = false
9
12
 
10
- @split_coordinate[str] ||= begin
11
- letter, number = split_coord(str)
12
- x = letter_to_number(letter)
13
- y = number
14
- [y, x]
13
+ s.each_byte do |b|
14
+ if !num_only && (index = char_index(b))
15
+ letter_num *= 26
16
+ letter_num += index
17
+ elsif index = num_index(b)
18
+ num_only = true
19
+ num *= 10
20
+ num += index
21
+ else
22
+ fail ArgumentError
23
+ end
15
24
  end
25
+ fail ArgumentError if letter_num == 0 || !num_only
26
+
27
+ Excelx::Coordinate.new(num, letter_num)
16
28
  end
17
29
 
18
- alias_method :ref_to_key, :split_coordinate
30
+ alias_method :ref_to_key, :extract_coordinate
19
31
 
20
- def split_coord(s)
21
- if s =~ /([a-zA-Z]+)([0-9]+)/
22
- letter = Regexp.last_match[1]
23
- number = Regexp.last_match[2].to_i
24
- else
25
- fail ArgumentError
26
- end
27
- [letter, number]
32
+ def split_coordinate(str)
33
+ warn "[DEPRECATION] `Roo::Utils.split_coordinate` is deprecated. Please use `Roo::Utils.extract_coordinate` instead."
34
+ extract_coordinate(str)
35
+ end
36
+
37
+
38
+
39
+ def split_coord(str)
40
+ coord = extract_coordinate(str)
41
+ [number_to_letter(coord.column), coord.row]
28
42
  end
29
43
 
30
44
  # convert a number to something like 'AB' (1 => 'A', 2 => 'B', ...)
31
45
  def number_to_letter(num)
32
- result = ""
46
+ result = +""
33
47
 
34
48
  until num.zero?
35
49
  num, index = (num - 1).divmod(26)
@@ -56,11 +70,30 @@ module Roo
56
70
  cells = str.split(':')
57
71
  return 1 if cells.count == 1
58
72
  raise ArgumentError.new("invalid range string: #{str}. Supported range format 'A1:B2'") if cells.count != 2
59
- x1, y1 = split_coordinate(cells[0])
60
- x2, y2 = split_coordinate(cells[1])
73
+ x1, y1 = extract_coordinate(cells[0])
74
+ x2, y2 = extract_coordinate(cells[1])
61
75
  (x2 - (x1 - 1)) * (y2 - (y1 - 1))
62
76
  end
63
77
 
78
+ def coordinates_in_range(str)
79
+ return to_enum(:coordinates_in_range, str) unless block_given?
80
+ coordinates = str.split(":", 2).map! { |s| extract_coordinate s }
81
+
82
+ case coordinates.size
83
+ when 1
84
+ yield coordinates[0]
85
+ when 2
86
+ tl, br = coordinates
87
+ rows = tl.row..br.row
88
+ cols = tl.column..br.column
89
+ rows.each do |row|
90
+ cols.each do |column|
91
+ yield Excelx::Coordinate.new(row, column)
92
+ end
93
+ end
94
+ end
95
+ end
96
+
64
97
  def load_xml(path)
65
98
  ::File.open(path, 'rb') do |file|
66
99
  ::Nokogiri::XML(file)
@@ -69,10 +102,27 @@ module Roo
69
102
 
70
103
  # Yield each element of a given type ('row', 'c', etc.) to caller
71
104
  def each_element(path, elements)
105
+ elements = Array(elements)
72
106
  Nokogiri::XML::Reader(::File.open(path, 'rb'), nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).each do |node|
73
- next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && Array(elements).include?(node.name)
107
+ next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && elements.include?(node.name)
74
108
  yield Nokogiri::XML(node.outer_xml).root if block_given?
75
109
  end
76
110
  end
111
+
112
+ private
113
+
114
+ def char_index(byte)
115
+ if byte >= 65 && byte <= 90
116
+ byte - 64
117
+ elsif byte >= 97 && byte <= 122
118
+ byte - 96
119
+ end
120
+ end
121
+
122
+ def num_index(byte)
123
+ if byte >= 48 && byte <= 57
124
+ byte - 48
125
+ end
126
+ end
77
127
  end
78
128
  end
data/lib/roo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Roo
2
- VERSION = "2.6.0"
2
+ VERSION = "2.8.3"
3
3
  end
data/lib/roo.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'roo/version'
1
4
  require 'roo/constants'
2
5
  require 'roo/errors'
3
6
  require 'roo/spreadsheet'
@@ -9,7 +12,7 @@ module Roo
9
12
  autoload :Excelx, 'roo/excelx'
10
13
  autoload :CSV, 'roo/csv'
11
14
 
12
- TEMP_PREFIX = 'roo_'.freeze
15
+ TEMP_PREFIX = 'roo_'
13
16
 
14
17
  CLASS_FOR_EXTENSION = {
15
18
  ods: Roo::OpenOffice,
data/roo.gemspec CHANGED
@@ -4,22 +4,25 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'roo/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = 'roo'
8
- spec.version = Roo::VERSION
9
- spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels']
10
- spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
11
- spec.summary = 'Roo can access the contents of various spreadsheet files.'
12
- spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
13
- spec.homepage = 'http://github.com/roo-rb/roo'
14
- spec.license = 'MIT'
7
+ spec.name = 'roo'
8
+ spec.version = Roo::VERSION
9
+ spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels', 'Anmol Chopra']
10
+ spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
11
+ spec.summary = 'Roo can access the contents of various spreadsheet files.'
12
+ spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
13
+ spec.homepage = 'https://github.com/roo-rb/roo'
14
+ spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.files.reject! { |fn| fn.include?('test/files') }
18
- spec.require_paths = ['lib']
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = ">= 2.3.0"
19
21
 
20
22
  spec.add_dependency 'nokogiri', '~> 1'
21
- spec.add_dependency 'rubyzip', '~> 1.1', '< 2.0.0'
23
+ spec.add_dependency 'rubyzip', '>= 1.3.0', '< 3.0.0'
22
24
 
23
25
  spec.add_development_dependency 'rake', '~> 10.1'
24
26
  spec.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.3'
27
+ spec.add_development_dependency 'rack', '~> 1.6', '< 2.0.0'
25
28
  end
@@ -127,10 +127,22 @@ describe Roo::Base do
127
127
  end
128
128
  end
129
129
 
130
- describe '#row' do
131
- it 'should return the specified row' do
130
+ describe "#row" do
131
+ it "should return the specified row" do
132
132
  expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
133
- expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', 'forty-three', 'forty-four', 'forty-five', nil, nil])
133
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
134
+ end
135
+
136
+ it "should return the specified row if default_sheet is set by a string" do
137
+ spreadsheet.default_sheet = "my_sheet"
138
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
139
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
140
+ end
141
+
142
+ it "should return the specified row if default_sheet is set by an integer" do
143
+ spreadsheet.default_sheet = 0
144
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
145
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
134
146
  end
135
147
  end
136
148
 
@@ -146,6 +158,11 @@ describe Roo::Base do
146
158
  expect { spreadsheet.row_with([/Missing Header/]) }.to \
147
159
  raise_error(Roo::HeaderRowNotFoundError)
148
160
  end
161
+
162
+ it 'returns missing headers' do
163
+ expect { spreadsheet.row_with([/Header/, /Missing Header 1/, /Missing Header 2/]) }.to \
164
+ raise_error(Roo::HeaderRowNotFoundError, '[/Missing Header 1/, /Missing Header 2/]')
165
+ end
149
166
  end
150
167
  end
151
168
 
@@ -173,6 +190,31 @@ describe Roo::Base do
173
190
  end
174
191
  end
175
192
 
193
+ describe "#default_sheet=" do
194
+ it "should correctly set the default sheet if passed a string" do
195
+ spreadsheet.default_sheet = "my_sheet"
196
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
197
+ end
198
+
199
+ it "should correctly set the default sheet if passed an integer" do
200
+ spreadsheet.default_sheet = 0
201
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
202
+ end
203
+
204
+ it "should correctly set the default sheet if passed an integer for the second sheet" do
205
+ spreadsheet.default_sheet = 1
206
+ expect(spreadsheet.default_sheet).to eq("blank sheet")
207
+ end
208
+
209
+ it "should raise an error if passed a sheet that does not exist as an integer" do
210
+ expect { spreadsheet.default_sheet = 10 }.to raise_error RangeError
211
+ end
212
+
213
+ it "should raise an error if passed a sheet that does not exist as a string" do
214
+ expect { spreadsheet.default_sheet = "does_not_exist" }.to raise_error RangeError
215
+ end
216
+ end
217
+
176
218
  describe '#to_yaml' do
177
219
  it 'should convert the spreadsheet to yaml' do
178
220
  expect(spreadsheet.to_yaml({}, 5, 1, 5, 1)).to eq("--- \n" + yaml_entry(5, 1, 'date', '1961-11-21'))
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Roo::Excelx::Relationships do
6
+ subject(:relationships) { Roo::Excelx::Relationships.new Roo::Excelx.new(path).rels_files[0] }
7
+
8
+ describe "#include_type?" do
9
+ [
10
+ ["with hyperlink type", "test/files/link.xlsx", true, false],
11
+ ["with nil path", "test/files/Bibelbund.xlsx", false, false],
12
+ ["with comments type", "test/files/comments-google.xlsx", false, true],
13
+ ].each do |context_desc, file_path, hyperlink_value, comments_value|
14
+ context context_desc do
15
+ let(:path) { file_path }
16
+
17
+ it "should return #{hyperlink_value} for hyperlink" do
18
+ expect(subject.include_type?("hyperlink")).to be hyperlink_value
19
+ end
20
+
21
+ it "should return #{hyperlink_value} for link" do
22
+ expect(subject.include_type?("link")).to be hyperlink_value
23
+ end
24
+
25
+ it "should return false for hypelink" do
26
+ expect(subject.include_type?("hypelink")).to be false
27
+ end
28
+
29
+ it "should return false for coment" do
30
+ expect(subject.include_type?("coment")).to be false
31
+ end
32
+
33
+ it "should return #{comments_value} for comments" do
34
+ expect(subject.include_type?("comments")).to be comments_value
35
+ end
36
+
37
+ it "should return #{comments_value} for comment" do
38
+ expect(subject.include_type?("comment")).to be comments_value
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Roo::Excelx::SheetDoc do
6
+ subject(:blank_children) { Roo::Excelx.new("test/files/blank_children.xlsx") }
7
+
8
+ example "#last_row" do
9
+ expect(subject.last_row).to eq 3
10
+ end
11
+ end