Add basic metadata to opengraph preview
Also refactor datetime & address utils Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
eee2d63309
commit
8caf1e302b
@ -5,6 +5,7 @@ defmodule Mobilizon.Cldr do
|
|||||||
|
|
||||||
use Cldr,
|
use Cldr,
|
||||||
locales: Application.get_env(:mobilizon, :cldr)[:locales],
|
locales: Application.get_env(:mobilizon, :cldr)[:locales],
|
||||||
|
add_fallback_locales: true,
|
||||||
gettext:
|
gettext:
|
||||||
if(Application.fetch_env!(:mobilizon, :env) == :prod,
|
if(Application.fetch_env!(:mobilizon, :env) == :prod,
|
||||||
do: Mobilizon.Web.Gettext,
|
do: Mobilizon.Web.Gettext,
|
||||||
|
95
lib/service/address/address.ex
Normal file
95
lib/service/address/address.ex
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
defmodule Mobilizon.Service.Address do
|
||||||
|
@moduledoc """
|
||||||
|
Module to render an `Mobilizon.Addresses.Address` struct to a string
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Mobilizon.Addresses.Address, as: AddressModel
|
||||||
|
|
||||||
|
@type address :: %{name: String.t(), alternative_name: String.t()}
|
||||||
|
|
||||||
|
def render_address(%AddressModel{} = address) do
|
||||||
|
%{name: name, alternative_name: alternative_name} = render_names(address)
|
||||||
|
|
||||||
|
cond do
|
||||||
|
defined?(alternative_name) && defined?(name) ->
|
||||||
|
"#{name}, #{alternative_name}"
|
||||||
|
|
||||||
|
defined?(name) ->
|
||||||
|
name
|
||||||
|
|
||||||
|
defined?(alternative_name) ->
|
||||||
|
alternative_name
|
||||||
|
|
||||||
|
true ->
|
||||||
|
raise ArgumentError, message: "Invalid address"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec render_names(AddressModel.t()) :: address()
|
||||||
|
def render_names(%AddressModel{type: nil} = address) do
|
||||||
|
render_names(%AddressModel{address | type: "house"})
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_names(%AddressModel{
|
||||||
|
type: type,
|
||||||
|
description: description,
|
||||||
|
postal_code: postal_code,
|
||||||
|
locality: locality,
|
||||||
|
country: country
|
||||||
|
})
|
||||||
|
when type in ["house", "street", "secondary"] do
|
||||||
|
%{
|
||||||
|
name: description,
|
||||||
|
alternative_name: [postal_code, locality, country] |> Enum.filter(& &1) |> Enum.join(", ")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_names(%AddressModel{
|
||||||
|
type: type,
|
||||||
|
description: description,
|
||||||
|
postal_code: postal_code,
|
||||||
|
locality: locality,
|
||||||
|
country: country
|
||||||
|
})
|
||||||
|
when type in ["zone", "city", "administrative"] do
|
||||||
|
%{
|
||||||
|
name: if(defined?(postal_code), do: "#{description} (#{postal_code})", else: description),
|
||||||
|
alternative_name:
|
||||||
|
[locality, country]
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|> Enum.filter(&(&1 != description))
|
||||||
|
|> Enum.join(", ")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_names(%AddressModel{
|
||||||
|
description: description,
|
||||||
|
street: street,
|
||||||
|
region: region,
|
||||||
|
locality: locality,
|
||||||
|
country: country
|
||||||
|
}) do
|
||||||
|
alternative_name =
|
||||||
|
cond do
|
||||||
|
defined?(street) ->
|
||||||
|
if defined?(locality), do: "#{street} (#{locality})", else: street
|
||||||
|
|
||||||
|
defined?(locality) ->
|
||||||
|
"#{locality}, #{region}, #{country}"
|
||||||
|
|
||||||
|
defined?(region) ->
|
||||||
|
"#{region}, #{country}"
|
||||||
|
|
||||||
|
defined?(country) ->
|
||||||
|
country
|
||||||
|
|
||||||
|
true ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
%{name: description, alternative_name: alternative_name}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp defined?(string) when is_binary(string), do: String.trim(string) != ""
|
||||||
|
defp defined?(_), do: false
|
||||||
|
end
|
41
lib/service/date_time/date_time.ex
Normal file
41
lib/service/date_time/date_time.ex
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
defmodule Mobilizon.Service.DateTime do
|
||||||
|
@moduledoc """
|
||||||
|
Module to represent a datetime in a given locale
|
||||||
|
"""
|
||||||
|
alias Cldr.DateTime.Relative
|
||||||
|
|
||||||
|
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
||||||
|
Mobilizon.Cldr.DateTime.to_string!(datetime, format: format, locale: locale_or_default(locale))
|
||||||
|
end
|
||||||
|
|
||||||
|
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
||||||
|
Mobilizon.Cldr.Time.to_string!(datetime, format: format, locale: locale_or_default(locale))
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec datetime_tz_convert(DateTime.t(), String.t()) :: DateTime.t()
|
||||||
|
def datetime_tz_convert(%DateTime{} = datetime, timezone) do
|
||||||
|
case DateTime.shift_zone(datetime, timezone) do
|
||||||
|
{:ok, datetime_with_user_tz} ->
|
||||||
|
datetime_with_user_tz
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
datetime
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
||||||
|
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
||||||
|
Relative.to_string!(datetime, Mobilizon.Cldr,
|
||||||
|
relative_to: DateTime.utc_now(),
|
||||||
|
locale: locale_or_default(locale)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp locale_or_default(locale) do
|
||||||
|
if Mobilizon.Cldr.known_locale_name(locale) do
|
||||||
|
locale
|
||||||
|
else
|
||||||
|
"en"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,19 +1,22 @@
|
|||||||
defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
||||||
alias Phoenix.HTML
|
alias Phoenix.HTML
|
||||||
alias Phoenix.HTML.Tag
|
alias Phoenix.HTML.Tag
|
||||||
|
alias Mobilizon.Addresses.Address
|
||||||
alias Mobilizon.Events.Event
|
alias Mobilizon.Events.Event
|
||||||
alias Mobilizon.Web.JsonLD.ObjectView
|
alias Mobilizon.Web.JsonLD.ObjectView
|
||||||
import Mobilizon.Service.Metadata.Utils, only: [process_description: 2, strip_tags: 1]
|
|
||||||
|
import Mobilizon.Service.Metadata.Utils,
|
||||||
|
only: [process_description: 2, strip_tags: 1, datetime_to_string: 2, render_address: 1]
|
||||||
|
|
||||||
def build_tags(%Event{} = event, locale \\ "en") do
|
def build_tags(%Event{} = event, locale \\ "en") do
|
||||||
event = Map.put(event, :description, process_description(event.description, locale))
|
formatted_description = description(event, locale)
|
||||||
|
|
||||||
tags = [
|
tags = [
|
||||||
Tag.content_tag(:title, event.title <> " - Mobilizon"),
|
Tag.content_tag(:title, event.title <> " - Mobilizon"),
|
||||||
Tag.tag(:meta, name: "description", content: event.description),
|
Tag.tag(:meta, name: "description", content: process_description(event.description, locale)),
|
||||||
Tag.tag(:meta, property: "og:title", content: event.title),
|
Tag.tag(:meta, property: "og:title", content: event.title),
|
||||||
Tag.tag(:meta, property: "og:url", content: event.url),
|
Tag.tag(:meta, property: "og:url", content: event.url),
|
||||||
Tag.tag(:meta, property: "og:description", content: event.description),
|
Tag.tag(:meta, property: "og:description", content: formatted_description),
|
||||||
Tag.tag(:meta, property: "og:type", content: "website"),
|
Tag.tag(:meta, property: "og:type", content: "website"),
|
||||||
# Tell Search Engines what's the origin
|
# Tell Search Engines what's the origin
|
||||||
Tag.tag(:link, rel: "canonical", href: event.url)
|
Tag.tag(:link, rel: "canonical", href: event.url)
|
||||||
@ -45,4 +48,25 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
|||||||
|> ObjectView.render(%{event: %{event | title: strip_tags(title)}})
|
|> ObjectView.render(%{event: %{event | title: strip_tags(title)}})
|
||||||
|> Jason.encode!()
|
|> Jason.encode!()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp description(
|
||||||
|
%Event{
|
||||||
|
description: description,
|
||||||
|
begins_on: begins_on,
|
||||||
|
physical_address: %Address{} = address
|
||||||
|
},
|
||||||
|
locale
|
||||||
|
) do
|
||||||
|
"#{datetime_to_string(begins_on, locale)} - #{render_address(address)} - #{process_description(description, locale)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp description(
|
||||||
|
%Event{
|
||||||
|
description: description,
|
||||||
|
begins_on: begins_on
|
||||||
|
},
|
||||||
|
locale
|
||||||
|
) do
|
||||||
|
"#{datetime_to_string(begins_on, locale)} - #{process_description(description, locale)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,7 @@ defmodule Mobilizon.Service.Metadata.Utils do
|
|||||||
Tools to convert tags to string.
|
Tools to convert tags to string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
alias Mobilizon.Service.{Address, DateTime}
|
||||||
alias Mobilizon.Service.Formatter.HTML, as: HTMLFormatter
|
alias Mobilizon.Service.Formatter.HTML, as: HTMLFormatter
|
||||||
alias Phoenix.HTML
|
alias Phoenix.HTML
|
||||||
import Mobilizon.Web.Gettext
|
import Mobilizon.Web.Gettext
|
||||||
@ -52,6 +53,9 @@ defmodule Mobilizon.Service.Metadata.Utils do
|
|||||||
gettext("The event organizer didn't add any description.")
|
gettext("The event organizer didn't add any description.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium), to: DateTime
|
||||||
|
defdelegate render_address(address), to: Address
|
||||||
|
|
||||||
defp maybe_slice(description, limit) do
|
defp maybe_slice(description, limit) do
|
||||||
if String.length(description) > limit do
|
if String.length(description) > limit do
|
||||||
description
|
description
|
||||||
|
@ -1,39 +1,15 @@
|
|||||||
defmodule Mobilizon.Web.EmailView do
|
defmodule Mobilizon.Web.EmailView do
|
||||||
use Mobilizon.Web, :view
|
use Mobilizon.Web, :view
|
||||||
|
|
||||||
alias Cldr.DateTime.Relative
|
alias Mobilizon.Service.DateTime, as: DateTimeRenderer
|
||||||
import Mobilizon.Web.Gettext
|
import Mobilizon.Web.Gettext
|
||||||
|
|
||||||
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium),
|
||||||
with {:ok, string} <-
|
to: DateTimeRenderer
|
||||||
Mobilizon.Cldr.DateTime.to_string(datetime, format: format, locale: locale) do
|
|
||||||
string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :hm) do
|
defdelegate datetime_to_time_string(datetime, locale \\ "en", format \\ :short),
|
||||||
with {:ok, string} <-
|
to: DateTimeRenderer
|
||||||
Mobilizon.Cldr.DateTime.to_string(datetime, format: format, locale: locale) do
|
|
||||||
string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec datetime_tz_convert(DateTime.t(), String.t()) :: DateTime.t()
|
defdelegate datetime_tz_convert(datetime, timezone), to: DateTimeRenderer
|
||||||
def datetime_tz_convert(%DateTime{} = datetime, timezone) do
|
defdelegate datetime_relative(datetime, locale \\ "en"), to: DateTimeRenderer
|
||||||
case DateTime.shift_zone(datetime, timezone) do
|
|
||||||
{:ok, datetime_with_user_tz} ->
|
|
||||||
datetime_with_user_tz
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
datetime
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
|
||||||
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
|
||||||
Relative.to_string!(datetime, Mobilizon.Cldr,
|
|
||||||
relative_to: DateTime.utc_now(),
|
|
||||||
locale: locale
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
58
test/service/address/address_test.exs
Normal file
58
test/service/address/address_test.exs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
defmodule Mobilizon.Service.AddressTest do
|
||||||
|
@moduledoc """
|
||||||
|
Test representing addresses
|
||||||
|
"""
|
||||||
|
use Mobilizon.DataCase
|
||||||
|
alias Mobilizon.Addresses.Address
|
||||||
|
alias Mobilizon.Service.Address, as: AddressRenderer
|
||||||
|
import Mobilizon.Factory
|
||||||
|
|
||||||
|
describe "render an address" do
|
||||||
|
test "basic" do
|
||||||
|
%Address{} = address = insert(:address)
|
||||||
|
|
||||||
|
assert AddressRenderer.render_address(address) ==
|
||||||
|
"#{address.description}, #{address.postal_code}, #{address.locality}, #{address.country}"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a house" do
|
||||||
|
assert AddressRenderer.render_address(%Address{
|
||||||
|
description: "somewhere",
|
||||||
|
type: "house",
|
||||||
|
postal_code: "35000",
|
||||||
|
locality: "Rennes"
|
||||||
|
}) ==
|
||||||
|
"somewhere, 35000, Rennes"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a city" do
|
||||||
|
assert AddressRenderer.render_address(%Address{
|
||||||
|
description: "Rennes",
|
||||||
|
type: "city",
|
||||||
|
postal_code: "35000",
|
||||||
|
locality: "Rennes"
|
||||||
|
}) ==
|
||||||
|
"Rennes (35000)"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a region" do
|
||||||
|
assert AddressRenderer.render_address(%Address{
|
||||||
|
description: "Ille et Vilaine",
|
||||||
|
type: "administrative",
|
||||||
|
postal_code: "",
|
||||||
|
locality: ""
|
||||||
|
}) ==
|
||||||
|
"Ille et Vilaine"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "only with description" do
|
||||||
|
assert AddressRenderer.render_address(%Address{description: "somewhere"}) == "somewhere"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with no data" do
|
||||||
|
assert_raise ArgumentError, "Invalid address", fn ->
|
||||||
|
AddressRenderer.render_address(%Address{})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
71
test/service/date_time/date_time.exs
Normal file
71
test/service/date_time/date_time.exs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
defmodule Mobilizon.Service.DateTimeTest do
|
||||||
|
@moduledoc """
|
||||||
|
Test representing datetimes in defined locale
|
||||||
|
"""
|
||||||
|
use Mobilizon.DataCase
|
||||||
|
alias Mobilizon.Service.DateTime, as: DateTimeRenderer
|
||||||
|
|
||||||
|
@datetime "2021-06-22T15:25:29.531539Z"
|
||||||
|
|
||||||
|
describe "render a datetime to string" do
|
||||||
|
test "standard datetime" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
assert DateTimeRenderer.datetime_to_string(datetime) == "Jun 22, 2021, 3:25:29 PM"
|
||||||
|
assert DateTimeRenderer.datetime_to_string(datetime, "fr") == "22 juin 2021, 15:25:29"
|
||||||
|
|
||||||
|
assert DateTimeRenderer.datetime_to_string(datetime, "fr", :long) ==
|
||||||
|
"22 juin 2021 à 15:25:29 UTC"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "non existing or loaded locale fallbacks to english" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
|
||||||
|
assert DateTimeRenderer.datetime_to_string(datetime, "es") == "Jun 22, 2021, 3:25:29 PM"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "render a time to string" do
|
||||||
|
test "standard time" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
assert DateTimeRenderer.datetime_to_time_string(datetime) == "3:25 PM"
|
||||||
|
assert DateTimeRenderer.datetime_to_time_string(datetime, "fr") == "15:25"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "non existing or loaded locale fallbacks to english" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
|
||||||
|
assert DateTimeRenderer.datetime_to_time_string(datetime, "pl") == "3:25 PM"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "convert a datetime with a timezone" do
|
||||||
|
test "with an existing tz" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
converted_datetime = DateTimeRenderer.datetime_tz_convert(datetime, "Europe/Paris")
|
||||||
|
|
||||||
|
assert %DateTime{time_zone: "Europe/Paris", utc_offset: 3600} = converted_datetime
|
||||||
|
assert converted_datetime |> DateTime.to_unix() == datetime |> DateTime.to_unix()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with an non existing tz" do
|
||||||
|
{:ok, datetime, _} = DateTime.from_iso8601(@datetime)
|
||||||
|
converted_datetime = DateTimeRenderer.datetime_tz_convert(datetime, "Planet/Mars")
|
||||||
|
|
||||||
|
assert converted_datetime == datetime
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "gets relative time to a datetime" do
|
||||||
|
test "standard time" do
|
||||||
|
then = DateTime.add(DateTime.utc_now(), 3600 * -5)
|
||||||
|
assert DateTimeRenderer.datetime_relative(then) == "5 hours ago"
|
||||||
|
assert DateTimeRenderer.datetime_relative(then, "fr") == "il y a 5 heures"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "non existing or loaded locale fallbacks to english" do
|
||||||
|
then = DateTime.add(DateTime.utc_now(), 3600 * -4)
|
||||||
|
|
||||||
|
assert DateTimeRenderer.datetime_relative(then, "pl") == "4 hours ago"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -6,6 +6,7 @@ defmodule Mobilizon.Service.MetadataTest do
|
|||||||
alias Mobilizon.Service.Metadata
|
alias Mobilizon.Service.Metadata
|
||||||
alias Mobilizon.Tombstone
|
alias Mobilizon.Tombstone
|
||||||
alias Mobilizon.Web.Endpoint
|
alias Mobilizon.Web.Endpoint
|
||||||
|
alias Mobilizon.Web.JsonLD.ObjectView
|
||||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||||
use Mobilizon.DataCase
|
use Mobilizon.DataCase
|
||||||
import Mobilizon.Factory
|
import Mobilizon.Factory
|
||||||
@ -37,29 +38,81 @@ defmodule Mobilizon.Service.MetadataTest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "build_tags/2 for an event" do
|
describe "build_tags/2 for an event" do
|
||||||
|
@long_description """
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada commodo nunc, dictum dignissim erat aliquet quis. Morbi iaculis scelerisque magna eu dapibus. Morbi ultricies mollis arcu, vel auctor enim dapibus ut. Cras tempus sapien eu lacus blandit suscipit. Fusce tincidunt fringilla velit non elementum. Etiam pretium venenatis placerat. Suspendisse interdum, justo efficitur faucibus commodo, dolor elit vehicula lacus, eu molestie nulla mi vel dolor. Nullam fringilla at lorem a gravida. Praesent viverra, ante eu porttitor rutrum, ex leo condimentum felis, vitae vestibulum neque turpis in nunc. Nullam aliquam rhoncus ornare. Suspendisse finibus finibus est sed eleifend. Nam a massa vestibulum, mollis lorem vel, placerat purus. Nam ex nunc, hendrerit ut lacinia ac, pellentesque eu est.</p>
|
||||||
|
|
||||||
|
<p>Fusce nec odio tellus. Aliquam at fermentum turpis, ut dictum tellus. Fusce ac nibh vehicula, imperdiet ipsum sit amet, pellentesque dui. Vivamus venenatis efficitur elementum. Quisque mattis dui ac faucibus mollis. Nullam ac malesuada nisi, vitae scelerisque nisi. Nulla placerat nunc non convallis sollicitudin. Donec sed pulvinar leo, quis tristique eros. Nulla pretium elit ante, consectetur aliquam sapien varius nec. Donec cursus, orci quis suscipit placerat, mi lectus convallis sem, et scelerisque urna libero nec sapien. Nam quis justo ante. Nulla placerat est nec suscipit euismod.</p>
|
||||||
|
"""
|
||||||
|
@truncated_description "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada commodo nunc, dictum dignissim erat aliquet quis. Morbi iaculis scelerisque magna eu dapibus. Morbi ultricies mollis arcu, vel…"
|
||||||
|
|
||||||
test "gives tags" do
|
test "gives tags" do
|
||||||
alias Mobilizon.Web.Endpoint
|
%Event{} = event = insert(:event, description: @long_description)
|
||||||
|
|
||||||
%Event{} = event = insert(:event)
|
tags_output = event |> Metadata.build_tags() |> Metadata.Utils.stringify_tags()
|
||||||
|
{:ok, document} = Floki.parse_fragment(tags_output)
|
||||||
|
assert "#{event.title} - Mobilizon" == document |> Floki.find("title") |> Floki.text()
|
||||||
|
|
||||||
# Because the description in Schema.org data is double-escaped
|
assert @truncated_description ==
|
||||||
a = "\n"
|
document
|
||||||
b = "\\n"
|
|> Floki.find("meta[name=\"description\"]")
|
||||||
|
|> Floki.attribute("content")
|
||||||
|
|> hd
|
||||||
|
|
||||||
assert event
|
assert event.title ==
|
||||||
|> Metadata.build_tags()
|
document
|
||||||
|> Metadata.Utils.stringify_tags() ==
|
|> Floki.find("meta[property=\"og:title\"]")
|
||||||
String.trim("""
|
|> Floki.attribute("content")
|
||||||
<title>#{event.title} - Mobilizon</title><meta content="#{event.description}" name="description"><meta content="#{event.title}" property="og:title"><meta content="#{event.url}" property="og:url"><meta content="#{event.description}" property="og:description"><meta content="website" property="og:type"><link href="#{event.url}" rel="canonical"><meta content="#{event.picture.file.url}" property="og:image"><meta content="summary_large_image" property="twitter:card"><script type="application/ld+json">{"@context":"https://schema.org","@type":"Event","description":"#{String.replace(event.description, a, b)}","endDate":"#{DateTime.to_iso8601(event.ends_on)}","eventStatus":"https://schema.org/EventScheduled","image":["#{event.picture.file.url}"],"location":{"@type":"Place","address":{"@type":"PostalAddress","addressCountry":"My Country","addressLocality":"My Locality","addressRegion":"My Region","postalCode":"My Postal Code","streetAddress":"My Street Address"},"name":"#{event.physical_address.description}"},"name":"#{event.title}","organizer":{"@type":"Person","name":"#{event.organizer_actor.preferred_username}"},"performer":{"@type":"Person","name":"#{event.organizer_actor.preferred_username}"},"startDate":"#{DateTime.to_iso8601(event.begins_on)}"}</script>
|
|> hd
|
||||||
""")
|
|
||||||
|
|
||||||
assert event
|
assert event.url ==
|
||||||
|> Map.put(:picture, nil)
|
document
|
||||||
|> Metadata.build_tags()
|
|> Floki.find("meta[property=\"og:url\"]")
|
||||||
|> Metadata.Utils.stringify_tags() ==
|
|> Floki.attribute("content")
|
||||||
String.trim("""
|
|> hd
|
||||||
<title>#{event.title} - Mobilizon</title><meta content="#{event.description}" name="description"><meta content="#{event.title}" property="og:title"><meta content="#{event.url}" property="og:url"><meta content="#{event.description}" property="og:description"><meta content="website" property="og:type"><link href="#{event.url}" rel="canonical"><meta content="summary_large_image" property="twitter:card"><script type="application/ld+json">{"@context":"https://schema.org","@type":"Event","description":"#{String.replace(event.description, a, b)}","endDate":"#{DateTime.to_iso8601(event.ends_on)}","eventStatus":"https://schema.org/EventScheduled","image":["#{"#{Endpoint.url()}/img/mobilizon_default_card.png"}"],"location":{"@type":"Place","address":{"@type":"PostalAddress","addressCountry":"My Country","addressLocality":"My Locality","addressRegion":"My Region","postalCode":"My Postal Code","streetAddress":"My Street Address"},"name":"#{event.physical_address.description}"},"name":"#{event.title}","organizer":{"@type":"Person","name":"#{event.organizer_actor.preferred_username}"},"performer":{"@type":"Person","name":"#{event.organizer_actor.preferred_username}"},"startDate":"#{DateTime.to_iso8601(event.begins_on)}"}</script>
|
|
||||||
""")
|
assert document
|
||||||
|
|> Floki.find("meta[property=\"og:description\"]")
|
||||||
|
|> Floki.attribute("content")
|
||||||
|
|> hd =~ @truncated_description
|
||||||
|
|
||||||
|
assert "website" ==
|
||||||
|
document
|
||||||
|
|> Floki.find("meta[property=\"og:type\"]")
|
||||||
|
|> Floki.attribute("content")
|
||||||
|
|> hd
|
||||||
|
|
||||||
|
assert event.url ==
|
||||||
|
document
|
||||||
|
|> Floki.find("link[rel=\"canonical\"]")
|
||||||
|
|> Floki.attribute("href")
|
||||||
|
|> hd
|
||||||
|
|
||||||
|
assert event.picture.file.url ==
|
||||||
|
document
|
||||||
|
|> Floki.find("meta[property=\"og:image\"]")
|
||||||
|
|> Floki.attribute("content")
|
||||||
|
|> hd
|
||||||
|
|
||||||
|
assert "summary_large_image" ==
|
||||||
|
document
|
||||||
|
|> Floki.find("meta[property=\"twitter:card\"]")
|
||||||
|
|> Floki.attribute("content")
|
||||||
|
|> hd
|
||||||
|
|
||||||
|
assert "event.json" |> ObjectView.render(%{event: event}) |> Jason.encode!() ==
|
||||||
|
document
|
||||||
|
|> Floki.find("script[type=\"application/ld+json\"]")
|
||||||
|
|> Floki.text(js: true)
|
||||||
|
|
||||||
|
tags_output =
|
||||||
|
event
|
||||||
|
|> Map.put(:picture, nil)
|
||||||
|
|> Metadata.build_tags()
|
||||||
|
|> Metadata.Utils.stringify_tags()
|
||||||
|
|
||||||
|
{:ok, document} = Floki.parse_fragment(tags_output)
|
||||||
|
|
||||||
|
assert [] == Floki.find(document, "meta[property=\"og:image\"]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user