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
@@ -151,6 +151,22 @@ describe Roo::Excelx do
151
151
  it 'returns the expected result' do
152
152
  expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
153
153
  end
154
+
155
+ it 'returns the expected result when passed a number' do
156
+ expect(subject.sheet_for(0).instance_variable_get("@name")).to eq "Tabelle1"
157
+ end
158
+
159
+ it 'returns the expected result when passed a number that is not the first sheet' do
160
+ expect(subject.sheet_for(1).instance_variable_get("@name")).to eq "Name of Sheet 2"
161
+ end
162
+
163
+ it "should raise an error if passed a sheet that does not exist as an integer" do
164
+ expect { subject.sheet_for(10) }.to raise_error RangeError
165
+ end
166
+
167
+ it "should raise an error if passed a sheet that does not exist as a string" do
168
+ expect { subject.sheet_for("does_not_exist") }.to raise_error RangeError
169
+ end
154
170
  end
155
171
 
156
172
  describe '#row' do
@@ -304,6 +320,18 @@ describe Roo::Excelx do
304
320
  end
305
321
  end
306
322
 
323
+ describe '#row' do
324
+ context 'integers with leading zero'
325
+ let(:path) { 'test/files/number_with_zero_prefix.xlsx' }
326
+
327
+ it 'returns base 10 integer' do
328
+ (1..50).each do |row_index|
329
+ range_start = (row_index - 1) * 20 + 1
330
+ expect(subject.row(row_index)).to eq (range_start..(range_start+19)).to_a
331
+ end
332
+ end
333
+ end
334
+
307
335
  describe '#excelx_format' do
308
336
  let(:path) { 'test/files/style.xlsx' }
309
337
 
@@ -351,14 +379,50 @@ describe Roo::Excelx do
351
379
  expect(subject.hyperlink?(1, 1)).to eq true
352
380
  expect(subject.hyperlink?(1, 2)).to eq false
353
381
  end
382
+
383
+ context 'defined on cell range' do
384
+ let(:path) { 'test/files/cell-range-link.xlsx' }
385
+
386
+ it 'returns the expected result' do
387
+ [[false]*3, *[[true, true, false]]*4, [false]*3].each.with_index(1) do |row, row_index|
388
+ row.each.with_index(1) do |value, col_index|
389
+ expect(subject.hyperlink?(row_index, col_index)).to eq(value)
390
+ end
391
+ end
392
+ end
393
+ end
354
394
  end
355
395
 
356
396
  describe '#hyperlink' do
357
- let(:path) { 'test/files/link.xlsx' }
397
+ context 'defined on cell range' do
398
+ let(:path) { 'test/files/cell-range-link.xlsx' }
358
399
 
359
- it 'returns the expected result' do
360
- expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
361
- expect(subject.hyperlink(1, 2)).to eq nil
400
+ it 'returns the expected result' do
401
+ link = "http://www.google.com"
402
+ [[nil]*3, *[[link, link, nil]]*4, [nil]*3].each.with_index(1) do |row, row_index|
403
+ row.each.with_index(1) do |value, col_index|
404
+ expect(subject.hyperlink(row_index, col_index)).to eq(value)
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+ context 'without location' do
411
+ let(:path) { 'test/files/link.xlsx' }
412
+
413
+ it 'returns the expected result' do
414
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
415
+ expect(subject.hyperlink(1, 2)).to eq nil
416
+ end
417
+ end
418
+
419
+ context 'with location' do
420
+ let(:path) { 'test/files/link_with_location.xlsx' }
421
+
422
+ it 'returns the expected result' do
423
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com/#hey"
424
+ expect(subject.hyperlink(1, 2)).to eq nil
425
+ end
362
426
  end
363
427
  end
364
428
 
@@ -480,34 +544,36 @@ describe Roo::Excelx do
480
544
  end
481
545
 
482
546
  describe '#html_strings' do
483
- let(:path) { 'test/files/html_strings_formatting.xlsx' }
547
+ describe "HTML Parsing Enabling" do
548
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
484
549
 
