diff --git a/config/site_settings.yml b/config/site_settings.yml
index f35b9db2b6c..6766ca226e2 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -1996,7 +1996,7 @@ security:
allow_any: false
choices: "['*'] + Onebox::Engine.all_iframe_origins"
allowed_iframes:
- default: "https://www.google.com/maps/embed?|https://www.openstreetmap.org/export/embed.html?|https://calendar.google.com/calendar/embed?|https://codepen.io/|https://www.instagram.com"
+ default: "https://www.google.com/maps/embed?|https://www.openstreetmap.org/export/embed.html?|https://calendar.google.com/calendar/embed?|https://codepen.io/|https://www.instagram.com|https://open.spotify.com"
type: list
list_type: simple
client: true
diff --git a/lib/onebox/engine/spotify_onebox.rb b/lib/onebox/engine/spotify_onebox.rb
new file mode 100644
index 00000000000..d3e3b179a34
--- /dev/null
+++ b/lib/onebox/engine/spotify_onebox.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Onebox
+ module Engine
+ class SpotifyOnebox
+ include Engine
+ include StandardEmbed
+
+ matches_regexp(%r{^https?://open\.spotify/\.com})
+ requires_iframe_origins "https://open.spotify.com"
+ always_https
+
+ def to_html
+ oembed = get_oembed
+ oembed.html
+ end
+
+ def placeholder_html
+ oembed = get_oembed
+ return if oembed.thumbnail_url.blank?
+ "
"
+ end
+
+ protected
+
+ def get_oembed_url
+ "https://open.spotify.com/oembed?url=#{url}"
+ end
+ end
+ end
+end
diff --git a/spec/fixtures/onebox/spotify.response b/spec/fixtures/onebox/spotify.response
new file mode 100644
index 00000000000..a40e6634918
--- /dev/null
+++ b/spec/fixtures/onebox/spotify.response
@@ -0,0 +1,14 @@
+{
+ "html": "",
+ "iframe_url": "https://open.spotify.com/embed/show/5eXZwvvxt3K2dxha3BSaAe?utm_source=oembed",
+ "width": 456,
+ "height": 152,
+ "version": "1.0",
+ "provider_name": "Spotify",
+ "provider_url": "https://spotify.com",
+ "type": "rich",
+ "title": "NerdOut@Spotify",
+ "thumbnail_url": "https://i.scdn.co/image/ab67656300005f1f3ed9a52396207aad8858a28a",
+ "thumbnail_width": 300,
+ "thumbnail_height": 300
+ }
\ No newline at end of file
diff --git a/spec/lib/onebox/engine/spotify_onebox_spec.rb b/spec/lib/onebox/engine/spotify_onebox_spec.rb
new file mode 100644
index 00000000000..e068936c849
--- /dev/null
+++ b/spec/lib/onebox/engine/spotify_onebox_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+RSpec.describe Onebox::Engine::SpotifyOnebox do
+ let(:link) { "https://open.spotify.com/show/5eXZwvvxt3K2dxha3BSaAe" }
+ let(:api_link) do
+ "https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Fshow%2F5eXZwvvxt3K2dxha3BSaAe"
+ end
+ let(:html) { described_class.new(link).to_html }
+ let(:placeholder_html) { described_class.new(link).placeholder_html }
+
+ before { stub_request(:get, api_link).to_return(status: 200, body: onebox_response("spotify")) }
+
+ describe "#placeholder_html" do
+ it "returns an image as the placeholder" do
+ expect(placeholder_html).to include(
+ "https://i.scdn.co/image/ab67656300005f1f3ed9a52396207aad8858a28a",
+ )
+ end
+
+ it "has a fixed height" do
+ expect(placeholder_html).to include("height='300'")
+ end
+ end
+
+ describe "#to_html" do
+ it "returns iframe embed" do
+ expect(html).to include(URI(link).path)
+ expect(html).to include("iframe")
+ end
+
+ it "has object id" do
+ expect(html).to include("5eXZwvvxt3K2dxha3BSaAe")
+ end
+
+ it "has the a fixed height" do
+ expect(html).to include('height="152"')
+ end
+ end
+end