commit
252b2794a4
18 changed files with 458 additions and 0 deletions
78
docs/_entities/event.md
Normal file
78
docs/_entities/event.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
title: Event
|
||||
---
|
||||
|
||||
This entity represents an event.
|
||||
|
||||
See also: [EventParticipation][event_participation]
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type (Length) | Description |
|
||||
| --------- | ---------------------------- | --------------------------------------------- |
|
||||
| `author` | [diaspora\* ID][diaspora-id] | The diaspora\* ID of the author of the event. |
|
||||
| `guid` | [GUID][guid] | The GUID of the event. |
|
||||
| `summary` | [String][string] (255) | The summary of the event. |
|
||||
| `start` | [Timestamp][timestamp] | The start time of the event (in UTC). |
|
||||
|
||||
## Optional Properties
|
||||
|
||||
| Property | Type (Length) | Description |
|
||||
| ------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `end` | [Timestamp][timestamp] | The end time of the event (in UTC). If missing it is an open-end or a single `all_day` event. |
|
||||
| `all_day` | [Boolean][boolean] | `true` if it is an all day event. Time/timezone is ignored. `false` by default. |
|
||||
| `timezone` | [Timezone][timezone] | If the event is fixed to a specific timezone, this can be set. The `start`/`end` timestamps are then displayed in this timezone. This is useful for local events. If missing or empty the timestamps are displayed in the timezone of the user. |
|
||||
| `description` | [Markdown][markdown] (65535) | Description of the event. |
|
||||
| `location` | [Location][location] | Location of the event. |
|
||||
|
||||
## Examples
|
||||
|
||||
### With start, end and timezone
|
||||
|
||||
~~~xml
|
||||
<event>
|
||||
<author>alice@example.org</author>
|
||||
<guid>bb8371f0b1c901342ebd55853a9b5d75</guid>
|
||||
<summary>Cool event</summary>
|
||||
<start>2016-12-27T12:00:00Z</start>
|
||||
<end>2016-12-27T13:00:00Z</end>
|
||||
<all_day>false</all_day>
|
||||
<timezone>Europe/Berlin</timezone>
|
||||
<description>You need to see this!</description>
|
||||
<location>
|
||||
<address>Vienna, Austria</address>
|
||||
<lat>48.208174</lat>
|
||||
<lng>16.373819</lng>
|
||||
</location>
|
||||
</event>
|
||||
~~~
|
||||
|
||||
### All day event
|
||||
|
||||
~~~xml
|
||||
<event>
|
||||
<author>alice@example.org</author>
|
||||
<guid>bb8371f0b1c901342ebd55853a9b5d75</guid>
|
||||
<summary>Cool event</summary>
|
||||
<start>2016-12-27T00:00:00Z</start>
|
||||
<end/>
|
||||
<all_day>true</all_day>
|
||||
<timezone/>
|
||||
<description>You need to see this!</description>
|
||||
<location>
|
||||
<address>Vienna, Austria</address>
|
||||
<lat>48.208174</lat>
|
||||
<lng>16.373819</lng>
|
||||
</location>
|
||||
</event>
|
||||
~~~
|
||||
|
||||
[event_participation]: {{ site.baseurl }}/entities/event_participation.html
|
||||
[diaspora-id]: {{ site.baseurl }}/federation/types.html#diaspora-id
|
||||
[guid]: {{ site.baseurl }}/federation/types.html#guid
|
||||
[string]: {{ site.baseurl }}/federation/types.html#string
|
||||
[timestamp]: {{ site.baseurl }}/federation/types.html#timestamp
|
||||
[markdown]: {{ site.baseurl }}/federation/types.html#markdown
|
||||
[boolean]: {{ site.baseurl }}/federation/types.html#boolean
|
||||
[timezone]: {{ site.baseurl }}/federation/types.html#timezone
|
||||
[location]: {{ site.baseurl }}/entities/location.html
|
||||
54
docs/_entities/event_participation.md
Normal file
54
docs/_entities/event_participation.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: EventParticipation
|
||||
---
|
||||
|
||||
This entity represents a participation in an [Event][event].
|
||||
|
||||
See also: [Relayable][relayable]
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `author` | [diaspora\* ID][diaspora-id] | The diaspora\* ID of the author of the event participation. |
|
||||
| `guid` | [GUID][guid] | The GUID of the event participation. |
|
||||
| `parent_guid` | [GUID][guid] | The GUID of the [Event][event]. |
|
||||
| `status` | [String][string] | The participation status, lowercase string as defined in [RFC 5545, Section 3.2.12][status] (`accepted`, `declined` or `tentative`). |
|
||||
| `author_signature` | [Signature][signature] | The signature from the author of the event participation. |
|
||||
| `parent_author_signature` | [Signature][signature] | The signature from the author of the [Event][event]. |
|
||||
|
||||
## Examples
|
||||
|
||||
### From author
|
||||
|
||||
~~~xml
|
||||
<event_participation>
|
||||
<author>alice@example.org</author>
|
||||
<guid>92f26ff0b1cb01342ebd55853a9b5d75</guid>
|
||||
<parent_guid>bb8371f0b1c901342ebd55853a9b5d75</parent_guid>
|
||||
<status>accepted</status>
|
||||
<author_signature>dT6KbT7kp0bE+s3//ZErxO1wvVIqtD0lY67i81+dO43B4D2m5kjCdzW240eWt/jZmcHIsdxXf4WHNdrb6ZDnamA8I1FUVnLjHA9xexBITQsSLXrcV88UdammSmmOxl1Ac4VUXqFpdavm6a7/MwOJ7+JHP8TbUO9siN+hMfgUbtY=</author_signature>
|
||||
<parent_author_signature/>
|
||||
</event_participation>
|
||||
~~~
|
||||
|
||||
### From parent author
|
||||
|
||||
~~~xml
|
||||
<event_participation>
|
||||
<author>alice@example.org</author>
|
||||
<guid>92f26ff0b1cb01342ebd55853a9b5d75</guid>
|
||||
<parent_guid>bb8371f0b1c901342ebd55853a9b5d75</parent_guid>
|
||||
<status>accepted</status>
|
||||
<author_signature>dT6KbT7kp0bE+s3//ZErxO1wvVIqtD0lY67i81+dO43B4D2m5kjCdzW240eWt/jZmcHIsdxXf4WHNdrb6ZDnamA8I1FUVnLjHA9xexBITQsSLXrcV88UdammSmmOxl1Ac4VUXqFpdavm6a7/MwOJ7+JHP8TbUO9siN+hMfgUbtY=</author_signature>
|
||||
<parent_author_signature>gWasNPpSnMcKBIMWyzfoVO6sr8eRYkhUqy3PIkkh53n/ki+DM9mnh3ayotI0+6un9aq1N3XkS7Vn05ZD3+nHVby6i21XkYgPnbD8pWYuBBj7VGPyahT70BUs/vSvY8KX8V3wYfsPsaiAgJsAFg2UHYdY3r4/oWdIIbBZc21O3zk=</parent_author_signature>
|
||||
</event_participation>
|
||||
~~~
|
||||
|
||||
[diaspora-id]: {{ site.baseurl }}/federation/types.html#diaspora-id
|
||||
[guid]: {{ site.baseurl }}/federation/types.html#guid
|
||||
[string]: {{ site.baseurl }}/federation/types.html#string
|
||||
[status]: https://tools.ietf.org/html/rfc5545#section-3.2.12
|
||||
[signature]: {{ site.baseurl }}/federation/types.html#signature
|
||||
[event]: {{ site.baseurl }}/entities/event.html
|
||||
[relayable]: {{ site.baseurl }}/federation/relayable.html
|
||||
|
|
@ -22,6 +22,7 @@ This entity represents a reshare of a status message. It inherits from [Post][po
|
|||
| `location` | [Location][location] | The Location information of the status message. |
|
||||
| `photo` | [Photo][photo]s | The attached Photos of the status message, the `status_message_guid` and the `author` need to match the status message. |
|
||||
| `poll` | [Poll][poll] | The attached Poll of the status message. |
|
||||
| `event` | [Event][event] | The attached Event of the status message. |
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
@ -183,3 +184,4 @@ This entity represents a reshare of a status message. It inherits from [Post][po
|
|||
[location]: {{ site.baseurl }}/entities/location.html
|
||||
[photo]: {{ site.baseurl }}/entities/photo.html
|
||||
[poll]: {{ site.baseurl }}/entities/poll.html
|
||||
[event]: {{ site.baseurl }}/entities/event.html
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ An [ISO 8601][iso8601] date.
|
|||
|
||||
Example: `2016-02-19`
|
||||
|
||||
## Timezone
|
||||
|
||||
A timezone in the form `Area/Location` as used in the [Time Zone Database][tz].
|
||||
|
||||
Example: `Europe/Berlin`
|
||||
|
||||
## Signature
|
||||
|
||||
Signature with the private RSA key using the RSA-SHA256 algorithm and base64-encoded.
|
||||
|
|
@ -98,3 +104,4 @@ Example:
|
|||
[entities]: {{ site.baseurl }}/entities/
|
||||
[commonmark]: http://spec.commonmark.org/
|
||||
[iso8601]: https://www.w3.org/TR/NOTE-datetime
|
||||
[tz]: https://www.iana.org/time-zones
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ require "diaspora_federation/entities/poll"
|
|||
require "diaspora_federation/entities/poll_participation"
|
||||
|
||||
require "diaspora_federation/entities/location"
|
||||
|
||||
require "diaspora_federation/entities/event"
|
||||
require "diaspora_federation/entities/event_participation"
|
||||
|
||||
require "diaspora_federation/entities/photo"
|
||||
require "diaspora_federation/entities/status_message"
|
||||
require "diaspora_federation/entities/reshare"
|
||||
|
|
|
|||
55
lib/diaspora_federation/entities/event.rb
Normal file
55
lib/diaspora_federation/entities/event.rb
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
module DiasporaFederation
|
||||
module Entities
|
||||
# This entity represents an event and it is federated as a part of a status message.
|
||||
#
|
||||
# @see Validators::EventValidator
|
||||
class Event < Entity
|
||||
# @!attribute [r] author
|
||||
# The diaspora* ID of the person who created the event
|
||||
# @see Person#author
|
||||
# @return [String] author diaspora* ID
|
||||
property :author, :string
|
||||
|
||||
# @!attribute [r] guid
|
||||
# A random string of at least 16 chars
|
||||
# @see Validation::Rule::Guid
|
||||
# @return [String] guid
|
||||
property :guid, :string
|
||||
|
||||
# @!attribute [r] summary
|
||||
# The summary of the event
|
||||
# @return [String] event summary
|
||||
property :summary, :string
|
||||
|
||||
# @!attribute [r] description
|
||||
# Description of the event
|
||||
# @return [String] event description
|
||||
property :description, :string, default: nil
|
||||
|
||||
# @!attribute [r] start
|
||||
# The start time of the event
|
||||
# @return [String] event start
|
||||
property :start, :timestamp
|
||||
|
||||
# @!attribute [r] end
|
||||
# The end time of the event
|
||||
# @return [String] event end
|
||||
property :end, :timestamp, default: nil
|
||||
|
||||
# @!attribute [r] all_day
|
||||
# Points if the event is an all day event
|
||||
# @return [Boolean] is it an all day event
|
||||
property :all_day, :boolean, default: false
|
||||
|
||||
# @!attribute [r] timezone
|
||||
# Timezone to which the event is fixed to
|
||||
# @return [String] timezone
|
||||
property :timezone, :string, default: nil
|
||||
|
||||
# @!attribute [r] location
|
||||
# Location of the event
|
||||
# @return [Entities::Location] location
|
||||
entity :location, Entities::Location, default: nil
|
||||
end
|
||||
end
|
||||
end
|
||||
27
lib/diaspora_federation/entities/event_participation.rb
Normal file
27
lib/diaspora_federation/entities/event_participation.rb
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
module DiasporaFederation
|
||||
module Entities
|
||||
# This entity represents a participation in an event, i.e. it is issued when a user responds to en event.
|
||||
#
|
||||
# @see Validators::EventParticipationValidator
|
||||
class EventParticipation < Entity
|
||||
# Old signature order
|
||||
# @deprecated
|
||||
LEGACY_SIGNATURE_ORDER = %i(author guid parent_guid status).freeze
|
||||
|
||||
# The {EventParticipation} parent is an {Event}
|
||||
PARENT_TYPE = "Event".freeze
|
||||
|
||||
include Relayable
|
||||
|
||||
# Redefine the author property without +diaspora_handle+ +xml_name+
|
||||
# @deprecated Can be removed after XMLs are generated with new names
|
||||
property :author, :string
|
||||
|
||||
# @!attribute [r] status
|
||||
# The participation status of the user
|
||||
# "accepted", "declined" or "tentative"
|
||||
# @return [String] event participation status
|
||||
property :status, :string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -26,6 +26,11 @@ module DiasporaFederation
|
|||
# @return [Entities::Poll] poll
|
||||
entity :poll, Entities::Poll, default: nil
|
||||
|
||||
# @!attribute [r] event
|
||||
# Optional event attached to the status message
|
||||
# @return [Entities::Event] event
|
||||
entity :event, Entities::Event, default: nil
|
||||
|
||||
# @!attribute [r] public
|
||||
# Shows whether the status message is visible to everyone or only to some aspects
|
||||
# @return [Boolean] is it public
|
||||
|
|
|
|||
|
|
@ -200,6 +200,24 @@ module DiasporaFederation
|
|||
poll_answer_guid { generate(:guid) }
|
||||
end
|
||||
|
||||
factory :event_entity, class: DiasporaFederation::Entities::Event do
|
||||
author { generate(:diaspora_id) }
|
||||
guid
|
||||
summary "Cool event"
|
||||
description "You need to see this!"
|
||||
start { Time.now.utc.change(min: 0).change(sec: 0).change(usec: 0) - 1.hour }
|
||||
add_attribute(:end) { Time.now.utc.change(min: 0).change(sec: 0).change(usec: 0) + 1.hour }
|
||||
all_day false
|
||||
timezone "Europe/Berlin"
|
||||
end
|
||||
|
||||
factory :event_participation_entity,
|
||||
class: DiasporaFederation::Entities::EventParticipation, parent: :relayable_entity do
|
||||
author { generate(:diaspora_id) }
|
||||
guid
|
||||
status "accepted"
|
||||
end
|
||||
|
||||
factory :related_entity, class: DiasporaFederation::Entities::RelatedEntity do
|
||||
author { generate(:diaspora_id) }
|
||||
local true
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ require "diaspora_federation/validators/account_deletion_validator"
|
|||
require "diaspora_federation/validators/comment_validator"
|
||||
require "diaspora_federation/validators/contact_validator"
|
||||
require "diaspora_federation/validators/conversation_validator"
|
||||
require "diaspora_federation/validators/event_participation_validator"
|
||||
require "diaspora_federation/validators/event_validator"
|
||||
require "diaspora_federation/validators/h_card_validator"
|
||||
require "diaspora_federation/validators/like_validator"
|
||||
require "diaspora_federation/validators/location_validator"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
module DiasporaFederation
|
||||
module Validators
|
||||
# This validates a {Entities::EventParticipation}.
|
||||
class EventParticipationValidator < Validation::Validator
|
||||
include Validation
|
||||
|
||||
include RelayableValidator
|
||||
|
||||
rule :status, regular_expression: {regex: /\A(accepted|declined|tentative)\z/}
|
||||
end
|
||||
end
|
||||
end
|
||||
21
lib/diaspora_federation/validators/event_validator.rb
Normal file
21
lib/diaspora_federation/validators/event_validator.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
module DiasporaFederation
|
||||
module Validators
|
||||
# This validates a {Entities::Event}.
|
||||
class EventValidator < Validation::Validator
|
||||
include Validation
|
||||
|
||||
rule :author, %i(not_empty diaspora_id)
|
||||
|
||||
rule :guid, :guid
|
||||
|
||||
rule :summary, [:not_empty, length: {maximum: 255}]
|
||||
rule :description, length: {maximum: 65_535}
|
||||
|
||||
rule :start, :not_nil
|
||||
|
||||
rule :all_day, :boolean
|
||||
|
||||
rule :timezone, regular_expression: {regex: %r{\A[A-Za-z_-]{,14}(/[A-Za-z_-]{,14}){1,2}\z}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -39,6 +39,12 @@ FactoryGirl.define do
|
|||
after(:create, &:save)
|
||||
end
|
||||
|
||||
factory :event, class: Entity do
|
||||
entity_type "Event"
|
||||
author { FactoryGirl.build(:person) }
|
||||
after(:create, &:save)
|
||||
end
|
||||
|
||||
factory :conversation, class: Entity do
|
||||
entity_type "Conversation"
|
||||
author { FactoryGirl.build(:person) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
module DiasporaFederation
|
||||
describe Entities::EventParticipation do
|
||||
let(:parent) { FactoryGirl.create(:event, author: bob) }
|
||||
let(:parent_entity) { FactoryGirl.build(:related_entity, author: bob.diaspora_id) }
|
||||
let(:data) {
|
||||
add_signatures(
|
||||
FactoryGirl.build(
|
||||
:event_participation_entity,
|
||||
author: alice.diaspora_id,
|
||||
parent_guid: parent.guid,
|
||||
parent: parent_entity
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let(:xml) { <<-XML }
|
||||
<event_participation>
|
||||
<author>#{data[:author]}</author>
|
||||
<guid>#{data[:guid]}</guid>
|
||||
<parent_guid>#{parent.guid}</parent_guid>
|
||||
<status>#{data[:status]}</status>
|
||||
<author_signature>#{data[:author_signature]}</author_signature>
|
||||
<parent_author_signature>#{data[:parent_author_signature]}</parent_author_signature>
|
||||
</event_participation>
|
||||
XML
|
||||
|
||||
let(:string) { "EventParticipation:#{data[:guid]}:#{parent.guid}" }
|
||||
|
||||
it_behaves_like "an Entity subclass"
|
||||
|
||||
it_behaves_like "an XML Entity"
|
||||
|
||||
it_behaves_like "a relayable Entity"
|
||||
end
|
||||
end
|
||||
52
spec/lib/diaspora_federation/entities/event_spec.rb
Normal file
52
spec/lib/diaspora_federation/entities/event_spec.rb
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
module DiasporaFederation
|
||||
describe Entities::Event do
|
||||
let(:location) { FactoryGirl.build(:location_entity) }
|
||||
let(:data) {
|
||||
FactoryGirl.attributes_for(:event_entity).merge(author: alice.diaspora_id, location: location)
|
||||
}
|
||||
|
||||
let(:xml) { <<-XML }
|
||||
<event>
|
||||
<author>#{data[:author]}</author>
|
||||
<guid>#{data[:guid]}</guid>
|
||||
<summary>#{data[:summary]}</summary>
|
||||
<description>#{data[:description]}</description>
|
||||
<start>#{data[:start].utc.iso8601}</start>
|
||||
<end>#{data[:end].utc.iso8601}</end>
|
||||
<all_day>#{data[:all_day]}</all_day>
|
||||
<timezone>#{data[:timezone]}</timezone>
|
||||
<location>
|
||||
<address>#{location.address}</address>
|
||||
<lat>#{location.lat}</lat>
|
||||
<lng>#{location.lng}</lng>
|
||||
</location>
|
||||
</event>
|
||||
XML
|
||||
|
||||
let(:string) { "Event:#{data[:guid]}" }
|
||||
|
||||
it_behaves_like "an Entity subclass"
|
||||
|
||||
it_behaves_like "an XML Entity"
|
||||
|
||||
context "default values" do
|
||||
it "uses default values" do
|
||||
minimal_xml = <<-XML
|
||||
<event>
|
||||
<author>#{data[:author]}</author>
|
||||
<guid>#{data[:guid]}</guid>
|
||||
<summary>#{data[:summary]}</summary>
|
||||
<start>#{data[:start].utc.iso8601}</start>
|
||||
</event>
|
||||
XML
|
||||
|
||||
parsed_instance = DiasporaFederation::Salmon::XmlPayload.unpack(Nokogiri::XML::Document.parse(minimal_xml).root)
|
||||
expect(parsed_instance.end).to be_nil
|
||||
expect(parsed_instance.all_day).to be_falsey
|
||||
expect(parsed_instance.timezone).to be_nil
|
||||
expect(parsed_instance.description).to be_nil
|
||||
expect(parsed_instance.location).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -9,6 +9,7 @@ module DiasporaFederation
|
|||
photos: [photo1, photo2],
|
||||
location: location,
|
||||
poll: nil,
|
||||
event: nil,
|
||||
provider_display_name: "something"
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
module DiasporaFederation
|
||||
describe Validators::EventParticipationValidator do
|
||||
let(:entity) { :event_participation_entity }
|
||||
|
||||
it_behaves_like "a common validator"
|
||||
|
||||
it_behaves_like "a relayable validator"
|
||||
|
||||
describe "#status" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :status }
|
||||
let(:wrong_values) { ["", "yes", "foobar"] }
|
||||
let(:correct_values) { %w(accepted declined tentative) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
module DiasporaFederation
|
||||
describe Validators::EventValidator do
|
||||
let(:entity) { :event_entity }
|
||||
|
||||
it_behaves_like "a common validator"
|
||||
|
||||
it_behaves_like "a diaspora* ID validator" do
|
||||
let(:property) { :author }
|
||||
let(:mandatory) { true }
|
||||
end
|
||||
|
||||
it_behaves_like "a guid validator" do
|
||||
let(:property) { :guid }
|
||||
end
|
||||
|
||||
describe "#summary" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :summary }
|
||||
let(:wrong_values) { ["a" * 256, nil, ""] }
|
||||
let(:correct_values) { ["a" * 255] }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#description" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :description }
|
||||
let(:wrong_values) { ["a" * 65_536] }
|
||||
let(:correct_values) { ["a" * 65_535, nil, ""] }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#start" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :start }
|
||||
let(:wrong_values) { [nil] }
|
||||
let(:correct_values) { [Time.now.utc] }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#end" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :end }
|
||||
let(:wrong_values) { [] }
|
||||
let(:correct_values) { [nil, Time.now.utc] }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#all_day" do
|
||||
it_behaves_like "a boolean validator" do
|
||||
let(:property) { :all_day }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#timezone" do
|
||||
it_behaves_like "a property with a value validation/restriction" do
|
||||
let(:property) { :timezone }
|
||||
let(:wrong_values) { ["foobar"] }
|
||||
let(:correct_values) { [nil, "Europe/Berlin", "America/Argentina/ComodRivadavia"] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue