percept 0.0.1 → 3.0.0

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.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +34 -0
  3. data/.gitignore +3 -1
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +110 -0
  6. data/.rubocop_todo.yml +383 -0
  7. data/.tool-versions +2 -0
  8. data/Gemfile +12 -1
  9. data/Gemfile.lock +138 -0
  10. data/Guardfile +10 -0
  11. data/README.md +20 -0
  12. data/Rakefile +18 -0
  13. data/bin/percept +8 -1
  14. data/lib/ext/rmagick_pixel.rb +19 -0
  15. data/lib/percept/checkbox_collection.rb +19 -0
  16. data/lib/percept/checkbox_detector.rb +19 -0
  17. data/lib/percept/checkbox_field.rb +24 -0
  18. data/lib/percept/color_utils.rb +17 -0
  19. data/lib/percept/config.rb +35 -0
  20. data/lib/percept/field.rb +74 -0
  21. data/lib/percept/field_collection.rb +29 -0
  22. data/lib/percept/field_detector.rb +56 -0
  23. data/lib/percept/image.rb +60 -0
  24. data/lib/percept/line.rb +116 -4
  25. data/lib/percept/line_collection.rb +88 -0
  26. data/lib/percept/line_detector.rb +102 -0
  27. data/lib/percept/line_filter.rb +95 -0
  28. data/lib/percept/pixel.rb +28 -0
  29. data/lib/percept/pixel_utils.rb +73 -0
  30. data/lib/percept/rmagick_image.rb +49 -0
  31. data/lib/percept/runner.rb +15 -96
  32. data/lib/percept/utils.rb +15 -0
  33. data/lib/percept/version.rb +3 -1
  34. data/lib/percept.rb +40 -1
  35. data/percept.gemspec +6 -7
  36. data/spec/fixtures/black_lines.png +0 -0
  37. data/spec/fixtures/bottom_line.png +0 -0
  38. data/spec/fixtures/bumpy_no_line.png +0 -0
  39. data/spec/fixtures/corners.png +0 -0
  40. data/spec/fixtures/divots.png +0 -0
  41. data/spec/fixtures/field_next_to_text.png +0 -0
  42. data/spec/fixtures/gray_cell_bottom.png +0 -0
  43. data/spec/fixtures/gray_image_section.png +0 -0
  44. data/spec/fixtures/grey_lines.png +0 -0
  45. data/spec/fixtures/high_line.png +0 -0
  46. data/spec/fixtures/large_checkbox.png +0 -0
  47. data/spec/fixtures/large_checkboxes.png +0 -0
  48. data/spec/fixtures/light_gray.png +0 -0
  49. data/spec/fixtures/low_line.png +0 -0
  50. data/spec/fixtures/low_lines.png +0 -0
  51. data/spec/fixtures/mid_lines.png +0 -0
  52. data/spec/fixtures/more_corners.png +0 -0
  53. data/spec/fixtures/more_text_on_line.png +0 -0
  54. data/spec/fixtures/nub_both_sides.png +0 -0
  55. data/spec/fixtures/nub_bottom_left.png +0 -0
  56. data/spec/fixtures/nub_top_right.png +0 -0
  57. data/spec/fixtures/nubs.png +0 -0
  58. data/spec/fixtures/slanted_left.png +0 -0
  59. data/spec/fixtures/slanted_right.png +0 -0
  60. data/spec/fixtures/small_checkbox.png +0 -0
  61. data/spec/fixtures/text_no_line.png +0 -0
  62. data/spec/fixtures/text_no_line_2.png +0 -0
  63. data/spec/fixtures/text_on_line.png +0 -0
  64. data/spec/fixtures/thick_line.png +0 -0
  65. data/spec/fixtures/thin_field.png +0 -0
  66. data/spec/percept/checkbox_field/height_spec.rb +15 -0
  67. data/spec/percept/checkbox_field/width_spec.rb +15 -0
  68. data/spec/percept/field/contains_spec.rb +50 -0
  69. data/spec/percept/field_detector/detect_field_spec.rb +90 -0
  70. data/spec/percept/field_detector/detect_fields_spec.rb +42 -0
  71. data/spec/percept/fields_collection/shovel_spec.rb +53 -0
  72. data/spec/percept/line/approxequals_spec.rb +60 -0
  73. data/spec/percept/line/initialize_spec.rb +29 -0
  74. data/spec/percept/line/length_spec.rb +22 -0
  75. data/spec/percept/line/merge_bang_spec.rb +58 -0
  76. data/spec/percept/line/pixels_spec.rb +15 -0
  77. data/spec/percept/line/split_spec.rb +28 -0
  78. data/spec/percept/line/to_s_spec.rb +13 -0
  79. data/spec/percept/line_collection/merge_line_spec.rb +50 -0
  80. data/spec/percept/line_collection/remove_unwanted_lines_bang_spec.rb +17 -0
  81. data/spec/percept/line_collection/split_spec.rb +20 -0
  82. data/spec/percept/line_collection/to_s_spec.rb +11 -0
  83. data/spec/percept/line_detector/detect_lines_spec.rb +93 -0
  84. data/spec/percept/line_detector/scaled_color_spec.rb +14 -0
  85. data/spec/percept/line_filter/filter_line_predicate_spec.rb +29 -0
  86. data/spec/percept/line_filter/left_bottom_corner_predicate_spec.rb +49 -0
  87. data/spec/percept/line_filter/left_top_corner_predicate_spec.rb +50 -0
  88. data/spec/percept/line_filter/right_bottom_corner_predicate_spec.rb +49 -0
  89. data/spec/percept/line_filter/right_top_corner_predicate_spec.rb +49 -0
  90. data/spec/percept/line_filter/table_bottom_predicate_spec.rb +48 -0
  91. data/spec/percept/line_filter/table_top_predicate_spec.rb +48 -0
  92. data/spec/percept/pixel/blackish_predicate_spec.rb +36 -0
  93. data/spec/percept/rmagick_image/interface_spec.rb +11 -0
  94. data/spec/percept/runner/color_fields_spec.rb +28 -0
  95. data/spec/percept/runner/color_lines_spec.rb +27 -0
  96. data/spec/shared_examples/image_interface_shared_examples.rb +162 -0
  97. data/spec/spec_helper.rb +52 -0
  98. data/tddium.yml +12 -0
  99. data/test_images/funky_image.png +0 -0
  100. data/test_images/interaction_test.png +0 -0
  101. data/test_images/jagged_lines.png +0 -0
  102. data/test_images/permission.png +0 -0
  103. data/test_images/rough.png +0 -0
  104. data/test_images/slanted.png +0 -0
  105. data/test_images/time_sheet.png +0 -0
  106. data/test_images/travel_reimbursement.png +0 -0
  107. data/test_images/warehouse_form.png +0 -0
  108. metadata +171 -34
  109. data/new_permission.png +0 -0
  110. data/permission.png +0 -0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,15 @@