485
- it 'returns the expected result' do
486
- expect(subject.excelx_value(1, 1, "Sheet1")).to eq "This has no formatting."
487
- expect(subject.excelx_value(2, 1, "Sheet1")).to eq "<html>This has<b> bold </b>formatting.</html>"
488
- expect(subject.excelx_value(2, 2, "Sheet1")).to eq "<html>This has <i>italics</i> formatting.</html>"
489
- expect(subject.excelx_value(2, 3, "Sheet1")).to eq "<html>This has <u>underline</u> format.</html>"
490
- expect(subject.excelx_value(2, 4, "Sheet1")).to eq "<html>Superscript. x<sup>123</sup></html>"
491
- expect(subject.excelx_value(2, 5, "Sheet1")).to eq "<html>SubScript. T<sub>j</sub></html>"
492
-
493
- expect(subject.excelx_value(3, 1, "Sheet1")).to eq "<html>Bold, italics <b><i>together</i></b>.</html>"
494
- expect(subject.excelx_value(3, 2, "Sheet1")).to eq "<html>Bold, Underline <b><u>together</u></b>.</html>"
495
- expect(subject.excelx_value(3, 3, "Sheet1")).to eq "<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>"
496
- expect(subject.excelx_value(3, 4, "Sheet1")).to eq "<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>"
497
- expect(subject.excelx_value(3, 5, "Sheet1")).to eq "<html>Italics, Underline <i><u>together</u></i>.</html>"
498
- expect(subject.excelx_value(3, 6, "Sheet1")).to eq "<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>"
499
- expect(subject.excelx_value(3, 7, "Sheet1")).to eq "<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>"
500
- expect(subject.excelx_value(4, 1, "Sheet1")).to eq "<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>"
501
- expect(subject.excelx_value(4, 2, "Sheet1")).to eq "<html>Bold, italics, superscript. <b>X</b><sup><b><i>abc</i></b></sup><b><i>123</i></b></html>"
502
- expect(subject.excelx_value(4, 3, "Sheet1")).to eq "<html>Bold, Italics, subscript. <b><i>Mg</i></b><sub><b><i>ha</i></b></sub><b><i>2</i></b></html>"
503
- expect(subject.excelx_value(4, 4, "Sheet1")).to eq "<html>Bold, Underline, superscript. <b><u>AB</u></b><sup><b><u>C12</u></b></sup><b><u>3</u></b></html>"
504
- expect(subject.excelx_value(4, 5, "Sheet1")).to eq "<html>Bold, Underline, subscript. <b><u>Good</u></b><sub><b><u>XYZ</u></b></sub></html>"
505
- expect(subject.excelx_value(4, 6, "Sheet1")).to eq "<html>Italics, Underline, superscript. <i><u>Up</u></i><sup><i><u>swing</u></i></sup></html>"
506
- expect(subject.excelx_value(4, 7, "Sheet1")).to eq "<html>Italics, Underline, subscript. <i><u>T</u></i><sub><i><u>swing</u></i></sub></html>"
507
- expect(subject.excelx_value(5, 1, "Sheet1")).to eq "<html>Bold, italics, underline, superscript. <b><i><u>GHJK</u></i></b><sup><b><i><u>190</u></i></b></sup><b><i><u>4</u></i></b></html>"
508
- expect(subject.excelx_value(5, 2, "Sheet1")).to eq "<html>Bold, italics, underline, subscript. <b><i><u>Mike</u></i></b><sub><b><i><u>drop</u></i></b></sub></html>"
509
- expect(subject.excelx_value(6, 1, "Sheet1")).to eq "See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>"
510
- expect(subject.excelx_value(7, 1, "Sheet1")).to eq "<html>Does create html tags when formatting is used..\n<ol>\n <li> <b>Denver Broncos</b> </li>\n <li> <i>Carolina Panthers </i></li>\n <li> <u>New England Patriots</u></li>\n <li>Arizona Panthers</li>\n</ol></html>"
550
+ it 'returns the expected result' do
551
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
552
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("<html>This has<b> bold </b>formatting.</html>")
553
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("<html>This has <i>italics</i> formatting.</html>")
554
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("<html>This has <u>underline</u> format.</html>")
555
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("<html>Superscript. x<sup>123</sup></html>")
556
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("<html>SubScript. T<sub>j</sub></html>")
557
+
558
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("<html>Bold, italics <b><i>together</i></b>.</html>")
559
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("<html>Bold, Underline <b><u>together</u></b>.</html>")
560
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>")
561
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>")
562
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("<html>Italics, Underline <i><u>together</u></i>.</html>")
563
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>")
564
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>")
565
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>")
566
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("<html>Bold, italics, superscript. <b>X</b><sup><b><i>abc</i></b></sup><b><i>123</i></b></html>")
567
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("<html>Bold, Italics, subscript. <b><i>Mg</i></b><sub><b><i>ha</i></b></sub><b><i>2</i></b></html>")
568
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("<html>Bold, Underline, superscript. <b><u>AB</u></b><sup><b><u>C12</u></b></sup><b><u>3</u></b></html>")
569
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("<html>Bold, Underline, subscript. <b><u>Good</u></b><sub><b><u>XYZ</u></b></sub></html>")
570
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("<html>Italics, Underline, superscript. <i><u>Up</u></i><sup><i><u>swing</u></i></sup></html>")
571
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("<html>Italics, Underline, subscript. <i><u>T</u></i><sub><i><u>swing</u></i></sub></html>")
572
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("<html>Bold, italics, underline, superscript. <b><i><u>GHJK</u></i></b><sup><b><i><u>190</u></i></b></sup><b><i><u>4</u></i></b></html>")
573
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("<html>Bold, italics, underline, subscript. <b><i><u>Mike</u></i></b><sub><b><i><u>drop</u></i></b></sub></html>")
574
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
575
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("<html>Does create html tags when formatting is used..\n<ol>\n <li> <b>Denver Broncos</b> </li>\n <li> <i>Carolina Panthers </i></li>\n <li> <u>New England Patriots</u></li>\n <li>Arizona Panthers</li>\n</ol></html>")
576
+ end
511
577
  end
