jekyll-seo-tag/spec/jekyll_seo_tag/drop_spec.rb

539 lines
14 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Jekyll::SeoTag::Drop do
let(:config) { { "title" => "site title" } }
let(:page_meta) { { "title" => "page title" } }
let(:page) { make_page(page_meta) }
let(:site) { make_site(config) }
let(:context) { make_context(:page => page, :site => site) }
let(:text) { "" }
subject { described_class.new(text, context) }
before do
Jekyll.logger.log_level = :error
end
# Drop includes liquid filters which expect arguments
# By default, in drops, `to_h` will call each public method with no arugments
# Here, that would cause the filters to explode. This test ensures that all
# public methods don't explode when called without arguments. Don't explode.
it "doesn't blow up on to_h" do
expect { subject.to_h }.to_not raise_error
end
it "returns the version" do
expect(subject.version).to eql(Jekyll::SeoTag::VERSION)
end
context "title?" do
it "knows to include the title" do
expect(subject.title?).to be_truthy
end
context "with title=false" do
let(:text) { "title=false" }
it "knows not to include the title" do
expect(subject.title?).to be_falsy
end
end
context "site title" do
it "knows the site title" do
expect(subject.site_title).to eql("site title")
end
context "with site.name" do
let(:config) { { "name" => "site title" } }
it "knows the site title" do
expect(subject.site_title).to eql("site title")
end
end
end
context "page title" do
it "knows the page title" do
expect(subject.page_title).to eql("page title")
end
context "without a page title" do
let(:page) { make_page }
it "knows the page title" do
expect(subject.page_title).to eql("site title")
end
end
end
context "title" do
context "with a page and site title" do
it "builds the title" do
expect(subject.title).to eql("page title | site title")
end
end
context "with a site description but no page title" do
let(:page) { make_page }
let(:config) do
{ "title" => "site title", "description" => "site description" }
end
it "builds the title" do
expect(subject.title).to eql("site title | site description")
end
end
context "with a site tagline but no page title" do
let(:page) { make_page }
let(:config) do
{ "title" => "site title", "description" => "site description", "tagline" => "site tagline" }
end
it "builds the title" do
expect(subject.title).to eql("site title | site tagline")
end
end
context "with just a page title" do
let(:site) { make_site }
it "builds the title" do
expect(subject.title).to eql("page title")
end
end
context "with just a site title" do
let(:page) { make_page }
it "builds the title" do
expect(subject.title).to eql("site title")
end
end
context "without a page or site title" do
let(:page) { make_page }
let(:site) { make_site }
it "returns nil" do
expect(subject.title).to be_nil
end
end
context "with an empty page title" do
let(:page_meta) { { :title => "" } }
it "builds the title" do
expect(subject.title).to eql("site title")
end
end
context "with an empty site title" do
let(:config) { { :title => "" } }
it "builds the title" do
expect(subject.title).to eql("page title")
end
end
context "with an empty page and site title" do
let(:page_meta) { { :title => "" } }
let(:config) { { :title => "" } }
it "returns nil" do
expect(subject.title).to be_nil
end
end
end
end
context "name" do
context "with seo.name" do
let(:page_meta) do
{ "seo" => { "name" => "seo name" } }
end
it "uses the seo name" do
expect(subject.name).to eql("seo name")
end
end
context "the index" do
let(:page_meta) { { "permalink" => "/" } }
context "with site.social.name" do
let(:config) { { "social" => { "name" => "social name" } } }
it "uses site.social.name" do
expect(subject.name).to eql("social name")
end
end
context "with site.social as an array" do
let(:config) { { "social" => %w(a b) } }
it "uses site.social.name" do
expect(subject.name).to be_nil
end
end
it "uses the site title" do
expect(subject.name).to eql("site title")
end
end
context "site description" do
context "with a site description" do
let(:config) { { :description => "site description " } }
it "returns the site discription" do
expect(subject.site_description).to eql("site description")
end
end
context "without a site description" do
let(:site) { make_site }
it "returns nil" do
expect(subject.site_description).to be_nil
end
end
end
context "page description" do
context "with a page description" do
let(:page_meta) { { "description"=> "page description" } }
it "uses the page description" do
expect(subject.description).to eql("page description")
end
end
context "with a page excerpt" do
let(:page_meta) { { "description"=> "page excerpt" } }
it "uses the page description" do
expect(subject.description).to eql("page excerpt")
end
end
context "with a site description" do
let(:config) { { "description"=> "site description" } }
it "uses the page description" do
expect(subject.description).to eql("site description")
end
end
context "with no descriptions" do
let(:page_meta) { { "description" => nil, "excerpt" => nil } }
let(:config) { { "description"=> nil } }
it "uses returns nil" do
expect(subject.description).to be_nil
end
end
context "truncation" do
context "without seo_description_max_words" do
let(:page_meta) { { "description" => "word " * 150 } }
it "truncates the description to the first 200 words" do
expect(subject.description).to eql(("word " * 100).chop.concat(""))
end
end
context "with an explicit seo_description_max_words property" do
let(:page_meta) { { "description" => "For a long time, I went to bed early", "seo_description_max_words" => 6 } }
it "truncates the description to the configured words count" do
expect(subject.description).to eql("For a long time, I went…")
end
end
end
end
context "author" do
let(:page_meta) { { "author" => "foo" } }
it "returns an AuthorDrop" do
expect(subject.author).to be_a(Jekyll::SeoTag::AuthorDrop)
end
it "passes page information" do
expect(subject.author.name).to eql("foo")
end
# Regression test to ensure to_liquid is called on site and page
# before being passed to AuthorDrop
context "with author as a front matter default" do
let(:page_meta) { {} }
let(:config) do
{
"defaults" => [
{
"scope" => { "path" => "" },
"values" => { "author" => "front matter default" },
},
],
}
end
it "uses the author from the front matter default" do
expect(subject.author["name"]).to eql("front matter default")
end
end
end
end
context "date published" do
let(:config) { { "timezone" => "America/New_York" } }
let(:page_meta) { { "date" => "2017-01-01" } }
it "uses page.date" do
expect(subject.date_published).to eql("2017-01-01T00:00:00-05:00")
end
end
context "date modified" do
let(:config) { { "timezone" => "America/New_York" } }
context "with seo.date_modified" do
let(:page_meta) { { "seo" => { "date_modified" => "2017-01-01" } } }
it "uses seo.date_modified" do
expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
context "with page.last_modified_at" do
let(:page_meta) { { "last_modified_at" => "2017-01-01" } }
it "uses page.last_modified_at" do
expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
context "date" do
let(:page_meta) { { "date" => "2017-01-01" } }
it "uses page.date" do
expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
end
context "type" do
context "with seo.type set" do
let(:page_meta) { { "seo" => { "type" => "test" } } }
it "uses seo.type" do
expect(subject.type).to eql("test")
end
end
context "with seo as an array" do
let(:page_meta) { { "seo" => %w(a b) } }
it "uses seo.type" do
expect(subject.type).to eql("WebPage")
end
end
context "the homepage" do
let(:page_meta) { { "permalink" => "/" } }
it "is a website" do
expect(subject.type).to eql("WebSite")
end
end
context "the about page" do
let(:page) { make_page("permalink" => "/about/") }
it "is a website" do
expect(subject.type).to eql("WebSite")
end
end
context "a blog post" do
let(:page_meta) { { "date" => "2017-01-01" } }
it "is a blog post" do
expect(subject.type).to eql("BlogPosting")
end
end
it "is a webpage" do
expect(subject.type).to eql("WebPage")
end
end
context "links" do
context "with seo.links" do
let(:page_meta) { { "seo" => { "links" => %w(foo bar) } } }
it "uses seo.links" do
expect(subject.links).to eql(%w(foo bar))
end
end
context "with site.social.links" do
let(:config) { { "social" => { "links"=> %w(a b) } } }
it "doesn't use site.social.links" do
expect(subject.links).to be_nil
end
context "the homepage" do
let(:page_meta) { { "permalink" => "/" } }
it "uses site.social.links" do
expect(subject.links).to eql(%w(a b))
end
end
end
end
context "logo" do
context "without site.logo" do
it "returns nothing" do
expect(subject.logo).to be_nil
end
end
context "with an absolute site.logo" do
let(:config) { { "logo" => "http://example.com/image.png" } }
it "uses site.logo" do
expect(subject.logo).to eql("http://example.com/image.png")
end
end
context "with a relative site.logo" do
let(:config) do
{
"logo" => "image.png",
"url" => "http://example.com",
}
end
it "uses site.logo" do
expect(subject.logo).to eql("http://example.com/image.png")
end
end
context "with a uri-escaped logo" do
let(:config) { { "logo" => "some image.png" } }
it "escapes the logo" do
expect(subject.logo).to eql("/some%20image.png")
end
end
end
context "image" do
let(:image) { "/foo.png" }
let(:page_meta) { { "image" => image } }
it "returns a Drop" do
expect(subject.image).to be_a(Jekyll::SeoTag::ImageDrop)
end
it "returns the image" do
expect(subject.image["path"]).to eql("/foo.png")
end
end
context "lang" do
context "with page.lang" do
let(:page_meta) { { "lang" => "en_GB" } }
it "uses page.lang" do
expect(subject.page_lang).to eql("en_GB")
end
end
context "with site.lang" do
let(:config) { { "lang" => "en_GB" } }
it "uses site.lang" do
expect(subject.page_lang).to eql("en_GB")
end
end
context "with nothing" do
it "defaults" do
expect(subject.page_lang).to eql("en_US")
end
end
end
context "homepage_or_about?" do
[
"/", "/index.html", "index.html", "/index.htm",
"/about/", "/about/index.html",
].each do |permalink|
context "when passed '#{permalink}' as a permalink" do
let(:page_meta) { { "permalink" => permalink } }
it "knows it's the home or about page" do
expect(subject.send(:homepage_or_about?)).to be_truthy
end
end
end
context "a random URL" do
let(:page_meta) { { "permalink" => "/about-foo/" } }
it "knows it's not the home or about page" do
expect(subject.send(:homepage_or_about?)).to be_falsy
end
end
end
context "canonical url" do
let(:config) { { :url => "http://example.com" } }
context "when canonical url is specified for a page" do
let(:canonical_url) { "https://github.com/jekyll/jekyll-seo-tag/" }
let(:page_meta) { { "title" => "page title", "canonical_url" => canonical_url } }
it "uses specified canonical url" do
expect(subject.canonical_url).to eq(canonical_url)
end
end
context "when canonical url is not specified for a page" do
it "uses site specific canonical url" do
expect(subject.canonical_url).to eq("http://example.com/page.html")
end
end
end
context "pagination" do
let(:context) do
make_context(
{ :page => page, :site => site },
"paginator" => { "page" => 2, "total_pages" => 10 }
)
end
it "render default pagination title" do
expect(subject.send(:page_number)).to eq("Page 2 of 10 for ")
end
context "render custom pagination title" do
let(:config) { { "seo_paginator_message" => "%<current>s of %<total>s" } }
it "renders the correct page number" do
expect(subject.send(:page_number)).to eq("2 of 10")
end
end
end
it "exposes the JSON-LD drop" do
expect(subject.json_ld).to be_a(Jekyll::SeoTag::JSONLDDrop)
end
end