1
+ describe Percept::CheckboxField, '#height' do
2
+
3
+ it 'returns the height' do
4
+ field = Percept::CheckboxField.new(
5
+ start_x: 5,
6
+ end_x: 10,
7
+ start_y: 7,
8
+ end_y: 12,
9
+ )
10
+ expect(field.height).to eq 5
11
+ field.start_y = 9
12
+ expect(field.height).to eq 3
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ describe Percept::CheckboxField, '#width' do
2
+
3
+ it 'returns the width' do
4
+ field = Percept::CheckboxField.new(
5
+ start_x: 5,
6
+ end_x: 10,
7
+ start_y: 7,
8
+ end_y: 12,
9
+ )
10
+ expect(field.width).to eq 5
11
+ field.start_x = 7
12
+ expect(field.width).to eq 3
13
+ end
14
+
15
+ end
@@ -0,0 +1,50 @@
1
+ describe Percept::Field, '#contains?' do
2
+
3
+ let(:field1) do
4
+ Percept::Field.new(
5
+ start_x: 10,
6
+ start_y: 10,
7
+ end_x: 20,
8
+ end_y: 20,
9
+ line: 'line',
10
+ image: 'image',
11
+ )
12
+ end
13
+
14
+ let(:field2) do
15
+ Percept::Field.new(
16
+ start_x: 15,
17
+ start_y: 15,
18
+ end_x: 25,
19
+ end_y: 18,
20
+ line: 'line',
21
+ image: 'image',
22
+ )
23
+ end
24
+
25
+ let(:field3) do
26
+ Percept::Field.new(
27
+ start_x: 100,
28
+ start_y: 100,
29
+ end_x: 200,
30
+ end_y: 200,
31
+ line: 'line',
32
+ image: 'image',
33
+ )
34
+ end
35
+
36
+ context 'when the fields overlap' do
37
+ it 'returns true' do
38
+ expect(field1.overlaps?(field2)).to eq true
39
+ expect(field2.overlaps?(field1)).to eq true
40
+ end
41
+ end
42
+
43
+ context 'when the fields do not overlap' do
44
+ it 'returns false' do
45
+ expect(field1.overlaps?(field3)).to eq false
46
+ expect(field3.overlaps?(field1)).to eq false
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,90 @@
1
+ describe Percept::FieldDetector, '#detect_field' do
2
+
3
+ let(:min_field_height) { 5 }
4
+ let(:max_field_height) { 10 }
5
+ let(:field_detector) { Percept::FieldDetector.new }
6
+
7
+ before(:each) do
8
+ Percept.configure do |config|
9
+ config.min_field_height = min_field_height
10
+ config.max_field_height = max_field_height
11
+ end
12
+ end
13
+
14
+ context 'when top of image > max_field_height above line' do
15
+ let(:image_path) { File.join(fixture_path, 'low_line.png') }
16
+ let(:image) { image_class.new(image_path) }
17
+
18
+ it 'returns a field that has height of max_field_height' do
19
+ expect(image.lines.size).to eq 1
20
+ field = field_detector.detect_field(image.lines.first, image)
21
+ expect(field.height).to eq max_field_height
22
+ expect(field.width).to eq 32
23
+ end
24
+ end
25
+
26
+ context 'when top of image < max_field_height above line' do
27
+ let(:image_path) { File.join(fixture_path, 'high_line.png') }
28
+ let(:image) { image_class.new(image_path) }
29
+
30
+ it 'returns field with height of distance between line and top' do
31
+ expect(image.lines.size).to eq 1
32
+ field = field_detector.detect_field(image.lines.first, image)
33
+ expect(field.height).to eq 5
34
+ end
35
+ end
36
+
37
+ context 'when another line is < max_field_height above line' do
38
+ let(:image_path) { File.join(fixture_path, 'mid_lines.png') }
39
+ let(:image) { image_class.new(image_path) }
40
+
41
+ it 'returns field with height of distance between lines' do
42
+ expect(image.lines.size).to eq 2
43
+ field = field_detector.detect_field(image.lines.last, image)
44
+ expect(field.height).to eq 6
45
+ end
46
+ end
47
+
48
+ context 'when another line is < min_field_height above line' do
49
+ let(:image_path) { File.join(fixture_path, 'low_lines.png') }
50
+ let(:image) { image_class.new(image_path) }
51
+
52
+ it 'does not return a field' do
53
+ expect(image.lines.size).to eq 2
54
+ field = field_detector.detect_field(image.lines.last, image)
55
+ expect(field).to be_nil
56
+ end
57
+ end
58
+
59
+ context 'when there are nubs above the line' do
60
+ let(:image_path) { File.join(fixture_path, 'nubs.png') }
61
+ let(:image) { image_class.new(image_path) }
62
+
63
+ it 'returns a field that ignores the nubs' do
64
+ expect(image.lines.size).to eq 1
65
+ field = field_detector.detect_field(image.lines.last, image)
66
+ expect(field).not_to be_nil
67
+ expect(field.end_y).to eq 12
68
+ expect(field.start_y).to eq 2
69
+ end
70
+ end
71
+
72
+ context 'when the line is slanted to the left' do
73
+ let(:image_path) { File.join(fixture_path, 'slanted_left.png') }
74
+ let(:image) { image_class.new(image_path) }
75
+
76
+ it 'returns a field from the top of the line' do
77
+ expect(image.lines.size).to eq 1
78
+ end
79
+ end
80
+
81
+ context 'when the line is slanted to the right' do
82
+ let(:image_path) { File.join(fixture_path, 'slanted_right.png') }
83
+ let(:image) { image_class.new(image_path) }
84
+
85
+ it 'returns a field from the top of the line' do
86
+ expect(image.lines.size).to eq 1
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,42 @@
1
+ describe Percept::FieldDetector, '#detect_fields' do
2
+
3
+ let(:field_detector) { Percept::FieldDetector.new }
4
+
5
+ it 'detects fields next to text' do
6
+ image = image_class.new(File.join(fixture_path, 'field_next_to_text.png'))
7
+ fields = field_detector.detect_fields(image)
8
+ expect(fields.size).to eq 1
9
+ end
10
+
11
+ it 'detects thin fields' do
12
+ image = image_class.new(File.join(fixture_path, 'thin_field.png'))
13
+ fields = field_detector.detect_fields(image)
14
+ expect(fields.size).to eq 1
15
+
16
+ field = fields.first
17
+ expect(field.start_x).to eq 33
18
+ expect(field.end_x).to eq 115
19
+ expect(field.start_y).to eq 14
20
+ expect(field.end_y).to eq 38
21
+ end
22
+
23
+ context 'when there is only text' do
24
+ it 'does not return any fields' do
25
+ image = image_class.new(File.join(fixture_path, 'text_no_line.png'))
26
+ expect(field_detector.detect_fields(image).size).to eq 0
27
+ image = image_class.new(File.join(fixture_path, 'text_no_line_2.png'))
28
+ expect(field_detector.detect_fields(image).size).to eq 0
29
+ end
30
+ end
31
+
32
+ it 'detects fields with text on them on the left side' do
33
+ image = image_class.new(File.join(fixture_path, 'text_on_line.png'))
34
+ expect(field_detector.detect_fields(image).size).to eq 1
35
+ end
36
+
37
+ it 'detects fields with text on them on the both sides' do
38
+ image = image_class.new(File.join(fixture_path, 'more_text_on_line.png'))
39
+ expect(field_detector.detect_fields(image).size).to eq 1
40
+ end
41
+
42
+ end
@@ -0,0 +1,53 @@
1
+ describe Percept::FieldCollection, '#<<' do
2
+ let(:field1) do
3
+ Percept::Field.new(
4
+ start_x: 10,
5
+ start_y: 10,
6
+ end_x: 20,
7
+ end_y: 20,
8
+ line: 'line',
9
+ image: 'image',
10
+ )
11
+ end
12
+ let(:field2) do
13
+ Percept::Field.new(
14
+ start_x: 15,
15
+ start_y: 15,
16
+ end_x: 25,
17
+ end_y: 18,
18
+ line: 'line',
19
+ image: 'image',
20
+ )
21
+ end
22
+ let(:field3) do
23
+ Percept::Field.new(
24
+ start_x: 100,
25
+ start_y: 100,
26
+ end_x: 200,
27
+ end_y: 200,
28
+ line: 'line',
29
+ image: 'image',
30
+ )
31
+ end
32
+ let(:fields_collection) { Percept::FieldCollection.new }
33
+
34
+ before(:each) do
35
+ fields_collection << field1
36
+ expect(fields_collection.size).to eq 1
37
+ end
38
+
39
+ context 'when the incoming field overlaps an existing one' do
40
+ it 'does not add the field to the list' do
41
+ fields_collection << field2
42
+ expect(fields_collection.size).to eq 1
43
+ end
44
+ end
45
+
46
+ context 'when the incoming field does not overlap an existing one' do
47
+ it 'adds the field to the list' do
48
+ fields_collection << field3
49
+ expect(fields_collection.size).to eq 2
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,60 @@
1
+ describe Percept::Line, '#=~' do
2
+ let(:params) { { rows: nil, image: nil } }
3
+
4
+ context 'when the lines have the same length' do
5
+ let(:params) { { start_x: 5, end_x: 10, rows: nil, image: nil } }
6
+
7
+ context 'when start_y equals the other end_y' do
8
+ it 'returns true' do
9
+ line1 = Percept::Line.new(params.merge(start_y: 8))
10
+ line2 = Percept::Line.new(params.merge(start_y: 7))
11
+ expect(line1 =~ line2).to be true
12
+ end
13
+ end
14
+
15
+ context 'when end_y equals the other start_y' do
16
+ it 'returns true' do
17
+ line1 = Percept::Line.new(params.merge(start_y: 7))
18
+ line2 = Percept::Line.new(params.merge(start_y: 8))
19
+ expect(line1 =~ line2).to be true
20
+ end
21
+ end
22
+
23
+ context 'when neither start_y matches the other end_y' do
24
+ it 'returns false' do
25
+ line1 = Percept::Line.new(params.merge(start_y: 6))
26
+ line2 = Percept::Line.new(params.merge(start_y: 8))
27
+ expect(line1 =~ line2).to be false
28
+ end
29
+ end
30
+ end
31
+
32
+ context 'when the lines have x overlap' do
33
+ it 'returns true' do
34
+ line1 = Percept::Line.new(params.merge(start_x: 2, end_x: 7, start_y: 7))
35
+ line2 = Percept::Line.new(params.merge(start_x: 4, end_x: 9, start_y: 8))
36
+ expect(line1 =~ line2).to be true
37
+ line1 = Percept::Line.new(params.merge(start_x: 4, end_x: 9, start_y: 7))
38
+ line2 = Percept::Line.new(params.merge(start_x: 2, end_x: 7, start_y: 8))
39
+ expect(line1 =~ line2).to be true
40
+ line1 = Percept::Line.new(params.merge(start_x: 5, end_x: 9, start_y: 7))
41
+ line2 = Percept::Line.new(params.merge(start_x: 2, end_x: 5, start_y: 8))
42
+ expect(line1 =~ line2).to be true
43
+ line1 = Percept::Line.new(params.merge(start_x: 2, end_x: 5, start_y: 7))
44
+ line2 = Percept::Line.new(params.merge(start_x: 5, end_x: 9, start_y: 8))
45
+ expect(line1 =~ line2).to be true
46
+ end
47
+ end
48
+
49
+ context 'when the lines do not have x overlap' do
50
+ it 'returns true' do
51
+ line1 = Percept::Line.new(params.merge(start_x: 2, end_x: 5, start_y: 7))
52
+ line2 = Percept::Line.new(params.merge(start_x: 6, end_x: 9, start_y: 8))
53
+ expect(line1 =~ line2).to be false
54
+ line1 = Percept::Line.new(params.merge(start_x: 6, end_x: 9, start_y: 7))
55
+ line2 = Percept::Line.new(params.merge(start_x: 2, end_x: 5, start_y: 8))
56
+ expect(line1 =~ line2).to be false
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,29 @@
1
+ describe Percept::Line, '#initialize' do
2
+
3
+ let(:params) do
4
+ { start_x: 3, end_x: 10, start_y: 5, row: 'my_row', image: 'my_image' }
5
+ end
6
+ let(:line) { Percept::Line.new(params) }
7
+
8
+ it 'sets its variables' do
9
+ expect(line.start_x).to eq 3
10
+ expect(line.end_x).to eq 10
11
+ expect(line.start_y).to eq 5
12
+ expect(line.rows).to eq ['my_row']
13
+ expect(line.image).to eq 'my_image'
14
+ end
15
+
16
+ context 'when :end_y is not given' do
17
+ it 'sets :end_y to :start_y + 1' do
18
+ expect(line.end_y).to eq 6
19
+ end
20
+ end
21
+
22
+ context 'when :end_y is given' do
23
+ it 'uses the given value' do
24
+ params[:end_y] = 15
25
+ expect(line.end_y).to eq 15
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,22 @@
1
+ describe Percept::Line, '#length' do
2
+
3
+ let(:line) do
4
+ Percept::Line.new(
5
+ start_y: 5,
6
+ end_y: 10,
7
+ start_x: 6,
8
+ end_x: 8,
9
+ row: 'no row',
10
+ image: 'no image',
11
+ )
12
+ end
13
+
14
+ it 'returns end_x - start_x' do
15
+ expect(line.length).to eq 2
16
+ line.end_x = 15
17
+ expect(line.length).to eq 9
18
+ line.start_x = 5
19
+ expect(line.length).to eq 10
20
+ end
21
+
22
+ end
@@ -0,0 +1,58 @@
1
+ describe Percept::Line, '#merge!' do
2
+
3
+ let(:params) do
4
+ { start_x: 3, end_x: 10, start_y: 5, row: 'my_row', image: 'my_image' }
5
+ end
6
+
7
+ let(:line) do
8
+ Percept::Line.new(params)
9
+ end
10
+
11
+ context 'when start_y is greater than the other start_y' do
12
+ it 'sets the start_y to the other start_y' do
13
+ other_line = Percept::Line.new(params.merge(start_y: 4))
14
+ line.merge!(other_line)
15
+ expect(line.start_y).to eq 4
16
+ end
17
+ end
18
+
19
+ context 'when end_y is less than the other end_y' do
20
+ it 'sets the end_y to the other end_y' do
21
+ other_line = Percept::Line.new(params.merge(start_y: 6))
22
+ line.merge!(other_line)
23
+ expect(line.end_y).to eq 7
24
+ end
25
+ end
26
+
27
+ context 'when start_x is greater than the other start_x' do
28
+ it 'sets the start_x to the other start_x' do
29
+ other_line = Percept::Line.new(params.merge(start_x: 2))
30
+ line.merge!(other_line)
31
+ expect(line.start_x).to eq 2
32
+ end
33
+ end
34
+
35
+ context 'when end_x is less than the other end_x' do
36
+ it 'sets the end_x to the other end_x' do
37
+ other_line = Percept::Line.new(params.merge(end_x: 11))
38
+ line.merge!(other_line)
39
+ expect(line.end_x).to eq 11
40
+ end
41
+
42
+ context 'when start_x is greater than the other start_x' do
43
+ it 'sets the start_x to the other start_x' do
44
+ other_line = Percept::Line.new(params.merge(end_x: 11, start_x: 2))
45
+ line.merge!(other_line)
46
+ expect(line.end_x).to eq 11
47
+ expect(line.start_x).to eq 2
48
+ end
49
+ end
50
+ end
51
+
52
+ it 'combines the rows' do
53
+ other_line = Percept::Line.new(params.merge(row: 'other_row'))
54
+ line.merge!(other_line)
55
+ expect(line.rows).to eq %w(my_row other_row)
56
+ end
57
+
58
+ end
@@ -0,0 +1,15 @@
1
+ describe Percept::Line, '#pixels' do
2
+
3
+ let(:image) { image_class.new(File.join(fixture_path, 'low_line.png')) }
4
+ let(:line) { image.lines.first }
5
+
6
+ before(:each) do
7
+ Percept.config.line_length = 30
8
+ end
9
+
10
+ it 'returns the associated pixels for the line' do
11
+ expect(line.pixels.size).to eq 32
12
+ expect(line.pixels.all?(&:blackish?)).to eq true
13
+ end
14
+
15
+ end
@@ -0,0 +1,28 @@
1
+ describe Percept::Line, '#split' do
2
+
3
+ let(:more_corners_path) { File.join(fixture_path, 'more_corners.png') }
4
+ let(:image) { image_class.new(more_corners_path) }
5
+
6
+ before(:each) do
7
+ Percept.config.line_length = 30
8
+ end
9
+
10
+ it 'returns a collection of lines split by vertical dividers' do
11
+ line = image.lines[8]
12
+ Percept.config.line_length = 32
13
+ lines = line.split
14
+ expect(lines).to be_empty
15
+ Percept.config.line_length = 5
16
+ lines = line.split
17
+ expect(lines.length).to eq 2
18
+ expect(lines.first.length).to eq 30
19
+ expect(lines.last.length).to eq 6
20
+
21
+ line_2 = image.lines[9]
22
+ lines = line_2.split
23
+ expect(lines.length).to eq 2
24
+ expect(lines.last.length).to eq 30
25
+ expect(lines.first.length).to eq 6
26
+ end
27
+
28
+ end
@@ -0,0 +1,13 @@
1
+ describe Percept::Line, '#to_s' do
2
+
3
+ let(:attributes) { { start_x: 3, end_x: 10, start_y: 5 } }
4
+
5
+ let(:line) do
6
+ Percept::Line.new(attributes.merge(row: 'my_row', image: 'my_image'))
7
+ end
8
+
9
+ it 'returns a string of the line attributes' do
10
+ expect(line.to_s).to eq attributes.merge(end_y: 6).to_s
11
+ end
12
+
13
+ end
@@ -0,0 +1,50 @@
1
+ describe Percept::LineCollection, '#merge_line' do
2
+
3
+ let(:thick_image_path) { File.join(fixture_path, 'thick_line.png') }
4
+ let(:thick_image) { image_class.new(thick_image_path) }
5
+ let(:nub_bottom_left_path) { File.join(fixture_path, 'nub_bottom_left.png') }
6
+ let(:nub_bottom_left) { image_class.new(nub_bottom_left_path) }
7
+ let(:nub_top_right_path) { File.join(fixture_path, 'nub_top_right.png') }
8
+ let(:nub_top_right) { image_class.new(nub_bottom_left_path) }
9
+ let(:nub_both_sides_path) { File.join(fixture_path, 'nub_both_sides.png') }
10
+ let(:nub_both_sides) { image_class.new(nub_bottom_left_path) }
11
+
12
+ before(:each) do
13
+ Percept.config.line_length = 30
14
+ end
15
+
16
+ context 'when there is a thick line in the image' do
17
+ it 'merges the lines together' do
18
+ lines = thick_image.lines
19
+ expect(lines.size).to eq 1
20
+ end
21
+ end
22
+
23
+ context 'when there is a nub on the bottom line to the left' do
24
+ it 'merges the two lines together' do
25
+ lines = nub_bottom_left.lines
26
+ expect(lines.size).to eq 1
27
+ line = lines.first
28
+ expect(line.end_y - line.start_y).to eq 2
29
+ end
30
+ end
31
+
32
+ context 'when there is a nub on the top line to the right' do
33
+ it 'merges the two lines together' do
34
+ lines = nub_top_right.lines
35
+ expect(lines.size).to eq 1
36
+ line = lines.first
37
+ expect(line.end_y - line.start_y).to eq 2
38
+ end
39
+ end
40
+
41
+ context 'when there is a nub on both sides of a line' do
42
+ it 'merges the two lines together' do
43
+ lines = nub_both_sides.lines
44
+ expect(lines.size).to eq 1
45
+ line = lines.first
46
+ expect(line.end_y - line.start_y).to eq 2
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,17 @@
1
+ describe Percept::LineCollection, '#remove_unwanted_lines!' do
2
+
3
+ let(:image_path) { File.join(fixture_path, 'corners.png') }
4
+ let(:image) { image_class.new(image_path) }
5
+ let(:collection) { image.lines }
6
+
7
+ before(:each) do
8
+ Percept.config.line_length = 30
9
+ end
10
+
11
+ it 'removes lines that are table borders' do
12
+ expect(collection.size).to eq 10
13
+ collection.remove_unwanted_lines!
14
+ expect(collection.size).to eq 9
15
+ end
16
+
17
+ end
@@ -0,0 +1,20 @@
1
+ describe Percept::LineCollection, '#split' do
2
+
3
+ let(:image_path) { File.join(fixture_path, 'more_corners.png') }
4
+ let(:image) { image_class.new(image_path) }
5
+ let(:collection) { image.lines }
6
+
7
+ before(:each) do
8
+ Percept.config.line_length = 30
9
+ end
10
+
11
+ it 'returns a new collection with associated lines split' do
12
+ expect(collection.length).to eq 10
13
+ new_collection = collection.split
14
+ expect(new_collection.length).to eq 10
15
+ Percept.config.line_length = 5
16
+ new_collection = collection.split
17
+ expect(new_collection.length).to eq 12
18
+ end
19
+
20
+ end
@@ -0,0 +1,11 @@
1
+ describe Percept::LineCollection, '#to_s' do
2
+
3
+ let(:collection) { Percept::LineCollection.new }
4
+
5
+ it 'returns a stringified version of its associated lines' do
6
+ lines = %w(line_1 line_2)
7
+ collection.lines = lines
8
+ expect(collection.to_s).to eq lines.to_s
9
+ end
10
+
11
+ end