512
578
  end
513
579
 
@@ -534,4 +600,57 @@ describe Roo::Excelx do
534
600
  expect(subject.sheet(0).excelx_format(2,1)).to eq 'm/d/yyyy" "h:mm:ss" "AM/PM'
535
601
  end
536
602
  end
603
+
604
+ describe 'images' do
605
+ let(:path) { 'test/files/images.xlsx' }
606
+
607
+ it 'returns array of images from default sheet' do
608
+ expect(subject.images).to be_kind_of(Array)
609
+ expect(subject.images.size).to eql(19)
610
+ end
611
+
612
+ it 'returns empty array if there is no images on the sheet' do
613
+ expect(subject.images("Sheet2")).to eql([])
614
+ end
615
+ end
537
616
  end
617
+
618
+ describe 'Roo::Excelx with options set' do
619
+ subject(:xlsx) do
620
+ Roo::Excelx.new(path, disable_html_wrapper: true)
621
+ end
622
+
623
+ describe '#html_strings' do
624
+ describe "HTML Parsing Disabled" do
625
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
626
+
627
+ it 'returns the expected result' do
628
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
629
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("This has bold formatting.")
630
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("This has italics formatting.")
631
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("This has underline format.")
632
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("Superscript. x123")
633
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("SubScript. Tj")
634
+
635
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("Bold, italics together.")
636
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("Bold, Underline together.")
637
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("Bold, Superscript. xN")
638
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("Bold, Subscript. Tabc")
639
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("Italics, Underline together.")
640
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("Italics, Superscript. Xabc")
641
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("Italics, Subscript. Befg")
642
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("Bold, italics underline, together.")
643
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("Bold, italics, superscript. Xabc123")
644
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("Bold, Italics, subscript. Mgha2")
645
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("Bold, Underline, superscript. ABC123")
646
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("Bold, Underline, subscript. GoodXYZ")
647
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("Italics, Underline, superscript. Upswing")
648
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("Italics, Underline, subscript. Tswing")
649
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("Bold, italics, underline, superscript. GHJK1904")
650
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("Bold, italics, underline, subscript. Mikedrop")
651
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
652
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("Does create html tags when formatting is used..\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
653
+ end
654
+ end
655
+ end
656
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::Excelx do
4
+ subject { Roo::Excelx.new('test/files/strict.xlsx') }
5
+
6
+ example '#sheets' do
7
+ expect(subject.sheets).to eq %w(Sheet1 Sheet2)
8
+ end
9
+
10
+ example '#sheet' do
11
+ expect(subject.sheet('Sheet1')).to be_a(Roo::Excelx)
12
+ end
13
+
14
+ example '#cell' do
15
+ expect(subject.cell(1, 1)).to eq 'Sheet 1'
16
+ expect(subject.cell(1, 1, 'Sheet2')).to eq 'Sheet 2'
17
+ end
18
+
19
+ example '#row' do
20
+ expect(subject.row(1)).to eq ['Sheet 1']
21
+ expect(subject.row(1, 'Sheet2')).to eq ['Sheet 2']
22
+ end
23
+
24
+ example '#first_row' do
25
+ expect(subject.first_row).to eq 1
26
+ expect(subject.first_row('Sheet2')).to eq 1
27
+ end
28
+
29
+ example '#last_row' do
30
+ expect(subject.last_row).to eq 1
31
+ expect(subject.last_row('Sheet2')).to eq 1
32
+ end
33
+
34
+ example '#first_column' do
35
+ expect(subject.first_column).to eq 1
36
+ expect(subject.first_column('Sheet2')).to eq 1
37
+ end
38
+
39
+ example '#last_column' do
40
+ expect(subject.last_column).to eq 1
41
+ expect(subject.last_column('Sheet2')).to eq 1
42
+ end
43
+ end
@@ -52,6 +52,15 @@ RSpec.describe ::Roo::Utils do
52
52
  end
53
53
  end
54
54
 
55
+ context '.extract_coordinate' do
56
+ it "returns the expected result" do
57
+ expect(described_class.extract_coordinate('A1')).to eq [1, 1]
58
+ expect(described_class.extract_coordinate('B2')).to eq [2, 2]
59
+ expect(described_class.extract_coordinate('R2')).to eq [2, 18]
60
+ expect(described_class.extract_coordinate('AR31')).to eq [31, 18 + 26]
61
+ end
62
+ end
63
+
55
64
  context '.split_coord' do
56
65
  it "returns the expected result" do
57
66
  expect(described_class.split_coord('A1')).to eq ["A", 1]
@@ -81,26 +90,39 @@ RSpec.describe ::Roo::Utils do
81
90
  end
82
91
  end
83
92
 
93
+ context '.coordinates_in_range' do
94
+ it "returns the expected result" do
95
+ expect(described_class.coordinates_in_range('').to_a).to eq []
96
+ expect(described_class.coordinates_in_range('B2').to_a).to eq [[2, 2]]
97
+ expect(described_class.coordinates_in_range('D2:G3').to_a).to eq [[2, 4], [2, 5], [2, 6], [2, 7], [3, 4], [3, 5], [3, 6], [3, 7]]
98
+ expect(described_class.coordinates_in_range('G3:D2').to_a).to eq []
99
+ end
100
+
101
+ it "raises an error when appropriate" do
102
+ expect { described_class.coordinates_in_range('D2:G3:I5').to_a }.to raise_error(ArgumentError)
103
+ end
104
+ end
105
+
84
106
  context '.load_xml' do
85
107
  it 'returns the expected result' do
86
108
  expect(described_class.load_xml('test/files/sheet1.xml')).to be_a(Nokogiri::XML::Document)
87
109
  expect(described_class.load_xml('test/files/sheet1.xml').
88
110
  remove_namespaces!.xpath("/worksheet/dimension").map do |dim|
89
- dim.attributes["ref"].value end.first).to eq "A1:B11"
111
+ dim["ref"] end.first).to eq "A1:B11"
90
112
  end
