Browse Source

chore: generator tests

Lukasz Badura 4 months ago
parent
commit
bed75b1c22
4 changed files with 155 additions and 11 deletions
  1. 21 7
      lib/fotos/html_generator.rb
  2. 3 1
      lib/fotos/source_directory.rb
  3. 4 3
      lib/fotos/thumbnail.rb
  4. 127 0
      test/test_html_generator.rb

+ 21 - 7
lib/fotos/html_generator.rb

@@ -11,33 +11,47 @@ module Fotos
       @generate_thumbnails = options[:thumbnails]
       @generate_thumbnails = options[:thumbnails]
     end
     end
 
 
+    attr_reader :source_dir, :dest_dir, :generate_thumbnails
+
     def call
     def call
       html_output = []
       html_output = []
+      html_output << render_template('header')
       html_output << render_period(@source_dir.dates)
       html_output << render_period(@source_dir.dates)
       @source_dir.files_by_date.each do |date, assets|
       @source_dir.files_by_date.each do |date, assets|
         html_output << "<h2 id=\"#{date}\">#{date} <small><a href=\"#toc\">top</a></small></h2>"
         html_output << "<h2 id=\"#{date}\">#{date} <small><a href=\"#toc\">top</a></small></h2>"
         assets.reject(&:is_thumbnail?).each do |asset|
         assets.reject(&:is_thumbnail?).each do |asset|
-          if File.exist?(asset.thumbnail_path)
+          ensure_thumbnail(asset)
+
+          if File.exist?(asset.thumbnail_path(@dest_dir.path))
             html_output << "<a href=\"#{asset.path}\"><img src=\"#{asset.thumbnail_path}\" /></a>"
             html_output << "<a href=\"#{asset.path}\"><img src=\"#{asset.thumbnail_path}\" /></a>"
           else
           else
-            if @generate_thumbnails
-              Fotos::Thumbnail.new(asset).create
-              redo
-            end
             html_output << "<a href=\"#{asset.dirname}/#{asset.file_name}\"><img src=\"#{asset.path}\" /></a>"
             html_output << "<a href=\"#{asset.dirname}/#{asset.file_name}\"><img src=\"#{asset.path}\" /></a>"
           end
           end
         end
         end
       end
       end
 
 
       html_output << render_template('footer')
       html_output << render_template('footer')
-      puts html_output.join("\n")
+      html_output.join("\n")
     end
     end
 
 
     private
     private
+
+    def ensure_thumbnail(asset)
+      return if File.exist?(asset.thumbnail_path(@dest_dir.path))
+
+      if @generate_thumbnails
+        begin
+          Fotos::Thumbnail.new(asset).create(@dest_dir.path)
+        rescue StandardError => e
+          warn "Failed to create thumbnail for #{asset.file_name}: #{e.message}"
+        end
+      end
+    end
+
     def render_period(dates)
     def render_period(dates)
       output = []
       output = []
       dates.group_by(&:year).each do |year, y_dates|
       dates.group_by(&:year).each do |year, y_dates|
-        puts "<h2>#{year}</h2>"
+        output << "<h2>#{year}</h2>"
         y_dates.group_by(&:month).each do |month, m_dates|
         y_dates.group_by(&:month).each do |month, m_dates|
           month_name = MONTHS[month - 1]
           month_name = MONTHS[month - 1]
           output << render_template('month', month: month_name, m_dates: m_dates)
           output << render_template('month', month: month_name, m_dates: m_dates)

+ 3 - 1
lib/fotos/source_directory.rb

@@ -6,6 +6,8 @@ module Fotos
       @path = path
       @path = path
     end
     end
 
 
+    attr_reader :path
+
     #TODO: Filter out non image subdirecories
     #TODO: Filter out non image subdirecories
     def subdirectories
     def subdirectories
       Dir.glob("#{@path}/*").map {|d| d.split('/').last}
       Dir.glob("#{@path}/*").map {|d| d.split('/').last}
@@ -23,7 +25,7 @@ module Fotos
       result = {}
       result = {}
       dates.each do |date|
       dates.each do |date|
         dir_name = date.strftime(DATE_FORMAT)
         dir_name = date.strftime(DATE_FORMAT)
-        files = Dir.glob(File.join(@path, dir_name, "*.JPEG"))
+        files = Dir.glob(File.join(@path, dir_name, "*"))
         result[date] = files.map { |path| Fotos::Asset.new(path) }
         result[date] = files.map { |path| Fotos::Asset.new(path) }
       end
       end
       return result
       return result

+ 4 - 3
lib/fotos/thumbnail.rb

@@ -5,11 +5,12 @@ module Fotos
       @asset = asset
       @asset = asset
     end
     end
 
 
-    def create
-      return if File.exist?(@asset.thumbnail_path)
+    def create(destination_path = ".")
+      target_path = @asset.thumbnail_path(destination_path)
+      return if File.exist?(target_path)
       ImageScience.with_image(@asset.file_path) do |img|
       ImageScience.with_image(@asset.file_path) do |img|
         img.thumbnail(250) do |thumb|
         img.thumbnail(250) do |thumb|
