Add "embed" entity

Fixes #93
This commit is contained in:
Benjamin Neff 2018-04-09 02:19:07 +02:00
parent cfbb89da6e
commit e0da26c7ee
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
12 changed files with 200 additions and 1 deletions

View file

@ -30,6 +30,7 @@ require "diaspora_federation/entities/poll_answer"
require "diaspora_federation/entities/poll"
require "diaspora_federation/entities/poll_participation"
require "diaspora_federation/entities/embed"
require "diaspora_federation/entities/location"
require "diaspora_federation/entities/event"

View file

@ -0,0 +1,44 @@
module DiasporaFederation
module Entities
# This entity is used to specify embed information about an URL that should be embedded.
#
# @see Validators::EmbedValidator
class Embed < Entity
# @!attribute [r] url
# URL that should be embedded.
# @return [String] url
property :url, :string, optional: true
# @!attribute [r] title
# The title of the embedded URL.
# @return [String] title
property :title, :string, optional: true
# @!attribute [r] description
# The description of the embedded URL.
# @return [String] description
property :description, :string, optional: true
# @!attribute [r] image
# The image of the embedded URL.
# @return [String] image
property :image, :string, optional: true
# @!attribute [r] nothing
# True, if nothing should be embedded.
# @return [String] nothing
property :nothing, :boolean, optional: true
# @return [String] string representation of this object
def to_s
"Embed#{":#{url}" if url}"
end
def validate
super
raise ValidationError, "Either 'url' must be set or 'nothing' must be 'true'" unless nothing ^ url
end
end
end
end

View file

@ -36,6 +36,11 @@ module DiasporaFederation
# @return [Entities::Event] event
entity :event, Entities::Event, optional: true
# @!attribute [r] embed
# Optional embed information of an URL that should be embedded in the status message
# @return [Entities::Embed] embed
entity :embed, Entities::Embed, optional: true
private
def validate

View file

@ -10,6 +10,7 @@
{"$ref": "#/definitions/reshare"},
{"$ref": "#/definitions/profile"},
{"$ref": "#/definitions/location"},
{"$ref": "#/definitions/embed"},
{"$ref": "#/definitions/photo"},
{"$ref": "#/definitions/poll"},
{"$ref": "#/definitions/poll_answer"}
@ -373,6 +374,26 @@
]
}
}
},
"embed": {
"type": "object",
"properties": {
"entity_type": {
"type": "string",
"pattern": "^embed$"
},
"entity_data": {
"type": "object",
"properties": {
"url": { "type": ["string", "null"] },
"title": { "type": ["string", "null"] },
"description": { "type": ["string", "null"] },
"image": { "type": ["string", "null"] },
"nothing": { "type": "boolean" }
}
}
}
}
}
}

View file

@ -207,6 +207,14 @@ module DiasporaFederation
edited_at { Time.now.utc }
end
Fabricator(:embed_entity, class_name: DiasporaFederation::Entities::Embed) do
url "https://example.org/"
title "Example Website"
description "This is an example!"
image "https://example.org/example.png"
nothing nil
end
Fabricator(:related_entity, class_name: DiasporaFederation::Entities::RelatedEntity) do
author { Fabricate.sequence(:diaspora_id) }
local true

View file

@ -46,6 +46,7 @@ require "diaspora_federation/validators/account_migration_validator"
require "diaspora_federation/validators/comment_validator"
require "diaspora_federation/validators/contact_validator"
require "diaspora_federation/validators/conversation_validator"
require "diaspora_federation/validators/embed_validator"
require "diaspora_federation/validators/event_participation_validator"
require "diaspora_federation/validators/event_validator"
require "diaspora_federation/validators/h_card_validator"

View file

@ -0,0 +1,13 @@
module DiasporaFederation
module Validators
# This validates a {Entities::Embed}.
class EmbedValidator < OptionalAwareValidator
include Validation
rule :url, :URI
rule :title, length: {maximum: 255}
rule :description, length: {maximum: 65_535}
rule :image, URI: %i[host path]
end
end
end