91
113
  end
92
114
 
93
115
  context '.each_element' do
94
116
  it 'returns the expected result' do
95
117
  described_class.each_element('test/files/sheet1.xml', 'dimension') do |dim|
96
- expect(dim.attributes["ref"].value).to eq "A1:B11"
118
+ expect(dim["ref"]).to eq "A1:B11"
97
119
  end
98
120
  rows = []
99
121
  described_class.each_element('test/files/sheet1.xml', 'row') do |row|
100
122
  rows << row
101
123
  end
102
124
  expect(rows.size).to eq 11
103
- expect(rows[2].attributes["r"].value).to eq "3"
125
+ expect(rows[2]["r"]).to eq "3"
104
126
  end
105
127
  end
106
128
  end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ if RUBY_PLATFORM == "java"
4
+ require 'java'
5
+ java_import 'java.lang.System'
6
+ end
7
+
8
+ describe Roo::Helpers::WeakInstanceCache do
9
+ let(:klass) do
10
+ Class.new do
11
+ include Roo::Helpers::WeakInstanceCache
12
+
13
+ def memoized_data
14
+ instance_cache(:@memoized_data) do
15
+ "Some Costly Operation #{rand(1000)}" * 1_000
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ subject do
22
+ klass.new
23
+ end
24
+
25
+ it 'should be lazy' do
26
+ expect(subject.instance_variables).to_not include(:@memoized_data)
27
+ data = subject.memoized_data
28
+ expect(subject.instance_variables).to include(:@memoized_data)
29
+ end
30
+
31
+
32
+ it 'should be memoized' do
33
+ data = subject.memoized_data
34
+ expect(subject.memoized_data).to equal(data)
35
+ end
36
+
37
+ it 'should recalculate after GC' do
38
+ expect(subject.instance_variables).to_not include(:@memoized_data)
39
+ GC.disable
40
+ subject.memoized_data && nil
41
+ expect(subject.instance_variables).to include(:@memoized_data)
42
+
43
+ force_gc
44
+ expect(subject.instance_variables).to_not include(:@memoized_data)
45
+ GC.disable
46
+ subject.memoized_data && nil
47
+ expect(subject.instance_variables).to include(:@memoized_data)
48
+ end
49
+
50
+ it 'must remove instance variable' do
51
+ expect(subject.instance_variables).to_not include(:@memoized_data)
52
+ GC.disable
53
+ subject.memoized_data && nil
54
+ expect(subject.instance_variables).to include(:@memoized_data)
55
+
56
+ force_gc
57
+ expect(subject.instance_variables).to_not include(:@memoized_data)
58
+ end
59
+
60
+ context '#inspect must not raise' do
61
+ it 'before calculation' do
62
+ expect{subject.inspect}.to_not raise_error
63
+ end
64
+ it 'after calculation' do
65
+ GC.disable
66
+ subject.memoized_data && nil
67
+ expect{subject.inspect}.to_not raise_error
68
+ expect(subject.inspect).to include("Some Costly Operation")
69
+ force_gc
70
+ end
71
+ it 'after GC' do
72
+ subject.memoized_data && nil
73
+ force_gc
74
+ expect(subject.instance_variables).to_not include(:@memoized_data)
75
+ expect{subject.inspect}.to_not raise_error
76
+ expect(subject.inspect).to_not include("Some Costly Operation")
77
+ end
78
+ end
79
+
80
+ if RUBY_PLATFORM == "java"
81
+ def force_gc
82
+ System.gc
83
+ sleep(0.1)
84
+ end
85
+ else
86
+ def force_gc
87
+ GC.start(full_mark: true, immediate_sweep: true)
88
+ sleep(0.1)
89
+ GC.start(full_mark: true, immediate_sweep: true)
90
+ end
91
+ end
92
+ end
File without changes
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,9 @@
1
1
  require 'simplecov'
