rbpod 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  /* playlist_collection.c */
2
2
 
3
3
  #include "rbpod.h"
4
+ #include "database.h"
4
5
  #include "playlist.h"
5
6
  #include "collection.h"
6
7
  #include "playlist_collection.h"
@@ -9,7 +10,7 @@
9
10
  * call-seq:
10
11
  * database() -> RbPod::Database
11
12
  *
12
- * The database from which this collection of playlists is attached to.
13
+ * Returns the database this playlist collection is attached to.
13
14
  */
14
15
  static VALUE rbpod_playlist_collection_database(VALUE self)
15
16
  {
@@ -18,65 +19,92 @@ static VALUE rbpod_playlist_collection_database(VALUE self)
18
19
 
19
20
  /*
20
21
  * call-seq:
21
- * [](index) -> RbPod::Playlist
22
- * [](name) -> RbPod::Playlist
22
+ * include?(playlist) -> Boolean
23
23
  *
24
- * Returns a playlist by either position or name in the collection, or nil if it wasn't found.
24
+ * Returns true or false if the given RbPod::Playlist +playlist+ exists within the database.
25
25
  */
26
- static VALUE rbpod_playlist_collection_get(VALUE self, VALUE key)
26
+ static VALUE rbpod_playlist_collection_include_p(VALUE self, VALUE playlist)
27
27
  {
28
- VALUE parent = rbpod_playlist_collection_database(self);
29
- Itdb_iTunesDB *database = TYPED_DATA_PTR(parent, Itdb_iTunesDB);
30
- Itdb_Playlist *playlist = NULL;
31
- int key_type = TYPE(key);
32
-
33
- if (key_type == T_SYMBOL || key_type == T_STRING) {
34
- playlist = itdb_playlist_by_name(database, StringValueCStr(key));
35
- return Data_Wrap_Struct(cRbPodPlaylist, NULL, NULL, (void *) playlist);
28
+ VALUE database = rbpod_playlist_collection_database(self);
29
+ Itdb_iTunesDB *_database = TYPED_DATA_PTR(database, Itdb_iTunesDB);
30
+ Itdb_Playlist *_playlist = TYPED_DATA_PTR(playlist, Itdb_Playlist);
31
+
32
+ if (rb_obj_is_instance_of(playlist, cRbPodPlaylist) == FALSE) {
33
+ rb_raise(eRbPodError, "Invalid argument: expected RbPod::Playlist, got %s", StringValueCStr(playlist));
34
+ return Qfalse;
36
35
  }
37
36
 
38
- if (key_type == T_FIXNUM) {
39
- playlist = itdb_playlist_by_nr(database, FIX2INT(key));
40
- return Data_Wrap_Struct(cRbPodPlaylist, NULL, NULL, (void *) playlist);
37
+ return BooleanValue(itdb_playlist_exists(_database, _playlist));
38
+ }
39
+
40
+ /*
41
+ * call-seq:
42
+ * master() -> RbPod::Playlist
43
+ *
44
+ * Returns the master playlist from the database.
45
+ */
46
+ static VALUE rbpod_playlist_collection_master(VALUE self)
47
+ {
48
+ VALUE database = rbpod_playlist_collection_database(self);
49
+ Itdb_iTunesDB *_database = TYPED_DATA_PTR(database, Itdb_iTunesDB);
50
+ Itdb_Playlist *_playlist = itdb_playlist_mpl(_database);
51
+
52
+ if (_playlist == NULL) {
53
+ return Qnil;
41
54
  }
42
55
 
43
- return Qnil;
56
+ /* Create a new instance of the master playlist from the data provided. */
57
+ return rb_class_new_instance_with_data(0, NULL, cRbPodPlaylist, _playlist);
44
58
  }
45
59
 
46
60
  /*
47
61
  * call-seq:
48
62
  * podcast() -> RbPod::Playlist
49
63
  *
50
- * Returns the podcast playlist in this collection.
64
+ * Returns the podcast playlist from the database.
51
65
  */
52
- static VALUE rbpod_playlist_collection_podcast_get(VALUE self)
66
+ static VALUE rbpod_playlist_collection_podcast(VALUE self)
53
67
  {
54
- VALUE parent = rbpod_playlist_collection_database(self);
55
- Itdb_iTunesDB *database = TYPED_DATA_PTR(parent, Itdb_iTunesDB);
56
- Itdb_Playlist *podcasts = itdb_playlist_podcasts(database);
57
- return Data_Wrap_Struct(cRbPodPlaylist, NULL, NULL, (void *) podcasts);
68
+ VALUE database = rbpod_playlist_collection_database(self);
69
+ Itdb_iTunesDB *_database = TYPED_DATA_PTR(database, Itdb_iTunesDB);
70
+ Itdb_Playlist *_playlist = itdb_playlist_podcasts(_database);
71
+
72
+ if (_playlist == NULL) {
73
+ return Qnil;
74
+ }
75
+
76
+ /* Create a new instance of the podcast playlist from the data provided. */
77
+ return rb_class_new_instance_with_data(0, NULL, cRbPodPlaylist, _playlist);
58
78
  }
59
79
 
60
80
  /*
61
81
  * call-seq:
62
- * master() -> RbPod::Playlist
82
+ * initialize(database) -> RbPod::PlaylistCollection
63
83
  *
64
- * Returns the master playlist in this collection.
84
+ * Given an RbPod::Database +database+ creates a collection of playlists from it.
65
85
  */
66
- static VALUE rbpod_playlist_collection_master_get(VALUE self)
86
+ static VALUE rbpod_playlist_collection_initialize(VALUE self, VALUE database)
67
87
  {
68
- VALUE parent = rbpod_playlist_collection_database(self);
69
- Itdb_iTunesDB *database = TYPED_DATA_PTR(parent, Itdb_iTunesDB);
70
- Itdb_Playlist *master = itdb_playlist_mpl(database);
71
- return Data_Wrap_Struct(cRbPodPlaylist, NULL, NULL, (void *) master);
88
+ Itdb_iTunesDB *_database = TYPED_DATA_PTR(database, Itdb_iTunesDB);
89
+
90
+ if (rb_obj_is_instance_of(database, cRbPodDatabase) == FALSE) {
91
+ rb_raise(eRbPodError, "Invalid Arguments: Expected RbPod::Database, got %s", StringValueCStr(database));
92
+ return Qnil;
93
+ }
94
+
95
+ rb_iv_set(self, "@database", database);
96
+
97
+ DATA_PTR(self) = _database->playlists;
98
+
99
+ return self;
72
100
  }
73
101
 
74
- inline VALUE rbpod_playlist_collection_create(VALUE database, GList *items)
102
+ /*
103
+ * :nodoc:
104
+ */
105
+ static VALUE rbpod_playlist_collection_type(VALUE self)
75
106
  {
76
- VALUE collection = rbpod_collection_create(items, cRbPodPlaylist);
77
- rb_extend_object(collection, mRbPodPlaylistCollection);
78
- rb_iv_set(collection, "@database", database);
79
- return collection;
107
+ return cRbPodPlaylist;
80
108
  }
81
109
 
82
110
  void Init_rbpod_playlist_collection(void)
@@ -84,15 +112,20 @@ void Init_rbpod_playlist_collection(void)
84
112
  #if RDOC_CAN_PARSE_DOCUMENTATION
85
113
  mRbPod = rb_define_module("RbPod");
86
114
  #endif
87
- /* This module extends any collection of playlists at runtime. */
88
- mRbPodPlaylistCollection = rb_define_module_under(mRbPod, "PlaylistCollection");
115
+ cRbPodPlaylistCollection = rb_define_class_under(mRbPod, "PlaylistCollection", rb_cObject);
116
+
117
+ rb_real_include_module(cRbPodPlaylistCollection, mRbPodCollection);
118
+
119
+ rb_define_private_method(cRbPodPlaylistCollection, "type", rbpod_playlist_collection_type, 0);
120
+
121
+ rb_define_method(cRbPodPlaylistCollection, "initialize", rbpod_playlist_collection_initialize, 1);
89
122
 
90
- rb_define_method(mRbPodPlaylistCollection, "database", rbpod_playlist_collection_database, 0);
123
+ rb_define_method(cRbPodPlaylistCollection, "database", rbpod_playlist_collection_database, 0);
91
124
 
92
- rb_define_method(mRbPodPlaylistCollection, "master", rbpod_playlist_collection_master_get, 0);
93
- rb_define_method(mRbPodPlaylistCollection, "podcast", rbpod_playlist_collection_podcast_get, 0);
125
+ rb_define_method(cRbPodPlaylistCollection, "include?", rbpod_playlist_collection_include_p, 1);
94
126
 
95
- rb_define_method(mRbPodPlaylistCollection, "[]", rbpod_playlist_collection_get, 1);
127
+ rb_define_method(cRbPodPlaylistCollection, "master", rbpod_playlist_collection_master, 0);
128
+ rb_define_method(cRbPodPlaylistCollection, "podcast", rbpod_playlist_collection_podcast, 0);
96
129
 
97
130
  return;
98
131
  }
@@ -3,12 +3,8 @@
3
3
  #ifndef RBPOD_PLAYLIST_COLLECTION_H
4
4
  #define RBPOD_PLAYLIST_COLLECTION_H
5
5
 
6
- #include "playlist.h"
7
-
8
- RUBY_EXTERN VALUE mRbPodPlaylistCollection;
6
+ RUBY_EXTERN VALUE cRbPodPlaylistCollection;
9
7
 
10
8
  void Init_rbpod_playlist_collection(void);
11
9
 
12
- inline VALUE rbpod_playlist_collection_create(VALUE parent, GList *items);
13
-
14
10
  #endif /* RBPOD_PLAYLIST_COLLECTION_H */
data/ext/rbpod/rbpod.c CHANGED
@@ -1,6 +1,7 @@
1
1
  /* rbpod.c */
2
2
 
3
3
  #include "rbpod.h"
4
+ #include "error.h"
4
5
  #include "track.h"
5
6
  #include "device.h"
6
7
  #include "playlist.h"
@@ -15,28 +16,15 @@ VALUE eRbPodError;
15
16
  VALUE cRbPodDatabase;
16
17
  VALUE cRbPodDevice;
17
18
 
18
- VALUE cRbPodCollection;
19
-
20
- VALUE cRbPodPlaylist;
21
- VALUE mRbPodPlaylistCollection;
22
-
23
19
  VALUE cRbPodTrack;
24
- VALUE mRbPodTrackCollection;
25
-
26
- VALUE rb_cPathname;
20
+ VALUE cRbPodPlaylist;
27
21
 
28
- inline VALUE rbpod_raise_error(GError *error)
29
- {
30
- VALUE error_message;
22
+ VALUE mRbPodCollection;
31
23
 
32
- if (error != NULL) {
33
- error_message = rb_str_new2(error->message);
34
- g_error_free(error);
35
- rb_raise(eRbPodError, "%s", StringValueCStr(error_message));
36
- }
24
+ VALUE cRbPodTrackCollection;
25
+ VALUE cRbPodPlaylistCollection;
37
26
 
38
- return Qnil;
39
- }
27
+ VALUE rb_cPathname;
40
28
 
41
29
  /*
42
30
  * call-seq:
@@ -50,16 +38,38 @@ static VALUE rbpod_load_database(VALUE self, VALUE mount_point)
50
38
  return rb_class_new_instance(1, &mount_point, cRbPodDatabase);
51
39
  }
52
40
 
41
+ /*
42
+ * This is a hack used to inject a pointer from the data of one class instance into another.
43
+ */
44
+ inline VALUE rb_class_new_instance_with_data(int argc, VALUE *argv, VALUE class, void *handle)
45
+ {
46
+ /* Create a new instance of this class. */
47
+ VALUE instance = rb_class_new_instance(argc, argv, class);
48
+
49
+ /* Assign it's DATA pointer to the given handle. */
50
+ DATA_PTR(instance) = handle;
51
+
52
+ return instance;
53
+ }
54
+
55
+ /*
56
+ * This is a hack so that including a module will trigger the +included+ singleton method.
57
+ */
58
+ inline void rb_real_include_module(VALUE klass, VALUE module)
59
+ {
60
+ ID included = rb_intern("included");
61
+
62
+ rb_include_module(klass, module);
63
+
64
+ rb_funcall(mRbPodCollection, included, 1, klass);
65
+ }
66
+
53
67
  void Init_rbpod(void)
54
68
  {
55
69
  /* This is the wrapper for all RbPod related classes. */
56
70
  mRbPod = rb_define_module("RbPod");
57
71
 
58
- /* This is a generic subclass of RuntimeError for RbPod-specific errors.*/
59
- eRbPodError = rb_define_class_under(mRbPod, "Error", rb_eRuntimeError);
60
-
61
- rb_cPathname = rb_const_get(rb_cObject, rb_intern("Pathname"));
62
-
72
+ Init_rbpod_error();
63
73
  Init_rbpod_database();
64
74
  Init_rbpod_device();
65
75
  Init_rbpod_collection();
@@ -70,6 +80,8 @@ void Init_rbpod(void)
70
80
 
71
81
  rb_define_global_function("RbPod", rbpod_load_database, 1);
72
82
 
83
+ rb_cPathname = rb_const_get(rb_cObject, rb_intern("Pathname"));
84
+
73
85
  return;
74
86
  }
75
87
 
data/ext/rbpod/rbpod.h CHANGED
@@ -15,6 +15,8 @@ RUBY_EXTERN VALUE eRbPodError;
15
15
 
16
16
  RUBY_EXTERN VALUE rb_cPathname;
17
17
 
18
- inline VALUE rbpod_raise_error(GError *error);
18
+ inline VALUE rb_class_new_instance_with_data(int argc, VALUE *argv, VALUE class, void *handle);
19
+
20
+ inline void rb_real_include_module(VALUE klass, VALUE module);
19
21
 
20
22
  #endif /* RBPOD_H */
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "rbpod.h"
4
4
  #include "track.h"
5
+ #include "playlist.h"
5
6
  #include "collection.h"
6
7
  #include "track_collection.h"
7
8
 
@@ -9,19 +10,41 @@
9
10
  * call-seq:
10
11
  * playlist() -> RbPod::Playlist
11
12
  *
12
- * The playlist from which this collection of tracks is attached to.
13
+ * Returns the playlist this track collection is attached to.
13
14
  */
14
15
  static VALUE rbpod_track_collection_playlist(VALUE self)
15
16
  {
16
- return rb_iv_get(self, "@pkaylist");
17
+ return rb_iv_get(self, "@playlist");
17
18
  }
18
19
 
19
- inline VALUE rbpod_track_collection_create(VALUE playlist, GList *items)
20
+ /*
21
+ * call-seq:
22
+ * initialize(playlist) -> RbPod::TrackCollection
23
+ *
24
+ * Given an RbPod::Playlist +playlist+, returns a collection of tracks within the playlist.
25
+ */
26
+ static VALUE rbpod_track_collection_initialize(VALUE self, VALUE playlist)
27
+ {
28
+ Itdb_Playlist *_playlist = TYPED_DATA_PTR(playlist, Itdb_Playlist);
29
+
30
+ if (rb_obj_is_instance_of(playlist, cRbPodPlaylist) == FALSE) {
31
+ rb_raise(eRbPodError, "Invalid Arguments: Expected RbPod::Playlist, got %s", StringValueCStr(playlist));
32
+ return Qnil;
33
+ }
34
+
35
+ rb_iv_set(self, "@playlist", playlist);
36
+
37
+ DATA_PTR(self) = _playlist->members;
38
+
39
+ return self;
40
+ }
41
+
42
+ /*
43
+ * :nodoc:
44
+ */
45
+ static VALUE rbpod_track_collection_type(VALUE self)
20
46
  {
21
- VALUE collection = rbpod_collection_create(items, cRbPodTrack);
22
- rb_extend_object(collection, mRbPodTrackCollection);
23
- rb_iv_set(collection, "@playlist", playlist);
24
- return collection;
47
+ return cRbPodTrack;
25
48
  }
26
49
 
27
50
  void Init_rbpod_track_collection(void)
@@ -29,10 +52,15 @@ void Init_rbpod_track_collection(void)
29
52
  #if RDOC_CAN_PARSE_DOCUMENTATION
30
53
  mRbPod = rb_define_module("RbPod");
31
54
  #endif
32
- /* This module extends any collection of tracks at runtime. */
33
- mRbPodTrackCollection = rb_define_module_under(mRbPod, "TrackCollection");
55
+ cRbPodTrackCollection = rb_define_class_under(mRbPod, "TrackCollection", rb_cObject);
56
+
57
+ rb_real_include_module(cRbPodTrackCollection, mRbPodCollection);
58
+
59
+ rb_define_method(cRbPodTrackCollection, "initialize", rbpod_track_collection_initialize, 1);
60
+
61
+ rb_define_private_method(cRbPodTrackCollection, "type", rbpod_track_collection_type, 0);
34
62
 
35
- rb_define_method(mRbPodTrackCollection, "playlist", rbpod_track_collection_playlist, 0);
63
+ rb_define_method(cRbPodTrackCollection, "playlist", rbpod_track_collection_playlist, 0);
36
64
 
37
65
  return;
38
66
  }
@@ -3,12 +3,8 @@
3
3
  #ifndef RBPOD_TRACK_COLLECTION_H
4
4
  #define RBPOD_TRACK_COLLECTION_H
5
5
 
6
- #include "track.h"
7
-
8
- RUBY_EXTERN VALUE mRbPodTrackCollection;
6
+ RUBY_EXTERN VALUE cRbPodTrackCollection;
9
7
 
10
8
  void Init_rbpod_track_collection(void);
11
9
 
12
- inline VALUE rbpod_track_collection_create(VALUE parent, GList *items);
13
-
14
10
  #endif /* RBPOD_TRACK_COLLECTION_H */
data/lib/rbpod/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RbPod # :nodoc:
2
- VERSION = "0.0.4" # :nodoc:
2
+ VERSION = "0.0.5" # :nodoc:
3
3
  end
@@ -0,0 +1,25 @@
1
+ shared_examples_for RbPod::Collection do
2
+ it 'should be a collection' do
3
+ collection.should be_kind_of(RbPod::Collection)
4
+ end
5
+
6
+ it 'should implement #each' do
7
+ collection.should respond_to(:each)
8
+ end
9
+
10
+ it 'should implement #size' do
11
+ collection.should respond_to(:size)
12
+ end
13
+
14
+ it 'should implement #first' do
15
+ collection.should respond_to(:first)
16
+ end
17
+
18
+ it 'should implement #last' do
19
+ collection.should respond_to(:last)
20
+ end
21
+
22
+ it 'should implement #[]' do
23
+ collection.should respond_to(:[])
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  describe RbPod::Database do
2
- context 'Overall' do
2
+ context 'Without a new database' do
3
3
  describe '.create!' do
4
4
  it 'should create an empty default database and load it' do
5
5
  within_temporary_directory do |directory|
@@ -33,55 +33,48 @@ describe RbPod::Database do
33
33
  end
34
34
  end
35
35
 
36
- context 'Given a blank database' do
37
- before do
38
- @directory = within_temporary_directory
39
- @database = RbPod::Database.create!(@directory)
40
- end
41
-
42
- after do
43
- # This is a godawful hack.
44
- FileUtils.remove_entry_secure(@directory)
45
- end
36
+ context 'With a new database' do
37
+ include_context 'a new database'
46
38
 
47
39
  describe '#initialize' do
48
40
  it 'should return a Database instance' do
49
- @database.should be_instance_of(RbPod::Database)
41
+ database.should be_instance_of(RbPod::Database)
50
42
  end
51
43
  end
52
44
 
53
45
  describe '#mountpoint' do
54
46
  it 'should match the mount point it was loaded from' do
55
- @database.mountpoint.to_s.should == @directory
47
+ database.mountpoint.to_s.should == directory
56
48
  end
57
49
  end
58
50
 
59
51
  describe '#filename' do
60
52
  it 'should be an existing iTunes database on the file system' do
61
- File.exists?(@database.filename).should be_true
53
+ File.exists?(database.filename).should be_true
62
54
  end
63
55
  end
64
56
 
65
57
  describe '#device' do
66
58
  it 'should return a Device instance' do
67
- @database.device.should be_instance_of(RbPod::Device)
59
+ database.device.should be_instance_of(RbPod::Device)
68
60
  end
69
61
  end
70
62
 
71
63
  describe '#synchronized?' do
72
64
  it 'should be marked as synchronized' do
73
- @database.should be_synchronized
65
+ database.should be_synchronized
74
66
  end
75
67
  end
76
68
 
77
69
  describe '#playlists' do
78
- it 'should return a collection' do
79
- @database.playlists.should be_instance_of(RbPod::Collection)
70
+ it 'should return a playlist collection' do
71
+ database.playlists.should be_instance_of(RbPod::PlaylistCollection)
80
72
  end
73
+ end
81
74
 
82
- it 'should have a single master playlist' do
83
- @database.playlists.length.should eq(1)
84
- @database.playlists.first.is_master_playlist?.should be_true
75
+ describe '#tracks' do
76
+ it 'should return a track collection' do
77
+ database.tracks.should be_instance_of(RbPod::TrackCollection)
85
78
  end
86
79
  end
87
80
  end
@@ -0,0 +1,70 @@
1
+ describe RbPod::Device do
2
+ context 'On a device backed by a new database' do
3
+ include_context 'a new database'
4
+
5
+ let(:device) { database.device }
6
+
7
+ describe '#[]' do
8
+ it 'should return a nil value for any key' do
9
+ device['ModelNumStr'].should be_nil
10
+ end
11
+
12
+ it 'should return nil with an invalid key' do
13
+ device['NonExistentValue'].should be_nil
14
+ end
15
+
16
+ it 'should return nil when unsetting a key' do
17
+ device['NotARealKey'] = nil
18
+ device['NotARealKey'].should be_nil
19
+ end
20
+ end
21
+
22
+ describe '#save!' do
23
+ it 'should return nil' do
24
+ device.save!.should eq(nil)
25
+ end
26
+ end
27
+
28
+ describe '#uuid' do
29
+ it 'should be nil' do
30
+ device.uuid.should eq(nil)
31
+ end
32
+ end
33
+
34
+ describe '#capacity' do
35
+ it 'should be zero' do
36
+ device.capacity.should be_kind_of(Float)
37
+ device.capacity.should eq(0.0)
38
+ end
39
+ end
40
+
41
+ describe '#generation' do
42
+ it 'should be "Unknown"' do
43
+ device.generation.should be_kind_of(String)
44
+ device.generation.should eq('Unknown')
45
+ end
46
+ end
47
+
48
+ describe '#model_name' do
49
+ it 'should be "Invalid"' do
50
+ device.model_name.should be_kind_of(String)
51
+ device.model_name.should eq('Invalid')
52
+ end
53
+ end
54
+
55
+ describe '#model_number' do
56
+ it 'should be "Invalid"' do
57
+ device.model_number.should be_kind_of(String)
58
+ device.model_number.should eq('Invalid')
59
+ end
60
+ end
61
+
62
+ %w[photos videos artwork podcasts chapter_images].each do |feature|
63
+ describe "#supports_#{feature}?" do
64
+ it 'should be false' do
65
+ device.send("supports_#{feature}?").should be_false
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,44 @@
1
+ describe RbPod::PlaylistCollection do
2
+ it_behaves_like RbPod::Collection
3
+ # Create a temporary database for the test.
4
+ include_context 'a new database'
5
+
6
+ # Use it as a parent to the playlist collection.
7
+ let (:collection) { RbPod::PlaylistCollection.new(database) }
8
+
9
+ describe '#database' do
10
+ it 'should return the parent database' do
11
+ collection.database.should eq(database)
12
+ collection.database.should be_kind_of(RbPod::Database)
13
+ end
14
+ end
15
+
16
+ describe '#master' do
17
+ it 'should return a playlist' do
18
+ collection.master.should be_kind_of(RbPod::Playlist)
19
+ end
20
+
21
+ it 'should be marked as the master playlist' do
22
+ collection.master.should be_master
23
+ end
24
+ end
25
+
26
+ describe '#podcast' do
27
+ context 'on a new database' do
28
+ it 'should return nil' do
29
+ collection.podcast.should be_nil
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '#include?' do
35
+ it 'should detect the master playlist' do
36
+ collection.include?(collection.master).should be_true
37
+ end
38
+
39
+ it 'should not detect a new playlist' do
40
+ anonymous_playlist = RbPod::Playlist.new()
41
+ collection.include?(anonymous_playlist).should be_false
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  describe RbPod::Playlist do
2
-
2
+ # Nothing yet.
3
3
  end
@@ -0,0 +1,15 @@
1
+ describe RbPod::TrackCollection do
2
+ it_behaves_like RbPod::Collection
3
+ # A track collection only requires a playlist, so we don't need a database.
4
+ let(:playlist) { RbPod::Playlist.new() }
5
+
6
+ # Use the new playlist as a parent for this track collection.
7
+ let(:collection) { described_class.new(playlist) }
8
+
9
+ describe '#playlist' do
10
+ it 'should return the parent playlist' do
11
+ collection.playlist.should eq(playlist)
12
+ collection.playlist.should be_kind_of(RbPod::Playlist)
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  describe RbPod::Track do
2
-
2
+ # Nothing yet.
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,8 @@ require 'rspec'
2
2
  require 'rbpod'
3
3
  require 'tmpdir'
4
4
 
5
+ require 'support/shared_contexts'
6
+
5
7
  RSpec.configure do |config|
6
8
  config.color_enabled = true
7
9
  config.formatter = 'documentation'
@@ -0,0 +1,18 @@
1
+ shared_context 'a new database' do
2
+ # Create a temporary folder and initialize a database in it.
3
+ before(:all) do
4
+ @directory = within_temporary_directory
5
+ @database = RbPod::Database.create!(@directory)
6
+ end
7
+
8
+ # This is a godawful hack, but it's needed to clean up after the tests finish.
9
+ after(:all) do
10
+ FileUtils.remove_entry_secure(@directory)
11
+ end
12
+
13
+ # Temporary directory for database.
14
+ let(:directory) { @directory }
15
+
16
+ # The database instance itself.
17
+ let(:database) { @database }
18
+ end