# frozen_string_literal: true require 'rails_helper' RSpec.describe LinkDetailsExtractor do subject { described_class.new(original_url, html, nil) } let(:original_url) { 'https://example.com/dog.html?tracking=123' } describe '#canonical_url' do let(:html) { "" } context 'when canonical URL points to the same host' do let(:url) { 'https://example.com/dog.html' } it 'ignores the canonical URLs' do expect(subject.canonical_url).to eq 'https://example.com/dog.html' end end context 'when canonical URL points to another host' do let(:url) { 'https://different.example.net/dog.html' } it 'ignores the canonical URLs' do expect(subject.canonical_url).to eq original_url end end context 'when canonical URL is set to "null"' do let(:url) { 'null' } it 'ignores the canonical URLs' do expect(subject.canonical_url).to eq original_url end end context 'when canonical URL is set to "undefined"' do let(:url) { 'undefined' } it 'ignores the canonical URLs' do expect(subject.canonical_url).to eq original_url end end end context 'when only basic metadata is present' do let(:html) { <<~HTML } Man bites dog HTML it 'extracts the expected values from html metadata' do expect(subject) .to have_attributes( title: eq('Man bites dog'), description: eq("A dog's tale"), language: eq('en'), icon: eq('https://example.com/favicon.ico') ) end end context 'when structured data is present' do let(:ld_json) do { '@context' => 'https://schema.org', '@type' => 'NewsArticle', 'headline' => 'Man bites dog', 'description' => "A dog's tale", 'datePublished' => '2022-01-31T19:53:00+00:00', 'author' => { '@type' => 'Organization', 'name' => 'Charlie Brown', }, 'publisher' => { '@type' => 'NewsMediaOrganization', 'name' => 'Pet News', 'url' => 'https://example.com', }, 'inLanguage' => { name: 'English', alternateName: 'en', }, }.to_json end shared_examples 'structured data' do it 'extracts the expected values from structured data' do expect(subject) .to have_attributes( title: eq('Man bites dog'), description: eq("A dog's tale"), published_at: eq('2022-01-31T19:53:00+00:00'), author_name: eq('Charlie Brown'), provider_name: eq('Pet News'), language: eq('en') ) end end context 'when is wrapped in CDATA tags' do let(:html) { <<~HTML } HTML it_behaves_like 'structured data' end context 'with the first tag is invalid JSON' do let(:html) { <<~HTML } HTML it_behaves_like 'structured data' end context 'with the first tag is null' do let(:html) { <<~HTML } HTML it_behaves_like 'structured data' end context 'with preceding block of unsupported LD+JSON' do let(:html) { <<~HTML } HTML it_behaves_like 'structured data' end context 'with unsupported in same block LD+JSON' do let(:html) { <<~HTML } HTML it_behaves_like 'structured data' end context 'with author names as array' do let(:ld_json) do { '@context' => 'https://schema.org', '@type' => 'NewsArticle', 'headline' => 'A lot of authors', 'description' => 'But we decided to cram them into one', 'author' => { '@type' => 'Person', 'name' => ['Author 1', 'Author 2'], }, }.to_json end let(:html) { <<~HTML } HTML it 'joins author names' do expect(subject.author_name).to eq 'Author 1, Author 2' end end context 'with embedded arrays' do let(:ld_json) do { '@context' => 'https://schema.org', '@type' => 'NewsArticle', 'headline' => 'A lot of authors', 'description' => 'But we decided to cram them into one', 'author' => [[{ '@type' => 'Person', 'name' => ['Author 1'], }]], 'publisher' => [[{ '@type' => 'NewsMediaOrganization', 'name' => 'Pet News', 'url' => 'https://example.com', }]], }.to_json end let(:html) { <<~HTML } HTML it 'gives correct author_name' do expect(subject.author_name).to eq 'Author 1' end it 'gives provider_name' do expect(subject.provider_name).to eq 'Pet News' end end context 'with headline and description as language tagged strings' do let(:ld_json) do { '@context' => 'https://schema.org', '@type' => 'NewsArticle', 'headline' => { '@value' => 'Title in English', '@language' => 'en', }, 'description' => { '@value' => 'Text in English.', '@language' => 'en', }, }.to_json end let(:html) { <<~HTML } HTML it 'gives correct title' do expect(subject.title).to eq 'Title in English' end it 'gives correct description' do expect(subject.description).to eq 'Text in English.' end end end context 'when Open Graph protocol data is present' do let(:html) { <<~HTML } HTML it 'extracts the expected values from open graph data' do expect(subject) .to have_attributes( canonical_url: eq('https://example.com/dog.html'), title: eq('Man bites dog'), description: eq("A dog's tale"), published_at: eq('2022-01-31T19:53:00+00:00'), author_name: eq('Charlie Brown'), language: eq('en'), image: eq('https://example.com/snoopy.jpg'), image_alt: eq('A good boy'), provider_name: eq('Pet News') ) end end end