Save track files in new Sound model:

* Consolidate migrations
* Add Sound model. Each sound can belong to a track and contains
  informations about one sound file.
This commit is contained in:
Thibault Jouan
2011-09-15 21:08:24 +00:00
parent f49a5a3f67
commit 27550fd14e
26 changed files with 265 additions and 216 deletions

View File

@@ -0,0 +1,25 @@
require 'spec_helper'
describe SoundsController do
before do
controller.current_user = Factory.create(:user)
end
describe 'GET show' do
let(:sound) { Factory.create(:sound) }
def do_show
get :show, :id => sound.id
end
it 'sends the sound file as the response body' do
do_show
response.body.should == File.read(sound.path)
end
it 'sets the sound file mime-type as the response content-type' do
do_show
response.content_type.should == sound.mime_type
end
end
end

View File

@@ -13,20 +13,6 @@ describe TracksController do
end
end
describe 'GET download' do
let(:track) { Factory.create(:track) }
it 'streams the requested track' do
get :download, :id => track.id.to_s
response.should be_success
end
it 'returns the track mime-type as content-type' do
get :download, :id => track.id.to_s
response.content_type.should == track.mime_type
end
end
describe 'GET new' do
it 'assigns a new track as @track' do
get :new
@@ -35,48 +21,46 @@ describe TracksController do
end
describe 'POST create' do
let(:track) { mock_model(Track).as_null_object }
let(:file) {
fixture_file_upload("#{Rails.root}/spec/fixtures/test.mp3", 'audio/mpeg')
}
before { Track.stub(:new).and_return(track) }
let(:track) { mock_model(Track).as_null_object }
let(:attributes) { Factory.attributes_for(:track).stringify_keys }
it 'creates a new track' do
attributes = Factory.attributes_for(:track)
Track.should_receive(:new).
with({:name => attributes[:name]}).
and_return(track)
post :create, :track => {
:name => attributes[:name],
:file => file
}
before do
Track.stub(:new).and_return(track)
end
it 'saves the track with a file' do
track.should_receive(:save_with_file).
with(file, 'audio/mpeg')
post :create, :track => { :file => file }
def do_create
post :create, :track => attributes
end
it 'creates a new track' do
Track.should_receive(:new).with(attributes)
do_create
end
it 'saves the track' do
track.should_receive :save
do_create
end
context 'when the track saves successfully' do
it 'redirects to the track page' do
post :create, :track => { :file => file }
do_create
response.should redirect_to(track)
end
end
context 'when the track fails to save' do
before do
track.stub(:save_with_file).and_return(false)
track.stub(:save).and_return(false)
end
it 'assigns the track as @track' do
post :create, :track => { :file => file }
do_create
assigns[:track].should == track
end
it 'renders the new template' do
post :create, :track => { :file => file }
do_create
response.should render_template('new')
end
end

View File

@@ -1,16 +1,24 @@
def build_sound_file
file = File.new("#{Rails.root}/spec/fixtures/test.mp3")
file.stub(:content_type => 'audio/mpeg')
file
end
FactoryGirl.define do
factory :playlist do
name 'Electro'
user
end
factory :sound do
file { build_sound_file }
end
factory :track do
name 'Mega song'
mime_type 'audio/ogg'
sha256 '94a5486a69a7261da350c57f9e5a1eaa789e08752cfc56a1989976a6ad82f7a8'
after_create do |t|
t.save_with_file(File.new("#{Rails.root}/spec/fixtures/test.mp3"), 'audio/mpeg')
factory :track_with_sound do
file { build_sound_file }
end
end

View File

@@ -28,17 +28,15 @@ feature 'Tracks' do
end
scenario 'plays track' do
track = Factory.create(:track, :name => 'Mega song')
file = File.new("#{Rails.root}/spec/fixtures/test.mp3")
track.save_with_file(file, 'audio/mpeg')
track = Factory.create(:track_with_sound)
visit track_path(track)
page.should have_xpath "//audio[@src='#{download_track_path(track)}']"
page.should have_xpath "//audio[@src='#{sound_path(track.sound)}']"
visit find('audio')[:src]
end
after do
`rm -f #{Rails.root}/data/tracks/*`
`rm -f #{Rails.root}/data/sounds/*`
end
end

