bidi2pdf 0.1.11 β†’ 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f566dbc37d780cfb8596d673639ab1ed944cf9306107a7ff65d0712d74fd9276
4
- data.tar.gz: 58273f6e806ea14372ae37f942c05582b80effe6a16cf172b965ea4f45e18108
3
+ metadata.gz: 71faf59892553b22a889f4502396d7c1670269b6223ce6aadf855a2651102e5d
4
+ data.tar.gz: 4af6722525e182f381430750e28ced8516fd6e3febbdd007560e4b5bf1e177a9
5
5
  SHA512:
6
- metadata.gz: 1ec28d088c92fb1d48b42a68f51613045c13ad3d115c8fcd208ea37268ccc1520bf33af1070df513eaa50001259438222af0413f378195539b3eb3e2c95ef292
7
- data.tar.gz: e52a3b58e025f726d46c1a512a54e932e744181a021e3e2b3c02b6f12f5d13b8a3d3d285568ce09e98f61476c37eb2ba13cb2b1920f75f443a076931f6dd067c
6
+ metadata.gz: 18ce08f28f70148e88c09f26238d4b840dacb75318cb36ef14b6d8d1e12d9fd475d734bf495ea30eb7bd4d41684b9da15d008b9d8f73f3e64a6881a8b09cdd9d
7
+ data.tar.gz: 62f78f1130380da20ffd72f5450e87db66bb7f21ae2c947d8f6b1ab1a3bc738690801c2b42117789c89d9a4566f1343f9e3d7b72fe5e5cd55c9e1f1e66d32c8c
data/.rubocop.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
- TargetRubyVersion: 3.3
3
+ TargetRubyVersion: 3.4
4
4
 
5
5
  Style/StringLiterals:
6
6
  EnforcedStyle: double_quotes
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.3.4
1
+ ruby-3.4.3
data/CHANGELOG.md CHANGED
@@ -6,10 +6,107 @@ All notable changes to this project will be documented in this file.
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
- [unreleased]: https://github.com///compare/v0.1.11..HEAD
9
+ ## [Unreleased]
10
+
11
+ [unreleased]: https://github.com/dieter-medium/bidi2pdf/compare/v0.1.12..HEAD
10
12
 
11
13
  <!-- generated by git-cliff end -->
12
14
 
