chili_videos 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data.tar.gz.sig +1 -0
  2. data/.autotest +5 -0
  3. data/Gemfile +13 -0
  4. data/Gemfile.lock +33 -0
  5. data/History.txt +4 -0
  6. data/LICENSE +20 -0
  7. data/Manifest.txt +63 -0
  8. data/README.md +169 -0
  9. data/Rakefile +45 -0
  10. data/app/controllers/videos_controller.rb +72 -0
  11. data/app/helpers/videos_helper.rb +34 -0
  12. data/app/models/assembly.rb +62 -0
  13. data/app/models/assembly_observer.rb +6 -0
  14. data/app/models/assembly_processor.rb +16 -0
  15. data/app/models/video.rb +24 -0
  16. data/app/views/settings/_settings.html.erb +13 -0
  17. data/app/views/videos/edit.html.erb +32 -0
  18. data/app/views/videos/index.html.erb +37 -0
  19. data/app/views/videos/new.html.erb +41 -0
  20. data/app/views/videos/plugin_not_configured.html.erb +6 -0
  21. data/app/views/videos/show.html.erb +40 -0
  22. data/app/views/videos/upload_complete.html.erb +7 -0
  23. data/assets/player.swf +0 -0
  24. data/assets/readme.html +84 -0
  25. data/assets/stylesheets/forms.css +7 -0
  26. data/assets/stylesheets/videos.css +76 -0
  27. data/assets/swfobject.js +8 -0
  28. data/assets/yt.swf +0 -0
  29. data/autotest/discover.rb +4 -0
  30. data/bin/delayed_job +23 -0
  31. data/config/locales/en.yml +15 -0
  32. data/config/routes.rb +3 -0
  33. data/db/migrate/20110301025054_create_videos.rb +15 -0
  34. data/db/migrate/20110309060901_create_assemblies.rb +14 -0
  35. data/db/migrate/20110314022354_create_delayed_jobs.rb +21 -0
  36. data/db/migrate/20110402043115_create_slugs.rb +18 -0
  37. data/db/migrate/20110402053931_add_slug_cache_to_videos.rb +11 -0
  38. data/init.rb +63 -0
  39. data/lang/en.yml +16 -0
  40. data/lib/chili_videos.rb +18 -0
  41. data/lib/chili_videos/config.rb +40 -0
  42. data/lib/chili_videos/error.rb +5 -0
  43. data/lib/tasks/chili_videos_tasks.rb +112 -0
  44. data/lib/tasks/contributor_tasks.rb +64 -0
  45. data/lib/tasks/delayed_job.rake +6 -0
  46. data/lib/tasks/friendly_id.rake +19 -0
  47. data/lib/video_project_patch.rb +10 -0
  48. data/lib/video_user_patch.rb +10 -0
  49. data/lib/video_version_patch.rb +9 -0
  50. data/rails/delayed_job +25 -0
  51. data/rails/init.rb +1 -0
  52. data/test/fixtures/incomplete_assembly.json +9 -0
  53. data/test/fixtures/single_video_processed_assembly.json +9 -0
  54. data/test/fixtures/standard_transloadit_response.json +6 -0
  55. data/test/functional/videos_controller_test.rb +232 -0
  56. data/test/integration/project_video_list_test.rb +104 -0
  57. data/test/integration/project_video_uploading_test.rb +56 -0
  58. data/test/integration/viewing_project_video_test.rb +74 -0
  59. data/test/test_helper.rb +77 -0
  60. data/test/unit/assembly_processor_test.rb +57 -0
  61. data/test/unit/assembly_test.rb +95 -0
  62. data/test/unit/chili_video_plugin/config_test.rb +49 -0
  63. data/test/unit/chili_video_plugin_test.rb +30 -0
  64. data/test/unit/video_test.rb +26 -0
  65. metadata +279 -0
  66. metadata.gz.sig +0 -0
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ProjectVideoUploadingTest < ActionController::IntegrationTest
4
+ def setup
5
+ @user = User.generate!(:login => 'existing', :password => 'existing', :password_confirmation => 'existing')
6
+ @project = Project.generate!.reload
7
+
8
+ User.add_to_project(@user, @project, Role.generate!(:permissions => [:view_video_list, :add_video]))
9
+
10
+ login_as
11
+ end
12
+
13
+ def plugin_settings(api_key, workflow)
14
+ Setting["plugin_chili_videos"] = HashWithIndifferentAccess.new({:transloadit_api_key => api_key, :transloadit_workflow => workflow})
15
+ end
16
+
17
+
18
+ context "Uploading a video" do
19
+ context "when the plugin is set up correctly" do
20
+ setup do
21
+ plugin_settings('api-key', 'workflow')
22
+ end
23
+
24
+ should "set the 'redirect_url' form param to the 'upload_complete' url" do
25
+ visit(new_project_video_path(@project))
26
+ proper_redirect_url = "&quot;redirect_url&quot;:&quot;http://www.example.com/projects/#{@project.to_param}/videos/upload_complete&quot;"
27
+ assert_match proper_redirect_url, response.body
28
+ end
29
+
30
+ should "set the 'template_id' form param to the setting stored in the plugin settings" do
31
+ visit(new_project_video_path(@project))
32
+ escaped_template_id = "&quot;template_id&quot;:&quot;workflow&quot;"
33
+ assert_match escaped_template_id, response.body
34
+ end
35
+
36
+ should "set the 'auth_key' form param to the setting stored in the plugin settings" do
37
+ visit(new_project_video_path(@project))
38
+ escaped_api_key = "&quot;key&quot;:&quot;api-key&quot;"
39
+ assert_match escaped_api_key, response.body
40
+ end
41
+ end
42
+
43
+ context "when the plugin does not have either the Transload.it workflow or API key stored in the plugin settings" do
44
+ setup do
45
+ plugin_settings('','')
46
+ end
47
+
48
+ should "display a message telling the user to set up the plugin on the plugin administration page" do
49
+ visit(new_project_video_path(@project))
50
+ within("p.warning") do
51
+ assert_have_selector('a', :href => '/settings/plugin/chili_videos')
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,74 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ViewingProjectVideoTest < ActionController::IntegrationTest
4
+ include VideosHelper
5
+
6
+ def setup
7
+ ChiliVideos::Config.update(:api_key => 'api-key', :workflow => 'wf')
8
+
9
+ @user = User.generate!(:login => 'existing', :password => 'existing', :password_confirmation => 'existing', :admin => true)
10
+ @project = Project.generate!.reload
11
+ User.add_to_project(@user, @project, Role.generate!(:permissions => [:view_video_list, :add_video, :view_specific_video]))
12
+ login_as
13
+ end
14
+
15
+ context "Viewing a specific video associated with a Project by clicking the video link" do
16
+ context "when the specified video is not associated with the project" do
17
+ setup do
18
+ Video.destroy_all
19
+ visit(project_video_path(@project, 'nonexistant-video'))
20
+ end
21
+
22
+ should "display an error message to the user" do
23
+ assert_have_selector("div.error")
24
+ end
25
+ end
26
+
27
+ context "when the requested video has been associated with the project" do
28
+ setup do
29
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
30
+ visit(project_video_path(@project, @video))
31
+ end
32
+
33
+ should "include the code to embed the video in another project page with the standard size" do
34
+ within("div.video") do
35
+ assert_have_selector("input.embed.standard[value='#{video_embed_macro_markup(@video)}']")
36
+ end
37
+ end
38
+
39
+ should "have a link to delete the video" do
40
+ within("div.contextual") do
41
+ assert_have_selector("a[class~='video-del'][href='#{project_video_path(@project, @video)}']")
42
+ end
43
+ end
44
+
45
+ should "have a link to edit the video" do
46
+ within("div.contextual") do
47
+ assert_have_selector("a[class~='video-edit'][href='#{edit_project_video_path(@project, @video)}']")
48
+ end
49
+ end
50
+
51
+ should "have a link to upload a new video" do
52
+ within("div.contextual") do
53
+ assert_have_selector("a", :href => new_project_video_path(@project))
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ context "Deleting a video by clicking the 'delete video' link" do
60
+ setup do
61
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
62
+ delete_via_redirect(project_video_path(@project, @video))
63
+ end
64
+
65
+ should "notify the user that the video was deleted" do
66
+ assert_have_selector(".notice")
67
+ end
68
+
69
+ should "removes the video from the project's list of videos" do
70
+ visit project_videos_path(@project)
71
+ assert_have_no_selector(".video##{@video.to_param}")
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,77 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
2
+
3
+ # Ensure that we are using the temporary fixture path
4
+ Engines::Testing.set_fixture_path
5
+
6
+
7
+ require 'webrat'
8
+ require 'fakeweb'
9
+ require 'chili_videos'
10
+
11
+ FakeWeb.allow_net_connect = false
12
+
13
+ Webrat.configure do |config|
14
+ config.mode = :rails
15
+ end
16
+
17
+ module IntegrationTestHelper
18
+ def login_as(user="existing", password="existing")
19
+ visit "/login"
20
+ fill_in 'Login', :with => user
21
+ fill_in 'Password', :with => password
22
+ click_button 'login'
23
+ assert_response :success
24
+ assert User.current.logged?
25
+ end
26
+
27
+ def visit_project(project)
28
+ visit '/'
29
+ assert_response :success
30
+
31
+ click_link 'Projects'
32
+ assert_response :success
33
+
34
+ click_link project.name
35
+ assert_response :success
36
+ end
37
+
38
+ def assert_forbidden
39
+ assert_response :forbidden
40
+ assert_template 'common/403'
41
+ end
42
+
43
+ # Cleanup current_url to remove the host; sometimes it's present, sometimes it's not
44
+ def current_path
45
+ return nil if current_url.nil?
46
+ return current_url.gsub("http://www.example.com","")
47
+ end
48
+
49
+ end
50
+
51
+ module TransloaditServiceHelper
52
+ def workflow_results(identifier = :standard)
53
+ YAML.load(File.open("test/fixtures/#{identifier}_transloadit_response.json"))
54
+ end
55
+
56
+ def stub_assembly_url(assembly = nil, fixture_base_name = :single_video_processed)
57
+ response = "test/fixtures/#{fixture_base_name.to_s}_assembly.json"
58
+ url = assembly.blank? ? assembly_url : assembly.assembly_url
59
+ FakeWeb.register_uri(:get, url, :response => response)
60
+ end
61
+
62
+ def assembly_url
63
+ 'http://fake.transload.it/assembly_url'
64
+ end
65
+ end
66
+
67
+ class ActionController::IntegrationTest
68
+ include IntegrationTestHelper
69
+ end
70
+
71
+ class ActiveSupport::TestCase
72
+ include TransloaditServiceHelper
73
+ end
74
+
75
+ class ActionController::TestCase
76
+ include TransloaditServiceHelper
77
+ end
@@ -0,0 +1,57 @@
1
+ require 'test/test_helper'
2
+
3
+ class AssemblyProcessorTest < ActiveSupport::TestCase
4
+ context '.process' do
5
+ setup do
6
+ stub_assembly_url
7
+
8
+ @project = Project.generate!
9
+ @assembly = Assembly.generate!(:project_id => @project.id, :assembly_url => assembly_url)
10
+ end
11
+
12
+ should 'create a new Video' do
13
+ Video.destroy_all
14
+ AssemblyProcessor.process(@assembly)
15
+ assert_equal 1, Video.count
16
+ end
17
+
18
+ should 'associate the video with the same project as the assembly' do
19
+ AssemblyProcessor.process(@assembly)
20
+ assert_equal @project.id, Video.last.project_id
21
+ end
22
+
23
+ should 'associate the video with the same user as the assembly' do
24
+ AssemblyProcessor.process(@assembly)
25
+ assert_equal @assembly.user_id, Video.last.user_id
26
+ end
27
+
28
+ context 'when a single video was uploaded it' do
29
+ should "store the S3 URL of the video associated with the assembly in the 'video_url' attribute" do
30
+ expected_url = 'http://fakebucket.s3.amazonaws.com/f1/192f2b2cb1755ad4494707d82dc7a5/tester.flv'
31
+ AssemblyProcessor.process(@assembly)
32
+ assert_equal expected_url, Video.last.url
33
+ end
34
+
35
+ should "store the value of the 'title' custom field on the video" do
36
+ AssemblyProcessor.process(@assembly)
37
+ assert_equal 'Title here', Video.last.title
38
+ #assert_equal 'Description here', Video.last.description
39
+ end
40
+
41
+ should "store the value of the 'description' custom field on the video" do
42
+ AssemblyProcessor.process(@assembly)
43
+ assert_equal 'Description here', Video.last.description
44
+ end
45
+
46
+ should "store the value of the 'version_id' custom field on the video" do
47
+ AssemblyProcessor.process(@assembly)
48
+ assert_equal 2, Video.last.version_id
49
+ end
50
+
51
+ should "store the duration of the video" do
52
+ AssemblyProcessor.process(@assembly)
53
+ assert_equal 10, Video.last.duration
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,95 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class AssemblyTest < ActiveSupport::TestCase
4
+ def setup
5
+ @project = Project.generate!
6
+ stub_assembly_url
7
+ end
8
+
9
+ context "creation" do
10
+ should "set 'processed' attribute to false" do
11
+ assembly = Assembly.generate!(:processed => true)
12
+ assert_equal false, assembly.processed
13
+ end
14
+ end
15
+
16
+ context ".encodings" do
17
+ setup do
18
+ @assembly = Assembly.generate!(:project_id => @project.id, :assembly_url => assembly_url)
19
+ end
20
+
21
+ context "when one video was uploaded it should" do
22
+ setup do
23
+ service_response = 'test/fixtures/single_video_processed_assembly.json'
24
+ FakeWeb.register_uri(:get, assembly_url, :response => service_response)
25
+ end
26
+
27
+ should "return an enumerable with one item" do
28
+ assert 1, @assembly.encodings.count
29
+ end
30
+
31
+ should "include the URL of the transcoded file" do
32
+ expected_url = 'http://fakebucket.s3.amazonaws.com/f1/192f2b2cb1755ad4494707d82dc7a5/tester.flv'
33
+ encoding = @assembly.encodings.first
34
+ assert expected_url, encoding.url
35
+ end
36
+ end
37
+
38
+ context "when the workflow has not completed yet" do
39
+ setup do
40
+ service_response = 'test/fixtures/incomplete_assembly.json'
41
+ FakeWeb.register_uri(:get, assembly_url, :response => service_response)
42
+ end
43
+
44
+ should "raises an IncompleteAssembly exception" do
45
+ assert_raise(ChiliVideos::Error::IncompleteAssembly) {@assembly.encodings}
46
+ end
47
+ end
48
+ end
49
+
50
+ context ".custom_fields" do
51
+ setup do
52
+ @assembly = Assembly.generate!(:project_id => @project.id, :assembly_url => assembly_url)
53
+ service_response = 'test/fixtures/single_video_processed_assembly.json'
54
+ FakeWeb.register_uri(:get, assembly_url, :response => service_response)
55
+ end
56
+
57
+ should "return a Hash-like object with key-value pairs of custom fields stored on the assembly" do
58
+ assert @assembly.custom_fields.has_key?('project_id')
59
+ assert @assembly.custom_fields.has_key?('user_id')
60
+ end
61
+
62
+ should "return an object which resolves String or Symbol keys" do
63
+ assert @assembly.custom_fields.has_key?('project_id')
64
+ assert @assembly.custom_fields.has_key?(:user_id)
65
+ end
66
+ end
67
+
68
+ context "processing" do
69
+ context "when an assembly is successfully created" do
70
+ setup do
71
+ Video.destroy_all
72
+ end
73
+
74
+ # Observers not called when in non-prod mode
75
+ #should "process the assembly and create a new video" do
76
+ # @assembly = Assembly.generate!(:project_id => @project.id, :assembly_url => assembly_url)
77
+ # assert_equal 1, Video.count
78
+ #end
79
+
80
+ context "but the video service has not finished transcoding the content" do
81
+ setup do
82
+ FakeWeb.clean_registry
83
+ service_response = 'test/fixtures/incomplete_assembly.json'
84
+ FakeWeb.register_uri(:get, assembly_url, :response => service_response)
85
+ end
86
+
87
+ should "enque a delayed job to handle the processing on Redmine's side later" do
88
+ simple_mock = OpenStruct.new(:process => true)
89
+ AssemblyProcessor.expects(:delay).returns(simple_mock)
90
+ Assembly.generate!(:project_id => @project.id, :assembly_url => assembly_url)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ include ChiliVideos
4
+
5
+ class ConfigTest < ActiveSupport::TestCase
6
+ setup do
7
+ Setting["plugin_chili_videos"] = HashWithIndifferentAccess.new({:transloadit_api_key => 'api_key', :transloadit_workflow => 'workflow_name'})
8
+ end
9
+
10
+ context '.api_key' do
11
+ should "returns the value of the plugin's 'transloadit_api_key' setting" do
12
+ assert_equal 'api_key', ChiliVideos::Config.api_key
13
+ end
14
+ end
15
+
16
+ context '.workflow' do
17
+ should "returns the value of the plugin's 'transloadit_workflow' setting" do
18
+ assert_equal 'workflow_name', ChiliVideos::Config.workflow
19
+ end
20
+ end
21
+
22
+ context '.update' do
23
+ context 'when all required parameters are supplied' do
24
+ setup do
25
+ @new_values = {:api_key => 'updated-api', :workflow => 'workflow-update'}
26
+ end
27
+
28
+ should "the value of the plugin's 'api_key' setting is updated" do
29
+ assert_equal 'api_key', ChiliVideos::Config.api_key
30
+ ChiliVideos::Config.update(@new_values)
31
+ assert_equal @new_values[:api_key], ChiliVideos::Config.api_key
32
+ end
33
+
34
+ should "the value of the plugin's 'workflow-update'' setting is updated" do
35
+ assert_equal 'workflow_name', ChiliVideos::Config.workflow
36
+ ChiliVideos::Config.update(@new_values)
37
+ assert_equal @new_values[:workflow], ChiliVideos::Config.workflow
38
+ end
39
+ end
40
+
41
+ context 'when a required parameter is missing' do
42
+ should "an ArgumentError is raised" do
43
+ assert_raise(ArgumentError) {
44
+ ChiliVideos::Config.update(:api_key => 'api_key')
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ChiliVideosTest < ActiveSupport::TestCase
4
+ setup do
5
+ Setting["plugin_chili_videos"] = HashWithIndifferentAccess.new({:transloadit_api_key => 'api_key', :transloadit_workflow => 'workflow'})
6
+ end
7
+
8
+ context '.configured?' do
9
+ context "when all required settings are stored" do
10
+ should "return true" do
11
+ assert ChiliVideos.configured?
12
+ end
13
+ end
14
+
15
+ context "when 'transloadit_api_key' is not set" do
16
+ should 'returns false' do
17
+ Setting["plugin_chili_videos"]['transloadit_api_key'] = ''
18
+ assert !ChiliVideos.configured?
19
+ end
20
+ end
21
+
22
+ context "when 'transloadit_workflow' is not set" do
23
+ should 'returns false' do
24
+ Setting["plugin_chili_videos"]['transloadit_workflow'] = ''
25
+ assert !ChiliVideos.configured?
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class VideoTest < ActiveSupport::TestCase
4
+ context "#length" do
5
+ context "when video is less than 1-minute" do
6
+ should "convert it to 0:XX format" do
7
+ video = Video.create!(:title => "Video 1", :duration => 32, :project_id => 1, :user_id => 1)
8
+ assert_equal "0:32", video.length
9
+ end
10
+ end
11
+
12
+ context "when video is longer than 1-minute" do
13
+ should "convert it to X:XX format" do
14
+ video = Video.create!(:title => "Video 1", :duration => 202, :project_id => 1, :user_id => 1)
15
+ assert_equal "3:22", video.length
16
+ end
17
+ end
18
+
19
+ context "when video duration is nil" do
20
+ should "return '0:00'" do
21
+ video = Video.create!(:title => "Video 1", :duration => nil, :project_id => 1, :user_id => 1)
22
+ assert_equal "0:00", video.length
23
+ end
24
+ end
25
+ end
26
+ end