From 2e90fc7238be8c500da34ea2176a214734f4a54b Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Wed, 23 Aug 2017 11:32:36 -0400 Subject: [PATCH] move author drop tests to their own spec --- lib/jekyll-seo-tag/author_drop.rb | 37 +++--- spec/jekyll_seo_tag/author_drop_spec.rb | 162 ++++++++++++++++++++++++ spec/jekyll_seo_tag/drop_spec.rb | 140 ++------------------ 3 files changed, 188 insertions(+), 151 deletions(-) create mode 100644 spec/jekyll_seo_tag/author_drop_spec.rb diff --git a/lib/jekyll-seo-tag/author_drop.rb b/lib/jekyll-seo-tag/author_drop.rb index 7827307..6992539 100644 --- a/lib/jekyll-seo-tag/author_drop.rb +++ b/lib/jekyll-seo-tag/author_drop.rb @@ -1,35 +1,32 @@ module Jekyll class SeoTag + # A drop representing the current page's author + # + # Author name will be pulled from: + # + # 1. The page's `author` key + # 2. The first author in the page's `authors` key + # 3. The `author` key in the site config + # + # If the result from the name search is a string, we'll also check + # for additional author metadata in `site.data.authors` class AuthorDrop < Jekyll::Drops::Drop - # A drop representing the current page's author + # Initialize a new AuthorDrop # - # Author name will be pulled from: - # - # 1. The page's `author` key - # 2. The first author in the page's `authors` key - # 3. The `author` key in the site config - # - # If the result from the name search is a string, we'll also check - # for additional author metadata in `site.data.authors` + # page - The page hash (e.g., Page#to_liquid) + # site - The Jekyll::Drops::SiteDrop def initialize(page: nil, site: nil) - raise ArugementError unless page && site + raise ArgumentError unless page && site @mutations = {} @page = page @site = site end - # Public methods to delegate to keys of the author hash - # Ensures keys will be present when `to_h` is called, even with nil values - DELEGATED_METHODS = %i[name picture].freeze - - DELEGATED_METHODS.each do |meth| - define_method meth do - author_hash[meth.to_s] - end - end - # AuthorDrop#to_s should return name, allowing the author drop to safely # replace `page.author`, if necessary, and remain backwards compatible + def name + author_hash["name"] + end alias_method :to_s, :name def twitter diff --git a/spec/jekyll_seo_tag/author_drop_spec.rb b/spec/jekyll_seo_tag/author_drop_spec.rb new file mode 100644 index 0000000..764b2a2 --- /dev/null +++ b/spec/jekyll_seo_tag/author_drop_spec.rb @@ -0,0 +1,162 @@ +RSpec.describe Jekyll::SeoTag::AuthorDrop do + let(:data) { {} } + let(:config) { { "author" => "site_author" } } + let(:site) do + site = make_site(config) + site.data = data + site + end + let(:site_payload) { site.site_payload["site"] } + + let(:name) { "foo" } + let(:twitter) { "foo" } + let(:picture) { nil } + let(:expected_hash) do + { + "name" => name, + "twitter" => twitter, + } + end + + let(:page_meta) { { "title" => "page title" } } + let(:page) { make_page(page_meta) } + subject { described_class.new(:page => page.to_liquid, :site => site_payload.to_liquid) } + + before do + Jekyll.logger.log_level = :error + end + + it "returns the author's name for #to_s" do + expect(subject.to_s).to eql("site_author") + end + + context "with site.authors as an array" do + let("data") { { "authors" => %w(foo bar) } } + let(:page_meta) { { "author" => "foo" } } + + it "doesn't error" do + expect(subject.to_h).to eql(expected_hash) + end + end + + context "with site.authors[author] as string" do + let("data") { { "authors" => { "foo" => "bar" } } } + let(:page_meta) { { "author" => "foo" } } + + it "doesn't error" do + expect(subject.to_h).to eql(expected_hash) + end + end + + %i[with without].each do |site_data_type| + context "#{site_data_type} site.author data" do + let(:data) do + if site_data_type == :with + { + "authors" => { + "author" => { "name" => "data_author", "image" => "author.png" }, + "array_author" => { "image" => "author.png" }, + "string_author" => { "image" => "author.png" }, + "site_author" => { "image" => "author.png" }, + }, + } + else + {} + end + end + + { + :string => { "author" => "string_author" }, + :array => { "authors" => %w(array_author author2) }, + :empty_string => { "author" => "" }, + :nil => { "author" => nil }, + :hash => { "author" => { "name" => "hash_author" } }, + }.each do |author_type, data| + context "with author as #{author_type}" do + let(:page_meta) { data } + let(:expected_author) do + "#{author_type}_author".sub("nil_", "site_").sub("empty_string_", "site_") + end + + it "returns the name" do + expect(subject["name"]).to eql(expected_author) + end + + it "returns the twitter handle" do + expect(subject["twitter"]).to eql(expected_author) + end + + if site_data_type == :with && author_type != :hash + it "returns arbitrary metadata" do + expect(subject["image"]).to eql("author.png") + end + end + end + end + end + end + + context "with author as a front matter default" do + let(:config) do + { + "defaults" => [ + { + "scope" => { "path" => "" }, + "values" => { "author" => "front matter default" }, + }, + ], + } + end + + it "uses the author from the front matter default" do + expect(subject["name"]).to eql("front matter default") + end + end + + context "twitter" do + let(:page_meta) { { "author" => "author" } } + + it "pulls the handle from the author" do + expect(subject["twitter"]).to eql("author") + end + + context "with an @" do + let(:page_meta) do + { + "author" => { + "name" => "author", + "twitter" => "@twitter", + }, + } + end + + it "strips the @" do + expect(subject["twitter"]).to eql("twitter") + end + end + + # See https://github.com/jekyll/jekyll-seo-tag/issues/202 + context "without an author name or handle" do + let(:page_meta) { { "author" => { "foo" => "bar" } } } + + it "dosen't blow up" do + expect(subject["twitter"]).to be_nil + end + end + + context "with an explicit handle" do + let(:page_meta) do + { + "author" => { + "name" => "author", + "twitter" => "twitter", + }, + } + end + + it "pulls the handle from the hash" do + expect(subject["twitter"]).to eql("twitter") + end + end + end +end diff --git a/spec/jekyll_seo_tag/drop_spec.rb b/spec/jekyll_seo_tag/drop_spec.rb index 27fd406..6510e20 100644 --- a/spec/jekyll_seo_tag/drop_spec.rb +++ b/spec/jekyll_seo_tag/drop_spec.rb @@ -223,95 +223,20 @@ RSpec.describe Jekyll::SeoTag::Drop do end context "author" do - let(:name) { "foo" } - let(:twitter) { "foo" } - let(:picture) { nil } - let(:expected_hash) do - { - "name" => name, - "twitter" => twitter, - "picture" => picture, - } - end - let(:data) { {} } - let(:config) { { "author" => "site_author" } } - let(:site) do - site = make_site(config) - site.data = data - site + let(:page_meta) { { "author" => "foo" } } + + it "returns an AuthorDrop" do + expect(subject.author).to be_a(Jekyll::SeoTag::AuthorDrop) end - context "with site.authors as an array" do - let("data") { { "authors" => %w(foo bar) } } - let(:page_meta) { { "author" => "foo" } } - - it "doesn't error" do - expect(subject.author.to_h).to eql(expected_hash) - end - end - - context "with site.authors[author] as string" do - let("data") { { "authors" => { "foo" => "bar" } } } - let(:page_meta) { { "author" => "foo" } } - - it "doesn't error" do - expect(subject.author.to_h).to eql(expected_hash) - end - end - - %i[with without].each do |site_data_type| - context "#{site_data_type} site.author data" do - let(:data) do - if site_data_type == :with - { - "authors" => { - "author" => { "name" => "data_author", "image" => "author.png" }, - "array_author" => { "image" => "author.png" }, - "string_author" => { "image" => "author.png" }, - "site_author" => { "image" => "author.png" }, - }, - } - else - {} - end - end - - { - :string => { "author" => "string_author" }, - :array => { "authors" => %w(array_author author2) }, - :empty_string => { "author" => "" }, - :nil => { "author" => nil }, - :hash => { "author" => { "name" => "hash_author" } }, - }.each do |author_type, data| - context "with author as #{author_type}" do - let(:page_meta) { data } - let(:expected_author) do - "#{author_type}_author".sub("nil_", "site_").sub("empty_string_", "site_") - end - - it "returns a Drop" do - expect(subject.author).to be_a(Jekyll::SeoTag::AuthorDrop) - end - - it "returns the name" do - expect(subject.author["name"]).to eql(expected_author) - end - - it "returns the twitter handle" do - expect(subject.author["twitter"]).to eql(expected_author) - end - - if site_data_type == :with && author_type != :hash - it "returns the image" do - expect(subject.author["image"]).to eql("author.png") - end - end - end - end - 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" => [ @@ -327,53 +252,6 @@ RSpec.describe Jekyll::SeoTag::Drop do expect(subject.author["name"]).to eql("front matter default") end end - - context "twitter" do - let(:page_meta) { { "author" => "author" } } - - it "pulls the handle from the author" do - expect(subject.author["twitter"]).to eql("author") - end - - context "with an @" do - let(:page_meta) do - { - "author" => { - "name" => "author", - "twitter" => "@twitter", - }, - } - end - - it "strips the @" do - expect(subject.author["twitter"]).to eql("twitter") - end - end - - # See https://github.com/jekyll/jekyll-seo-tag/issues/202 - context "without an author name or handle" do - let(:page_meta) { { "author" => { "foo" => "bar" } } } - - it "dosen't blow up" do - expect(subject.author["twitter"]).to be_nil - end - end - - context "with an explicit handle" do - let(:page_meta) do - { - "author" => { - "name" => "author", - "twitter" => "twitter", - }, - } - end - - it "pulls the handle from the hash" do - expect(subject.author["twitter"]).to eql("twitter") - end - end - end end end