15
+ ## [0.1.13] - 2026-03-28
16
+
17
+ ### πŸ”„ Changed
18
+
19
+ - Merge pull request #77 from dieter-medium/enhance-chromedriver-params by @dieter-medium
20
+ in [#77](https://github.com/dieter-medium/bidi2pdf/pull/77)
21
+ - Merge pull request #76 from dieter-medium/chore by @dieter-medium
22
+ in [#76](https://github.com/dieter-medium/bidi2pdf/pull/76)
23
+ - Merge pull request #73 from dieter-medium/dependabot/bundler/bundler-3a1337c73c by @dieter-medium
24
+ in [#73](https://github.com/dieter-medium/bidi2pdf/pull/73)
25
+ - Merge pull request #68 from dieter-medium/dependabot/bundler/main/json-2.18.1 by @dieter-medium
26
+ in [#68](https://github.com/dieter-medium/bidi2pdf/pull/68)
27
+ - Merge pull request #60 from dieter-medium/dependabot/bundler/main/pdf-reader-2.15.1 by @dieter-medium
28
+ in [#60](https://github.com/dieter-medium/bidi2pdf/pull/60)
29
+ - Merge pull request #66 from dieter-medium/dependabot/bundler/main/rubocop-1.84.1 by @dieter-medium
30
+ in [#66](https://github.com/dieter-medium/bidi2pdf/pull/66)
31
+ - Merge pull request #63 from dieter-medium/dependabot/bundler/main/rbs-3.10.2 by @dependabot[bot]
32
+ in [#63](https://github.com/dieter-medium/bidi2pdf/pull/63)
33
+ - Merge pull request #65 from dieter-medium/dependabot/bundler/main/thor-1.5.0 by @dependabot[bot]
34
+ in [#65](https://github.com/dieter-medium/bidi2pdf/pull/65)
35
+ - Merge pull request #58 from dieter-medium/dependabot/bundler/main/ruby-vips-2.3.0 by @dieter-medium
36
+ in [#58](https://github.com/dieter-medium/bidi2pdf/pull/58)
37
+ - Merge pull request #52 from dieter-medium/dependabot/bundler/main/rubocop-1.81.7 by @dependabot[bot]
38
+ in [#52](https://github.com/dieter-medium/bidi2pdf/pull/52)
39
+ - Merge pull request #51 from dieter-medium/dependabot/bundler/main/rake-13.3.1 by @dieter-medium
40
+ in [#51](https://github.com/dieter-medium/bidi2pdf/pull/51)
41
+ - Merge pull request #49 from dieter-medium/dependabot/bundler/main/rubocop-1.81.6 by @dependabot[bot]
42
+ in [#49](https://github.com/dieter-medium/bidi2pdf/pull/49)
43
+ - Merge pull request #48 from dieter-medium/dependabot/bundler/main/rspec-3.13.2 by @dependabot[bot]
44
+ in [#48](https://github.com/dieter-medium/bidi2pdf/pull/48)
45
+ - Merge pull request #47 from dieter-medium/dependabot/bundler/main/json-2.15.1 by @dieter-medium
46
+ in [#47](https://github.com/dieter-medium/bidi2pdf/pull/47)
47
+ - Merge pull request #46 from dieter-medium/dependabot/bundler/main/rubocop-1.81.1 by @dieter-medium
48
+ in [#46](https://github.com/dieter-medium/bidi2pdf/pull/46)
49
+ - Merge pull request #45 from dieter-medium/dependabot/bundler/main/json-2.15.0 by @dieter-medium
50
+ in [#45](https://github.com/dieter-medium/bidi2pdf/pull/45)
51
+ - Merge pull request #44 from dieter-medium/dependabot/bundler/main/rubocop-1.80.2 by @dependabot[bot]
52
+ in [#44](https://github.com/dieter-medium/bidi2pdf/pull/44)
53
+ - Merge pull request #43 from dieter-medium/dependabot/bundler/main/rbs-3.9.5 by @dieter-medium
54
+ in [#43](https://github.com/dieter-medium/bidi2pdf/pull/43)
55
+ - Merge pull request #41 from dieter-medium/dependabot/bundler/main/rubocop-1.80.1 by @dieter-medium
56
+ in [#41](https://github.com/dieter-medium/bidi2pdf/pull/41)
57
+
58
+ ### πŸ”§ Build
59
+
60
+ - Bump json in the bundler group across 1 directory by @dependabot[bot]
61
+ - Bump json from 2.18.0 to 2.18.1 by @dependabot[bot]
62
+ - Bump pdf-reader from 2.15.0 to 2.15.1 by @dependabot[bot]
63
+ - Bump rubocop from 1.81.7 to 1.84.1 by @dependabot[bot]
64
+ - Bump rbs from 3.9.5 to 3.10.2 by @dependabot[bot]
65
+ - Bump thor from 1.4.0 to 1.5.0 by @dependabot[bot]
66
+ - Bump ruby-vips from 2.2.5 to 2.3.0 by @dependabot[bot]
67
+ - Bump rubocop from 1.81.6 to 1.81.7 by @dependabot[bot]
68
+ - Bump rake from 13.3.0 to 13.3.1 by @dependabot[bot]
69
+ - Bump rubocop from 1.81.1 to 1.81.6 by @dependabot[bot]
70
+ - Bump rspec from 3.13.1 to 3.13.2 by @dependabot[bot]
71
+ - Bump json from 2.15.0 to 2.15.1 by @dependabot[bot]
72
+ - Bump rubocop from 1.80.2 to 1.81.1 by @dependabot[bot]
73
+ - Bump json from 2.13.2 to 2.15.0 by @dependabot[bot]
74
+ - Bump rubocop from 1.80.1 to 1.80.2 by @dependabot[bot]
75
+ - Bump rbs from 3.9.4 to 3.9.5 by @dependabot[bot]
76
+ - Bump rubocop from 1.79.2 to 1.80.1 by @dependabot[bot]
77
+
78
+ ### πŸš€ Added
79
+
80
+ - Enhance chromedriver parameters by @dieter-medium
81
+
82
+ ## [0.1.12] - 2025-09-02
83
+
84
+ ### πŸ”„ Changed
85
+
86
+ - Merge pull request #37 from dieter-medium/dependabot/bundler/main/ruby-vips-2.2.5
87
+ - Merge pull request #34 from dieter-medium/enhance-timeout-error-handling-during-navigate
88
+ - Merge pull request #33 from dieter-medium/dependabot/bundler/main/rubocop-1.79.2
89
+ - Merge pull request #32 from dieter-medium/dependabot/bundler/main/rubocop-1.79.1
90
+ - Merge pull request #31 from dieter-medium/dependabot/bundler/main/json-2.13.2
91
+ - Merge branch 'main' into dependabot/bundler/main/json-2.13.2
92
+ - Merge pull request #30 from dieter-medium/dependabot/bundler/main/rubocop-1.79.0
93
+ - Merge pull request #29 from dieter-medium/remove-codeclimate
94
+ - Merge pull request #27 from dieter-medium/dependabot/bundler/main/json-2.13.0
95
+ - Merge branch 'main' into dependabot/bundler/main/json-2.13.0
96
+ - Merge pull request #28 from dieter-medium/dependabot/bundler/main/thor-1.4.0
97
+ - Merge pull request #26 from dieter-medium/dependabot/bundler/main/rubocop-1.78.0
98
+
99
+ ### πŸ”§ Build
100
+
101
+ - Bump ruby-vips from 2.2.4 to 2.2.5
102
+ - Bump rubocop from 1.77.0 to 1.79.2
103
+ - Bump json from 2.12.2 to 2.13.2
104
+ - Bump thor from 1.3.2 to 1.4.0
105
+
106
+ ### πŸš€ Added
107
+
108
+ - Improve navigation timeout error handling
109
+
13
110
  ## [0.1.11] - 2025-07-09
14
111
 
15
112
  ### πŸ› Fixed
@@ -271,7 +368,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
271
368
 
272
369
  ### πŸ”„ Released
273
370
 
274
- - [unreleased](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.11..HEAD)
371
+ - [unreleased](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.13..HEAD)
372
+ - [0.1.13](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.12..V0.1.13)
373
+ - [0.1.12](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.11..V0.1.12)
275
374
  - [0.1.11](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.10..V0.1.11)
276
375
  - [0.1.10](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.9..V0.1.10)
277
376
  - [0.1.9](https://github.com/dieter-medium/bidi2pdf/compare/v0.1.8..v0.1.9)
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  [![Build Status](https://github.com/dieter-medium/bidi2pdf/actions/workflows/ruby.yml/badge.svg)](https://github.com/dieter-medium/bidi2pdf/blob/main/.github/workflows/ruby.yml)
2
2
  [![Maintainability](https://api.codeclimate.com/v1/badges/6425d9893aa3a9ca243e/maintainability)](https://codeclimate.com/github/dieter-medium/bidi2pdf/maintainability)
3
3
  [![Gem Version](https://badge.fury.io/rb/bidi2pdf.svg)](https://badge.fury.io/rb/bidi2pdf)
4
- [![Test Coverage](https://api.codeclimate.com/v1/badges/6425d9893aa3a9ca243e/test_coverage)](https://codeclimate.com/github/dieter-medium/bidi2pdf/test_coverage)
5
4
  [![Open Source Helpers](https://www.codetriage.com/dieter-medium/bidi2pdf/badges/users.svg)](https://www.codetriage.com/dieter-medium/bidi2pdf)
6
5
 
7
6
  ---
data/docker/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:3.3
1
+ FROM ruby:3.4
2
2
 
3
3
  ENV DEBIAN_FRONTEND=noninteractive
4
4
 
data/docker/entrypoint.sh CHANGED
@@ -45,10 +45,10 @@ fi
45
45
 
46
46
  # DISPLAY=:99 /home/appuser/.webdrivers/chromedriver --port=33259 --whitelisted-ips="" --allowed-origins="*" --disable-dev-shm-usage --disable-gpu --verbose
47
47
  /home/appuser/.webdrivers/chromedriver --port=${CHROMEDRIVER_PORT} \
48
- --headless \
49
- --whitelisted-ips="" \
48
+ --allowed-ips="" \
50
49
  --allowed-origins="*" \
51
50
  --disable-dev-shm-usage \
52
51
  --disable-gpu \
53
52
  --user-data-dir=${USER_DATA_DIR} \
54
- --verbose
53
+ --log-level=${CHROMEDRIVER_LOG_LEVEL:-INFO} \
54
+ --readable-timestamp
@@ -172,7 +172,7 @@ module Bidi2pdf
172
172
  # @raise [NavigationError] If the URL is invalid or improperly formatted.
173
173
  # @example
174
174
  # browser_tab.navigate_to("https://example.com")
175
- def navigate_to(url)
175
+ def navigate_to(url, wait: "complete")
176
176
  begin
177
177
  URI.parse(url)
178
178
  rescue URI::InvalidURIError => e
@@ -180,14 +180,15 @@ module Bidi2pdf
180
180
  end
181
181
 
182
182
  Bidi2pdf.notification_service.instrument("navigate_to.bidi2pdf", url: url) do
183
- navigate_with_listeners url
183
+ navigate_with_listeners url, wait: wait
184
184
  end
185
185
  end
186
186
 
187
187
  # Renders HTML content in the browser tab.
188
188
  #
189
189
  # @param [String] html_content The HTML content to render.
190
- def render_html_content(html_content)
190
+ # rubocop:disable Metrics/BlockLength
191
+ def render_html_content(html_content, wait: "complete")
191
192
  Bidi2pdf.notification_service.instrument("render_html_content.bidi2pdf", url: "data:text/html") do |instrumentation_payload|
192
193
  base64_encoded = Base64.strict_encode64(html_content)
193
194
 
@@ -195,10 +196,51 @@ module Bidi2pdf
195
196
 
196
197
  data_url = "data:text/html;charset=utf-8;base64,#{base64_encoded}"
197
198
 
198
- navigate_with_listeners data_url
199
+ begin
200
+ navigate_with_listeners data_url, wait: wait
201
+ rescue Bidi2pdf::CmdTimeoutError
202
+ Bidi2pdf.logger.info "Waiting for page to load seemed to have timed out. Checking if page is ready via javascript..."
203
+
204
+ # check if the page is still loading
205
+ execute_script <<~JS, wrap_in_promise: false
206
+ const desiredState = "interactive";#{" "}
207
+ const timeoutMs = 30000;#{" "}
208
+ const intervalMs = 50;
209
+
210
+ result = new Promise((resolveReady, rejectReady) => {
211
+ const start = Date.now();
212
+
213
+ const reachedDesired = (state) =>
214
+ desiredState === "interactive"
215
+ ? state === "interactive" || state === "complete"
216
+ : state === "complete";
217
+
218
+ const check = () => {
219
+ const state = document.readyState;
220
+ if (reachedDesired(state)) {
221
+ resolveReady(state); // resolves to "interactive" or "complete"
222
+ return;
223
+ }
224
+ if (Date.now() - start >= timeoutMs) {
225
+ rejectReady(new Error(`Timeout waiting for document.readyState="${desiredState}". Last state="${state}".`));
226
+ return;
227
+ }
228
+
229
+ console.warn(`Waiting for document.readyState="${desiredState}". Last state="${state}".`);
230
+
231
+ setTimeout(check, intervalMs);
232
+ };
233
+
234
+ // Immediate check in case the page is already loaded
235
+ check();
236
+ });
237
+ JS
238
+ end
199
239
  end
200
240
  end
201
241
 
242
+ # rubocop:enable Metrics/BlockLength
243
+
202
244
  # Executes a script in the browser tab.
203
245
  #
204
246
  # This method allows you to execute JavaScript code within the context of the browser tab.
@@ -434,10 +476,10 @@ module Bidi2pdf
434
476
  end
435
477
  end
436
478
 
437
- def navigate_with_listeners(url)
479
+ def navigate_with_listeners(url, wait: "complete")
438
480
  register_event_listeners
439
481
 
440
- cmd = Bidi2pdf::Bidi::Commands::BrowsingContextNavigate.new url: url, context: browsing_context_id
482
+ cmd = Bidi2pdf::Bidi::Commands::BrowsingContextNavigate.new url: url, context: browsing_context_id, wait: wait
441
483
 
442
484
  client.send_cmd_and_wait(cmd) do |response|
443
485
  Bidi2pdf.logger.debug "Navigated to page url: #{url} response: #{response}"
@@ -9,8 +9,8 @@ module Bidi2pdf
9
9
  self.source_location = block.source_location
10
10
  end
11
11
 
12
- def call(*args)
13
- block.call(*args)
12
+ def call(*)
13
+ block.call(*)
14
14
  end
15
15
 
16
16
  def ==(other)
@@ -185,6 +185,8 @@ module Bidi2pdf
185
185
  cmd = [bin]
186
186
  cmd << "--port=#{@port}" unless @port.zero?
187
187
  cmd << "--headless" if @headless
188
+ cmd << "--log-level=#{chromedriver_log_level}"
189
+ cmd << "--readable-timestamp"
188
190
 
189
191
  cmd << user_data_dir_arg
190
192
  cmd.concat(process_chrome_args)
@@ -192,6 +194,15 @@ module Bidi2pdf
192
194
  cmd.join(" ")
193
195
  end
194
196
 
197
+ def chromedriver_log_level
198
+ case Bidi2pdf.logger.level
199
+ when Logger::DEBUG then "ALL"
200
+ when Logger::INFO then "INFO"
201
+ when Logger::WARN then "WARNING"
202
+ else "SEVERE"
203
+ end
204
+ end
205
+
195
206
  def user_data_dir_arg
196
207
  provided = @chrome_args&.find { |arg| arg.include?("--user-data-dir") }
197
208
  return provided if provided
@@ -36,8 +36,8 @@ module Bidi2pdf
36
36
  end
37
37
 
38
38
  def build_process_map
39
- ProcTable.ps.each_with_object({}) do |process, map|
40
- map[process.pid] = { info: process, children: [] }
39
+ ProcTable.ps.to_h do |process|
40
+ [process.pid, { info: process, children: [] }]
41
41
  end
42
42
  end
43
43
 
@@ -5,6 +5,10 @@ module Bidi2pdf
5
5
  # This module provides helper methods for handling PDF files in tests.
6
6
  # It includes methods for debugging, storing, and managing PDF files.
7
7
  module PdfFileHelper
8
+ def reporter
9
+ RSpec.configuration.reporter
10
+ end
11
+
8
12
  # Executes a block with the given PDF data and handles debugging in case of test failures.
9
13
  # If an expectation fails, the PDF data is saved to a file for debugging purposes.
10
14
  # @param [String] pdf_data the PDF data to debug
@@ -14,7 +18,7 @@ module Bidi2pdf
14
18
  yield pdf_data
15
19
  rescue RSpec::Expectations::ExpectationNotMetError => e
16
20
  failure_output = store_pdf_file pdf_data, "test-failure"
17
- puts "Test failed! PDF saved to: #{failure_output}"
21
+ reporter.message("Test failed! PDF saved to: #{failure_output}")
18
22
  raise e
19
23
  end
20
24
 
@@ -7,187 +7,109 @@ require "diff/lcs/hunk"
7
7
  module Bidi2pdf
8
8
  module TestHelpers
9
9
  # rubocop: disable Metrics/ModuleLength
10
- # Provides utilities for sanitizing and comparing PDF text content.
11
- # This module includes methods for cleaning text, comparing PDF content,
12
- # and reporting differences between actual and expected PDF outputs.
13
- #
14
- # The sanitization process includes normalizing whitespace, replacing
15
- # typographic ligatures, and handling other common text formatting issues.
16
- #
17
- # @example Cleaning text
18
- # sanitized_text = Bidi2pdf::TestHelpers::PDFTextSanitizer.clean("Some text")
19
- #
20
- # @example Comparing PDF content
21
- # match = Bidi2pdf::TestHelpers::PDFTextSanitizer.match?(actual_pdf, expected_pdf)
22
10
  module PDFTextSanitizer
23
11
  class << self
24
- # Cleans the given text by replacing common typographic ligatures,
25
- # normalizing whitespace, and removing unnecessary characters.
26
- #
27
- # @param [String] text The text to clean.
28
- # @return [String] The cleaned text.
29
12
  def clean(text)
30
13
  text = UnicodeUtils.nfkd(text)
31
14
 
32
15
  text.gsub("\uFB01", "fi")
33
16
  .gsub("\uFB02", "fl")
34
17
  .gsub("-\n", "")
35
- .gsub(/["]/, '"')
36
- .gsub(/[']/, "'")
18
+ .gsub('"', '"')
19
+ .gsub("'", "'")
37
20
  .gsub("…", "...")
38
21
  .gsub("β€”", "--")
39
22
  .gsub("–", "-")
40
- .gsub(/\s+/, " ") # Replace all whitespace sequences with a single space
23
+ .gsub(/\s+/, " ")
41
24
  .strip
42
25
  end
43
26
 
44
- # Cleans an array of PDF page texts by applying the `clean` method
45
- # to each page's content.
46
- #
47
- # @param [Object] actual_pdf_thingy The PDF object to clean.
48
- # @return [Array<String>] An array of cleaned page texts.
49
- def clean_pages(actual_pdf_thingy)
50
- Bidi2pdf::TestHelpers::PDFReaderUtils.pdf_text(actual_pdf_thingy).map { |text| clean(text) }
27
+ def clean_pages(pdf)
28
+ Bidi2pdf::TestHelpers::PDFReaderUtils.pdf_text(pdf).map { |text| clean(text) }
51
29
  end
52
30
 
53
- # Cleans the given text and removes all whitespace for comparison purposes.
54
- #
55
- # @param [String] text The text to clean and normalize.
56
- # @return [String] The cleaned text without whitespace.
57
31
  def normalize(text)
58
32
  clean(text).gsub(/\s+/, "")
59
33
  end
60
34
 
61
- # Checks if the given PDF contains the expected text or pattern.
62
- #
63
- # @param [Object] actual_pdf_thingy The PDF object to search.
64
- # @param [String, Regexp] expected The expected text or pattern.
65
- # @param [Integer, nil] page_number The specific page to search (optional).
66
- # @return [Boolean] `true` if the expected text is found, `false` otherwise.
67
35
  def contains?(actual_pdf_thingy, expected, page_number = nil)
68
- pages = Bidi2pdf::TestHelpers::PDFReaderUtils.pdf_text(actual_pdf_thingy)
69
- cleaned_pages = clean_pages(pages)
36
+ cleaned_pages = clean_pages(actual_pdf_thingy)
70
37
 
71
38
  return false if page_number && page_number > cleaned_pages.size
72
39
 
73
- # Narrow to specific page if requested
74
40
  if page_number
75
41
  text = cleaned_pages[page_number - 1]
76
42
  return match_expected?(text, expected)
77
43
  end
78
44
 
79
- # Search all pages
80
45
  cleaned_pages.any? { |page| match_expected?(page, expected) }
81
46
  end
82
47
 
83
- # Matches the given text against the expected text or pattern.
84
- #
85
- # @param [String] text The text to match.
86
- # @param [String, Regexp] expected The expected text or pattern.
87
- # @return [Boolean] `true` if the text matches, `false` otherwise.
88
48
  def match_expected?(text, expected)
89
49
  return false unless text
90
50
 
91
51
  expected.is_a?(Regexp) ? text.match?(expected) : text.include?(expected.to_s)
92
52
  end
93
53
 
94
- # Compares the content of two PDF objects for equality.
95
- #
96
- # @param [Object] actual_pdf_thingy The actual PDF object.
97
- # @param [Object] expected_pdf_thingy The expected PDF object.
98
- # @return [Boolean] `true` if the content matches, `false` otherwise.
99
54
  def match?(actual_pdf_thingy, expected_pdf_thingy)
100
- actual = Bidi2pdf::TestHelpers::PDFReaderUtils.pdf_text actual_pdf_thingy
101
- expected = Bidi2pdf::TestHelpers::PDFReaderUtils.pdf_text expected_pdf_thingy
55
+ cleaned_actual = clean_pages(actual_pdf_thingy)
56
+ cleaned_expected = clean_pages(expected_pdf_thingy)
102
57
 
103
- cleaned_actual = clean_pages(actual)
104
- cleaned_expected = clean_pages(expected)
105
-
106
- # Compare without whitespace for equality check
107
58
  actual_for_comparison = cleaned_actual.map { |text| normalize(text) }
108
59
  expected_for_comparison = cleaned_expected.map { |text| normalize(text) }
109
60
 
110
- if actual_for_comparison == expected_for_comparison
111
- true
112
- else
113
- report_content_mismatch(cleaned_actual, cleaned_expected)
114
- false
115
- end
61
+ return true if actual_for_comparison == expected_for_comparison
62
+
63
+ report_content_mismatch(cleaned_actual, cleaned_expected)
64
+ false
116
65
  end
117
66
 
118
- # Reports differences between actual and expected PDF content.
119
- #
120
- # @param [Array<String>] actual The actual PDF content.
121
- # @param [Array<String>] expected The expected PDF content.
122
- # @return [void]
123
67
  def report_content_mismatch(actual, expected)
124
- puts "--- PDF content mismatch ---"
125
- print_differences(actual, expected)
68
+ reporter.message(content_mismatch_message(actual, expected))
126
69
  end
127
70
 
128
- # Prints detailed differences between actual and expected PDF content.
129
- #
130
- # @param [Array<String>] actual The actual PDF content.
131
- # @param [Array<String>] expected The expected PDF content.
132
- # @return [void]
133
- def print_differences(actual, expected)
71
+ def content_mismatch_message(actual, expected)
72
+ sections = ["--- PDF content mismatch ---"]
134
73
  max_pages = [actual.length, expected.length].max
135
74
 
136
75
  (0...max_pages).each do |page_idx|
137
76
  actual_page = actual[page_idx] || "(missing page)"
138
77
  expected_page = expected[page_idx] || "(missing page)"
139
78
 
140
- print_differences_for_page(actual_page, expected_page, page_idx)
79
+ page_message = page_difference_message(actual_page, expected_page, page_idx)
80
+ sections << page_message if page_message
141
81
  end
82
+
83
+ sections.join("\n")
142
84
  end
143
85
 
144
- # Prints the differences between actual and expected content for a specific page.
145
- # This method compares the content ignoring whitespace and, if differences are found,
146
- # outputs a formatted representation of those differences.
147
- #
148
- # @param [String] actual_page The actual page content.
149
- # @param [String] expected_page The expected page content.
150
- # @param [Integer] page_idx The zero-based index of the page being compared.
151
- # @return [void]
152
- def print_differences_for_page(actual_page, expected_page, page_idx)
153
- # Compare without whitespace
86
+ def page_difference_message(actual_page, expected_page, page_idx)
154
87
  actual_no_space = normalize(actual_page.to_s)
155
88
  expected_no_space = normalize(expected_page.to_s)
156
89
 
157
- return if actual_no_space == expected_no_space
158
-
159
- puts "\nPage #{page_idx + 1} differences (ignoring whitespace):"
90
+ return nil if actual_no_space == expected_no_space
160
91
 
161
- # Create diffs between the two pages
162
92
  diffs = Diff::LCS.sdiff(expected_page, actual_page)
163
93
 
164
- # Format and display the differences
165
- puts format_diff_output(diffs, expected_page, actual_page)
94
+ [
95
+ "",
96
+ "Page #{page_idx + 1} differences (ignoring whitespace):",
97
+ format_diff_output(diffs, expected_page, actual_page)
98
+ ].join("\n")
166
99
  end
167
100
 
168
- # Formats the output of differences for display.
169
- #
170
- # @param [Array<Diff::LCS::ContextChange>] diffs The list of differences.
171
- # @param [String] expected The expected text.
172
- # @param [String] actual The actual text.
173
- # @return [String] The formatted differences.
174
101
  def format_diff_output(diffs, expected, actual)
175
- output = []
176
-
177
102
  changes = group_changed_diffs(diffs)
178
103
 
179
- # Output each change with context
180
- changes.each do |change|
181
- output += format_change expected, actual, change
182
- end
104
+ changes.flat_map { |change| format_change(expected, actual, change) }.join("\n")
105
+ end
183
106
 
184
- output.join("\n")
107
+ def reporter
108
+ RSpec.configuration.reporter
185
109
  end
186
110
 
187
111
  private
188
112
 
189
- # Groups contiguous β€œreal” diffs (added/removed/changed) into blocks,
190
- # splitting whenever you hit an unchanged (β€œ=”) diff.
191
113
  def group_changed_diffs(diffs)
192
114
  diffs
193
115
  .chunk_while { |_prev, curr| curr.action != "=" }
@@ -212,7 +134,6 @@ module Bidi2pdf
212
134
  }
213
135
  end
214
136
 
215
- # 3. Build the final lines of output
216
137
  def build_output(snip_data, pos)
217
138
  start = snip_data[:context_start]
218
139
  ctx = snip_data[:context]
@@ -16,6 +16,10 @@ module Bidi2pdf
16
16
  end
17
17
 
18
18
  module SessionTestHelper
19
+ def reporter
20
+ RSpec.configuration.reporter
21
+ end
22
+
19
23
  def chrome_args
20
24
  chrome_args = Bidi2pdf::Bidi::Session::DEFAULT_CHROME_ARGS.dup
21
25
 
@@ -24,7 +28,7 @@ module Bidi2pdf
24
28
  if ENV["DISABLE_CHROME_SANDBOX"]
25
29
  chrome_args << "--no-sandbox"
26
30
 
27
- puts "🚨 Chrome sandbox disabled"
31
+ reporter.message("🚨 Chrome sandbox disabled")
28
32
  end
29
33
  chrome_args
30
34
  end
@@ -51,7 +55,7 @@ RSpec.configure do |config|
51
55
  shared_network: config.shared_network
52
56
  )
53
57
 
54
- puts "πŸš€ chromedriver container started for tests"
58
+ reporter.message("πŸš€ chromedriver container started for tests")
55
59
  end
56
60
  end
57
61
 
@@ -61,20 +65,31 @@ RSpec.configure do |config|
61
65
  end
62
66
 
63
67
  def stop_container(container)
64
- if container&.running?
68
+ return unless container
65
69
 
66
- if ENV["SHOW_CONTAINER_LOGS"]
67
- puts "Container logs:"
68
- logs_std, logs_error = container.logs
70
+ dump_container_logs(container) if container.running?
71
+ stop_running_container(container)
72
+ container.remove
73
+ end
69
74
 
70
- puts logs_error
71
- puts logs_std
72
- end
75
+ def dump_container_logs(container)
76
+ return unless ENV["SHOW_CONTAINER_LOGS"]
73
77
 
74
- puts "🧹 #{container.image} stopping container..."
75
- container.stop
76
- end
77
- container&.remove
78
+ stdout, stderr = container.logs
79
+ reporter.message("Container logs:")
80
+ reporter.message(stderr.to_s) unless stderr.to_s.empty?
81
+ reporter.message(stdout.to_s) unless stdout.to_s.empty?
82
+ end
83
+
84
+ def stop_running_container(container)
85
+ return unless container.running?
86
+
87
+ reporter.message("🧹 #{container.image} stopping container...")
88
+ container.stop
89
+ end
90
+
91
+ def reporter
92
+ RSpec.configuration.reporter
78
93
  end
79
94
 
80
95
  def chromedriver_tests_present?
@@ -11,7 +11,7 @@ RSpec.configure do |config|
11
11
 
12
12
  if uses_containers
13
13
  config.shared_network = Docker::Network.create("bidi2pdf-test-net-#{SecureRandom.hex(4)}")
14
- puts "πŸ•ΈοΈ started shared network #{config.shared_network}"
14
+ reporter.message("πŸ•ΈοΈ started shared network #{config.shared_network}")
15
15
  end
16
16
  end
17
17
 
@@ -19,3 +19,7 @@ RSpec.configure do |config|
19
19
  config.shared_network&.remove
20
20
  end
21
21
  end
22
+
23
+ def reporter
24
+ RSpec.configuration.reporter
25
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bidi2pdf
4
- VERSION = "0.1.11"
4
+ VERSION = "0.1.13"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bidi2pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dieter S.
@@ -195,14 +195,14 @@ dependencies:
195
195
  requirements:
196
196
  - - "~>"
197
197
  - !ruby/object:Gem::Version
198
- version: '3.4'
198
+ version: '4.0'
199
199
  type: :development
200
200
  prerelease: false
201
201
  version_requirements: !ruby/object:Gem::Requirement
202
202
  requirements:
203
203
  - - "~>"
204
204
  - !ruby/object:Gem::Version
205
- version: '3.4'
205
+ version: '4.0'
206
206
  - !ruby/object:Gem::Dependency
207
207
  name: rspec
208
208
  requirement: !ruby/object:Gem::Requirement
@@ -538,14 +538,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
538
538
  requirements:
539
539
  - - ">="
540
540
  - !ruby/object:Gem::Version
541
- version: 3.3.0
541
+ version: 3.4.0
542
542
  required_rubygems_version: !ruby/object:Gem::Requirement
543
543
  requirements:
544
544
  - - ">="
545
545
  - !ruby/object:Gem::Version
546
546
  version: '0'
547
547
  requirements: []
548
- rubygems_version: 3.6.8
548
+ rubygems_version: 3.6.7
549
549
  specification_version: 4
550
550
  summary: A Ruby gem that generates PDFs from web pages using Chrome's BiDi protocol,
551
551
  providing high-quality PDF documents from any URL with full support for modern web