@ -122,4 +122,147 @@ struct SmartPlaylistTests {
if case . int ( let y ) = decoded [ 1 ] . value { # expect ( y = = 1960 ) } else { Issue . record ( " Expected int " ) }
if case . int ( let y ) = decoded [ 1 ] . value { # expect ( y = = 1960 ) } else { Issue . record ( " Expected int " ) }
if case . date ( let d ) = decoded [ 2 ] . value { # expect ( d = = Date ( timeIntervalSince1970 : 0 ) ) } else { Issue . record ( " Expected date " ) }
if case . date ( let d ) = decoded [ 2 ] . value { # expect ( d = = Date ( timeIntervalSince1970 : 0 ) ) } else { Issue . record ( " Expected date " ) }
}
}
// C r e a t e s a n i n - m e m o r y D B ( w h i c h r u n s a l l m i g r a t i o n s i n c l u d i n g v 5 ) a n d v e r i f i e s
// t h a t e x i s t i n g F T S s m a r t p l a y l i s t s ( c o n d i t i o n s = n i l ) s t i l l l o a d c o r r e c t l y .
@ Test func existingFTSPlaylistSurvivesMigration ( ) throws {
// S t e p 1 : C r e a t e D B — m i g r a t i o n v 5 r u n s a u t o m a t i c a l l y , a d d i n g t h e c o n d i t i o n s c o l u m n
// S t e p 2 : C r e a t e a F T S s m a r t p l a y l i s t u s i n g t h e o l d s e a r c h Q u e r y p a t h
// S t e p 3 : F e t c h i t b a c k a n d v e r i f y c o n d i t i o n s i s n i l , s e a r c h Q u e r y i s i n t a c t
let db = try DatabaseService ( inMemory : true )
_ = try db . createSmartPlaylist ( name : " Jazz " , searchQuery : " jazz " )
let all = try db . fetchSmartPlaylists ( )
# expect ( all . count = = 1 )
# expect ( all [ 0 ] . searchQuery = = " jazz " )
# expect ( all [ 0 ] . conditions = = nil )
}
// I n s e r t s t w o t r a c k s w i t h d i f f e r e n t a r t i s t s , f e t c h e s w i t h a n e q u a l s c o n d i t i o n
// o n a r t i s t , a n d v e r i f i e s o n l y t h e m a t c h i n g t r a c k i s r e t u r n e d .
@ Test func fetchTracksWithEqualsCondition ( ) throws {
// S t e p 1 : I n s e r t t w o t r a c k s w i t h d i f f e r e n t a r t i s t s
// S t e p 2 : B u i l d a c o n d i t i o n : a r t i s t e q u a l s " M i l e s D a v i s "
// S t e p 3 : F e t c h t r a c k s w i t h t h a t c o n d i t i o n a n d v e r i f y o n l y o n e r e t u r n e d
let db = try DatabaseService ( inMemory : true )
var t1 = Track . fixture ( fileURL : " /a.mp3 " , title : " Kind of Blue " , artist : " Miles Davis " )
var t2 = Track . fixture ( fileURL : " /b.mp3 " , title : " Hotel California " , artist : " Eagles " )
try db . insert ( & t1 )
try db . insert ( & t2 )
let conditions = [ SmartPlaylistCondition ( field : . artist , op : . equals , value : . string ( " Miles Davis " ) ) ]
let results = try db . fetchTracks ( conditions : conditions , sortColumn : " title " , ascending : true )
# expect ( results . count = = 1 )
# expect ( results [ 0 ] . artist = = " Miles Davis " )
}
// V e r i f i e s t h a t s t r i n g e q u a l s m a t c h i n g i s c a s e - i n s e n s i t i v e .
@ Test func fetchTracksEqualsIsCaseInsensitive ( ) throws {
// S t e p 1 : I n s e r t a t r a c k w i t h m i x e d - c a s e a r t i s t " M i l e s D a v i s "
// S t e p 2 : F e t c h u s i n g l o w e r c a s e " m i l e s d a v i s "
// S t e p 3 : V e r i f y t h e t r a c k i s r e t u r n e d
let db = try DatabaseService ( inMemory : true )
var t = Track . fixture ( fileURL : " /a.mp3 " , artist : " Miles Davis " )
try db . insert ( & t )
let conditions = [ SmartPlaylistCondition ( field : . artist , op : . equals , value : . string ( " miles davis " ) ) ]
let results = try db . fetchTracks ( conditions : conditions , sortColumn : " title " , ascending : true )
# expect ( results . count = = 1 )
}
// V e r i f i e s t h a t s t a r t s W i t h m a t c h e s c a s e - i n s e n s i t i v e l y o n t h e l e a d i n g p r e f i x .
@ Test func fetchTracksWithStartsWithCondition ( ) throws {
// S t e p 1 : I n s e r t a M i l e s D a v i s t r a c k a n d a n E a g l e s t r a c k
// S t e p 2 : F e t c h w i t h a r t i s t s t a r t s W i t h " m i l e s " ( l o w e r c a s e )
// S t e p 3 : V e r i f y o n l y M i l e s D a v i s i s r e t u r n e d
let db = try DatabaseService ( inMemory : true )
var t1 = Track . fixture ( fileURL : " /a.mp3 " , artist : " Miles Davis " )
var t2 = Track . fixture ( fileURL : " /b.mp3 " , artist : " Eagles " )
try db . insert ( & t1 )
try db . insert ( & t2 )
let conditions = [ SmartPlaylistCondition ( field : . artist , op : . startsWith , value : . string ( " miles " ) ) ]
let results = try db . fetchTracks ( conditions : conditions , sortColumn : " title " , ascending : true )
# expect ( results . count = = 1 )
# expect ( results [ 0 ] . artist = = " Miles Davis " )
}
// V e r i f i e s t h a t g r e a t e r T h a n o n a n i n t e g e r f i e l d r e t u r n s o n l y t r a c k s s t r i c t l y
// a b o v e t h e t h r e s h o l d v a l u e .
@ Test func fetchTracksWithGreaterThanCondition ( ) throws {
// S t e p 1 : I n s e r t t r a c k s w i t h y e a r s 1 9 9 0 , 2 0 1 0 , 2 0 2 0
// S t e p 2 : F e t c h w i t h y e a r > 2 0 0 0
// S t e p 3 : V e r i f y 2 0 1 0 a n d 2 0 2 0 a r e r e t u r n e d ; 1 9 9 0 i s n o t
let db = try DatabaseService ( inMemory : true )
var t1 = Track . fixture ( fileURL : " /a.mp3 " , year : 1990 )
var t2 = Track . fixture ( fileURL : " /b.mp3 " , year : 2010 )
var t3 = Track . fixture ( fileURL : " /c.mp3 " , year : 2020 )
try db . insert ( & t1 )
try db . insert ( & t2 )
try db . insert ( & t3 )
let conditions = [ SmartPlaylistCondition ( field : . year , op : . greaterThan , value : . int ( 2000 ) ) ]
let results = try db . fetchTracks ( conditions : conditions , sortColumn : " title " , ascending : true )
# expect ( results . count = = 2 )
# expect ( results . allSatisfy { ( $0 . year ? ? 0 ) > 2000 } )
}
// V e r i f i e s t h a t m u l t i p l e c o n d i t i o n s a r e A N D - e d : o n l y t r a c k s m a t c h i n g a l l
// c o n d i t i o n s a r e r e t u r n e d .
@ Test func fetchTracksWithMultipleAndConditions ( ) throws {
// S t e p 1 : I n s e r t t h r e e t r a c k s — t w o M i l e s D a v i s ( 1 9 5 9 , 1 9 7 0 ) a n d o n e E a g l e s ( 1 9 7 5 )
// S t e p 2 : F e t c h w i t h a r t i s t = " M i l e s D a v i s " A N D y e a r > 1 9 6 0
// S t e p 3 : V e r i f y o n l y t h e 1 9 7 0 M i l e s D a v i s t r a c k i s r e t u r n e d
let db = try DatabaseService ( inMemory : true )
var t1 = Track . fixture ( fileURL : " /a.mp3 " , title : " Kind of Blue " , artist : " Miles Davis " , year : 1959 )
var t2 = Track . fixture ( fileURL : " /b.mp3 " , title : " Bitches Brew " , artist : " Miles Davis " , year : 1970 )
var t3 = Track . fixture ( fileURL : " /c.mp3 " , title : " Hotel California " , artist : " Eagles " , year : 1975 )
try db . insert ( & t1 )
try db . insert ( & t2 )
try db . insert ( & t3 )
let conditions = [
SmartPlaylistCondition ( field : . artist , op : . equals , value : . string ( " Miles Davis " ) ) ,
SmartPlaylistCondition ( field : . year , op : . greaterThan , value : . int ( 1960 ) )
]
let results = try db . fetchTracks ( conditions : conditions , sortColumn : " title " , ascending : true )
# expect ( results . count = = 1 )
# expect ( results [ 0 ] . title = = " Bitches Brew " )
}
// C r e a t e s a c o n d i t i o n s - b a s e d s m a r t p l a y l i s t , f e t c h e s i t b a c k , a n d v e r i f i e s t h e
// c o n d i t i o n s s u r v i v e t h e J S O N r o u n d - t r i p t h r o u g h G R D B ' s C o d a b l e s y n t h e s i s .
@ Test func createSmartPlaylistWithConditionsPersists ( ) throws {
// S t e p 1 : C r e a t e a c o n d i t i o n s - b a s e d p l a y l i s t w i t h a r t i s t e q u a l s a n d y e a r > c o n d i t i o n s
// S t e p 2 : F e t c h a l l s m a r t p l a y l i s t s
// S t e p 3 : V e r i f y b o t h c o n d i t i o n s s u r v i v e d t h e D B r o u n d - t r i p i n t a c t
let db = try DatabaseService ( inMemory : true )
let conditions = [
SmartPlaylistCondition ( field : . artist , op : . equals , value : . string ( " Miles Davis " ) ) ,
SmartPlaylistCondition ( field : . year , op : . greaterThan , value : . int ( 1960 ) )
]
_ = try db . createSmartPlaylist ( name : " Late Miles " , conditions : conditions )
let all = try db . fetchSmartPlaylists ( )
# expect ( all . count = = 1 )
# expect ( all [ 0 ] . conditions ? . count = = 2 )
# expect ( all [ 0 ] . conditions ? [ 0 ] . field = = . artist )
# expect ( all [ 0 ] . conditions ? [ 1 ] . op = = . greaterThan )
if case . int ( let y ) = all [ 0 ] . conditions ? [ 1 ] . value {
# expect ( y = = 1960 )
} else {
Issue . record ( " Expected int value " )
}
}
// U p d a t e s t h e c o n d i t i o n s o f a s t r u c t u r e d s m a r t p l a y l i s t a n d v e r i f i e s t h e u p d a t e d
// c o n d i t i o n s a r e p e r s i s t e d a n d f e t c h b a c k c o r r e c t l y .
@ Test func updateSmartPlaylistConditionsPersists ( ) throws {
// S t e p 1 : C r e a t e a p l a y l i s t w i t h a r t i s t = " E a g l e s "
// S t e p 2 : U p d a t e i t s c o n d i t i o n s t o g e n r e s t a r t s W i t h " J a z z "
// S t e p 3 : F e t c h a n d v e r i f y t h e u p d a t e d c o n d i t i o n s a r e s t o r e d
let db = try DatabaseService ( inMemory : true )
let sp = try db . createSmartPlaylist (
name : " Test " ,
conditions : [ SmartPlaylistCondition ( field : . artist , op : . equals , value : . string ( " Eagles " ) ) ]
)
let newConditions = [ SmartPlaylistCondition ( field : . genre , op : . startsWith , value : . string ( " Jazz " ) ) ]
try db . updateSmartPlaylistConditions ( id : sp . id ! , conditions : newConditions )
let all = try db . fetchSmartPlaylists ( )
# expect ( all [ 0 ] . conditions ? . count = = 1 )
# expect ( all [ 0 ] . conditions ? [ 0 ] . field = = . genre )
}
}
}