46
spec/models/sound_spec.rb Normal file
View File

@@ -0,0 +1,46 @@
require 'spec_helper'
describe Sound do
subject { sound }
let(:sound) { Factory.build(:sound) }
context 'with valid attributes' do
it { should be_valid }
end
context 'when sha256 empty' do
before { sound.sha256 = '' }
it { should_not be_valid }
end
context 'when mime_type empty' do
before { sound.mime_type = '' }
it { should_not be_valid }
end
describe '#path' do
it 'returns the sound file path based on the SHA256 digest' do
sound.path.should == "#{Rails.root}/data/sounds/#{sound.sha256}"
end
end
describe '#file=' do
let (:file) { Factory.attributes_for(:sound)[:file] }
it 'saves the file SHA256 digest' do
sound.sha256.should == Digest::SHA256.file(file.path).hexdigest
end
it 'copies the file to #path' do
File.read(sound.path).should == file.read
end
it 'saves the file MIME type' do
sound.mime_type.should == 'audio/mpeg'
end
end
after do
`rm -f #{Rails.root}/data/sounds/*`
end
end

View File

@@ -1,7 +1,7 @@
require 'spec_helper'
describe Track do
subject { track }
subject { track }
let(:track) { Factory.build(:track) }
context 'with valid attributes' do
@@ -13,47 +13,49 @@ describe Track do
it { should_not be_valid }
end
context 'when mime_type empty' do
before { track.mime_type = '' }
it { should_not be_valid }
end
context 'when sha256 empty' do
before { track.sha256 = '' }
it { should_not be_valid }
end
describe '#filepath' do
it 'returns the path to the track file' do
track.filepath.should == "#{Rails.root}/data/tracks/#{track.sha256}"
describe '#file=' do
it 'builds a new related sound with the file' do
file = Factory.attributes_for(:track_with_sound)[:file]
sounds = mock('sounds association proxy')
track.stub(:sounds => sounds)
sounds.should_receive(:build).with({:file => file})
track.file = file
end
end
describe '#save_with_file' do
let(:file) { File.new("#{Rails.root}/spec/fixtures/test.mp3") }
describe '#sounds' do
it 'responds to sound' do
track.should respond_to(:sounds)
end
end
it 'calls save' do
Track.any_instance.should_receive(:save!)
track.save_with_file(file, 'audio/ogg')
describe '#sound' do
context 'with a sound' do
before do
track.sounds << Factory.create(:sound)
end
it 'returns a sound' do
track.sound.should be_a(Sound)
end
end
end
describe '#sound?' do
context 'without a sound' do
it 'returns false' do
track.sound?.should be_false
end
end
it 'saves the file content' do
track.save_with_file(file, 'audio/ogg')
File.read(track.filepath).should == File.read(file.path)
end
context 'with a sound' do
before do
track.sounds << Factory.create(:sound)
end
it 'saves the file SHA256 digest' do
track.save_with_file(file, 'audio/ogg')
track.sha256.should == Digest::SHA256.file(file.path).hexdigest
end
it 'saves the file mime type' do
track.save_with_file(file, 'audio/mpeg')
track.mime_type.should == 'audio/mpeg'
end
after do
`rm -f #{Rails.root}/data/tracks/*`
it 'returns true' do
track.sound?.should be_true
end
end
end

View File

@@ -1,9 +1,7 @@
require 'spec_helper'
describe 'tracks/show.html.haml' do
let(:track) do
mock_model('Track', :name => 'Mega song')
end
let(:track) { Factory.create(:track) }
before do
assign :track, track
@@ -14,7 +12,9 @@ describe 'tracks/show.html.haml' do
rendered.should have_selector('h1', :text => 'Mega song')
end
context 'audio tag' do
context 'when track has a sound' do
let(:track) { Factory.create(:track_with_sound) }
it 'provides an audio stream for the track' do
render
rendered.should have_selector('audio[src]')