110 行
4.1 KiB
Ruby
110 行
4.1 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe PostMetadataFetcher do
|
|
Response = Struct.new(:body)
|
|
|
|
def fetch_with_published_time(value, url: 'https://example.com/video')
|
|
html = <<~HTML
|
|
<html><head>
|
|
<meta property="article:published_time" content="#{ value }">
|
|
</head></html>
|
|
HTML
|
|
uri = URI.parse(url)
|
|
allow(Preview::UrlSafety).to receive(:validate).with(url).and_return([uri, ['8.8.8.8']])
|
|
allow(Preview::HttpFetcher).to receive(:fetch).and_return(Response.new(html))
|
|
allow(Preview::HtmlMetadataExtractor).to receive(:extract)
|
|
.and_return(title: 'title', image_url: nil)
|
|
|
|
described_class.fetch(url)
|
|
end
|
|
|
|
it 'builds ranges explicitly for year, month, and day precision' do
|
|
year = fetch_with_published_time('2024')
|
|
month = fetch_with_published_time('2024-02')
|
|
day = fetch_with_published_time('2024-02-03')
|
|
|
|
expect(year).to include(
|
|
original_created_from: Time.zone.local(2024, 1, 1).iso8601,
|
|
original_created_before: Time.zone.local(2025, 1, 1).iso8601
|
|
)
|
|
expect(month).to include(
|
|
original_created_from: Time.zone.local(2024, 2, 1).iso8601,
|
|
original_created_before: Time.zone.local(2024, 3, 1).iso8601
|
|
)
|
|
expect(day).to include(
|
|
original_created_from: Time.zone.local(2024, 2, 3).iso8601,
|
|
original_created_before: Time.zone.local(2024, 2, 4).iso8601
|
|
)
|
|
end
|
|
|
|
it 'rounds second and fractional-second timestamps down to one-minute ranges' do
|
|
result = fetch_with_published_time('2024-02-03T12:34:56.123+02:30')
|
|
|
|
expect(Time.iso8601(result.fetch(:original_created_from)))
|
|
.to eq(Time.iso8601('2024-02-03T12:34:00+02:30'))
|
|
expect(
|
|
Time.iso8601(result.fetch(:original_created_before)) -
|
|
Time.iso8601(result.fetch(:original_created_from))
|
|
).to eq(60)
|
|
expect(result.fetch(:original_created_from)).not_to include('.')
|
|
end
|
|
|
|
it 'adds platform tags for known video URLs' do
|
|
result = fetch_with_published_time('2024', url: 'https://youtu.be/abc123')
|
|
|
|
expect(result.fetch(:tags)).to eq('動画 YouTube')
|
|
end
|
|
|
|
it 'returns nil dates for an invalid timestamp' do
|
|
result = fetch_with_published_time('not-a-time')
|
|
|
|
expect(result.fetch(:original_created_from)).to be_nil
|
|
expect(result.fetch(:original_created_before)).to be_nil
|
|
end
|
|
|
|
it 'returns nil dates for an invalid timestamp second value' do
|
|
result = fetch_with_published_time('2024-02-03T12:34:99Z')
|
|
|
|
expect(result.fetch(:original_created_from)).to be_nil
|
|
expect(result.fetch(:original_created_before)).to be_nil
|
|
end
|
|
|
|
it 'returns nil dates for invalid calendar dates and invalid hour values' do
|
|
invalid_day = fetch_with_published_time('2024-02-31T12:00Z')
|
|
invalid_leap = fetch_with_published_time('2023-02-29T12:00Z')
|
|
invalid_hour = fetch_with_published_time('2024-02-29T24:00Z')
|
|
|
|
[invalid_day, invalid_leap, invalid_hour].each do |result|
|
|
expect(result.fetch(:original_created_from)).to be_nil
|
|
expect(result.fetch(:original_created_before)).to be_nil
|
|
end
|
|
end
|
|
|
|
it 'accepts a valid leap-day timestamp at minute precision' do
|
|
result = fetch_with_published_time('2024-02-29T12:34Z')
|
|
|
|
expect(result.fetch(:original_created_from)).to eq('2024-02-29T12:34:00Z')
|
|
expect(result.fetch(:original_created_before)).to eq('2024-02-29T12:35:00Z')
|
|
end
|
|
|
|
it 'serialises metadata duration as the same seconds string contract used by forms' do
|
|
html = <<~HTML
|
|
<html><head>
|
|
<meta property="article:published_time" content="2024-02-03T12:34:56.123+02:30">
|
|
<meta property="og:video:duration" content="2.5">
|
|
</head></html>
|
|
HTML
|
|
uri = URI.parse('https://example.com/video')
|
|
allow(Preview::UrlSafety).to receive(:validate)
|
|
.with('https://example.com/video')
|
|
.and_return([uri, ['8.8.8.8']])
|
|
allow(Preview::HttpFetcher).to receive(:fetch).and_return(Response.new(html))
|
|
allow(Preview::HtmlMetadataExtractor).to receive(:extract)
|
|
.and_return(title: 'title', image_url: nil)
|
|
|
|
result = described_class.fetch('https://example.com/video')
|
|
|
|
expect(result.fetch(:duration)).to eq('2.5')
|
|
end
|
|
end
|