spontaneous 0.2.0.beta9 → 0.2.0.beta10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -0
- data/LICENSE +18 -17
- data/Rakefile +1 -1
- data/application/css/core.css.scss +1 -1
- data/application/css/dialogue.css.scss +8 -20
- data/application/js/preview.js +28 -7
- data/application/js/publish.js +15 -4
- data/application/js/top_bar.js +0 -16
- data/application/js/views/piece_view.js +1 -1
- data/lib/spontaneous/asset/environment.rb +16 -1
- data/lib/spontaneous/box.rb +68 -0
- data/lib/spontaneous/capistrano/deploy.rb +7 -4
- data/lib/spontaneous/capistrano/sync.rb +2 -2
- data/lib/spontaneous/cli/init.rb +70 -19
- data/lib/spontaneous/cli/init/db.rb +34 -55
- data/lib/spontaneous/cli/init/mysql.rb +5 -5
- data/lib/spontaneous/cli/init/postgresql.rb +8 -9
- data/lib/spontaneous/cli/init/sqlite.rb +1 -2
- data/lib/spontaneous/cli/migrate.rb +0 -1
- data/lib/spontaneous/cli/site.rb +4 -0
- data/lib/spontaneous/collections/entry_set.rb +11 -0
- data/lib/spontaneous/data_mapper/content_model.rb +2 -0
- data/lib/spontaneous/data_mapper/content_model/serialization.rb +2 -2
- data/lib/spontaneous/extensions/array.rb +12 -2
- data/lib/spontaneous/field/base.rb +10 -0
- data/lib/spontaneous/field/file.rb +32 -2
- data/lib/spontaneous/field/image.rb +24 -2
- data/lib/spontaneous/field/select.rb +8 -0
- data/lib/spontaneous/field/webvideo.rb +8 -0
- data/lib/spontaneous/generators/site/config/initializers/fields.rb +55 -0
- data/lib/spontaneous/json.rb +3 -2
- data/lib/spontaneous/logger.rb +2 -2
- data/lib/spontaneous/media/file.rb +3 -3
- data/lib/spontaneous/media/image/attributes.rb +72 -6
- data/lib/spontaneous/media/image/renderable.rb +53 -20
- data/lib/spontaneous/media/store.rb +3 -3
- data/lib/spontaneous/media/store/backend.rb +16 -0
- data/lib/spontaneous/media/store/cloud.rb +52 -12
- data/lib/spontaneous/media/store/local.rb +6 -3
- data/lib/spontaneous/model.rb +3 -0
- data/lib/spontaneous/model/core/entries.rb +34 -13
- data/lib/spontaneous/model/core/entry.rb +3 -1
- data/lib/spontaneous/model/page/controllers.rb +1 -2
- data/lib/spontaneous/model/page/paths.rb +18 -7
- data/lib/spontaneous/output/context.rb +0 -8
- data/lib/spontaneous/output/template/renderer.rb +2 -0
- data/lib/spontaneous/plugins/application/state.rb +0 -4
- data/lib/spontaneous/prototypes/field_prototype.rb +4 -0
- data/lib/spontaneous/publishing/immediate.rb +0 -5
- data/lib/spontaneous/publishing/progress.rb +2 -2
- data/lib/spontaneous/publishing/rerender.rb +1 -4
- data/lib/spontaneous/publishing/simultaneous.rb +19 -17
- data/lib/spontaneous/publishing/steps.rb +12 -3
- data/lib/spontaneous/rack.rb +2 -0
- data/lib/spontaneous/rack/asset_server.rb +5 -2
- data/lib/spontaneous/rack/back.rb +9 -1
- data/lib/spontaneous/rack/back/base.rb +1 -0
- data/lib/spontaneous/rack/back/changes.rb +5 -0
- data/lib/spontaneous/rack/back/preview.rb +4 -4
- data/lib/spontaneous/rack/back/private.rb +11 -0
- data/lib/spontaneous/rack/middleware/scope.rb +16 -4
- data/lib/spontaneous/rack/page_controller.rb +2 -2
- data/lib/spontaneous/rack/public.rb +52 -4
- data/lib/spontaneous/sequel.rb +10 -13
- data/lib/spontaneous/site.rb +28 -8
- data/lib/spontaneous/site/publishing.rb +1 -1
- data/lib/spontaneous/site/storage.rb +7 -4
- data/lib/spontaneous/tasks/environment.rake +3 -0
- data/lib/spontaneous/utils/database/postgres_dumper.rb +23 -2
- data/lib/spontaneous/version.rb +1 -1
- data/spontaneous.gemspec +7 -12
- data/test/fixtures/assets/public1/css/data.css.scss +1 -1
- data/test/functional/test_application.rb +15 -0
- data/test/functional/test_cli.rb +109 -3
- data/test/functional/test_front.rb +108 -10
- data/test/test_helper.rb +3 -3
- data/test/unit/fields/test_boolean_fields.rb +80 -0
- data/test/unit/fields/test_date_fields.rb +47 -0
- data/test/unit/fields/test_file_field.rb +210 -0
- data/test/unit/{test_images.rb → fields/test_image_fields.rb} +133 -15
- data/test/unit/fields/test_location_fields.rb +41 -0
- data/test/unit/fields/test_option_fields.rb +61 -0
- data/test/unit/fields/test_tag_list_fields.rb +45 -0
- data/test/unit/fields/test_text_fields.rb +124 -0
- data/test/unit/fields/test_web_video_fields.rb +198 -0
- data/test/unit/test_assets.rb +22 -22
- data/test/unit/test_boxes.rb +34 -13
- data/test/unit/test_changesets.rb +1 -0
- data/test/unit/test_extensions.rb +17 -0
- data/test/unit/test_fields.rb +20 -643
- data/test/unit/test_media.rb +9 -9
- data/test/unit/test_page.rb +47 -0
- data/test/unit/test_publishing_pipeline.rb +2 -2
- data/test/unit/test_serialisation.rb +37 -0
- data/test/unit/test_storage.rb +42 -3
- metadata +37 -17
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../../../test_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
describe "Location fields" do
|
7
|
+
before do
|
8
|
+
@site = setup_site
|
9
|
+
@now = Time.now
|
10
|
+
stub_time(@now)
|
11
|
+
Spontaneous::State.delete
|
12
|
+
@site.background_mode = :immediate
|
13
|
+
@content_class = Class.new(::Piece) do
|
14
|
+
field :location
|
15
|
+
end
|
16
|
+
@content_class.stubs(:name).returns("ContentClass")
|
17
|
+
@instance = @content_class.new
|
18
|
+
@field = @instance.location
|
19
|
+
end
|
20
|
+
|
21
|
+
it "use a standard string editor" do
|
22
|
+
@content_class.fields.location.export(nil)[:type].must_equal "Spontaneous.Field.String"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "successfully geolocate an address" do
|
26
|
+
# TODO: use mocking to avoid an external API request to googles geolocation service
|
27
|
+
@field.value = "Cambridge, England"
|
28
|
+
@field.value(:lat).must_equal 52.2053370
|
29
|
+
@field.value(:lng).must_equal 0.1218170
|
30
|
+
@field.value(:country).must_equal "United Kingdom"
|
31
|
+
@field.value(:formatted_address).must_equal "Cambridge, Cambridge, UK"
|
32
|
+
|
33
|
+
@field.latitude.must_equal 52.2053370
|
34
|
+
@field.longitude.must_equal 0.1218170
|
35
|
+
@field.lat.must_equal 52.2053370
|
36
|
+
@field.lng.must_equal 0.1218170
|
37
|
+
|
38
|
+
@field.country.must_equal "United Kingdom"
|
39
|
+
@field.formatted_address.must_equal "Cambridge, Cambridge, UK"
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../../../test_helper', __FILE__)
|
4
|
+
|
5
|
+
describe "Option fields" do
|
6
|
+
before do
|
7
|
+
@site = setup_site
|
8
|
+
@now = Time.now
|
9
|
+
stub_time(@now)
|
10
|
+
Spontaneous::State.delete
|
11
|
+
@site.background_mode = :immediate
|
12
|
+
@content_class = Class.new(::Piece) do
|
13
|
+
field :options, :select, :options => [
|
14
|
+
["a", "Value A"],
|
15
|
+
["b", "Value B"],
|
16
|
+
["c", "Value C"]
|
17
|
+
]
|
18
|
+
end
|
19
|
+
@content_class.stubs(:name).returns("ContentClass")
|
20
|
+
@instance = @content_class.new
|
21
|
+
@field = @instance.options
|
22
|
+
end
|
23
|
+
|
24
|
+
it "use a specific editor class" do
|
25
|
+
@content_class.fields.options.export(nil)[:type].must_equal "Spontaneous.Field.Select"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "select the options class for fields named options" do
|
29
|
+
@content_class.field :type, :select, :options => [["a", "A"]]
|
30
|
+
assert @content_class.fields.options.instance_class.ancestors.include?(Spontaneous::Field::Select)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "accept a list of strings as options" do
|
34
|
+
@content_class.field :type, :select, :options => ["a", "b"]
|
35
|
+
@instance = @content_class.new
|
36
|
+
@instance.type.option_list.must_equal [["a", "a"], ["b", "b"]]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "accept a json string as a value and convert it properly" do
|
40
|
+
@field.value = %(["a", "Value A"])
|
41
|
+
@field.value.must_equal "a"
|
42
|
+
@field.value(:label).must_equal "Value A"
|
43
|
+
@field.label.must_equal "Value A"
|
44
|
+
@field.unprocessed_value.must_equal %(["a", "Value A"])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows for the setting of a default value' do
|
48
|
+
@content_class.field :type, :select, :options => [["a", "A Label"], ["b", "B Label"], ["c", "C Label"]], default: "b"
|
49
|
+
@instance = @content_class.new
|
50
|
+
@instance.type.value.must_equal "b"
|
51
|
+
@instance.type.value(:label).must_equal "B Label"
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'exports properly with a null value' do
|
55
|
+
@content_class.field :type, :select, :options => [["a", "A Label"], ["b", "B Label"], ["c", "C Label"]]
|
56
|
+
@instance = @content_class.new
|
57
|
+
e = @instance.fields[:type].export(nil)
|
58
|
+
e[:unprocessed_value].must_equal ""
|
59
|
+
e[:processed_value].must_equal ""
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../../../test_helper', __FILE__)
|
4
|
+
|
5
|
+
describe "Tag list fields" do
|
6
|
+
before do
|
7
|
+
@site = setup_site
|
8
|
+
@now = Time.now
|
9
|
+
stub_time(@now)
|
10
|
+
Spontaneous::State.delete
|
11
|
+
@site.background_mode = :immediate
|
12
|
+
@content_class = Class.new(::Piece)
|
13
|
+
@prototype = @content_class.field :tags
|
14
|
+
@content_class.stubs(:name).returns("ContentClass")
|
15
|
+
@instance = @content_class.create
|
16
|
+
@field = @instance.tags
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has a distinct editor class" # eventually...
|
20
|
+
|
21
|
+
it "adopts any field called 'tags'" do
|
22
|
+
assert @field.is_a?(Spontaneous::Field::Tags), "Field should be an instance of TagsField but instead has the following ancestors #{ @prototype.instance_class.ancestors }"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "defaults to an empty list" do
|
26
|
+
@field.value(:html).must_equal ""
|
27
|
+
@field.value(:tags).must_equal []
|
28
|
+
end
|
29
|
+
|
30
|
+
it "correctly parses strings" do
|
31
|
+
@field.value = 'this that "the other" more'
|
32
|
+
@field.value(:html).must_equal 'this that "the other" more'
|
33
|
+
@field.value(:tags).must_equal ["this", "that", "the other", "more"]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "includes Enumerable" do
|
37
|
+
@field.value = 'this that "the other" more'
|
38
|
+
@field.map(&:upcase).must_equal ["THIS", "THAT", "THE OTHER", "MORE"]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "allows for tags with commas" do
|
42
|
+
@field.value = %(this that "the, other" more)
|
43
|
+
@field.map(&:upcase).must_equal ["THIS", "THAT", "THE, OTHER", "MORE"]
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../../../test_helper', __FILE__)
|
4
|
+
|
5
|
+
describe "Text fields" do
|
6
|
+
before do
|
7
|
+
@site = setup_site
|
8
|
+
@now = Time.now
|
9
|
+
stub_time(@now)
|
10
|
+
Spontaneous::State.delete
|
11
|
+
@site.background_mode = :immediate
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
teardown_site
|
16
|
+
end
|
17
|
+
describe "String fields" do
|
18
|
+
before do
|
19
|
+
@content_class = Class.new(::Piece) do
|
20
|
+
field :title, :string
|
21
|
+
end
|
22
|
+
@instance = @content_class.new
|
23
|
+
@field = @instance.title
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should escape ampersands for the html format" do
|
27
|
+
@field.value = "This & That"
|
28
|
+
@field.value(:html).must_equal "This & That"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "be aliased to the :title type" do
|
32
|
+
@content_class = Class.new(::Piece) do
|
33
|
+
field :title, default: "Right"
|
34
|
+
field :something, :title
|
35
|
+
end
|
36
|
+
instance = @content_class.new
|
37
|
+
assert instance.fields.title.class.ancestors.include?(Spontaneous::Field::String), ":title type should inherit from StringField"
|
38
|
+
instance.title.value.must_equal "Right"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
describe "Markdown fields" do
|
42
|
+
before do
|
43
|
+
class ::MarkdownContent < Piece
|
44
|
+
field :text1, :markdown
|
45
|
+
field :text2, :richtext
|
46
|
+
field :text3, :markup
|
47
|
+
end
|
48
|
+
@instance = MarkdownContent.new
|
49
|
+
end
|
50
|
+
after do
|
51
|
+
Object.send(:remove_const, :MarkdownContent)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "be available as the :markdown type" do
|
55
|
+
assert MarkdownContent.field_prototypes[:text1].field_class < Spontaneous::Field::Markdown
|
56
|
+
end
|
57
|
+
it "be available as the :richtext type" do
|
58
|
+
assert MarkdownContent.field_prototypes[:text2].field_class < Spontaneous::Field::Markdown
|
59
|
+
end
|
60
|
+
it "be available as the :markup type" do
|
61
|
+
assert MarkdownContent.field_prototypes[:text3].field_class < Spontaneous::Field::Markdown
|
62
|
+
end
|
63
|
+
|
64
|
+
it "process input into HTML" do
|
65
|
+
@instance.text1 = "*Hello* **World**"
|
66
|
+
@instance.text1.value.must_equal "<p><em>Hello</em> <strong>World</strong></p>\n"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "use more sensible linebreaks" do
|
70
|
+
@instance.text1 = "With\nLinebreak"
|
71
|
+
@instance.text1.value.must_equal "<p>With<br />\nLinebreak</p>\n"
|
72
|
+
@instance.text2 = "With \nLinebreak"
|
73
|
+
@instance.text2.value.must_equal "<p>With<br />\nLinebreak</p>\n"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "LongString fields" do
|
78
|
+
before do
|
79
|
+
class ::LongStringContent < Piece
|
80
|
+
field :long1, :longstring
|
81
|
+
field :long2, :long_string
|
82
|
+
field :long3, :text
|
83
|
+
end
|
84
|
+
@instance = LongStringContent.new
|
85
|
+
end
|
86
|
+
after do
|
87
|
+
Object.send(:remove_const, :LongStringContent)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "is available as the :longstring type" do
|
91
|
+
assert LongStringContent.field_prototypes[:long1].field_class < Spontaneous::Field::LongString
|
92
|
+
end
|
93
|
+
|
94
|
+
it "is available as the :long_string type" do
|
95
|
+
assert LongStringContent.field_prototypes[:long2].field_class < Spontaneous::Field::LongString
|
96
|
+
end
|
97
|
+
|
98
|
+
it "is available as the :text type" do
|
99
|
+
assert LongStringContent.field_prototypes[:long3].field_class < Spontaneous::Field::LongString
|
100
|
+
end
|
101
|
+
|
102
|
+
it "translates newlines to <br/> tags" do
|
103
|
+
@instance.long1 = "this\nlong\nstring"
|
104
|
+
@instance.long1.value.must_equal "this<br />\nlong<br />\nstring"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "HTML fields" do
|
109
|
+
before do
|
110
|
+
@content_class = Class.new(::Piece) do
|
111
|
+
field :raw, :html
|
112
|
+
end
|
113
|
+
@content_class.stubs(:name).returns("ContentClass")
|
114
|
+
@instance = @content_class.new
|
115
|
+
@field = @instance.raw
|
116
|
+
end
|
117
|
+
|
118
|
+
it "does no escaping of input" do
|
119
|
+
@field.value = "<script>\n</script>"
|
120
|
+
@field.value(:html).must_equal "<script>\n</script>"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../../../test_helper', __FILE__)
|
4
|
+
|
5
|
+
describe "WebVideo fields" do
|
6
|
+
before do
|
7
|
+
@site = setup_site
|
8
|
+
@now = Time.now
|
9
|
+
stub_time(@now)
|
10
|
+
Spontaneous::State.delete
|
11
|
+
@site.background_mode = :immediate
|
12
|
+
@content_class = Class.new(::Piece) do
|
13
|
+
field :video, :webvideo
|
14
|
+
end
|
15
|
+
@content_class.stubs(:name).returns("ContentClass")
|
16
|
+
@instance = @content_class.new
|
17
|
+
@field = @instance.video
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
teardown_site
|
22
|
+
end
|
23
|
+
|
24
|
+
it "have their own editor type" do
|
25
|
+
@content_class.fields.video.export(nil)[:type].must_equal "Spontaneous.Field.WebVideo"
|
26
|
+
@instance.video = "http://www.youtube.com/watch?v=_0jroAM_pO4&feature=feedrec_grec_index"
|
27
|
+
fields = @instance.export(nil)[:fields]
|
28
|
+
fields[0][:processed_value].must_equal @instance.video.src
|
29
|
+
end
|
30
|
+
|
31
|
+
it "recognise youtube URLs" do
|
32
|
+
@instance.video = "http://www.youtube.com/watch?v=_0jroAM_pO4&feature=feedrec_grec_index"
|
33
|
+
@instance.video.value.must_equal "http://www.youtube.com/watch?v=_0jroAM_pO4&feature=feedrec_grec_index"
|
34
|
+
@instance.video.video_id.must_equal "_0jroAM_pO4"
|
35
|
+
@instance.video.provider_id.must_equal "youtube"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "recognise Vimeo URLs" do
|
39
|
+
@instance.video = "http://vimeo.com/31836285"
|
40
|
+
@instance.video.value.must_equal "http://vimeo.com/31836285"
|
41
|
+
@instance.video.video_id.must_equal "31836285"
|
42
|
+
@instance.video.provider_id.must_equal "vimeo"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "recognise Vine URLs" do
|
46
|
+
@instance.video = "https://vine.co/v/brI7pTPb3qU"
|
47
|
+
@instance.video.value.must_equal "https://vine.co/v/brI7pTPb3qU"
|
48
|
+
@instance.video.video_id.must_equal "brI7pTPb3qU"
|
49
|
+
@instance.video.provider_id.must_equal "vine"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "silently handles unknown providers" do
|
53
|
+
@instance.video = "https://idontdovideo.com/video?id=brI7pTPb3qU"
|
54
|
+
@instance.video.value.must_equal "https://idontdovideo.com/video?id=brI7pTPb3qU"
|
55
|
+
@instance.video.video_id.must_equal "https://idontdovideo.com/video?id=brI7pTPb3qU"
|
56
|
+
@instance.video.provider_id.must_equal nil
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
it "use the YouTube api to extract video metadata" do
|
61
|
+
youtube_info = {"thumbnail_large" => "http://i.ytimg.com/vi/_0jroAM_pO4/hqdefault.jpg", "thumbnail_small"=>"http://i.ytimg.com/vi/_0jroAM_pO4/default.jpg", "title" => "Hilarious QI Moment - Cricket", "description" => "Rob Brydon makes a rather embarassing choice of words whilst discussing the relationship between a cricket's chirping and the temperature. Taken from QI XL Series H episode 11 - Highs and Lows", "user_name" => "morthasa", "upload_date" => "2011-01-14 19:49:44", "tags" => "Hilarious, QI, Moment, Cricket, fun, 11, stephen, fry, alan, davies, Rob, Brydon, SeriesH, Fred, MacAulay, Sandi, Toksvig", "duration" => 78, "stats_number_of_likes" => 297, "stats_number_of_plays" => 53295, "stats_number_of_comments" => 46}#.symbolize_keys
|
62
|
+
|
63
|
+
response_xml_file = File.expand_path("../../../fixtures/fields/youtube_api_response.xml", __FILE__)
|
64
|
+
connection = mock()
|
65
|
+
Spontaneous::Field::WebVideo::YouTube.any_instance.expects(:open).with("http://gdata.youtube.com/feeds/api/videos/_0jroAM_pO4?v=2").returns(connection)
|
66
|
+
doc = Nokogiri::XML(File.open(response_xml_file))
|
67
|
+
Nokogiri.expects(:XML).with(connection).returns(doc)
|
68
|
+
@field.value = "http://www.youtube.com/watch?v=_0jroAM_pO4"
|
69
|
+
@field.values.must_equal youtube_info.merge(:video_id => "_0jroAM_pO4", :provider => "youtube", :html => "http://www.youtube.com/watch?v=_0jroAM_pO4")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "use the Vimeo api to extract video metadata" do
|
73
|
+
vimeo_info = {"id"=>29987529, "title"=>"Neon Indian Plays The UO Music Shop", "description"=>"Neon Indian plays electronic instruments from the UO Music Shop, Fall 2011. Read more at blog.urbanoutfitters.com.", "url"=>"http://vimeo.com/29987529", "upload_date"=>"2011-10-03 18:32:47", "mobile_url"=>"http://vimeo.com/m/29987529", "thumbnail_small"=>"http://b.vimeocdn.com/ts/203/565/203565974_100.jpg", "thumbnail_medium"=>"http://b.vimeocdn.com/ts/203/565/203565974_200.jpg", "thumbnail_large"=>"http://b.vimeocdn.com/ts/203/565/203565974_640.jpg", "user_name"=>"Urban Outfitters", "user_url"=>"http://vimeo.com/urbanoutfitters", "user_portrait_small"=>"http://b.vimeocdn.com/ps/251/111/2511118_30.jpg", "user_portrait_medium"=>"http://b.vimeocdn.com/ps/251/111/2511118_75.jpg", "user_portrait_large"=>"http://b.vimeocdn.com/ps/251/111/2511118_100.jpg", "user_portrait_huge"=>"http://b.vimeocdn.com/ps/251/111/2511118_300.jpg", "stats_number_of_likes"=>85, "stats_number_of_plays"=>26633, "stats_number_of_comments"=>0, "duration"=>100, "width"=>1280, "height"=>360, "tags"=>"neon indian, analog, korg, moog, theremin, micropiano, microkorg, kaossilator, kaossilator pro", "embed_privacy"=>"anywhere"}.symbolize_keys
|
74
|
+
|
75
|
+
connection = mock()
|
76
|
+
connection.expects(:read).returns(Spontaneous.encode_json([vimeo_info]))
|
77
|
+
Spontaneous::Field::WebVideo::Vimeo.any_instance.expects(:open).with("http://vimeo.com/api/v2/video/29987529.json").returns(connection)
|
78
|
+
@field.value = "http://vimeo.com/29987529"
|
79
|
+
@field.values.must_equal vimeo_info.merge(:video_id => "29987529", :provider => "vimeo", :html => "http://vimeo.com/29987529")
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "with player settings" do
|
83
|
+
before do
|
84
|
+
@content_class.field :video2, :webvideo, :player => {
|
85
|
+
:width => 680, :height => 384,
|
86
|
+
:fullscreen => true, :autoplay => true, :loop => true,
|
87
|
+
:showinfo => false,
|
88
|
+
:youtube => { :theme => 'light', :hd => true, :controls => false },
|
89
|
+
:vimeo => { :color => "ccc", :api => true }
|
90
|
+
}
|
91
|
+
@instance = @content_class.new
|
92
|
+
@field = @instance.video2
|
93
|
+
end
|
94
|
+
|
95
|
+
it "use the configuration in the youtube player HTML" do
|
96
|
+
@field.value = "http://www.youtube.com/watch?v=_0jroAM_pO4&feature=feedrec_grec_index"
|
97
|
+
html = @field.render(:html)
|
98
|
+
html.must_match /^<iframe/
|
99
|
+
html.must_match %r{src="//www\.youtube\.com/embed/_0jroAM_pO4}
|
100
|
+
html.must_match /width="680"/
|
101
|
+
html.must_match /height="384"/
|
102
|
+
html.must_match /theme=light/
|
103
|
+
html.must_match /hd=1/
|
104
|
+
html.must_match /fs=1/
|
105
|
+
html.must_match /controls=0/
|
106
|
+
html.must_match /autoplay=1/
|
107
|
+
html.must_match /showinfo=0/
|
108
|
+
html.must_match /showsearch=0/
|
109
|
+
@field.render(:html, :youtube => {:showsearch => 1}).must_match /showsearch=1/
|
110
|
+
@field.render(:html, :youtube => {:theme => 'dark'}).must_match /theme=dark/
|
111
|
+
@field.render(:html, :width => 100).must_match /width="100"/
|
112
|
+
@field.render(:html, :loop => true).must_match /loop=1/
|
113
|
+
end
|
114
|
+
|
115
|
+
it "use the configuration in the Vimeo player HTML" do
|
116
|
+
@field.value = "http://vimeo.com/31836285"
|
117
|
+
html = @field.render(:html)
|
118
|
+
html.must_match /^<iframe/
|
119
|
+
html.must_match %r{src="//player\.vimeo\.com/video/31836285}
|
120
|
+
html.must_match /width="680"/
|
121
|
+
html.must_match /height="384"/
|
122
|
+
html.must_match /color=ccc/
|
123
|
+
html.must_match /webkitAllowFullScreen="yes"/
|
124
|
+
html.must_match /allowFullScreen="yes"/
|
125
|
+
html.must_match /autoplay=1/
|
126
|
+
html.must_match /title=0/
|
127
|
+
html.must_match /byline=0/
|
128
|
+
html.must_match /portrait=0/
|
129
|
+
html.must_match /api=1/
|
130
|
+
@field.render(:html, :vimeo => {:color => 'f0abcd'}).must_match /color=f0abcd/
|
131
|
+
@field.render(:html, :loop => true).must_match /loop=1/
|
132
|
+
@field.render(:html, :title => true).must_match /title=1/
|
133
|
+
@field.render(:html, :title => true).must_match /byline=0/
|
134
|
+
end
|
135
|
+
|
136
|
+
it "provide a version of the YouTube player params in JSON/JS format" do
|
137
|
+
@field.value = "http://www.youtube.com/watch?v=_0jroAM_pO4&feature=feedrec_grec_index"
|
138
|
+
json = Spontaneous::JSON.parse(@field.render(:json))
|
139
|
+
json[:"tagname"].must_equal "iframe"
|
140
|
+
json[:"tag"].must_equal "<iframe/>"
|
141
|
+
attr = json[:"attr"]
|
142
|
+
attr.must_be_instance_of(Hash)
|
143
|
+
attr[:"src"].must_match %r{^//www\.youtube\.com/embed/_0jroAM_pO4}
|
144
|
+
attr[:"src"].must_match /theme=light/
|
145
|
+
attr[:"src"].must_match /hd=1/
|
146
|
+
attr[:"src"].must_match /fs=1/
|
147
|
+
attr[:"src"].must_match /controls=0/
|
148
|
+
attr[:"src"].must_match /autoplay=1/
|
149
|
+
attr[:"src"].must_match /showinfo=0/
|
150
|
+
attr[:"src"].must_match /showsearch=0/
|
151
|
+
attr[:"width"].must_equal 680
|
152
|
+
attr[:"height"].must_equal 384
|
153
|
+
attr[:"frameborder"].must_equal "0"
|
154
|
+
attr[:"type"].must_equal "text/html"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "provide a version of the Vimeo player params in JSON/JS format" do
|
158
|
+
@field.value = "http://vimeo.com/31836285"
|
159
|
+
json = Spontaneous::JSON.parse(@field.render(:json))
|
160
|
+
json[:"tagname"].must_equal "iframe"
|
161
|
+
json[:"tag"].must_equal "<iframe/>"
|
162
|
+
attr = json[:"attr"]
|
163
|
+
attr.must_be_instance_of(Hash)
|
164
|
+
attr[:"src"].must_match /color=ccc/
|
165
|
+
attr[:"src"].must_match /autoplay=1/
|
166
|
+
attr[:"src"].must_match /title=0/
|
167
|
+
attr[:"src"].must_match /byline=0/
|
168
|
+
attr[:"src"].must_match /portrait=0/
|
169
|
+
attr[:"src"].must_match /api=1/
|
170
|
+
attr[:"webkitAllowFullScreen"].must_equal "yes"
|
171
|
+
attr[:"allowFullScreen"].must_equal "yes"
|
172
|
+
attr[:"width"].must_equal 680
|
173
|
+
attr[:"height"].must_equal 384
|
174
|
+
attr[:"frameborder"].must_equal "0"
|
175
|
+
attr[:"type"].must_equal "text/html"
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
it "can properly embed a Vine video" do
|
180
|
+
@field.value = "https://vine.co/v/brI7pTPb3qU"
|
181
|
+
embed = @field.render(:html)
|
182
|
+
embed.must_match %r(iframe)
|
183
|
+
embed.must_match %r(src=["']//vine\.co/v/brI7pTPb3qU/card["'])
|
184
|
+
# Vine videos are square
|
185
|
+
embed.must_match %r(width=["']680["'])
|
186
|
+
embed.must_match %r(height=["']680["'])
|
187
|
+
end
|
188
|
+
|
189
|
+
it "falls back to a simple iframe for unknown providers xxx" do
|
190
|
+
@field.value = "https://unknownprovider.net/xx/brI7pTPb3qU"
|
191
|
+
embed = @field.render(:html)
|
192
|
+
embed.must_match %r(iframe)
|
193
|
+
embed.must_match %r(src=["']https://unknownprovider.net/xx/brI7pTPb3qU["'])
|
194
|
+
embed.must_match %r(width=["']680["'])
|
195
|
+
embed.must_match %r(height=["']384["'])
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|