2
2
  require 'roo'
3
- require 'vcr'
4
3
  require 'helpers'
5
4
 
6
5
  RSpec.configure do |c|
7
6
  c.include Helpers
8
- end
9
-
10
- VCR.configure do |c|
11
- c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
12
- c.hook_into :webmock # or :fakeweb
7
+ c.color = true
8
+ c.formatter = :documentation if ENV["USE_REPORTERS"]
13
9
  end
@@ -0,0 +1,72 @@
1
+ require "test_helper"
2
+
3
+ class TestAttrReaderDefault < Minitest::Test
4
+ def base
5
+ Roo::Excelx::Cell::Base
6
+ end
7
+
8
+ def boolean
9
+ Roo::Excelx::Cell::Boolean
10
+ end
11
+
12
+ def class_date
13
+ Roo::Excelx::Cell::Date
14
+ end
15
+
16
+ def datetime
17
+ Roo::Excelx::Cell::DateTime
18
+ end
19
+
20
+ def empty
21
+ Roo::Excelx::Cell::Empty
22
+ end
23
+
24
+ def number
25
+ Roo::Excelx::Cell::Number
26
+ end
27
+
28
+ def string
29
+ Roo::Excelx::Cell::String
30
+ end
31
+
32
+ def base_date
33
+ ::Date.new(1899, 12, 30)
34
+ end
35
+
36
+ def base_timestamp
37
+ ::Date.new(1899, 12, 30).to_datetime.to_time.to_i
38
+ end
39
+
40
+ def class_time
41
+ Roo::Excelx::Cell::Time
42
+ end
43
+
44
+ def test_cell_default_values
45
+ assert_values base.new(nil, nil, [], 1, nil, nil), default_type: :base, :@default_type => nil, style: 1, :@style => nil
46
+ assert_values boolean.new("1", nil, nil, nil, nil), default_type: :boolean, :@default_type => nil, cell_type: :boolean, :@cell_type => nil
47
+ assert_values class_date.new("41791", nil, [:numeric_or_formula, "mm-dd-yy"], 6, nil, base_date, nil), default_type: :date, :@default_type => nil
48
+ assert_values class_time.new("0.521", nil, [:numeric_or_formula, "hh:mm"], 6, nil, base_timestamp, nil), default_type: :time, :@default_type => nil
49
+ assert_values datetime.new("41791.521", nil, [:numeric_or_formula, "mm-dd-yy hh:mm"], 6, nil, base_timestamp, nil), default_type: :datetime, :@default_type => nil
50
+ assert_values empty.new(nil), default_type: nil, :@default_type => nil, style: nil, :@style => nil
51
+ assert_values number.new("42", nil, ["0"], nil, nil, nil), default_type: :float, :@default_type => nil
52
+ assert_values string.new("1", nil, nil, nil, nil), default_type: :string, :@default_type => nil, cell_type: :string, :@cell_type => nil
53
+
54
+ assert_values base.new(nil, nil, [], 2, nil, nil), style: 2, :@style => 2
55
+ end
56
+
57
+ def assert_values(object, value_hash)
58
+ value_hash.each do |attr_name, expected_value|
59
+ value = if attr_name.to_s.include?("@")
60
+ object.instance_variable_defined?(attr_name) ? object.instance_variable_get(attr_name) : nil
61
+ else
62
+ object.public_send(attr_name)
63
+ end
64
+
65
+ if expected_value
66
+ assert_equal expected_value, value
67
+ else
68
+ assert_nil value
69
+ end
70
+ end
71
+ end
72
+ end
@@ -25,6 +25,11 @@ class TestRooExcelxCellBase < Minitest::Test
25
25
  refute cell.empty?
