Refactor Telegram bot logs with performance enhancements and view improvements
- Add comprehensive file information display (content type, size, dimensions) - Move complex image dimension logic from views to TelegramBotLogsHelper - Add percentage calculations to performance metrics section - Use Rails associations instead of manual BlobFile lookups - Update slow requests filtering to use total_request_time column - Enhance search result thumbnails and improve post linking - Add comprehensive test coverage for helper methods - Improve error handling and type safety throughout
This commit is contained in:
@@ -95,12 +95,7 @@ class TelegramBotLogsController < ApplicationController
|
||||
|
||||
# Filter by performance metrics
|
||||
if params[:slow_requests].present? && params[:slow_requests] == "true"
|
||||
# Consider requests with total processing time > 1 second as slow
|
||||
scope =
|
||||
scope.where(
|
||||
"(fingerprint_computation_time + search_computation_time) > ? OR fingerprint_computation_time IS NULL OR search_computation_time IS NULL",
|
||||
1.0,
|
||||
)
|
||||
scope = scope.slow_requests
|
||||
end
|
||||
|
||||
scope
|
||||
|
||||
@@ -18,4 +18,30 @@ module TelegramBotLogsHelper
|
||||
"bg-slate-100 text-slate-800"
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(blob_file: T.nilable(BlobFile)).returns(String) }
|
||||
def image_dimensions_for_blob_file(blob_file)
|
||||
return "N/A" unless blob_file
|
||||
return "N/A" unless blob_file.content_type&.start_with?("image/")
|
||||
|
||||
begin
|
||||
media =
|
||||
LoadedMedia.from_file(
|
||||
T.must(blob_file.content_type),
|
||||
blob_file.absolute_file_path,
|
||||
)
|
||||
if media.is_a?(LoadedMedia::StaticImage)
|
||||
vips_image = media.instance_variable_get(:@vips_image)
|
||||
"#{vips_image.width}×#{vips_image.height}"
|
||||
elsif media.is_a?(LoadedMedia::Gif)
|
||||
width = media.instance_variable_get(:@width)
|
||||
height = media.instance_variable_get(:@height)
|
||||
"#{width}×#{height}"
|
||||
else
|
||||
"N/A"
|
||||
end
|
||||
rescue StandardError
|
||||
"Unable to determine"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -316,11 +316,10 @@ module Tasks
|
||||
search_results
|
||||
.take(5)
|
||||
.map do |result|
|
||||
post = result.fingerprint.post_file&.post
|
||||
post_file = result.fingerprint.post_file
|
||||
{
|
||||
similarity: result.similarity_percentage.round(1),
|
||||
post_id: post&.id,
|
||||
url: post&.external_url_for_view,
|
||||
post_file_id: post_file&.id,
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
class TelegramBotLog < ReduxApplicationRecord
|
||||
self.table_name = "telegram_bot_logs"
|
||||
|
||||
SLOW_REQUEST_THRESHOLD_MS = 5000
|
||||
|
||||
# Association to processed image blob
|
||||
belongs_to :processed_image,
|
||||
foreign_key: :processed_image_sha256,
|
||||
@@ -61,6 +63,13 @@ class TelegramBotLog < ReduxApplicationRecord
|
||||
->(start_date, end_date) do
|
||||
where(request_timestamp: start_date..end_date)
|
||||
end
|
||||
scope :slow_requests,
|
||||
-> do
|
||||
where(
|
||||
"total_request_time > ? OR total_request_time IS NULL",
|
||||
TelegramBotLog::SLOW_REQUEST_THRESHOLD_MS / 1000.0,
|
||||
)
|
||||
end
|
||||
|
||||
# Helper methods
|
||||
sig { returns(String) }
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:items-center">
|
||||
<div class="sm:flex sm:items-center mt-6">
|
||||
<div class="sm:flex-auto">
|
||||
<h1 class="text-2xl font-semibold text-slate-900">Telegram Bot Audit Logs</h1>
|
||||
<p class="mt-2 text-sm text-slate-700">
|
||||
Comprehensive audit trail of all Telegram bot interactions and performance metrics.
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
||||
<div class="text-sm text-slate-600">
|
||||
@@ -87,11 +84,11 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">User</th>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Image</th>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Status</th>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Results</th>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Performance</th>
|
||||
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Timestamp</th>
|
||||
<th class="relative pb-2"><span class="sr-only">Actions</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-200">
|
||||
@@ -105,6 +102,21 @@
|
||||
ID: <%= log.telegram_user_id %>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-3 pr-4 text-sm">
|
||||
<% if log.processed_image_sha256.present? %>
|
||||
<%= link_to telegram_bot_log_path(log) do %>
|
||||
<img src="<%= blob_path(HexUtil.bin2hex(log.processed_image_sha256), format: "jpg", thumb: "small") %>"
|
||||
alt="Processed image"
|
||||
class="max-w-32 max-h-32 object-cover rounded border border-slate-200 hover:border-slate-300 transition-colors" />
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="max-w-32 max-h-32 bg-slate-100 rounded border border-slate-200 flex items-center justify-center">
|
||||
<svg class="w-6 h-6 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="py-3 pr-4 text-sm">
|
||||
<span class="<%= status_color_class(log) %> inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium">
|
||||
<%= log.status.humanize %>
|
||||
@@ -168,10 +180,6 @@
|
||||
<%= time_ago_in_words(log.request_timestamp) %> ago
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-3 text-right text-sm font-medium">
|
||||
<%= link_to "View", telegram_bot_log_path(log),
|
||||
class: "text-blue-600 hover:text-blue-800 font-medium" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
||||
@@ -93,42 +93,114 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Processed Image -->
|
||||
<% if @telegram_bot_log.processed_image_sha256.present? %>
|
||||
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium leading-6 text-slate-900">Processed Image</h3>
|
||||
<div class="mt-4 flex justify-center">
|
||||
<%= link_to blob_path(HexUtil.bin2hex(@telegram_bot_log.processed_image_sha256), format: "jpg") do %>
|
||||
<img src="<%= blob_path(HexUtil.bin2hex(@telegram_bot_log.processed_image_sha256), format: "jpg", thumb: "content-container") %>"
|
||||
alt="Processed image from Telegram"
|
||||
class="max-w-64 max-h-64 object-contain rounded border border-slate-200 shadow-sm" />
|
||||
<% end %>
|
||||
</div>
|
||||
<!-- File Information -->
|
||||
<% blob_file = @telegram_bot_log.processed_image %>
|
||||
<% if blob_file %>
|
||||
<div class="mt-6 bg-slate-50 rounded-lg p-4">
|
||||
<h4 class="text-sm font-medium text-slate-900 mb-3">File Information</h4>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm">
|
||||
<div>
|
||||
<span class="font-medium text-slate-500">Content Type:</span>
|
||||
<div class="text-slate-900 font-mono"><%= blob_file.content_type %></div>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-medium text-slate-500">File Size:</span>
|
||||
<div class="text-slate-900"><%= number_to_human_size(blob_file.size_bytes) %></div>
|
||||
</div>
|
||||
<% dimensions = image_dimensions_for_blob_file(blob_file) %>
|
||||
<% unless dimensions == "N/A" %>
|
||||
<div>
|
||||
<span class="font-medium text-slate-500">Dimensions:</span>
|
||||
<div class="text-slate-900">
|
||||
<% if dimensions == "Unable to determine" %>
|
||||
<span class="text-slate-400"><%= dimensions %></span>
|
||||
<% else %>
|
||||
<%= dimensions %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- Performance Metrics -->
|
||||
<% if @telegram_bot_log.has_performance_metrics? %>
|
||||
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium leading-6 text-slate-900">Performance Metrics</h3>
|
||||
<% total_time = @telegram_bot_log.total_request_time %>
|
||||
<div class="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Download Time</div>
|
||||
<div class="text-xl font-bold text-blue-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.download_time) %>s
|
||||
<% if @telegram_bot_log.download_time.present? %>
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Download Time</div>
|
||||
<div class="text-xl font-bold text-blue-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.download_time) %>s
|
||||
</div>
|
||||
<div class="text-xs text-blue-600">
|
||||
From Telegram
|
||||
<% if total_time && total_time > 0 %>
|
||||
• <%= sprintf("%.1f", (@telegram_bot_log.download_time / total_time) * 100) %>%
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-blue-600">From Telegram</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if @telegram_bot_log.image_processing_time.present? %>
|
||||
<div class="bg-purple-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Processing Time</div>
|
||||
<div class="text-xl font-bold text-purple-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.image_processing_time) %>s
|
||||
</div>
|
||||
<div class="text-xs text-purple-600">File handling</div>
|
||||
<div class="text-xs text-purple-600">
|
||||
File handling
|
||||
<% if total_time && total_time > 0 %>
|
||||
• <%= sprintf("%.1f", (@telegram_bot_log.image_processing_time / total_time) * 100) %>%
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="bg-yellow-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Fingerprint Time</div>
|
||||
<div class="text-xl font-bold text-yellow-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.fingerprint_computation_time) %>s
|
||||
<% if @telegram_bot_log.fingerprint_computation_time.present? %>
|
||||
<div class="bg-yellow-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Fingerprint Time</div>
|
||||
<div class="text-xl font-bold text-yellow-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.fingerprint_computation_time) %>s
|
||||
</div>
|
||||
<div class="text-xs text-yellow-600">
|
||||
Image analysis
|
||||
<% if total_time && total_time > 0 %>
|
||||
• <%= sprintf("%.1f", (@telegram_bot_log.fingerprint_computation_time / total_time) * 100) %>%
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-yellow-600">Image analysis</div>
|
||||
</div>
|
||||
<div class="bg-green-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Search Time</div>
|
||||
<div class="text-xl font-bold text-green-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.search_computation_time) %>s
|
||||
<% end %>
|
||||
<% if @telegram_bot_log.search_computation_time.present? %>
|
||||
<div class="bg-green-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Search Time</div>
|
||||
<div class="text-xl font-bold text-green-700 font-mono">
|
||||
<%= sprintf("%.3f", @telegram_bot_log.search_computation_time) %>s
|
||||
</div>
|
||||
<div class="text-xs text-green-600">
|
||||
Find matches
|
||||
<% if total_time && total_time > 0 %>
|
||||
• <%= sprintf("%.1f", (@telegram_bot_log.search_computation_time / total_time) * 100) %>%
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-green-600">Find matches</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="bg-slate-50 p-4 rounded-lg">
|
||||
<div class="text-sm font-medium text-slate-500">Total Request Time</div>
|
||||
<div class="text-xl font-bold font-mono
|
||||
@@ -144,35 +216,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- Processed Image -->
|
||||
<% if @telegram_bot_log.processed_image.present? %>
|
||||
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<h3 class="text-lg font-medium leading-6 text-slate-900">Processed Image</h3>
|
||||
<div class="mt-4 space-y-3">
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-sm font-medium text-slate-500">Content Type</dt>
|
||||
<dd class="text-sm text-slate-900 font-mono"><%= @telegram_bot_log.processed_image.content_type %></dd>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-sm font-medium text-slate-500">File Size</dt>
|
||||
<dd class="text-sm text-slate-900"><%= number_to_human_size(@telegram_bot_log.processed_image.size_bytes) %></dd>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-sm font-medium text-slate-500">SHA256 Hash</dt>
|
||||
<dd class="text-sm text-slate-900 font-mono break-all"><%= @telegram_bot_log.processed_image.sha256.unpack1('H*') %></dd>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-sm font-medium text-slate-500">Created</dt>
|
||||
<dd class="text-sm text-slate-900">
|
||||
<%= @telegram_bot_log.processed_image.created_at.strftime("%B %d, %Y at %I:%M:%S %p") %>
|
||||
<div class="text-xs text-slate-500"><%= time_ago_in_words(@telegram_bot_log.processed_image.created_at) %> ago</div>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- Response Data -->
|
||||
<% if @telegram_bot_log.response_data.present? && @telegram_bot_log.response_data.any? %>
|
||||
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
||||
@@ -196,30 +239,58 @@
|
||||
<h4 class="font-medium text-slate-900 mb-3">Search Results</h4>
|
||||
<div class="space-y-2">
|
||||
<% @telegram_bot_log.response_data["results"].each_with_index do |result, index| %>
|
||||
<% post_file = result["post_file_id"].present? ? Domain::PostFile.find_by(id: result["post_file_id"]) : nil %>
|
||||
<% post = post_file&.post %>
|
||||
<% blob = post_file&.blob %>
|
||||
<div class="bg-slate-50 p-3 rounded border">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<div class="text-sm font-medium text-slate-900">
|
||||
Result #<%= index + 1 %>
|
||||
</div>
|
||||
<% if result["post_id"] %>
|
||||
<div class="text-xs text-slate-500">Post ID: <%= result["post_id"] %></div>
|
||||
<div class="flex gap-3">
|
||||
<!-- Thumbnail -->
|
||||
<div class="flex-shrink-0">
|
||||
<% if blob&.sha256.present? %>
|
||||
<% thumbnail_sha256 = HexUtil.bin2hex(blob.sha256) %>
|
||||
<% if post %>
|
||||
<%= link_to domain_post_path(post), class: "block" do %>
|
||||
<img src="<%= blob_path(thumbnail_sha256, format: "jpg", thumb: "small") %>"
|
||||
alt="Result thumbnail"
|
||||
class="max-w-32 max-h-32 object-cover rounded border border-slate-200 hover:border-slate-300 transition-colors" />
|
||||
<% end %>
|
||||
<% else %>
|
||||
<img src="<%= blob_path(thumbnail_sha256, format: "jpg", thumb: "small") %>"
|
||||
alt="Result thumbnail"
|
||||
class="max-w-32 max-h-32 object-cover rounded border border-slate-200" />
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="max-w-32 max-h-32 bg-slate-100 rounded border border-slate-200 flex items-center justify-center">
|
||||
<svg class="w-8 h-8 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-sm font-bold
|
||||
<%= result["similarity"] >= 95 ? 'text-green-600' : result["similarity"] >= 90 ? 'text-yellow-600' : 'text-red-600' %>">
|
||||
<%= result["similarity"] %>% similar
|
||||
<!-- Result Details -->
|
||||
<div class="flex-grow">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<div class="text-sm font-medium text-slate-900">
|
||||
<%= link_to post.to_param, domain_post_path(post),
|
||||
class: "text-blue-600 hover:text-blue-800 text-xs" %>
|
||||
</div>
|
||||
<% if post&.id %>
|
||||
<div class="text-xs text-slate-500">Post ID: <%= post.id %></div>
|
||||
<% end %>
|
||||
<% if post_file&.id %>
|
||||
<div class="text-xs text-slate-500">File ID: <%= post_file.id %></div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-sm font-bold
|
||||
<%= result["similarity"] >= 95 ? 'text-green-600' : result["similarity"] >= 90 ? 'text-yellow-600' : 'text-red-600' %>">
|
||||
<%= result["similarity"] %>% similar
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% if result["url"] %>
|
||||
<div class="mt-2">
|
||||
<%= link_to result["url"], result["url"],
|
||||
target: "_blank",
|
||||
class: "text-blue-600 hover:text-blue-800 text-xs break-all" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -179,6 +179,7 @@ RSpec.describe TelegramBotLogsController, type: :controller do
|
||||
:successful,
|
||||
fingerprint_computation_time: 0.1,
|
||||
search_computation_time: 0.2,
|
||||
total_request_time: 0.3,
|
||||
)
|
||||
slow_log =
|
||||
create(
|
||||
@@ -186,6 +187,7 @@ RSpec.describe TelegramBotLogsController, type: :controller do
|
||||
:successful,
|
||||
fingerprint_computation_time: 0.8,
|
||||
search_computation_time: 0.9,
|
||||
total_request_time: 6.0,
|
||||
)
|
||||
|
||||
get :index, params: { slow_requests: "true" }
|
||||
|
||||
@@ -43,4 +43,84 @@ RSpec.describe TelegramBotLogsHelper, type: :helper do
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#image_dimensions_for_blob_file" do
|
||||
it "returns N/A for nil blob_file" do
|
||||
expect(helper.image_dimensions_for_blob_file(nil)).to eq("N/A")
|
||||
end
|
||||
|
||||
it "returns N/A for non-image content type" do
|
||||
blob_file = build(:blob_file, content_type: "text/plain")
|
||||
expect(helper.image_dimensions_for_blob_file(blob_file)).to eq("N/A")
|
||||
end
|
||||
|
||||
it "returns dimensions for static image" do
|
||||
blob_file = build(:blob_file, content_type: "image/jpeg")
|
||||
mock_vips_image = double("Vips::Image", width: 1920, height: 1080)
|
||||
mock_media = instance_double(LoadedMedia::StaticImage)
|
||||
|
||||
allow(LoadedMedia).to receive(:from_file).with(
|
||||
blob_file.content_type,
|
||||
blob_file.absolute_file_path,
|
||||
).and_return(mock_media)
|
||||
allow(mock_media).to receive(:is_a?).with(
|
||||
LoadedMedia::StaticImage,
|
||||
).and_return(true)
|
||||
allow(mock_media).to receive(:instance_variable_get).with(
|
||||
:@vips_image,
|
||||
).and_return(mock_vips_image)
|
||||
|
||||
expect(helper.image_dimensions_for_blob_file(blob_file)).to eq(
|
||||
"1920×1080",
|
||||
)
|
||||
end
|
||||
|
||||
it "returns dimensions for GIF" do
|
||||
blob_file = build(:blob_file, content_type: "image/gif")
|
||||
mock_media = instance_double(LoadedMedia::Gif)
|
||||
|
||||
allow(LoadedMedia).to receive(:from_file).with(
|
||||
blob_file.content_type,
|
||||
blob_file.absolute_file_path,
|
||||
).and_return(mock_media)
|
||||
allow(mock_media).to receive(:is_a?).with(
|
||||
LoadedMedia::StaticImage,
|
||||
).and_return(false)
|
||||
allow(mock_media).to receive(:is_a?).with(LoadedMedia::Gif).and_return(
|
||||
true,
|
||||
)
|
||||
allow(mock_media).to receive(:instance_variable_get).with(
|
||||
:@width,
|
||||
).and_return(800)
|
||||
allow(mock_media).to receive(:instance_variable_get).with(
|
||||
:@height,
|
||||
).and_return(600)
|
||||
|
||||
expect(helper.image_dimensions_for_blob_file(blob_file)).to eq("800×600")
|
||||
end
|
||||
|
||||
it "returns N/A for unsupported media type" do
|
||||
blob_file = build(:blob_file, content_type: "image/webp")
|
||||
mock_media = double("UnsupportedMedia")
|
||||
|
||||
allow(LoadedMedia).to receive(:from_file).with(
|
||||
blob_file.content_type,
|
||||
blob_file.absolute_file_path,
|
||||
).and_return(mock_media)
|
||||
|
||||
expect(helper.image_dimensions_for_blob_file(blob_file)).to eq("N/A")
|
||||
end
|
||||
|
||||
it "returns 'Unable to determine' when exception occurs" do
|
||||
blob_file = build(:blob_file, content_type: "image/jpeg")
|
||||
|
||||
allow(LoadedMedia).to receive(:from_file).and_raise(
|
||||
StandardError.new("File not found"),
|
||||
)
|
||||
|
||||
expect(helper.image_dimensions_for_blob_file(blob_file)).to eq(
|
||||
"Unable to determine",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -85,7 +85,7 @@ describe Domain::Fa::Job::BrowsePageJob do
|
||||
end
|
||||
|
||||
unless expect_to_enqueue
|
||||
it "does not enqueue user page job", quiet: false do
|
||||
it "does not enqueue user page job" do
|
||||
expect(SpecUtil.enqueued_jobs(Domain::Fa::Job::UserPageJob)).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,8 +126,7 @@ RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
|
||||
end
|
||||
let(:args) { { user: user, caused_by_entry: nil } }
|
||||
|
||||
it "correctly handles posts with a null last_file_update_datetime",
|
||||
quiet: false do
|
||||
it "correctly handles posts with a null last_file_update_datetime" do
|
||||
expect { perform_now(args) }.to(
|
||||
change(Domain::Post::InkbunnyPost, :count).by(1),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user