Improve social card caching 🚀 (#3265)

* Add failing tests for social previews controller. HTML changes between
requests, which breaks caching.

Since we use the HTML to generate the cache key. When the views have any
randomness in them, it breaks the cache, which means we regenerate
images on each request, rather than using what's in memcached.

Adding test to protect from regressions

* Fix randomness in social card templates

The aria tags are randomly generated. Since this is for rendering
images, they aren't needed.

* Make the linter happy by using the sanitize helper
This commit is contained in:
Mike Coutermarsh 2019-06-25 06:45:30 -06:00 committed by Ben Halpern
parent e3c2bf08e6
commit 8afb797ec9
5 changed files with 60 additions and 5 deletions

View file

@ -128,7 +128,7 @@
<%= truncate @article.user.name, length: 25 %>・<%= @article.readable_publish_date %>
</div>
<div class="preview-dev-logo">
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: true, title: "DEV logo") %>
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: false, title: "DEV logo") %>
</div>
</div>
</div>

View file

@ -74,13 +74,13 @@
<h1 style="font-size:<%= font_size %>vw;"><%= @listing.title %></h1>
</div>
<div class="preview-body">
<%= @listing.processed_html.html_safe %>
<%= sanitize_rendered_markdown(@listing.processed_html) %>
</div>
<div class="preview-category">
<%= @category %>
</div>
<div class="preview-dev-logo">
<%= inline_svg("devlistings-horizontal.svg", class: "logo", size: "30vw*10vw", aria: true, title: "DEV logo") %>
<%= inline_svg("devlistings-horizontal.svg", class: "logo", size: "30vw*10vw", aria: false, title: "DEV logo") %>
</div>
</div>
</div>

View file

@ -102,7 +102,7 @@
</h2>
<% end %>
<div class="preview-dev-logo">
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: true, title: "DEV logo") %>
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: false, title: "DEV logo") %>
</div>
</div>
</div>

View file

@ -90,7 +90,7 @@
<%= @user.name %>
</h1>
<div class="preview-dev-logo">
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: true, title: "DEV logo") %>
<%= inline_svg("devplain.svg", class: "logo", size: "9vw * 9vw", aria: false, title: "DEV logo") %>
</div>
</div>
</div>

View file

@ -21,6 +21,17 @@ RSpec.describe "SocialPreviews", type: :request do
expect(response.body).to include CGI.escapeHTML(article.title)
end
it "renders consistent HTML between requests" do
# We use the HTML for caching. It needs to be deterministic (if data is unchanged, the HTML should be the same)
get "/social_previews/article/#{article.id}"
first_request_body = response.body
get "/social_previews/article/#{article.id}"
second_request_body = response.body
expect(first_request_body).to eq second_request_body
end
it "renders shecoded template when tagged with shecoded" do
she_coded_article = create(:article, tags: "shecoded")
@ -42,6 +53,17 @@ RSpec.describe "SocialPreviews", type: :request do
expect(response.body).to include CGI.escapeHTML(user.name)
end
it "renders consistent HTML between requests" do
# We use the HTML for caching. It needs to be deterministic (if data is unchanged, the HTML should be the same)
get "/social_previews/user/#{user.id}"
first_request_body = response.body
get "/social_previews/user/#{user.id}"
second_request_body = response.body
expect(first_request_body).to eq second_request_body
end
it "renders an image when requested and redirects to image url" do
get "/social_previews/user/#{user.id}.png"
@ -55,6 +77,17 @@ RSpec.describe "SocialPreviews", type: :request do
expect(response.body).to include CGI.escapeHTML(organization.name)
end
it "renders consistent HTML between requests" do
# We use the HTML for caching. It needs to be deterministic (if data is unchanged, the HTML should be the same)
get "/social_previews/organization/#{organization.id}"
first_request_body = response.body
get "/social_previews/organization/#{organization.id}"
second_request_body = response.body
expect(first_request_body).to eq second_request_body
end
it "renders an image when requested and redirects to image url" do
get "/social_previews/organization/#{organization.id}.png"
@ -68,6 +101,17 @@ RSpec.describe "SocialPreviews", type: :request do
expect(response.body).to include CGI.escapeHTML(tag.name)
end
it "renders consistent HTML between requests" do
# We use the HTML for caching. It needs to be deterministic (if data is unchanged, the HTML should be the same)
get "/social_previews/tag/#{tag.id}"
first_request_body = response.body
get "/social_previews/tag/#{tag.id}"
second_request_body = response.body
expect(first_request_body).to eq second_request_body
end
it "renders an image when requested and redirects to image url" do
get "/social_previews/tag/#{tag.id}.png"
@ -81,6 +125,17 @@ RSpec.describe "SocialPreviews", type: :request do
expect(response.body).to include CGI.escapeHTML("Call For Proposal")
end
it "renders consistent HTML between requests" do
# We use the HTML for caching. It needs to be deterministic (if data is unchanged, the HTML should be the same)
get "/social_previews/listing/#{listing.id}"
first_request_body = response.body
get "/social_previews/listing/#{listing.id}"
second_request_body = response.body
expect(first_request_body).to eq second_request_body
end
it "renders and image when requested and redirects to iamge url" do
get "/social_previews/listing/#{listing.id}.png"
expect(response).to redirect_to(image_url)