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,6 @@
1
+ begin
2
+ gem 'delayed_job', '~>2.0.4'
3
+ require 'delayed/tasks'
4
+ rescue LoadError
5
+ STDERR.puts "The 'delayed_job' gem is missing. Please install version ~> 2.0.4"
6
+ end
@@ -0,0 +1,19 @@
1
+ namespace :friendly_id do
2
+ desc "Make slugs for a model."
3
+ task :make_slugs => :environment do
4
+ FriendlyId::TaskRunner.new.make_slugs do |record|
5
+ puts "#{record.class}(#{record.id}): friendly_id set to '#{record.slug.name}'" if record.slug
6
+ end
7
+ end
8
+
9
+ desc "Regenereate slugs for a model."
10
+ task :redo_slugs => :environment do
11
+ FriendlyId::TaskRunner.new.delete_slugs
12
+ Rake::Task["friendly_id:make_slugs"].invoke
13
+ end
14
+
15
+ desc "Destroy obsolete slugs older than DAYS=45 days."
16
+ task :remove_old_slugs => :environment do
17
+ FriendlyId::TaskRunner.new.delete_old_slugs
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module VideoProjectPatch
2
+ def self.included(base) # :nodoc:
3
+ base.class_eval do
4
+ unloadable # Send unloadable so it will not be unloaded in development
5
+ has_many :videos, :dependent => :destroy, :order => "created_at DESC"
6
+ has_many :assemblies, :dependent => :destroy
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,10 @@
1
+ module VideoUserPatch
2
+ def self.included(base) # :nodoc:
3
+ base.class_eval do
4
+ unloadable # Send unloadable so it will not be unloaded in development
5
+ has_many :videos, :dependent => :destroy
6
+ has_many :assemblies, :dependent => :destroy
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,9 @@
1
+ module VideoVersionPatch
2
+ def self.included(base) # :nodoc:
3
+ base.class_eval do
4
+ unloadable # Send unloadable so it will not be unloaded in development
5
+ has_many :videos, :dependent => :destroy
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+ require 'rubygems'
4
+ require 'daemon_spawn'
5
+
6
+ RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
7
+
8
+ class DelayedJobWorker < DaemonSpawn::Base
9
+ def start(args)
10
+ ENV['RAILS_ENV'] ||= args.first || 'development'
11
+ Dir.chdir RAILS_ROOT
12
+ require File.join('config', 'environment')
13
+
14
+ Delayed::Worker.new.start
15
+ end
16
+
17
+ def stop
18
+ system("kill `cat #{RAILS_ROOT}/tmp/pids/delayed_job.pid`")
19
+ end
20
+ end
21
+
22
+ DelayedJobWorker.spawn!(:log_file => File.join(RAILS_ROOT, "log", "delayed_job.log"),
23
+ :pid_file => File.join(RAILS_ROOT, 'tmp', 'pids', 'delayed_job.pid'),
24
+ :sync_log => true,
25
+ :working_dir => RAILS_ROOT)
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/../init"
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Content-Type: text/plain
3
+ Access-Control-Allow-Origin: *
4
+ Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
5
+ Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Content-Length
6
+ Connection: close
7
+ Transfer-Encoding: chunked
8
+
9
+ {"ok":"ASSEMBLY_EXECUTING","message":"The assembly is currently being executed.","assembly_id":"bae2c2898289953553c3977501c1ea8c","assembly_url":"http://api2.camilla.transloadit.com/assemblies/bae2c2898289953553c3977501c1ea8c","bytes_received":3916723,"bytes_expected":3916723,"client_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_6) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.3 Safari/534.24","client_ip":"71.201.59.160","client_referer":"http://localhost:3000/projects/sample/videos/new","start_date":"2011/03/13 23:18:04 GMT","upload_duration":7.925,"execution_duration":null,"fields":{"project_id":"sample","user_id":"1"},"uploads":[{"id":"d2a2c713f9ca2db7b2218b54ff567a13","name":"tester2.mov","basename":"tester2","ext":"mov","size":3916061,"mime":"video/mp4","type":"video","field":"my_file","original_id":"d2a2c713f9ca2db7b2218b54ff567a13","url":"http://tmp.camilla.transloadit.com/upload/68b1c6d17bae9f24ff53c0a404300614.mov","meta":{"duration":76,"width":720,"height":450,"framerate":30,"video_bitrate":327704,"video_codec":"ffh264","audio_bitrate":80712,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":"2011/03/04 03:50:10","date_file_modified":"2011/03/13 23:18:12 GMT","device_vendor":"Apple","device_name":null,"device_software":"ScreenFlow","latitude":null,"longitude":null,"rotation":0}}],"results":{"thumbs":[{"id":"e3166acf2360c6fcd122cbd04302d33c","name":"tester2.jpg","basename":"tester2","ext":"jpg","size":43996,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"d2a2c713f9ca2db7b2218b54ff567a13","url":"http://tk-transloadtest.s3.amazonaws.com/e3/166acf2360c6fcd122cbd04302d33c/tester2.jpg","meta":{"duration":76,"width":720,"height":450,"framerate":30,"video_bitrate":327704,"video_codec":"ffh264","audio_bitrate":80712,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/13 23:18:12 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":1,"thumb_offset":30.4,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"c92b6bd89125d961abf5c344c6d895e4","name":"tester2.jpg","basename":"tester2","ext":"jpg","size":43966,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"d2a2c713f9ca2db7b2218b54ff567a13","url":"http://tk-transloadtest.s3.amazonaws.com/c9/2b6bd89125d961abf5c344c6d895e4/tester2.jpg","meta":{"duration":76,"width":720,"height":450,"framerate":30,"video_bitrate":327704,"video_codec":"ffh264","audio_bitrate":80712,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/13 23:18:12 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":0,"thumb_offset":15.2,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"91ff7eb211b5ed6c00b56e6b2cbbff87","name":"tester2.jpg","basename":"tester2","ext":"jpg","size":27112,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"d2a2c713f9ca2db7b2218b54ff567a13","url":"http://tk-transloadtest.s3.amazonaws.com/91/ff7eb211b5ed6c00b56e6b2cbbff87/tester2.jpg","meta":{"duration":76,"width":720,"height":450,"framerate":30,"video_bitrate":327704,"video_codec":"ffh264","audio_bitrate":80712,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/13 23:18:13 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":3,"thumb_offset":60.8,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"0623c4607d89c297426b84b560707288","name":"tester2.jpg","basename":"tester2","ext":"jpg","size":44139,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"d2a2c713f9ca2db7b2218b54ff567a13","url":"http://tk-transloadtest.s3.amazonaws.com/06/23c4607d89c297426b84b560707288/tester2.jpg","meta":{"duration":76,"width":720,"height":450,"framerate":30,"video_bitrate":327704,"video_codec":"ffh264","audio_bitrate":80712,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/13 23:18:13 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":2,"thumb_offset":45.599999999999994,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}}]}}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Content-Type: text/plain
3
+ Access-Control-Allow-Origin: *
4
+ Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
5
+ Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Content-Length
6
+ Connection: close
7
+ Transfer-Encoding: chunked
8
+
9
+ {"ok":"ASSEMBLY_COMPLETED","message":"The assembly was successfully completed.","assembly_id":"cb4600f87734befa70123a5a5d3a0ab0","assembly_url":"http://api2.camilla.transloadit.com/assemblies/cb4600f87734befa70123a5a5d3a0ab0","bytes_received":247365,"bytes_expected":247365,"client_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_6) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.0 Safari/534.24","client_ip":"99.4.98.94","client_referer":"http://localhost:3000/projects/sample/videos/new","start_date":"2011/03/10 00:34:11 GMT","upload_duration":10.061,"execution_duration":2.824,"fields":{"project_id":"sample","user_id":"1","title":"Title here","description":"Description here","version_id":"2"},"uploads":[{"id":"227b3918703edf786241c754d84ee93e","name":"tester.mov","basename":"tester","ext":"mov","size":246704,"mime":"video/mp4","type":"video","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://tmp.camilla.transloadit.com/upload/bce048091fb1b4ca2b9677d5d77a4625.mov","meta":{"duration":10,"width":720,"height":450,"framerate":30,"video_bitrate":106776,"video_codec":"ffh264","audio_bitrate":86016,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":"2011/03/01 05:56:37","date_file_modified":"2011/03/10 00:34:21 GMT","device_vendor":"Apple","device_name":null,"device_software":"ScreenFlow","latitude":null,"longitude":null,"rotation":0}}],"results":{"thumbs":[{"id":"b15e351b2c8290566b960179b6df36ca","name":"tester.jpg","basename":"tester","ext":"jpg","size":25667,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://fakebucket.s3.amazonaws.com/b1/5e351b2c8290566b960179b6df36ca/tester.jpg","meta":{"duration":10,"width":720,"height":450,"framerate":30,"video_bitrate":106776,"video_codec":"ffh264","audio_bitrate":86016,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/10 00:34:22 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":1,"thumb_offset":4,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"96944efbb3d443c3e8c177f138f51a0e","name":"tester.jpg","basename":"tester","ext":"jpg","size":25667,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://fakebucket.s3.amazonaws.com/96/944efbb3d443c3e8c177f138f51a0e/tester.jpg","meta":{"duration":10,"width":720,"height":450,"framerate":30,"video_bitrate":106776,"video_codec":"ffh264","audio_bitrate":86016,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/10 00:34:22 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":0,"thumb_offset":2,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"ffa686e9d659cd23db69efae094b94c3","name":"tester.jpg","basename":"tester","ext":"jpg","size":25941,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://fakebucket.s3.amazonaws.com/ff/a686e9d659cd23db69efae094b94c3/tester.jpg","meta":{"duration":10,"width":720,"height":450,"framerate":30,"video_bitrate":106776,"video_codec":"ffh264","audio_bitrate":86016,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/10 00:34:22 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":3,"thumb_offset":8,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}},{"id":"ce46097eb40eec3158a1788acd9b2f2f","name":"tester.jpg","basename":"tester","ext":"jpg","size":25667,"mime":"image/jpeg","type":"image","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://fakebucket.s3.amazonaws.com/ce/46097eb40eec3158a1788acd9b2f2f/tester.jpg","meta":{"duration":10,"width":720,"height":450,"framerate":30,"video_bitrate":106776,"video_codec":"ffh264","audio_bitrate":86016,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"ffaac","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/10 00:34:22 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":0,"thumb_index":2,"thumb_offset":6,"title":null,"description":null,"location":null,"city":null,"state":null,"country":null,"country_code":null,"keywords":null,"aperture":null,"exposure_compensation":null,"exposure_mode":null,"exposure_time":null,"flash":null,"focal_length":null,"f_number":null,"iso":null,"light_value":null,"metering_mode":null,"shutter_speed":null,"white_balance":null,"frame_count":null}}],"encode":[{"id":"f1192f2b2cb1755ad4494707d82dc7a5","name":"tester.flv","basename":"tester","ext":"flv","size":1176396,"mime":"video/x-flv","type":"video","field":"my_file","original_id":"227b3918703edf786241c754d84ee93e","url":"http://fakebucket.s3.amazonaws.com/f1/192f2b2cb1755ad4494707d82dc7a5/tester.flv","meta":{"duration":10.08,"width":960,"height":700,"framerate":25,"video_bitrate":500000,"video_codec":"ffflv","audio_bitrate":64000,"audio_samplerate":44100,"audio_channels":2,"audio_codec":"mp3","seekable":true,"date_recorded":null,"date_file_created":null,"date_file_modified":"2011/03/10 00:34:24 GMT","device_vendor":null,"device_name":null,"device_software":null,"latitude":null,"longitude":null,"rotation":null}}]}}
@@ -0,0 +1,6 @@
1
+ --- !map:Hash
2
+ assembly_url: http://fake.transload.it/assembly_url
3
+ project_id: sample
4
+ action: upload_complete
5
+ controller: videos
6
+ assembly_id: assembly_url
@@ -0,0 +1,232 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class VideosControllerTest < ActionController::TestCase
4
+ def setup
5
+ ChiliVideos::Config.update(:api_key => 'key', :workflow => 'workflow')
6
+ @project = Project.generate!.reload
7
+ @user = User.generate!
8
+ User.add_to_project(@user, @project, Role.generate!(:permissions => [:view_video_list, :add_video, :view_specific_video, :delete_video, :modify_videos]))
9
+
10
+ # "log in" the user
11
+ @request.session[:user_id] = @user.id
12
+ end
13
+
14
+ context 'Viewing the videos available to a project' do
15
+ context "when the plugin has not been set up" do
16
+ setup do
17
+ ChiliVideos::Config.update(:api_key => '', :workflow => '')
18
+ end
19
+
20
+ should "renders the 'plugin not set up' page" do
21
+ get :index, :project_id => @project.to_param
22
+ assert_template 'plugin_not_configured'
23
+ end
24
+ end
25
+
26
+ context "when the plugin has been set up" do
27
+ context "and there are unprocessed assemblies" do
28
+ setup do
29
+ Assembly.generate!(:processed => false, :project_id => @project.id)
30
+ end
31
+
32
+ should "set a notification message for the view template" do
33
+ get :index, :project_id => @project.to_param
34
+ assert_not_nil flash[:notice]
35
+ end
36
+ end
37
+
38
+ context "and all assemblies have been processed" do
39
+ setup do
40
+ Assembly.destroy_all
41
+ end
42
+
43
+ should "does not set a notification message for the view template" do
44
+ get :index, :project_id => @project.to_param
45
+ assert_nil flash[:notice]
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ context 'Adding a new video' do
52
+ context "when the plugin has been set up" do
53
+ setup do
54
+ ChiliVideos::Config.update(:api_key => 'key', :workflow => 'workflow')
55
+ end
56
+
57
+ should "renders the upload form" do
58
+ get :new, :project_id => @project.to_param
59
+ assert_template 'new'
60
+ end
61
+
62
+ should 'set up an @api_key instance variable for the view template' do
63
+ get :new, :project_id => @project.to_param
64
+ assert_equal 'key', assigns(:api_key)
65
+ end
66
+
67
+ should 'set up an @workflow instance variable for the view template' do
68
+ get :new, :project_id => @project.to_param
69
+ assert_equal 'workflow', assigns(:workflow)
70
+ end
71
+
72
+ should 'set up a @versions instance variable for the view template' do
73
+ version = Version.generate!(:project_id => @project.id)
74
+ get :new, :project_id => @project.to_param
75
+ assert_equal [version], assigns(:versions)
76
+ end
77
+ end
78
+
79
+ context "when the plugin has not been set up" do
80
+ setup do
81
+ ChiliVideos::Config.update(:api_key => '', :workflow => '')
82
+ end
83
+
84
+ should "renders the 'plugin not set up' page" do
85
+ get :new, :project_id => @project.to_param
86
+ assert_template 'plugin_not_configured'
87
+ end
88
+ end
89
+ end
90
+
91
+ context 'Handling requests from Transload.it' do
92
+ setup do
93
+ Assembly.destroy_all
94
+ stub_assembly_url
95
+ end
96
+
97
+ should 'create a new Assembly' do
98
+ get :upload_complete, workflow_results.merge({'project_id' => @project.to_param})
99
+ assert_equal 1, Assembly.count
100
+ end
101
+
102
+ should 'assigns the assembly to the logged in user' do
103
+ get :upload_complete, workflow_results.merge({'project_id' => @project.to_param})
104
+ assert_equal @user.id, Assembly.first.user_id
105
+ end
106
+ end
107
+
108
+ context "Viewing a specific video associated with a Project" do
109
+ context "when no videos have been associated with the project" do
110
+ setup do
111
+ Video.destroy_all
112
+ get :show, :project_id => @project.to_param, :id => 'nonexistant-video'
113
+ end
114
+
115
+ should "redirect back to the list of project videos" do
116
+ assert_redirected_to(project_videos_path(:project_id => @project.to_param))
117
+ end
118
+
119
+ should "display an error message to the user" do
120
+ assert_not_nil flash[:error]
121
+ end
122
+ end
123
+
124
+ context "when videos have been associated with the project" do
125
+ setup do
126
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
127
+ get :show, :project_id => @project.to_param, :id => @video.to_param
128
+ end
129
+
130
+ should "assign the requested video to @video for the view template" do
131
+ assert_equal @video, assigns(:video)
132
+ end
133
+
134
+ should "assign the project associted with the requested video to @project for the view template" do
135
+ assert_equal @project, assigns(:project)
136
+ end
137
+ end
138
+ end
139
+
140
+ context "Deleting a video" do
141
+ setup do
142
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
143
+ end
144
+
145
+ should "actually delete the video from the database" do
146
+ delete :destroy, :project_id => @project.to_param, :id => @video.to_param
147
+ assert_nil Video.find_by_id(@video.id)
148
+ end
149
+
150
+ should "redirect to the list of videos for the project" do
151
+ delete :destroy, :project_id => @project.to_param, :id => @video.to_param
152
+ assert_redirected_to project_videos_path(@project)
153
+ end
154
+ end
155
+
156
+ context "Editing a video" do
157
+ context "when the requested videos has been associated with the project" do
158
+ setup do
159
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
160
+ end
161
+
162
+ should "render the 'edit' view template" do
163
+ get :edit, :project_id => @project.to_param, :id => @video.to_param
164
+ assert_template("videos/edit")
165
+ end
166
+
167
+ should "loads the specified video for the view template into an @video instance variable" do
168
+ get :edit, :project_id => @project.to_param, :id => @video.to_param
169
+ assert_equal @video, assigns(:video)
170
+ end
171
+
172
+ should "load the associated project for the view template into an @project instance variable" do
173
+ get :edit, :project_id => @project.to_param, :id => @video.to_param
174
+ assert_equal @project, assigns(:project)
175
+ end
176
+
177
+ should "load the the 'versions' associated with the project for the view template into an @versions instance variable" do
178
+ version = @project.versions.create!(:name => "Slippery Slope")
179
+ get :edit, :project_id => @project.to_param, :id => @video.to_param
180
+ assert_equal [version], assigns(:versions)
181
+ end
182
+ end
183
+
184
+ context "when the requested videos has not been associated with the project" do
185
+ setup do
186
+ Video.destroy_all
187
+ get :edit, :project_id => @project.to_param, :id => 'nonexistant-video'
188
+ end
189
+
190
+ should "redirect back to the list of project videos" do
191
+ assert_redirected_to(project_videos_path(:project_id => @project.to_param))
192
+ end
193
+
194
+ should "display an error message to the user" do
195
+ assert_not_nil flash[:error]
196
+ end
197
+ end
198
+ end
199
+
200
+ context "Saving modifications to a video's metadata" do
201
+ context "when the requested videos has been associated with the project" do
202
+ setup do
203
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
204
+ end
205
+
206
+ should "save the new metadata to the video" do
207
+ new_title = "new title"
208
+ put :update, :project_id => @project.to_param, :id => @video.to_param, :video => {:title => new_title}
209
+ assert_equal new_title, @video.reload.title
210
+ end
211
+
212
+ should "redirect back to the page for that specific video" do
213
+ put :update, :project_id => @project.to_param, :id => @video.to_param
214
+ assert_redirected_to project_video_path(@project, @video)
215
+ end
216
+ end
217
+ context "when the requested videos has not been associated with the project" do
218
+ setup do
219
+ Video.destroy_all
220
+ put :update, :project_id => @project.to_param, :id => 'nonexistant-video', :video => {:title => "new title"}
221
+ end
222
+
223
+ should "redirect back to the list of project videos" do
224
+ assert_redirected_to(project_videos_path(:project_id => @project.to_param))
225
+ end
226
+
227
+ should "display an error message to the user" do
228
+ assert_not_nil flash[:error]
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,104 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ProjectVideoListTest < 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')
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 "Clicking the 'Videos' tab on a Project page" do
16
+ setup do
17
+ visit_project(@project)
18
+ click_link("Videos")
19
+ end
20
+
21
+ should "take you to the project's list of videos" do
22
+ assert_equal project_videos_path(@project), current_path
23
+ end
24
+
25
+ context "when no videos exist" do
26
+ setup do
27
+ Video.destroy_all
28
+ end
29
+
30
+ should "display a link to add a new video to the project in the contextual menu" do
31
+ within("div.contextual") do
32
+ assert_have_selector("a", :href => new_project_video_path(@project))
33
+ end
34
+ end
35
+ end
36
+
37
+ context "when the ChiliVideo plugin has not been configured" do
38
+ setup do
39
+ ChiliVideos::Config.update(:api_key => '', :workflow => '')
40
+ end
41
+
42
+ should "display a message telling the user to set up the plugin on the plugin administration page" do
43
+ visit(project_videos_path(@project))
44
+ within("p.warning") do
45
+ assert_have_selector('a', :href => '/settings/plugin/chili_videos')
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ context "Viewing the list of uploaded videos associated with a Project" do
52
+ context "when no videos have been associated with the project" do
53
+ setup do
54
+ Video.destroy_all
55
+ visit(project_videos_path(@project))
56
+ end
57
+
58
+ should "display a 'no videos' message" do
59
+ assert_have_selector('p.nodata')
60
+ end
61
+
62
+ should "display a link to upload one in the 'no videos' message area" do
63
+ within('p.nodata') do
64
+ assert_have_selector('a', :href => new_project_video_path(@project))
65
+ end
66
+ end
67
+
68
+ should "not have a list of videos" do
69
+ assert_have_no_selector('ul.videos')
70
+ end
71
+ end
72
+
73
+ context "when videos have been associated with the project" do
74
+ setup do
75
+ @video = Video.create!(:title => "Video 1", :description => "Description...", :url => "http://some-url-here.com/", :project_id => @project.id, :user_id => @user.id)
76
+ visit(project_videos_path(@project))
77
+ end
78
+
79
+ should "show a list of videos" do
80
+ within(".videos") do
81
+ assert_have_selector(".video")
82
+ end
83
+ end
84
+
85
+ context "a video in the list" do
86
+ should "have an id which matches the video's database id" do
87
+ within("ul.videos") do
88
+ assert_have_selector(".video##{@video.to_param}")
89
+ end
90
+ end
91
+
92
+ should "include the video title as a link to the 'show' page" do
93
+ within(".videos .video##{@video.to_param} a[href='#{project_video_path(@project, @video)}']") do
94
+ assert_match(/#{@video.title}/, response.body)
95
+ end
96
+ end
97
+ end
98
+
99
+ should "not display a 'no videos' message" do
100
+ assert_have_no_selector('p.nodata')
101
+ end
102
+ end
103
+ end
104
+ end