26
26
  end
27
27
 
28
+ def test_presence
29
+ cell = base.new(value, nil, [], nil, nil, nil)
30
+ assert_equal cell, cell.presence
31
+ end
32
+
28
33
  def test_cell_type_is_formula
29
34
  formula = true
30
35
  cell = base.new(value, formula, [], nil, nil, nil)
@@ -2,12 +2,12 @@ require 'test_helper'
2
2
 
3
3
  class TestRooExcelxCellDateTime < Minitest::Test
4
4
  def test_cell_value_is_datetime
5
- cell = datetime.new('30000.323212', nil, ['mm-dd-yy'], nil, nil, base_date, nil)
5
+ cell = datetime.new('30000.323212', nil, ['mm-dd-yy'], nil, nil, base_timestamp, nil)
6
6
  assert_kind_of ::DateTime, cell.value
7
7
  end
8
8
 
9
9
  def test_cell_type_is_datetime
10
- cell = datetime.new('30000.323212', nil, [], nil, nil, base_date, nil)
10
+ cell = datetime.new('30000.323212', nil, [], nil, nil, base_timestamp, nil)
11
11
  assert_equal :datetime, cell.type
12
12
  end
13
13
 
@@ -19,7 +19,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
19
19
  ['mmm-yy', 'JAN-15'],