View file

@ -0,0 +1,56 @@
module DiasporaFederation
describe Entities::Embed do
let(:data) { Fabricate.attributes_for(:embed_entity) }
let(:xml) { <<-XML }
<embed>
<url>#{data[:url]}</url>
<title>#{data[:title]}</title>
<description>#{data[:description]}</description>
<image>#{data[:image]}</image>
</embed>
XML
let(:json) { <<-JSON }
{
"entity_type": "embed",
"entity_data": {
"url": "#{data[:url]}",
"title": "#{data[:title]}",
"description": "#{data[:description]}",
"image": "#{data[:image]}"
}
}
JSON
let(:string) { "Embed:#{data[:url]}" }
it_behaves_like "an Entity subclass"
it_behaves_like "an XML Entity"
it_behaves_like "a JSON Entity"
describe "#validate" do
it "allows 'url' to be set if 'nothing' is not true" do
expect { Entities::Embed.new(data) }.not_to raise_error
end
it "allows 'url' to be missing if 'nothing' is true" do
expect { Entities::Embed.new(nothing: true) }.not_to raise_error
end
it "doesn't allow 'url' to be set if 'nothing' is true" do
expect {
Entities::Embed.new(data.merge(nothing: true))
}.to raise_error Entity::ValidationError, "Either 'url' must be set or 'nothing' must be 'true'"
end
it "doesn't allow 'url' to be missing if 'nothing' is not true" do
expect {
Entities::Embed.new({})
}.to raise_error Entity::ValidationError, "Either 'url' must be set or 'nothing' must be 'true'"
end
end
end
end

View file

@ -10,6 +10,7 @@ module DiasporaFederation
location: location,
poll: nil,
event: nil,
embed: nil,
provider_display_name: "something"
)
}
@ -137,6 +138,8 @@ XML
expect(parsed_instance.photos).to eq([])
expect(parsed_instance.location).to be_nil
expect(parsed_instance.poll).to be_nil
expect(parsed_instance.event).to be_nil
expect(parsed_instance.embed).to be_nil
expect(parsed_instance.public).to be_falsey
expect(parsed_instance.provider_display_name).to be_nil
end

View file

@ -0,0 +1,40 @@
module DiasporaFederation
describe Validators::EmbedValidator do
let(:entity) { :embed_entity }
it_behaves_like "a common validator"
describe "#url" do
it_behaves_like "a property with a value validation/restriction" do
let(:property) { :url }
let(:wrong_values) { %w[https://asdf$%.com example.com] }
let(:correct_values) { [nil, "https://example.org", "https://example.org/index.html"] }
end
end
describe "#title" do
it_behaves_like "a length validator" do
let(:property) { :title }
let(:length) { 255 }
end
end
describe "#description" do
it_behaves_like "a length validator" do
let(:property) { :description }
let(:length) { 65_535 }
end
end
describe "#image" do
it_behaves_like "a property with a value validation/restriction" do
let(:property) { :image }
let(:wrong_values) { %w[https://asdf$%.com example.com] }
let(:correct_values) { [nil] }
end
it_behaves_like "a url path validator" do
let(:property) { :image }
end
end
end
end

View file

@ -27,7 +27,7 @@ module DiasporaFederation
describe "##{prop}" do
it_behaves_like "a property with a value validation/restriction" do
let(:property) { prop }
let(:wrong_values) { %w[https://asdf$.com example.com] }
let(:wrong_values) { %w[https://asdf$%.com example.com] }
let(:correct_values) { [nil] }
end

View file

@ -277,6 +277,13 @@ shared_examples "a url validator without path" do
end
shared_examples "a url path validator" do
it "validates url with a path" do
validator = described_class.new(entity_stub(entity, property => "https://example.com/some/path"))
expect(validator).to be_valid
expect(validator.errors).to be_empty
end
it "fails for url with special chars" do
validator = described_class.new(entity_stub(entity, property => "https://asdf$%.com/some/path"))