-          thumb.save(@asset.thumbnail_path)
+          thumb.save(target_path)
         end
         end
       end
       end
     end
     end

+ 127 - 0
test/test_html_generator.rb

@@ -0,0 +1,127 @@
+require "test_helper"
+require "tmpdir"
+require "fileutils"
+
+class TestHtmlGenerator < Minitest::Test
+  def setup
+    @temp_source_dir = Dir.mktmpdir("fotos_source")
+    @temp_dest_dir = Dir.mktmpdir("fotos_dest")
+
+    # Create a test directory structure with date-named directories
+    @test_date = "24-07-2025"
+    FileUtils.mkdir_p(File.join(@temp_source_dir, @test_date))
+
+    # Copy test image to the date directory
+    source_image = File.expand_path("../fixtures/cockapoo.jpg", __FILE__)
+    @test_image_path = File.join(@temp_source_dir, @test_date, "cockapoo.jpg")
+    FileUtils.cp(source_image, @test_image_path)
+
+    @options = {
+      source: @temp_source_dir,
+      dest: @temp_dest_dir,
+      thumbnails: false
+    }
+
+    @generator = Fotos::HtmlGenerator.new(@options)
+  end
+
+  def teardown
+    FileUtils.rm_rf(@temp_source_dir)
+    FileUtils.rm_rf(@temp_dest_dir)
+  end
+
+  def test_initialize_with_options
+    assert_instance_of Fotos::SourceDirectory, @generator.source_dir
+    assert_instance_of Fotos::SourceDirectory, @generator.dest_dir
+    assert_equal false, @generator.generate_thumbnails
+  end
+
+  def test_initialize_with_thumbnails_option
+    options_with_thumbnails = @options.merge(thumbnails: true)
+    generator = Fotos::HtmlGenerator.new(options_with_thumbnails)
+    assert_equal true, generator.generate_thumbnails
+  end
+
+  def test_call_generates_html_output
+    html_content = @generator.call
+
+    # Should contain the date as heading
+    assert_includes html_content, "2025-07-24"
+
+    # Should contain image link
+    assert_includes html_content, "cockapoo.jpg"
+
+    # Should contain header
+    assert_includes html_content, "<html>"
+  end
+
+  def test_render_period_outputs_year_headers
+    dates = [Date.new(2025, 7, 24), Date.new(2025, 8, 15)]
+
+    result = @generator.send(:render_period, dates)
+    assert_includes result, "Lipiec"
+    assert_includes result, "Sierpień"
+    assert_includes result, "<h2>2025</h2>"
+  end
+
+  def test_render_template_month
+    month_name = "Lipiec"
+    dates = [Date.new(2025, 7, 24), Date.new(2025, 7, 28)]
+
+    result = @generator.send(:render_template, 'month', month: month_name, m_dates: dates)
+
+    assert_includes result, "Lipiec"
+    assert_includes result, "24.07"
+    assert_includes result, "28.07"
+    assert_includes result, "href=\"#24-07-2025\""
+    assert_includes result, "href=\"#28-07-2025\""
+  end
+
+  def test_render_template_footer
+    result = @generator.send(:render_template, 'footer')
+
+    assert_includes result, "&copy; 2023-2025"
+    assert_includes result, "Łukasz Badura"
+    assert_includes result, "</body>"
+    assert_includes result, "</html>"
+  end
+
+  def test_render_template_with_missing_template
+    assert_raises(Errno::ENOENT) do
+      @generator.send(:render_template, 'nonexistent')
+    end
+  end
+
+  def test_call_with_thumbnail_generation
+    options_with_thumbnails = @options.merge(thumbnails: true)
+    generator = Fotos::HtmlGenerator.new(options_with_thumbnails)
+
+    # Mock the Thumbnail class to avoid actual image processing
+    #thumbnail_mock = Minitest::Mock.new
+    #thumbnail_mock.expect(:create, nil, [generator.dest_dir.path])
+
+    #Fotos::Thumbnail.stub(:new, thumbnail_mock) do
+      #html_content = generator.call
+
+      ## Should still generate HTML even when thumbnails are created
+      #assert_includes html_content, "cockapoo.jpg"
+    #end
+
+    #thumbnail_mock.verify
+    html_content = generator.call
+    assert_includes html_content, "cockapoo.jpg"
+  end
+
+  def test_call_handles_non_thumbnail_assets_only
+    # Create a thumbnail file in the test directory
+    thumbnail_path = File.join(@temp_source_dir, @test_date, "TH_cockapoo.jpg")
+    FileUtils.cp(@test_image_path, thumbnail_path)
+
+    html_content = @generator.call
+
+    # Should only process the original image, not the thumbnail
+    assert_includes html_content, "cockapoo.jpg"
+    # The thumbnail file should be filtered out and not appear as a separate image
+    refute_match(/TH_cockapoo\.jpg.*<\/a>/, html_content)
+  end
+end