20
20
  ['m/d/yy h:mm', '1/25/15 8:15']
21
21
  ].each do |format, formatted_value|
22
- cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
22
+ cell = datetime.new '42029.34375', nil, [format], nil, nil, base_timestamp, nil
23
23
  assert_equal formatted_value, cell.formatted_value
24
24
  end
25
25
  end
@@ -30,7 +30,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
30
30
  ['h:mm:ss000 mm/yy', '8:15:00000 01/15'],
31
31
  ['mmm yyy', '2015-01-25 08:15:00']
32
32
  ].each do |format, formatted_value|
33
- cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
33
+ cell = datetime.new '42029.34375', nil, [format], nil, nil, base_timestamp, nil
34
34
  assert_equal formatted_value, cell.formatted_value
35
35
  end
36
36
  end
@@ -39,7 +39,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
39
39
  Roo::Excelx::Cell::DateTime
40
40
  end
41
41
 
42
- def base_date
43
- Date.new(1899, 12, 30)
42
+ def base_timestamp
43
+ DateTime.new(1899, 12, 30).to_time.to_i
44
44
  end
45
45
  end
@@ -4,4 +4,15 @@ class TestRooExcelxCellEmpty < Minitest::Test
4
4
  def empty
5
5
  Roo::Excelx::Cell::Empty
6
6
  end
7
+
8
+ def test_empty?
9
+ cell = empty.new(nil)
10
+ assert_same true, cell.empty?
11
+ end
12
+
13
+ def test_nil_presence
14
+ cell = empty.new(nil)
15
+ assert_nil cell.presence
16
+ end
17
+
7
18
  end
@@ -25,6 +25,11 @@ class TestRooExcelxCellNumber < Minitest::Test
25
25
  assert_kind_of(Float, cell.value)
26
26
  end
27
27
 
28
+ def test_very_simple_scientific_notation
29
+ cell = Roo::Excelx::Cell::Number.new '1e6', nil, ['0'], nil, nil, nil
30
+ assert_kind_of(Float, cell.value)
31
+ end
32
+
28
33
  def test_percent
29
34
  cell = Roo::Excelx::Cell::Number.new '42.1', nil, ['0.00%'], nil, nil, nil
30
35
  assert_kind_of(Float, cell.value)
@@ -53,8 +58,12 @@ class TestRooExcelxCellNumber < Minitest::Test
53
58
  def test_formats
54
59
  [
55
60
  ['General', '1042'],
61
+ ['GENERAL', '1042'],
56
62
  ['0', '1042'],
63
+ ['000000', '001042'],
57
64
  ['0.00', '1042.00'],
65
+ ['0.0000', '1042.0000'],
66
+ ['0.000000000', '1042.000000000'],
58
67
  ['#,##0', '1,042'],
59
68
  ['#,##0.00', '1,042.00'],
60
69
  ['0%', '104200%'],
@@ -25,4 +25,24 @@ class TestRooExcelxCellString < Minitest::Test
25
25
  cell = string.new '0', nil, nil, nil, nil
26
26
  assert_equal '0', cell.value
27
27
  end
28
+
29
+ def test_not_empty?
30
+ cell = string.new '1', nil, nil, nil, nil
31
+ assert_equal false, cell.empty?
32
+ end
33
+
34
+ def test_empty?
35
+ cell = string.new '', nil, nil, nil, nil
36
+ assert_equal true, cell.empty?
37
+ end
38
+
39
+ def test_presence
40
+ cell = string.new '1', nil, nil, nil, nil
41
+ assert_equal cell, cell.presence
42
+ end
43
+
44
+ def test_nil_presence
45
+ cell = string.new '', nil, nil, nil, nil
46
+ assert_nil cell.presence
47
+ end
28
48
  end