@@ -2,1140 +2,928 @@ module Test.Main where
22
33import Prelude
44
5−import Data.Array (head, drop)
6−import Data.Date as Date
7−import Data.DateTime (DateTime(..), Time(..))
8−import Data.DateTime.Instant (toDateTime)
9−import Data.Either (Either(..))
10−import Data.Enum (toEnum)
11−import Data.Maybe (Maybe(..), isNothing, maybe)
12−import Data.Time.Duration (Milliseconds(..))
13−import Data.Traversable (traverse)
14−import Data.Tuple (Tuple(..), uncurry)
15−import Database.IndexedDB.Core (CursorDirection(..), Database, Index, ObjectStore, Transaction, TransactionMode(..))
16−import Database.IndexedDB.IDBCursor as IDBCursor
17−import Database.IndexedDB.IDBDatabase as IDBDatabase
18−import Database.IndexedDB.IDBFactory as IDBFactory
19−import Database.IndexedDB.IDBIndex as IDBIndex
20−import Database.IndexedDB.IDBKey (Key, none, toKey)
21−import Database.IndexedDB.IDBKeyRange as IDBKeyRange
22−import Database.IndexedDB.IDBObjectStore as IDBObjectStore
23−import Database.IndexedDB.IDBTransaction as IDBTransaction
24−import Effect (Effect)
25−import Effect.Aff (Aff, attempt, delay, forkAff, launchAff, launchAff_)
26−import Effect.Aff.AVar (AVar)
27−import Effect.Aff.AVar as AVar
28−import Effect.Class (liftEffect)
29−import Effect.Console (log)
30−import Effect.Exception (name)
31−import Effect.Now (now)
32−import Test.Spec (describe, it)
33−import Test.Spec.Assertions (shouldEqual, fail)
34−import Test.Spec.Reporter (consoleReporter)
35−import Test.Spec.Runner (runSpec)
36−
37−infixr 7 Tuple as :+:
38−
39−launchAff' :: forall a. Aff a -> Effect Unit
40−launchAff' =
41− launchAff_ <<< void
42−
43−modifyAVar :: forall a. (a -> a) -> AVar a -> Aff Unit
44−modifyAVar fn v = do
45− val <- AVar.take v
46− AVar.put (fn val) v
47−
48−main :: Effect Unit
49−main = do
50− launchAff_ $ runSpec [ consoleReporter ] $ do
51− describe "IDBFactory" do
52− let
53− tearDown name version db = do
54− IDBDatabase.close db
55− version' <- IDBFactory.deleteDatabase name
56− liftEffect $ log $ show version'
57− version' `shouldEqual` version
58−
59− it "open default" do
60− let
61− name = "db-default"
5+import Control.Monad.Aff (Aff, launchAff, forkAff, delay)
6+import Control.Monad.Aff.Console (log)
7+import Control.Monad.Aff.AVar (AVAR, makeVar', modifyVar, peekVar, killVar)
8+import Control.Monad.Eff (Eff)
9+import Control.Monad.Eff.Class (liftEff)
10+import Control.Monad.Eff.Exception (EXCEPTION)
11+import Data.Date as Date
12+import Data.DateTime as DateTime
13+import Data.DateTime (DateTime(..), Date(..), Time(..))
14+import Data.Enum (toEnum)
15+import Data.Maybe (Maybe(..), isNothing)
16+import Data.Time.Duration (Milliseconds(..))
17+import Test.Spec (describe, it)
18+import Test.Spec.Assertions (shouldEqual, fail)
19+import Test.Spec.Mocha (MOCHA, runMocha)
20+
21+import Database.IndexedDB.Core
22+import Database.IndexedDB.IDBKey
23+import Database.IndexedDB.IDBDatabase as IDBDatabase
24+import Database.IndexedDB.IDBFactory as IDBFactory
25+import Database.IndexedDB.IDBObjectStore as IDBObjectStore
26+import Database.IndexedDB.IDBKeyRange as IDBKeyRange
27+
28+
29+tearDown :: forall eff. String -> Int -> Database -> Aff (idb :: INDEXED_DB, exception :: EXCEPTION | eff) Unit
30+tearDown name version db = do
31+ liftEff $ IDBDatabase.close db
32+ version' <- IDBFactory.deleteDatabase name
33+ version' `shouldEqual` version
34+
35+-- main :: forall eff. Eff (mocha :: MOCHA, idb :: INDEXED_DB, exception :: EXCEPTION, avar :: AVAR | eff) Unit
36+main = runMocha do
37+ describe "IDBFactory" do
38+ it "open default" do
39+ let name = "db-default"
6240 version = 1
63− db <- IDBFactory.open name Nothing
64− { onUpgradeNeeded: Nothing
65− , onBlocked: Nothing
66− }
67− IDBDatabase.name db `shouldEqual` name
68− tearDown name version db
69−
70− it "open specific version" do
71− let
72− name = "db-specific"
41+ db <- IDBFactory.open name Nothing
42+ { onUpgradeNeeded : Nothing
43+ , onBlocked : Nothing
44+ }
45+ IDBDatabase.name db `shouldEqual` name
46+ tearDown name version db
47+
48+
49+ it "open specific version" do
50+ let name = "db-specific"
7351 version = 14
74− db <- IDBFactory.open name (Just version)
75− { onUpgradeNeeded: Nothing
76− , onBlocked: Nothing
77− }
78− IDBDatabase.name db `shouldEqual` name
79− tearDown name version db
80−
81− it "open specific version -> close -> open latest" do
82− let
83− name = "db-latest"
52+ db <- IDBFactory.open name (Just version)
53+ { onUpgradeNeeded : Nothing
54+ , onBlocked : Nothing
55+ }
56+ IDBDatabase.name db `shouldEqual` name
57+ tearDown name version db
58+
59+
60+ it "open specific version -> close -> open latest" do
61+ let name = "db-latest"
8462 version = 14
85− db01 <- IDBFactory.open name (Just version)
86− { onUpgradeNeeded: Nothing
87− , onBlocked: Nothing
88− }
89− IDBDatabase.name db01 `shouldEqual` name
90− IDBDatabase.close db01
91− db02 <- IDBFactory.open name Nothing
92− { onUpgradeNeeded: Nothing
93− , onBlocked: Nothing
94− }
95− tearDown name version db02
96−
97− it "open + onUpgradeNeed" do
98− let
99− name = "db-upgrade-needed"
63+ db <- IDBFactory.open name (Just version)
64+ { onUpgradeNeeded : Nothing
65+ , onBlocked : Nothing
66+ }
67+ IDBDatabase.name db `shouldEqual` name
68+ liftEff $ IDBDatabase.close db
69+ db <- IDBFactory.open name Nothing
70+ { onUpgradeNeeded : Nothing
71+ , onBlocked : Nothing
72+ }
73+ tearDown name version db
74+
75+
76+ it "open + onUpgradeNeed" do
77+ let name = "db-upgrade-needed"
10078 version = 1
101− callback (Tuple varName varVersion) db _ { oldVersion } = do
102− _ <- launchAff $ modifyAVar (const $ IDBDatabase.name db) varName
103− _ <- launchAff $ modifyAVar (const $ oldVersion) varVersion
79+ callback var db = do
80+ _ <- launchAff $ modifyVar (const $ IDBDatabase.name db) var
10481 pure unit
105− varName <- AVar.new "-"
106− varVersion <- AVar.new (-1)
107− db <- IDBFactory.open name Nothing
108− { onUpgradeNeeded: Just (callback (Tuple varName varVersion))
109− , onBlocked: Nothing
110− }
111− name' <- AVar.read varName
112− version' <- AVar.read varVersion
113− name' `shouldEqual` name
114− version' `shouldEqual` 0
115− tearDown name version db
116−
117− it "open + onBlocked" do
118− let
119− name = "db-blocked"
82+ var <- makeVar' "-"
83+ db <- IDBFactory.open name Nothing
84+ { onUpgradeNeeded : Just (callback var)
85+ , onBlocked : Nothing
86+ }
87+ name <- peekVar var
88+ name `shouldEqual` name
89+ tearDown name version db
90+
91+
92+ it "open + onBlocked" do
93+ let name = "db-blocked"
12094 version = 14
12195 callback var = do
122− _ <- launchAff $ modifyAVar (const $ "db-blocked") var
96+ _ <- launchAff $ modifyVar (const $ "db-blocked") var
12397 pure unit
12498
125− var <- AVar.new "-"
126− db01 <- IDBFactory.open name Nothing
127− { onUpgradeNeeded: Nothing
128− , onBlocked: Nothing
129− }
130− _ <- forkAff do
131− delay (Milliseconds 100.0)
132− IDBDatabase.close db01
133−
134− db02 <- IDBFactory.open name (Just version)
135− { onUpgradeNeeded: Nothing
136− , onBlocked: Just (callback var)
137− }
138− name' <- AVar.read var
139− name' `shouldEqual` name
140− tearDown name version db02
141−
142− describe "IDBKeyRange" do
143− it "only(int)" do
144− let
145− key = 14
99+ var <- makeVar' "-"
100+ db01 <- IDBFactory.open name Nothing
101+ { onUpgradeNeeded : Nothing
102+ , onBlocked : Nothing
103+ }
104+ _ <- forkAff do
105+ delay (Milliseconds 100.0)
106+ liftEff $ IDBDatabase.close db01
107+
108+ db02 <- IDBFactory.open name (Just version)
109+ { onUpgradeNeeded : Nothing
110+ , onBlocked : Just (callback var)
111+ }
112+ name <- peekVar var
113+ name `shouldEqual` name
114+ tearDown name version db02
115+
116+ describe "IDBKeyRange" do
117+ it "only(int)" do
118+ let key = 14
146119 range = IDBKeyRange.only key
147− IDBKeyRange.includes range (toKey key) `shouldEqual` true
120+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
148121
149− it "only(string)" do
150− let
151− key = "patate"
122+ it "only(string)" do
123+ let key = "patate"
152124 range = IDBKeyRange.only key
153− IDBKeyRange.includes range (toKey key) `shouldEqual` true
125+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
154126
155− it "only(float)" do
156− let
157− key = 14.42
127+ it "only(float)" do
128+ let key = 14.42
158129 range = IDBKeyRange.only key
159− IDBKeyRange.includes range (toKey key) `shouldEqual` true
130+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
160131
161− it "only(date)" do
162− let
163− mkey = DateTime
132+ it "only(date)" do
133+ let mkey = DateTime
164134 <$> (Date.canonicalDate <$> toEnum 2017 <*> toEnum 6 <*> toEnum 23)
165135 <*> (Time <$> toEnum 17 <*> toEnum 59 <*> toEnum 34 <*> toEnum 42)
166136
167− case mkey of
168− Nothing ->
169− fail "unable to create datetime"
170− Just key -> do
171− let range = IDBKeyRange.only key
172− IDBKeyRange.includes range (toKey key) `shouldEqual` true
137+ case mkey of
138+ Nothing ->
139+ fail "unable to create datetime"
140+ Just key -> do
141+ let range = IDBKeyRange.only key
142+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
173143
174− it "only([int])" do
175− let
176− key = [ 14, 42 ]
144+ it "only([int])" do
145+ let key = [14, 42]
177146 range = IDBKeyRange.only key
178− IDBKeyRange.includes range (toKey key) `shouldEqual` true
147+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
179148
180− it "only([string])" do
181− let
182− key = [ "patate", "autruche" ]
149+ it "only([string])" do
150+ let key = ["patate", "autruche"]
183151 range = IDBKeyRange.only key
184− IDBKeyRange.includes range (toKey key) `shouldEqual` true
152+ IDBKeyRange.includes range (toKey key) `shouldEqual` true
185153
186− it "lowerBound(14, open)" do
187− let
188− key = 14
189− open = true
154+ it "lowerBound(14, open)" do
155+ let key = 14
156+ open = true
190157 range = IDBKeyRange.lowerBound key open
191− IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` true
192− IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
193− IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` false
194−
195− it "lowerBound(14, close)" do
196− let
197− key = 14
198− open = false
158+ IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` true
159+ IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
160+ IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` false
161+
162+ it "lowerBound(14, close)" do
163+ let key = 14
164+ open = false
199165 range = IDBKeyRange.lowerBound key open
200− IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` true
201− IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
202− IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` false
203−
204− it "upperBound(14, open)" do
205− let
206− key = 14
207− open = true
166+ IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` true
167+ IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
168+ IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` false
169+
170+ it "upperBound(14, open)" do
171+ let key = 14
172+ open = true
208173 range = IDBKeyRange.upperBound key open
209− IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` false
210− IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
211− IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` true
212−
213− it "upperBound(14, close)" do
214− let
215− key = 14
216− open = false
174+ IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` false
175+ IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
176+ IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` true
177+
178+ it "upperBound(14, close)" do
179+ let key = 14
180+ open = false
217181 range = IDBKeyRange.upperBound key open
218− IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` false
219− IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
220− IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` true
221−
222− it "bound(42, 14, open, open) => Nothing" do
223− let
224− lower = 42
225− upper = 14
182+ IDBKeyRange.includes range (toKey (key + 1)) `shouldEqual` false
183+ IDBKeyRange.includes range (toKey key) `shouldEqual` (not open)
184+ IDBKeyRange.includes range (toKey (key - 1)) `shouldEqual` true
185+
186+ it "bound(42, 14, open, open) => Nothing" do
187+ let lower = 42
188+ upper = 14
226189 lowerOpen = true
227190 upperOpen = true
228− mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
229− isNothing mrange `shouldEqual` true
191+ mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
192+ isNothing mrange `shouldEqual` true
230193
231− it "bound(14, 42, open, open)" do
232− let
233− lower = 14
234− upper = 42
194+ it "bound(14, 42, open, open)" do
195+ let lower = 14
196+ upper = 42
235197 lowerOpen = true
236198 upperOpen = true
237− mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
238− case mrange of
239− Nothing ->
240− fail "invalid range provided"
241− Just range -> do
242− IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
243− IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
244− IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
245− IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
246− IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
247− IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
248−
249− it "bound(14, 42, open, close)" do
250− let
251− lower = 14
252− upper = 42
199+ mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
200+ case mrange of
201+ Nothing ->
202+ fail "invalid range provided"
203+ Just range -> do
204+ IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
205+ IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
206+ IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
207+ IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
208+ IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
209+ IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
210+
211+ it "bound(14, 42, open, close)" do
212+ let lower = 14
213+ upper = 42
253214 lowerOpen = true
254215 upperOpen = false
255− mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
256− case mrange of
257− Nothing ->
258− fail "invalid range provided"
259− Just range -> do
260− IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
261− IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
262− IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
263− IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
264− IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
265− IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
266−
267− it "bound(14, 42, close, open)" do
268− let
269− lower = 14
270− upper = 42
216+ mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
217+ case mrange of
218+ Nothing ->
219+ fail "invalid range provided"
220+ Just range -> do
221+ IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
222+ IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
223+ IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
224+ IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
225+ IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
226+ IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
227+
228+ it "bound(14, 42, close, open)" do
229+ let lower = 14
230+ upper = 42
271231 lowerOpen = false
272232 upperOpen = true
273− mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
274− case mrange of
275− Nothing ->
276− fail "invalid range provided"
277− Just range -> do
278− IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
279− IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
280− IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
281− IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
282− IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
283− IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
284−
285− it "bound(14, 42, close, close)" do
286− let
287− lower = 14
288− upper = 42
233+ mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
234+ case mrange of
235+ Nothing ->
236+ fail "invalid range provided"
237+ Just range -> do
238+ IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
239+ IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
240+ IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
241+ IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
242+ IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
243+ IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
244+
245+ it "bound(14, 42, close, close)" do
246+ let lower = 14
247+ upper = 42
289248 lowerOpen = false
290249 upperOpen = false
291− mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
292− case mrange of
293− Nothing ->
294− fail "invalid range provided"
295− Just range -> do
296− IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
297− IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
298− IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
299− IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
300− IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
301− IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
302−
303− it "can access attributes of a range" do
304− let range = IDBKeyRange.lowerBound 14 false
305− IDBKeyRange.lower range `shouldEqual` (Just $ toKey 14)
306− IDBKeyRange.upper range `shouldEqual` none
307− IDBKeyRange.lowerOpen range `shouldEqual` false
308− IDBKeyRange.upperOpen range `shouldEqual` true
309−
310− describe "IDBDatabase" do
311− let
312− tearDown db = do
313− IDBDatabase.close db
314− _ <- IDBFactory.deleteDatabase (IDBDatabase.name db)
315− pure unit
316−
317− setup storeParams = do
318− let
319− onUpgradeNeeded var db _ _ = launchAff' do
320− store <- IDBDatabase.createObjectStore db "store" storeParams
321− _ <- AVar.put { db, store } var
322− pure unit
250+ mrange = IDBKeyRange.bound { lower, upper, lowerOpen, upperOpen }
251+ case mrange of
252+ Nothing ->
253+ fail "invalid range provided"
254+ Just range -> do
255+ IDBKeyRange.includes range (toKey (lower + 1)) `shouldEqual` true
256+ IDBKeyRange.includes range (toKey (upper - 1)) `shouldEqual` true
257+ IDBKeyRange.includes range (toKey (lower - 1)) `shouldEqual` false
258+ IDBKeyRange.includes range (toKey (upper + 1)) `shouldEqual` false
259+ IDBKeyRange.includes range (toKey lower) `shouldEqual` (not lowerOpen)
260+ IDBKeyRange.includes range (toKey upper) `shouldEqual` (not upperOpen)
261+
262+ it "can access attributes of a range" do
263+ let range = IDBKeyRange.lowerBound 14 true
264+ IDBKeyRange.lower range `shouldEqual` (Just $ toKey 14)
265+ IDBKeyRange.upper range `shouldEqual` (Nothing :: Maybe Key)
266+ IDBKeyRange.lowerOpen range `shouldEqual` true
267+ -- NOTE Not true on Chrome 56.x => The default value for the flag is `true`
268+ -- IDBKeyRange.upperOpen range `shouldEqual` false
269+
270+ describe "IDBDatabase" do
271+ it "createObjectStore (keyPath: [], autoIncrement: true)" do
272+ let dbName = "db-create-store-01"
273+ dbVersion = 1
274+ storeName = "store"
275+ keyPath = []
276+ autoIncrement = true
277+ callback var db = do
278+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
279+ _ <- launchAff $ IDBObjectStore.name store `shouldEqual` storeName
280+ _ <- launchAff $ IDBObjectStore.keyPath store `shouldEqual` keyPath
281+ _ <- launchAff $ IDBObjectStore.autoIncrement store `shouldEqual` autoIncrement
282+ _ <- launchAff $ IDBObjectStore.indexNames store `shouldEqual` []
283+ _ <- launchAff $ modifyVar (const true) var
284+ pure unit
323285
324− var <- AVar.empty
325− _ <- IDBFactory.open "db" Nothing
326− { onUpgradeNeeded: Just (onUpgradeNeeded var)
327− , onBlocked: Nothing
328− }
286+ var <- makeVar' false
287+ db <- IDBFactory.open dbName Nothing
288+ { onUpgradeNeeded : Just (callback var)
289+ , onBlocked : Nothing
290+ }
291+ hasBeenCalled <- peekVar var
292+ hasBeenCalled `shouldEqual` true
293+ tearDown dbName dbVersion db
294+
295+
296+ it "createObjectStore (keyPath: [\"field\"], autoIncrement: true)" do
297+ let dbName = "db-create-store-02"
298+ dbVersion = 1
299+ storeName = "store"
300+ keyPath = ["field"]
301+ autoIncrement = true
302+ callback var db = do
303+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
304+ _ <- launchAff $ IDBObjectStore.name store `shouldEqual` storeName
305+ _ <- launchAff $ IDBObjectStore.keyPath store `shouldEqual` keyPath
306+ _ <- launchAff $ IDBObjectStore.autoIncrement store `shouldEqual` autoIncrement
307+ _ <- launchAff $ IDBObjectStore.indexNames store `shouldEqual` []
308+ _ <- launchAff $ modifyVar (const true) var
309+ pure unit
329310
330− AVar.take var
331−
332− it "createObjectStore (keyPath: [], autoIncrement: true)" do
333− { db, store } <- setup { keyPath: [], autoIncrement: true }
334− IDBObjectStore.name store `shouldEqual` "store"
335− IDBObjectStore.keyPath store `shouldEqual` []
336− IDBObjectStore.autoIncrement store `shouldEqual` true
337− IDBObjectStore.indexNames store `shouldEqual` []
338− tearDown db
339−
340− it "createObjectStore (keyPath: [\"patate\"], autoIncrement: true)" do
341− { db, store } <- setup { keyPath: [ "patate" ], autoIncrement: true }
342− IDBObjectStore.name store `shouldEqual` "store"
343− IDBObjectStore.keyPath store `shouldEqual` [ "patate" ]
344− IDBObjectStore.autoIncrement store `shouldEqual` true
345− IDBObjectStore.indexNames store `shouldEqual` []
346− tearDown db
347−
348− it "createObjectStore (keyPath: [\"a\", \"b\"], autoIncrement: false)" do
349− { db, store } <- setup { keyPath: [ "patate", "autruche" ], autoIncrement: false }
350− IDBObjectStore.name store `shouldEqual` "store"
351− IDBObjectStore.keyPath store `shouldEqual` [ "patate", "autruche" ]
352− IDBObjectStore.autoIncrement store `shouldEqual` false
353− IDBObjectStore.indexNames store `shouldEqual` []
354− tearDown db
355−
356− it "deleteObjectStore" do
357− let
358− onUpgradeNeeded var db _ _ = launchAff' do
359− _ <- IDBDatabase.deleteObjectStore db "store"
360− AVar.put true var
361−
362− var <- AVar.empty
363− { db } <- setup IDBDatabase.defaultParameters
364− IDBDatabase.close db
365− db' <- IDBFactory.open "db" (Just 999)
366− { onUpgradeNeeded: Just (onUpgradeNeeded var)
367− , onBlocked: Nothing
368− }
369− deleted <- AVar.take var
370− deleted `shouldEqual` true
371− tearDown db'
372−
373− describe "IDBObjectStore" do
374− let
375− tearDown db = do
376− IDBDatabase.close db
377− _ <- IDBFactory.deleteDatabase (IDBDatabase.name db)
378− pure unit
379−
380− setup { storeParams, onUpgradeNeeded } = do
381− let
382− onUpgradeNeeded' var db _ _ = launchAff' do
383− store <- IDBDatabase.createObjectStore db "store" storeParams
384− liftEffect $ maybe (pure unit) identity (onUpgradeNeeded <*> pure db <*> pure store)
385− AVar.put { db, store } var
386−
387− var <- AVar.empty
388− _ <- IDBFactory.open "db" Nothing
389− { onUpgradeNeeded: Just (onUpgradeNeeded' var)
390− , onBlocked: Nothing
311+ var <- makeVar' false
312+ db <- IDBFactory.open dbName Nothing
313+ { onUpgradeNeeded : Just (callback var)
314+ , onBlocked : Nothing
315+ }
316+ hasBeenCalled <- peekVar var
317+ hasBeenCalled `shouldEqual` true
318+ tearDown dbName dbVersion db
319+
320+
321+ it "createObjectStore (keyPath: [\"a\", \"b\"], autoIncrement: false)" do
322+ let dbName = "db-create-store-03"
323+ dbVersion = 1
324+ storeName = "store"
325+ keyPath = ["a", "b"]
326+ autoIncrement = false
327+ callback var db = do
328+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
329+ _ <- launchAff $ IDBObjectStore.name store `shouldEqual` storeName
330+ _ <- launchAff $ IDBObjectStore.keyPath store `shouldEqual` keyPath
331+ _ <- launchAff $ IDBObjectStore.autoIncrement store `shouldEqual` autoIncrement
332+ _ <- launchAff $ IDBObjectStore.indexNames store `shouldEqual` []
333+ _ <- launchAff $ modifyVar (const true) var
334+ pure unit
335+
336+ var <- makeVar' false
337+ db <- IDBFactory.open dbName Nothing
338+ { onUpgradeNeeded : Just (callback var)
339+ , onBlocked : Nothing
340+ }
341+ hasBeenCalled <- peekVar var
342+ hasBeenCalled `shouldEqual` true
343+ tearDown dbName dbVersion db
344+
345+
346+ it "createObjectStore (keyPath: [\"field\"], autoIncrement: false)" do
347+ let dbName = "db-create-store-04"
348+ dbVersion = 1
349+ storeName = "store"
350+ keyPath = ["field"]
351+ autoIncrement = false
352+ callback var db = do
353+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
354+ _ <- launchAff $ IDBObjectStore.name store `shouldEqual` storeName
355+ _ <- launchAff $ IDBObjectStore.keyPath store `shouldEqual` keyPath
356+ _ <- launchAff $ IDBObjectStore.autoIncrement store `shouldEqual` autoIncrement
357+ _ <- launchAff $ IDBObjectStore.indexNames store `shouldEqual` []
358+ _ <- launchAff $ modifyVar (const true) var
359+ pure unit
360+
361+ var <- makeVar' false
362+ db <- IDBFactory.open dbName Nothing
363+ { onUpgradeNeeded : Just (callback var)
364+ , onBlocked : Nothing
365+ }
366+ hasBeenCalled <- peekVar var
367+ hasBeenCalled `shouldEqual` true
368+ tearDown dbName dbVersion db
369+
370+
371+ it "deleteObjectStore" do
372+ let dbName = "db-delete-store"
373+ dbVersion = 2
374+ storeName = "store"
375+ keyPath = []
376+ autoIncrement = true
377+ callback db = do
378+ _ <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
379+ pure unit
380+ callback2 var db = do
381+ _ <- IDBDatabase.deleteObjectStore db storeName
382+ _ <- launchAff $ modifyVar (const true) var
383+ pure unit
384+
385+ var <- makeVar' false
386+ db <- IDBFactory.open dbName Nothing
387+ { onUpgradeNeeded : Just callback
388+ , onBlocked : Nothing
389+ }
390+ liftEff $ IDBDatabase.close db
391+ db <- IDBFactory.open dbName (Just dbVersion)
392+ { onUpgradeNeeded : Just (callback2 var)
393+ , onBlocked : Nothing
394+ }
395+ hasBeenCalled <- peekVar var
396+ hasBeenCalled `shouldEqual` true
397+ tearDown dbName dbVersion db
398+
399+ describe "IDBObjectStore" do
400+ it "add(\"patate\", Nothing )" do
401+ let dbName = "db-add"
402+ dbVersion = 1
403+ storeName = "store"
404+ keyPath = []
405+ autoIncrement = true
406+ key = 1
407+ callback db = do
408+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
409+ key <- launchAff $ ((unsafeFromKey >>> shouldEqual key)
410+ <$> IDBObjectStore.add store "patate" Nothing)
411+ pure unit
412+
413+ db <- IDBFactory.open dbName Nothing
414+ { onUpgradeNeeded : Just callback
415+ , onBlocked : Nothing
416+ }
417+ tearDown dbName dbVersion db
418+
419+ it "add(\"patate\", Just 14 )" do
420+ let dbName = "db-add"
421+ dbVersion = 1
422+ storeName = "store"
423+ keyPath = []
424+ autoIncrement = true
425+ key = 14
426+ callback db = do
427+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
428+ key <- launchAff $ ((unsafeFromKey >>> shouldEqual key)
429+ <$> IDBObjectStore.add store "patate" (Just $ toKey key))
430+ pure unit
431+
432+ db <- IDBFactory.open dbName Nothing
433+ { onUpgradeNeeded : Just callback
434+ , onBlocked : Nothing
435+ }
436+ tearDown dbName dbVersion db
437+
438+ it "add(\"patate\", Just \"key\" )" do
439+ let dbName = "db-add"
440+ dbVersion = 1
441+ storeName = "store"
442+ keyPath = []
443+ autoIncrement = true
444+ key = "key"
445+ callback db = do
446+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
447+ key <- launchAff $ ((unsafeFromKey >>> shouldEqual key)
448+ <$> IDBObjectStore.add store "patate" (Just $ toKey key))
449+ pure unit
450+
451+ db <- IDBFactory.open dbName Nothing
452+ { onUpgradeNeeded : Just callback
453+ , onBlocked : Nothing
454+ }
455+ tearDown dbName dbVersion db
456+
457+ it "add(\"patate\", Just <date> )" do
458+ let dbName = "db-add"
459+ dbVersion = 1
460+ storeName = "store"
461+ keyPath = []
462+ autoIncrement = true
463+ mkey = DateTime
464+ <$> (Date.canonicalDate <$> toEnum 2017 <*> toEnum 6 <*> toEnum 23)
465+ <*> (Time <$> toEnum 17 <*> toEnum 59 <*> toEnum 34 <*> toEnum 42)
466+
467+ case mkey of
468+ Nothing ->
469+ fail "unable to create datetime"
470+ Just key -> do
471+ let callback db = do
472+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
473+ key <- launchAff $ ((unsafeFromKey >>> shouldEqual key)
474+ <$> IDBObjectStore.add store "patate" (Just $ toKey key))
475+ pure unit
476+
477+ db <- IDBFactory.open dbName Nothing
478+ { onUpgradeNeeded : Just callback
479+ , onBlocked : Nothing
391480 }
481+ tearDown dbName dbVersion db
482+
483+ it "add(\"patate\", Just [14, 42] )" do
484+ let dbName = "db-add"
485+ dbVersion = 1
486+ storeName = "store"
487+ keyPath = []
488+ autoIncrement = true
489+ key = [14, 42]
490+ callback db = do
491+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
492+ key <- launchAff $ ((unsafeFromKey >>> shouldEqual key)
493+ <$> IDBObjectStore.add store "patate" (Just $ toKey key))
494+ pure unit
392495
393− AVar.take var
394−
395− it "add()" do
396− date <- liftEffect $ toDateTime <$> now
397− { db } <- setup
398− { storeParams: { autoIncrement: true, keyPath: [] }
399− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
400− -- no key
401− key <- IDBObjectStore.add store "patate" none
402− (toKey 1) `shouldEqual` key
403−
404− -- int key
405− key' <- IDBObjectStore.add store "patate" (Just 14)
406− (toKey 14) `shouldEqual` key'
407−
408− -- number key
409− key'' <- IDBObjectStore.add store "patate" (Just 14.42)
410− (toKey 14.42) `shouldEqual` key''
411−
412− -- string key
413− key''' <- IDBObjectStore.add store "patate" (Just "key")
414− (toKey "key") `shouldEqual` key'''
415−
416− -- date key
417− key'''' <- IDBObjectStore.add store "patate" (Just date)
418− (toKey date) `shouldEqual` key''''
419−
420− -- array key
421− key''''' <- IDBObjectStore.add store "patate" (Just $ toKey [ 14, 42 ])
422− (toKey [ 14, 42 ]) `shouldEqual` key'''''
423− }
424− tearDown db
425−
426− it "clear()" do
427− { db } <- setup
428− { storeParams: IDBDatabase.defaultParameters
429− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
430− key <- IDBObjectStore.add store "patate" (Just 14)
496+ db <- IDBFactory.open dbName Nothing
497+ { onUpgradeNeeded : Just callback
498+ , onBlocked : Nothing
499+ }
500+ tearDown dbName dbVersion db
501+
502+ it "clear()" do
503+ let dbName = "db-clear"
504+ dbVersion = 1
505+ storeName = "store"
506+ keyPath = []
507+ autoIncrement = true
508+ callback db = do
509+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
510+ _ <- launchAff $ do
511+ _ <- IDBObjectStore.add store "patate" (Just $ toKey 14)
431512 _ <- IDBObjectStore.clear store
432− val <- IDBObjectStore.get store (IDBKeyRange.only key)
433− val `shouldEqual` (Nothing :: Maybe String)
434− }
435− tearDown db
436−
437− it "count()" do
438− { db } <- setup
439− { storeParams: IDBDatabase.defaultParameters
440− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
441− _ <- IDBObjectStore.add store "patate" (Just 14)
442− _ <- IDBObjectStore.add store "autruche" (Just 42)
513+ v <- IDBObjectStore.get store (IDBKeyRange.only 14)
514+ v `shouldEqual` (Nothing :: Maybe Int)
515+
516+ pure unit
517+
518+ db <- IDBFactory.open dbName Nothing
519+ { onUpgradeNeeded : Just callback
520+ , onBlocked : Nothing
521+ }
522+ tearDown dbName dbVersion db
523+
524+ it "count(Nothing) " do
525+ let dbName = "db-count"
526+ dbVersion = 1
527+ storeName = "store"
528+ keyPath = []
529+ autoIncrement = true
530+ callback db = do
531+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
532+ _ <- launchAff $ do
533+ _ <- IDBObjectStore.add store "patate" Nothing
534+ _ <- IDBObjectStore.add store 14 Nothing
443535 n <- IDBObjectStore.count store Nothing
444536 n `shouldEqual` 2
445− }
446− tearDown db
447−
448− it "getKey()" do
449− { db } <- setup
450− { storeParams: IDBDatabase.defaultParameters
451− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
452− key <- IDBObjectStore.add store "patate" (Just 14)
537+ pure unit
538+
539+ db <- IDBFactory.open dbName Nothing
540+ { onUpgradeNeeded : Just callback
541+ , onBlocked : Nothing
542+ }
543+ tearDown dbName dbVersion db
544+
545+
546+ it "getKey() (fixed)" do
547+ let dbName = "db-getKey"
548+ dbVersion = 1
549+ storeName = "store"
550+ keyPath = ["id"]
551+ key = "patate"
552+ autoIncrement = false
553+ callback db = do
554+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
555+ _ <- launchAff $ do
556+ key' <- IDBObjectStore.add store { id: key, value: 14 } Nothing
557+ (unsafeFromKey key') `shouldEqual` key
558+ key' <- IDBObjectStore.getKey store (IDBKeyRange.only key)
559+ (unsafeFromKey <$> key') `shouldEqual` (Just key)
560+ pure unit
561+
562+ db <- IDBFactory.open dbName Nothing
563+ { onUpgradeNeeded : Just callback
564+ , onBlocked : Nothing
565+ }
566+ tearDown dbName dbVersion db
567+
568+ it "getKey() (given)" do
569+ let dbName = "db-getKey"
570+ dbVersion = 1
571+ storeName = "store"
572+ keyPath = []
573+ autoIncrement = true
574+ callback db = do
575+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
576+ _ <- launchAff $ do
577+ key <- IDBObjectStore.add store "patate" Nothing
578+ mkey <- IDBObjectStore.getKey store (IDBKeyRange.only key)
579+ mkey `shouldEqual` Just key
580+ pure unit
581+
582+ db <- IDBFactory.open dbName Nothing
583+ { onUpgradeNeeded : Just callback
584+ , onBlocked : Nothing
585+ }
586+ tearDown dbName dbVersion db
587+
588+ it "getKey() unknown" do
589+ let dbName = "db-getKey"
590+ dbVersion = 1
591+ storeName = "store"
592+ keyPath = []
593+ autoIncrement = true
594+ callback db = do
595+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
596+ _ <- launchAff $ do
597+ key <- IDBObjectStore.add store "patate" Nothing
453598 mkey <- IDBObjectStore.getKey store (IDBKeyRange.only 14)
454− mkey `shouldEqual` (Just key)
455−
456− mkey' <- IDBObjectStore.getKey store (IDBKeyRange.only 42)
457− mkey' `shouldEqual` none
458− }
459− tearDown db
460−
461− it "getAllKeys()" do
462− { db } <- setup
463− { storeParams: IDBDatabase.defaultParameters
464− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
465− key1 <- IDBObjectStore.add store "patate" (Just 14)
466− key2 <- IDBObjectStore.add store "autruche" (Just 42)
467− key3 <- IDBObjectStore.add store 14 (Just 1337)
468−
469− -- no bounds
599+ mkey `shouldEqual` Nothing
600+ pure unit
601+
602+ db <- IDBFactory.open dbName Nothing
603+ { onUpgradeNeeded : Just callback
604+ , onBlocked : Nothing
605+ }
606+ tearDown dbName dbVersion db
607+
608+ it "getAllKeys(nothing, nothing)" do
609+ let dbName = "db-getAllKeys"
610+ dbVersion = 1
611+ storeName = "store"
612+ keyPath = []
613+ autoIncrement = true
614+ callback db = do
615+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
616+ _ <- launchAff $ do
617+ k1 <- IDBObjectStore.add store "patate" Nothing
618+ k2 <- IDBObjectStore.add store "autruche" Nothing
470619 keys <- IDBObjectStore.getAllKeys store Nothing Nothing
471− keys `shouldEqual` [ key1, key2, key3 ]
472−
473− -- lower bound
474− keys' <- IDBObjectStore.getAllKeys store (Just $ IDBKeyRange.lowerBound 14 true) Nothing
475− keys' `shouldEqual` [ key2, key3 ]
476−
477− -- upper bound
478− keys'' <- IDBObjectStore.getAllKeys store (Just $ IDBKeyRange.upperBound 42 false) Nothing
479− keys'' `shouldEqual` [ key1, key2 ]
480−
481− -- count
482− keys''' <- IDBObjectStore.getAllKeys store (Just $ IDBKeyRange.lowerBound 1 true) (Just 2)
483− keys''' `shouldEqual` [ key1, key2 ]
484− }
485− tearDown db
486−
487− it "openCursor()" do
488− let
489− cb =
490− { onSuccess: const $ pure unit
491− , onError: show >>> fail >>> launchAff'
492− , onComplete: pure unit
493− }
494− { db } <- setup
495− { storeParams: IDBDatabase.defaultParameters
496− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
497− _ <- IDBObjectStore.openCursor store Nothing Next cb
498− _ <- IDBObjectStore.openCursor store Nothing NextUnique cb
499− _ <- IDBObjectStore.openCursor store Nothing Prev cb
500− _ <- IDBObjectStore.openCursor store Nothing PrevUnique cb
501− _ <- IDBObjectStore.openCursor store (Just $ IDBKeyRange.upperBound 1 true) Next cb
620+ keys `shouldEqual` [k1,k2]
621+ pure unit
622+
623+ db <- IDBFactory.open dbName Nothing
624+ { onUpgradeNeeded : Just callback
625+ , onBlocked : Nothing
626+ }
627+ tearDown dbName dbVersion db
628+
629+ it "getAllKeys(lowerBound(1, true), nothing)" do
630+ let dbName = "db-getAllKeys"
631+ dbVersion = 1
632+ storeName = "store"
633+ keyPath = []
634+ autoIncrement = true
635+ callback db = do
636+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
637+ _ <- launchAff $ do
638+ k1 <- IDBObjectStore.add store "patate" Nothing
639+ k2 <- IDBObjectStore.add store "autruche" Nothing
640+ k3 <- IDBObjectStore.add store 14 Nothing
641+ keys <- IDBObjectStore.getAllKeys store (Just $ IDBKeyRange.lowerBound 1 true) Nothing
642+ keys `shouldEqual` [k2, k3]
643+ pure unit
644+
645+ db <- IDBFactory.open dbName Nothing
646+ { onUpgradeNeeded : Just callback
647+ , onBlocked : Nothing
648+ }
649+ tearDown dbName dbVersion db
650+
651+ it "openCursor(Nothing, Next)" do
652+ let dbName = "db-openCursor"
653+ dbVersion = 1
654+ storeName = "store"
655+ keyPath = []
656+ autoIncrement = true
657+ callback db = do
658+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
659+ _ <- launchAff $ do
660+ _ <- IDBObjectStore.openCursor store Nothing Next
502661 pure unit
503− }
504− tearDown db
505−
506− it "openKeyCursor()" do
507− let
508− cb =
509− { onSuccess: const $ pure unit
510− , onError: show >>> fail >>> launchAff'
511− , onComplete: pure unit
512− }
513− { db } <- setup
514− { storeParams: IDBDatabase.defaultParameters
515− , onUpgradeNeeded: Just $ \_ store -> launchAff' do
516− _ <- IDBObjectStore.openKeyCursor store Nothing Next cb
517− _ <- IDBObjectStore.openKeyCursor store Nothing NextUnique cb
518− _ <- IDBObjectStore.openKeyCursor store Nothing Prev cb
519− _ <- IDBObjectStore.openKeyCursor store Nothing PrevUnique cb
520− _ <- IDBObjectStore.openKeyCursor store (Just $ IDBKeyRange.lowerBound 1 true) Next cb
662+ pure unit
663+
664+ db <- IDBFactory.open dbName Nothing
665+ { onUpgradeNeeded : Just callback
666+ , onBlocked : Nothing
667+ }
668+ tearDown dbName dbVersion db
669+
670+ it "openCursor(Nothing, NextUnique)" do
671+ let dbName = "db-openCursor"
672+ dbVersion = 1
673+ storeName = "store"
674+ keyPath = []
675+ autoIncrement = true
676+ callback db = do
677+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
678+ _ <- launchAff $ do
679+ _ <- IDBObjectStore.openCursor store Nothing NextUnique
521680 pure unit
522− }
523− tearDown db
524−
525− describe "IDBIndex" do
526− let
527− tearDown db = do
528− IDBDatabase.close db
529− _ <- IDBFactory.deleteDatabase (IDBDatabase.name db)
530− pure unit
531−
532− setup
533− :: forall value
534− . { storeParams :: { keyPath :: Array String, autoIncrement :: Boolean }
535− , indexParams :: { unique :: Boolean, multiEntry :: Boolean }
536− , values :: Array (Tuple value (Maybe Key))
537− , keyPath :: Array String
538− , onUpgradeNeeded :: Maybe (Database -> Transaction -> Index -> Effect Unit)
539− }
540− -> Aff { db :: Database, index :: Index, store :: ObjectStore }
541− setup { storeParams, indexParams, values, keyPath, onUpgradeNeeded } = do
542− let
543− onUpgradeNeeded' var db tx _ = launchAff' do
544− store <- IDBDatabase.createObjectStore db "store" storeParams
545− _ <- traverse (uncurry (IDBObjectStore.add store)) values
546− index <- IDBObjectStore.createIndex store "index" keyPath indexParams
547− liftEffect $ maybe (pure unit) identity (onUpgradeNeeded <*> pure db <*> pure tx <*> pure index)
548− AVar.put { db, index, store } var
549−
550− var <- AVar.empty
551− _ <- IDBFactory.open "db" Nothing
552− { onUpgradeNeeded: Just (onUpgradeNeeded' var)
553− , onBlocked: Nothing
554− }
555− AVar.take var
556−
557− it "returns an IDBIndex and the properties are set correctly" do
558− { db, index } <- setup
559− { storeParams: IDBDatabase.defaultParameters
560− , indexParams: IDBObjectStore.defaultParameters
561− , onUpgradeNeeded: Nothing
562− , keyPath: []
563− , values: []
564− }
565− IDBIndex.name index `shouldEqual` "index"
566− IDBIndex.keyPath index `shouldEqual` []
567− IDBIndex.unique index `shouldEqual` IDBObjectStore.defaultParameters.unique
568− IDBIndex.multiEntry index `shouldEqual` IDBObjectStore.defaultParameters.multiEntry
569− tearDown db
570−
571− it "attempt to create an index that requires unique values on an object store already contains duplicates" do
572− let onAbort var = launchAff' (AVar.put true var)
573− txVar <- AVar.empty
574− dbVar <- AVar.empty
575− res <- attempt $ setup
576− { storeParams: IDBDatabase.defaultParameters
577− , indexParams:
578− { unique: true
579− , multiEntry: false
580− }
581− , keyPath: [ "indexedProperty" ]
582− , values:
583− [ { indexedProperty: "bar" } :+: (Just $ toKey 1)
584− , { indexedProperty: "bar" } :+: (Just $ toKey 2)
585− ]
586− , onUpgradeNeeded: Just $ \db tx _ -> launchAff' do
587− IDBTransaction.onAbort tx (onAbort txVar)
588− IDBDatabase.onAbort db (onAbort dbVar)
589− }
590− case res of
591− Right _ ->
592− fail "expected abort"
593− _ -> do
594− shouldEqual true =<< AVar.take txVar
595− shouldEqual true =<< AVar.take dbVar
596−
597− it "the index is usable right after being made" do
598− { db } <- setup
599− { storeParams:
600− { keyPath: [ "key" ]
601− , autoIncrement: false
602− }
603− , indexParams: IDBObjectStore.defaultParameters
604− , keyPath: [ "indexedProperty" ]
605− , values:
606− [ { key: "key1", indexedProperty: "indexed_1" } :+: Nothing
607− , { key: "key2", indexedProperty: "indexed_2" } :+: Nothing
608− , { key: "key3", indexedProperty: "indexed_3" } :+: Nothing
609− ]
610− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
611− val <- IDBIndex.get index (IDBKeyRange.only "indexed_2")
612− ((\r -> r.key) <$> val) `shouldEqual` (Just $ toKey "key2")
613− }
614− tearDown db
615−
616− it "empty keyPath" do
617− { db } <- setup
618− { storeParams: IDBDatabase.defaultParameters
619− , indexParams: IDBObjectStore.defaultParameters
620− , keyPath: []
621− , values:
622− [ "object_1" :+: (Just $ toKey 1)
623− , "object_2" :+: (Just $ toKey 2)
624− , "object_3" :+: (Just $ toKey 3)
625− ]
626− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
627− val <- IDBIndex.get index (IDBKeyRange.only "object_3")
628− val `shouldEqual` (Just "object_3")
629− }
630− tearDown db
631−
632− it "index can be valid keys [date]" do
633− date <- liftEffect $ toDateTime <$> now
634− { db } <- setup
635− { storeParams:
636− { keyPath: [ "key" ]
637− , autoIncrement: false
638− }
639− , indexParams: IDBObjectStore.defaultParameters
640− , keyPath: [ "i" ]
641− , values:
642− [ { key: "date", i: (toKey date) } :+: Nothing
643− ]
644− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
645− val <- IDBIndex.get index (IDBKeyRange.only date)
646− ((\r -> r.key) <$> val) `shouldEqual` (Just "date")
647− }
648− tearDown db
649−
650− it "index can be valid keys [num]" do
651− let num = 14
652− { db } <- setup
653− { storeParams:
654− { keyPath: [ "key" ]
655− , autoIncrement: false
656− }
657− , indexParams: IDBObjectStore.defaultParameters
658− , keyPath: [ "i" ]
659− , values:
660− [ { key: "num", i: (toKey num) } :+: Nothing
661− ]
662− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
663− val <- IDBIndex.get index (IDBKeyRange.only num)
664− ((\r -> r.key) <$> val) `shouldEqual` (Just "num")
665− }
666− tearDown db
667−
668− it "index can be valid keys [array]" do
669− let array = [ "patate", "autruche" ]
670− { db } <- setup
671− { storeParams:
672− { keyPath: [ "key" ]
673− , autoIncrement: false
674− }
675− , indexParams: IDBObjectStore.defaultParameters
676− , keyPath: [ "i" ]
677− , values:
678− [ { key: "array", i: (toKey array) } :+: Nothing
679− ]
680− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
681− val <- IDBIndex.get index (IDBKeyRange.only array)
682− ((\r -> r.key) <$> val) `shouldEqual` (Just "array")
683− }
684− tearDown db
685−
686− it "openKeyCursor() - throw InvalidStateError on index deleted by aborted upgrade" do
687− res <- attempt $ setup
688− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
689− , indexParams: IDBObjectStore.defaultParameters
690− , keyPath: [ "indexedProperty" ]
691− , values:
692− [ { key: 14, indexedProperty: "patate" } :+: Nothing
693− ]
694− , onUpgradeNeeded: Just $ \db tx index -> launchAff' do
695− let
696− cb =
697− { onSuccess: const $ pure unit
698− , onError: show >>> fail >>> launchAff'
699− , onComplete: pure unit
700− }
701− IDBTransaction.onAbort tx (pure unit)
702− IDBDatabase.onAbort db (pure unit)
703− IDBTransaction.abort tx
704− cursor <- attempt $ IDBIndex.openKeyCursor index Nothing Next cb
705− case cursor of
706− Right _ -> fail "expected InvalidStateError"
707− Left err -> name err `shouldEqual` "InvalidStateError"
708− }
709− case res of
710− Right _ -> fail "expected InvalidStateError"
711− _ -> pure unit
712−
713− it "openKeyCursor() - throw TransactionInactiveError on aborted transaction" do
714− { db } <- setup
715− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
716− , indexParams: IDBObjectStore.defaultParameters
717− , keyPath: [ "indexedProperty" ]
718− , values:
719− [ { key: 14, indexedProperty: "patate" } :+: Nothing
720− ]
721− , onUpgradeNeeded: Nothing
722− }
723− let
724− cb =
725− { onSuccess: const $ pure unit
726− , onError: show >>> fail >>> launchAff'
727− , onComplete: pure unit
728− }
729− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
730− store <- IDBTransaction.objectStore tx "store"
731− index <- IDBObjectStore.index store "index"
732− IDBTransaction.onAbort tx (pure unit)
733− IDBTransaction.abort tx
734− cursor <- attempt $ IDBIndex.openKeyCursor index Nothing Next cb
735− case cursor of
736− Right _ -> fail "expected TransactionInactiveError"
737− Left err -> name err `shouldEqual` "TransactionInactiveError"
738−
739− tearDown db
740−
741− it "openKeyCursor() - throw InvalidStateError when the index is deleted" do
742− { db } <- setup
743− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
744− , indexParams: IDBObjectStore.defaultParameters
745− , keyPath: [ "indexedProperty" ]
746− , values:
747− [ { key: 14, indexedProperty: "patate" } :+: Nothing
748− ]
749− , onUpgradeNeeded: Just $ \_ tx index -> launchAff' do
750− let
751− cb =
752− { onSuccess: const $ pure unit
753− , onError: show >>> fail >>> launchAff'
754− , onComplete: pure unit
755− }
756− store <- IDBTransaction.objectStore tx "store"
757− IDBObjectStore.deleteIndex store "index"
758− cursor <- attempt $ IDBIndex.openKeyCursor index Nothing Next cb
759− case cursor of
760− Right _ -> fail "expected InvalidStateError"
761− Left err -> name err `shouldEqual` "InvalidStateError"
762− }
763−
764− tearDown db
765−
766− it "openCursor() - throw InvalidStateError on index deleted by aborted upgrade" do
767− res <- attempt $ setup
768− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
769− , indexParams: IDBObjectStore.defaultParameters
770− , keyPath: [ "indexedProperty" ]
771− , values:
772− [ { key: 14, indexedProperty: "patate" } :+: Nothing
773− ]
774− , onUpgradeNeeded: Just $ \db tx index -> launchAff' do
775− let
776− cb =
777− { onSuccess: const $ pure unit
778− , onError: show >>> fail >>> launchAff'
779− , onComplete: pure unit
780− }
781− IDBTransaction.onAbort tx (pure unit)
782− IDBDatabase.onAbort db (pure unit)
783− IDBTransaction.abort tx
784− cursor <- attempt $ IDBIndex.openCursor index Nothing Next cb
785− case cursor of
786− Right _ -> fail "expected InvalidStateError"
787− Left err -> name err `shouldEqual` "InvalidStateError"
788− }
789− case res of
790− Right _ -> fail "expected InvalidStateError"
791− _ -> pure unit
792−
793− it "openCursor() - throw TransactionInactiveError on aborted transaction" do
794− { db } <- setup
795− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
796− , indexParams: IDBObjectStore.defaultParameters
797− , keyPath: [ "indexedProperty" ]
798− , values:
799− [ { key: 14, indexedProperty: "patate" } :+: Nothing
800− ]
801− , onUpgradeNeeded: Nothing
802− }
803− let
804− cb =
805− { onSuccess: const $ pure unit
806− , onError: show >>> fail >>> launchAff'
807− , onComplete: pure unit
808− }
809− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
810− store <- IDBTransaction.objectStore tx "store"
811− index <- IDBObjectStore.index store "index"
812− IDBTransaction.onAbort tx (pure unit)
813− IDBTransaction.abort tx
814− cursor <- attempt $ IDBIndex.openCursor index Nothing Next cb
815− case cursor of
816− Right _ -> fail "expected TransactionInactiveError"
817− Left err -> name err `shouldEqual` "TransactionInactiveError"
818−
819− tearDown db
820−
821− it "openCursor() - throw InvalidStateError when the index is deleted" do
822− { db } <- setup
823− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
824− , indexParams: IDBObjectStore.defaultParameters
825− , keyPath: [ "indexedProperty" ]
826− , values:
827− [ { key: 14, indexedProperty: "patate" } :+: Nothing
828− ]
829− , onUpgradeNeeded: Just $ \db tx index -> launchAff' do
830− let
831− cb =
832− { onSuccess: const $ pure unit
833− , onError: show >>> fail >>> launchAff'
834− , onComplete: pure unit
835− }
836− store <- IDBTransaction.objectStore tx "store"
837− IDBObjectStore.deleteIndex store "index"
838− cursor <- attempt $ IDBIndex.openCursor index Nothing Next cb
839− case cursor of
840− Right _ -> fail "expected InvalidStateError"
841− Left err -> name err `shouldEqual` "InvalidStateError"
842− }
843−
844− tearDown db
845−
846− it "getKey() - multiEntry - adding keys" do
847− { db } <- setup
848− { storeParams: IDBDatabase.defaultParameters
849− , indexParams: { unique: false, multiEntry: true }
850− , keyPath: [ "name" ]
851− , values:
852− [ { name: [ "patate", "autruche" ] } :+: (Just $ toKey 1)
853− , { name: [ "bob" ] } :+: (Just $ toKey 2)
854− ]
855− , onUpgradeNeeded: Just $ \_ _ index -> launchAff' do
856− key <- IDBIndex.getKey index (IDBKeyRange.only "patate")
857− key `shouldEqual` (Just $ toKey 1)
858−
859− key' <- IDBIndex.getKey index (IDBKeyRange.only "autruche")
860− key' `shouldEqual` (Just $ toKey 1)
861−
862− key'' <- IDBIndex.getKey index (IDBKeyRange.only "bob")
863− key'' `shouldEqual` (Just $ toKey 2)
864− }
865− tearDown db
866−
867− it "get() - returns the record with the first key in the range" do
868− { db } <- setup
869− { storeParams: { keyPath: [ "key" ], autoIncrement: false }
870− , indexParams: IDBObjectStore.defaultParameters
871− , keyPath: [ "indexedProperty" ]
872− , values:
873− [ { key: 14, indexedProperty: "patate" } :+: Nothing
874− , { key: 42, indexedProperty: "autruche" } :+: Nothing
875− , { key: 1337, indexedProperty: "baguette" } :+: Nothing
876− ]
877− , onUpgradeNeeded: Nothing
878− }
879−
880− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
881− store <- IDBTransaction.objectStore tx "store"
882− index <- IDBObjectStore.index store "index"
883− val <- IDBIndex.get index (IDBKeyRange.lowerBound "autruche" false)
884− ((\r -> r.key) <$> val) `shouldEqual` (Just 42)
885−
886− tearDown db
887−
888− describe "IDBCursor" do
889− let
890− tearDown db = do
891− IDBDatabase.close db
892− _ <- IDBFactory.deleteDatabase (IDBDatabase.name db)
893− pure unit
894−
895− setup
896− :: forall value
897− . { storeParams :: { keyPath :: Array String, autoIncrement :: Boolean }
898− , indexParams :: { unique :: Boolean, multiEntry :: Boolean }
899− , values :: Array (Tuple value (Maybe Key))
900− , keyPath :: Array String
901− , onUpgradeNeeded :: Maybe (Database -> Transaction -> Index -> Effect Unit)
902− }
903− -> Aff { db :: Database, index :: Index, store :: ObjectStore }
904− setup { storeParams, indexParams, values, keyPath, onUpgradeNeeded } = do
905− let
906− onUpgradeNeeded' var db tx _ = launchAff' do
907− store <- IDBDatabase.createObjectStore db "store" storeParams
908− _ <- traverse (uncurry (IDBObjectStore.add store)) values
909− index <- IDBObjectStore.createIndex store "index" keyPath indexParams
910− liftEffect $ maybe (pure unit) identity (onUpgradeNeeded <*> pure db <*> pure tx <*> pure index)
911− AVar.put { db, index, store } var
912−
913− var <- AVar.empty
914− db <- IDBFactory.open "db" Nothing
915− { onUpgradeNeeded: Just (onUpgradeNeeded' var)
916− , onBlocked: Nothing
917− }
918− AVar.take var
919−
920− it "continue() - iterate to the next record" do
921− { db } <- setup
922− { storeParams: IDBDatabase.defaultParameters
923− , indexParams: IDBObjectStore.defaultParameters
924− , keyPath: []
925− , values:
926− [ "cupcake" :+: (Just $ toKey 4)
927− , "pancake" :+: (Just $ toKey 2)
928− , "pie" :+: (Just $ toKey 1)
929− , "pie" :+: (Just $ toKey 3)
930− ]
931− , onUpgradeNeeded: Nothing
932− }
933− let
934− cb vdone vvals =
935− { onComplete: launchAff' do
936− AVar.put unit vdone
937−
938− , onError: \error -> launchAff' do
939− fail $ "unexpected error: " <> show error
940−
941− , onSuccess: \cursor -> launchAff' do
942− vals <- AVar.take vvals
943− pure (IDBCursor.value cursor) >>= shouldEqual (maybe "" _.v $ head vals)
944− IDBCursor.primaryKey cursor >>= shouldEqual (maybe (toKey 0) _.k $ head vals)
945− AVar.put (drop 1 vals) vvals
946− IDBCursor.continue cursor none
947− }
948− vdone <- AVar.empty
949− vvals <- AVar.new
950− [ { v: "pie", k: toKey 1 }
951− , { v: "pancake", k: toKey 2 }
952− , { v: "pie", k: toKey 3 }
953− , { v: "cupcake", k: toKey 4 }
954− ]
955− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
956− store <- IDBTransaction.objectStore tx "store"
957− IDBObjectStore.openCursor store Nothing Next (cb vdone vvals)
958− AVar.take vdone
959− tearDown db
960−
961− it "continue() - attempt to iterate in the wrong direction" do
962− { db } <- setup
963− { storeParams: IDBDatabase.defaultParameters
964− , indexParams: IDBObjectStore.defaultParameters
965− , keyPath: []
966− , values:
967− [ "cupcake" :+: (Just $ toKey 4)
968− , "pancake" :+: (Just $ toKey 2)
969− , "pie" :+: (Just $ toKey 1)
970− , "pie" :+: (Just $ toKey 3)
971− ]
972− , onUpgradeNeeded: Nothing
973− }
974− let
975− cb vdone =
976− { onComplete: launchAff' do
977− fail $ "shouldn't complete"
978−
979− , onError: \error -> launchAff' do
980− fail $ "unexpected error: " <> show error
981−
982− , onSuccess: \cursor -> launchAff' do
983− res <- attempt $ IDBCursor.continue cursor (Just 1)
984− case res of
985− Left err -> do
986− name err `shouldEqual` "DataError"
987− AVar.put unit vdone
988− Right _ -> do
989− fail "expected continue to fail"
990− }
991− vdone <- AVar.empty
992− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
993− store <- IDBTransaction.objectStore tx "store"
994− IDBObjectStore.openCursor store Nothing Next (cb vdone)
995− AVar.take vdone
996− tearDown db
997−
998− it "advance() - iterate cursor number of times specified by count" do
999− { db } <- setup
1000− { storeParams: { keyPath: [ "pKey" ], autoIncrement: false }
1001− , indexParams: IDBObjectStore.defaultParameters
1002− , keyPath: []
1003− , values:
1004− [ { pKey: "pkey_0", iKey: "ikey_0" } :+: Nothing
1005− , { pKey: "pkey_1", iKey: "ikey_1" } :+: Nothing
1006− , { pKey: "pkey_2", iKey: "ikey_2" } :+: Nothing
1007− , { pKey: "pkey_3", iKey: "ikey_3" } :+: Nothing
1008− ]
1009− , onUpgradeNeeded: Nothing
1010− }
1011− let
1012− cb vdone vjump =
1013− { onComplete: launchAff' do
1014− AVar.put unit vdone
1015−
1016− , onError: \error -> launchAff' do
1017− fail $ "unexpected error: " <> show error
1018−
1019− , onSuccess: \cursor -> launchAff' do
1020− jump <- AVar.take vjump
1021− if jump then do
1022− IDBCursor.advance cursor 3
1023− else do
1024− let value = IDBCursor.value cursor
1025− value.pKey `shouldEqual` "pkey_3"
1026− value.iKey `shouldEqual` "ikey_3"
1027− IDBCursor.continue cursor none
1028− AVar.put false vjump
1029− }
1030− vdone <- AVar.empty
1031− vjump <- AVar.new true
1032− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
1033− store <- IDBTransaction.objectStore tx "store"
1034− IDBObjectStore.openCursor store Nothing Next (cb vdone vjump)
1035− AVar.take vdone
1036− tearDown db
1037−
1038− it "delete() - remove a record from the object store" do
1039− { db } <- setup
1040− { storeParams: { keyPath: [ "pKey" ], autoIncrement: false }
1041− , indexParams: IDBObjectStore.defaultParameters
1042− , keyPath: []
1043− , values:
1044− [ { pKey: "pkey_0", iKey: "ikey_0" } :+: Nothing
1045− , { pKey: "pkey_1", iKey: "ikey_1" } :+: Nothing
1046− , { pKey: "pkey_2", iKey: "ikey_2" } :+: Nothing
1047− , { pKey: "pkey_3", iKey: "ikey_3" } :+: Nothing
1048− ]
1049− , onUpgradeNeeded: Nothing
1050− }
1051− let
1052− cb vdone store =
1053− { onComplete: launchAff' do
1054− mval <- map _.pKey <$> IDBIndex.get store (IDBKeyRange.only "pkey_0")
1055− mval `shouldEqual` (Nothing :: Maybe String)
1056− AVar.put unit vdone
1057−
1058− , onError: \error -> launchAff' do
1059− fail $ "unexpected error: " <> show error
1060−
1061− , onSuccess: \cursor -> launchAff' do
1062− let value = IDBCursor.value cursor
1063− value.pKey `shouldEqual` "pkey_0"
1064− IDBCursor.delete cursor
1065− IDBCursor.advance cursor 4
1066− }
1067− vdone <- AVar.empty
1068− tx <- IDBDatabase.transaction db [ "store" ] ReadWrite
1069− store <- IDBTransaction.objectStore tx "store"
1070− IDBObjectStore.openCursor store Nothing Next (cb vdone store)
1071− AVar.take vdone
1072− tearDown db
1073−
1074− it "update() - modify a record in the object store" do
1075− { db } <- setup
1076− { storeParams: { keyPath: [ "pKey" ], autoIncrement: false }
1077− , indexParams: IDBObjectStore.defaultParameters
1078− , keyPath: []
1079− , values:
1080− [ { pKey: "pkey_0", iKey: "ikey_0" } :+: Nothing
1081− ]
1082− , onUpgradeNeeded: Nothing
1083− }
1084− let
1085− cb vdone store =
1086− { onComplete: launchAff' do
1087− mval <- map _.iKey <$> IDBIndex.get store (IDBKeyRange.only "pkey_0")
1088− mval `shouldEqual` (Just "patate")
1089− AVar.put unit vdone
1090−
1091− , onError: \error -> launchAff' do
1092− fail $ "unexpected error: " <> show error
1093−
1094− , onSuccess: \cursor -> launchAff' do
1095− let value = IDBCursor.value cursor
1096− value.pKey `shouldEqual` "pkey_0"
1097− key <- IDBCursor.update cursor { pKey: "pkey_0", iKey: "patate" }
1098− key `shouldEqual` toKey "pkey_0"
1099− IDBCursor.advance cursor 4
1100− }
1101− vdone <- AVar.empty
1102− tx <- IDBDatabase.transaction db [ "store" ] ReadWrite
1103− store <- IDBTransaction.objectStore tx "store"
1104− IDBObjectStore.openCursor store Nothing Next (cb vdone store)
1105− AVar.take vdone
1106− tearDown db
1107−
1108− it "update() - throw ReadOnlyError after update on ReadOnly transaction" do
1109− { db } <- setup
1110− { storeParams: { keyPath: [ "pKey" ], autoIncrement: false }
1111− , indexParams: IDBObjectStore.defaultParameters
1112− , keyPath: []
1113− , values:
1114− [ { pKey: "pkey_0", iKey: "ikey_0" } :+: Nothing
1115− ]
1116− , onUpgradeNeeded: Nothing
1117− }
1118− let
1119− cb vdone =
1120− { onComplete: launchAff' do
1121− fail $ "shouldn't complete"
1122−
1123− , onError: \error -> launchAff' do
1124− fail $ "unexpected error: " <> show error
1125−
1126− , onSuccess: \cursor -> launchAff' do
1127− res <- attempt $ IDBCursor.update cursor "patate"
1128− case res of
1129− Left err -> do
1130− name err `shouldEqual` "ReadOnlyError"
1131− AVar.put unit vdone
1132− Right _ ->
1133− fail $ "expected ReadOnlyError"
1134− }
1135− vdone <- AVar.empty
1136− tx <- IDBDatabase.transaction db [ "store" ] ReadOnly
1137− store <- IDBTransaction.objectStore tx "store"
1138− IDBObjectStore.openCursor store Nothing Next (cb vdone)
1139− AVar.take vdone
1140− tearDown db
681+ pure unit
682+
683+ db <- IDBFactory.open dbName Nothing
684+ { onUpgradeNeeded : Just callback
685+ , onBlocked : Nothing
686+ }
687+ tearDown dbName dbVersion db
688+
689+ it "openCursor(Nothing, Prev)" do
690+ let dbName = "db-openCursor"
691+ dbVersion = 1
692+ storeName = "store"
693+ keyPath = []
694+ autoIncrement = true
695+ callback db = do
696+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
697+ _ <- launchAff $ do
698+ _ <- IDBObjectStore.openCursor store Nothing Prev
699+ pure unit
700+ pure unit
701+
702+ db <- IDBFactory.open dbName Nothing
703+ { onUpgradeNeeded : Just callback
704+ , onBlocked : Nothing
705+ }
706+ tearDown dbName dbVersion db
707+
708+ it "openCursor(Nothing, PrevUnique)" do
709+ let dbName = "db-openCursor"
710+ dbVersion = 1
711+ storeName = "store"
712+ keyPath = []
713+ autoIncrement = true
714+ callback db = do
715+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
716+ _ <- launchAff $ do
717+ _ <- IDBObjectStore.openCursor store Nothing PrevUnique
718+ pure unit
719+ pure unit
720+
721+ db <- IDBFactory.open dbName Nothing
722+ { onUpgradeNeeded : Just callback
723+ , onBlocked : Nothing
724+ }
725+ tearDown dbName dbVersion db
726+
727+ it "openCursor(Just upperBound, Next)" do
728+ let dbName = "db-openCursor"
729+ dbVersion = 1
730+ storeName = "store"
731+ keyPath = []
732+ autoIncrement = true
733+ callback db = do
734+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
735+ _ <- launchAff $ do
736+ _ <- IDBObjectStore.openCursor store (Just $ IDBKeyRange.upperBound 10 true) Next
737+ pure unit
738+ pure unit
739+
740+ db <- IDBFactory.open dbName Nothing
741+ { onUpgradeNeeded : Just callback
742+ , onBlocked : Nothing
743+ }
744+ tearDown dbName dbVersion db
745+
746+ it "openKeyCursor(Nothing, Next)" do
747+ let dbName = "db-openKeyCursor"
748+ dbVersion = 1
749+ storeName = "store"
750+ keyPath = []
751+ autoIncrement = true
752+ callback db = do
753+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
754+ _ <- launchAff $ do
755+ _ <- IDBObjectStore.openKeyCursor store Nothing Next
756+ pure unit
757+ pure unit
758+
759+ db <- IDBFactory.open dbName Nothing
760+ { onUpgradeNeeded : Just callback
761+ , onBlocked : Nothing
762+ }
763+ tearDown dbName dbVersion db
764+
765+ it "openKeyCursor(Nothing, NextUnique)" do
766+ let dbName = "db-openKeyCursor"
767+ dbVersion = 1
768+ storeName = "store"
769+ keyPath = []
770+ autoIncrement = true
771+ callback db = do
772+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
773+ _ <- launchAff $ do
774+ _ <- IDBObjectStore.openKeyCursor store Nothing NextUnique
775+ pure unit
776+ pure unit
777+
778+ db <- IDBFactory.open dbName Nothing
779+ { onUpgradeNeeded : Just callback
780+ , onBlocked : Nothing
781+ }
782+ tearDown dbName dbVersion db
783+
784+ it "openKeyCursor(Nothing, Prev)" do
785+ let dbName = "db-openKeyCursor"
786+ dbVersion = 1
787+ storeName = "store"
788+ keyPath = []
789+ autoIncrement = true
790+ callback db = do
791+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
792+ _ <- launchAff $ do
793+ _ <- IDBObjectStore.openKeyCursor store Nothing Prev
794+ pure unit
795+ pure unit
796+
797+ db <- IDBFactory.open dbName Nothing
798+ { onUpgradeNeeded : Just callback
799+ , onBlocked : Nothing
800+ }
801+ tearDown dbName dbVersion db
802+
803+ it "openKeyCursor(Nothing, PrevUnique)" do
804+ let dbName = "db-openKeyCursor"
805+ dbVersion = 1
806+ storeName = "store"
807+ keyPath = []
808+ autoIncrement = true
809+ callback db = do
810+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
811+ _ <- launchAff $ do
812+ _ <- IDBObjectStore.openKeyCursor store Nothing PrevUnique
813+ pure unit
814+ pure unit
815+
816+ db <- IDBFactory.open dbName Nothing
817+ { onUpgradeNeeded : Just callback
818+ , onBlocked : Nothing
819+ }
820+ tearDown dbName dbVersion db
821+
822+ it "openKeyCursor(Just upperBound, Next)" do
823+ let dbName = "db-openKeyCursor"
824+ dbVersion = 1
825+ storeName = "store"
826+ keyPath = []
827+ autoIncrement = true
828+ callback db = do
829+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
830+ _ <- launchAff $ do
831+ _ <- IDBObjectStore.openKeyCursor store (Just $ IDBKeyRange.upperBound 10 true) Next
832+ pure unit
833+ pure unit
834+
835+ db <- IDBFactory.open dbName Nothing
836+ { onUpgradeNeeded : Just callback
837+ , onBlocked : Nothing
838+ }
839+ tearDown dbName dbVersion db
840+
841+ it "store.autoIncrement[true]" do
842+ let dbName = "db-autoIncrement"
843+ dbVersion = 1
844+ storeName = "store"
845+ keyPath = []
846+ autoIncrement = true
847+ callback db = do
848+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
849+ let autoIncrement' = IDBObjectStore.autoIncrement store
850+ _ <- launchAff $ autoIncrement `shouldEqual` autoIncrement'
851+ pure unit
852+
853+ db <- IDBFactory.open dbName Nothing
854+ { onUpgradeNeeded : Just callback
855+ , onBlocked : Nothing
856+ }
857+ tearDown dbName dbVersion db
858+
859+ it "store.autoIncrement[false]" do
860+ let dbName = "db-autoIncrement"
861+ dbVersion = 1
862+ storeName = "store"
863+ keyPath = []
864+ autoIncrement = false
865+ callback db = do
866+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
867+ let autoIncrement' = IDBObjectStore.autoIncrement store
868+ _ <- launchAff $ autoIncrement `shouldEqual` autoIncrement'
869+ pure unit
870+
871+ db <- IDBFactory.open dbName Nothing
872+ { onUpgradeNeeded : Just callback
873+ , onBlocked : Nothing
874+ }
875+ tearDown dbName dbVersion db
876+
877+ it "store.keyPath[\"patate\"]" do
878+ let dbName = "db-keyPath"
879+ dbVersion = 1
880+ storeName = "store"
881+ keyPath = ["patate"]
882+ autoIncrement = false
883+ callback db = do
884+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
885+ let keyPath' = IDBObjectStore.keyPath store
886+ _ <- launchAff $ keyPath `shouldEqual` keyPath'
887+ pure unit
888+
889+ db <- IDBFactory.open dbName Nothing
890+ { onUpgradeNeeded : Just callback
891+ , onBlocked : Nothing
892+ }
893+ tearDown dbName dbVersion db
894+
895+ it "store.indexNames[]" do
896+ let dbName = "db-indexNames"
897+ dbVersion = 1
898+ storeName = "store"
899+ keyPath = []
900+ autoIncrement = false
901+ callback db = do
902+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
903+ let indexNames = IDBObjectStore.indexNames store
904+ _ <- launchAff $ indexNames `shouldEqual` []
905+ pure unit
906+
907+ db <- IDBFactory.open dbName Nothing
908+ { onUpgradeNeeded : Just callback
909+ , onBlocked : Nothing
910+ }
911+ tearDown dbName dbVersion db
912+
913+ it "store.name[\"store\"]" do
914+ let dbName = "db-indexNames"
915+ dbVersion = 1
916+ storeName = "store"
917+ keyPath = []
918+ autoIncrement = false
919+ callback db = do
920+ store <- IDBDatabase.createObjectStore db storeName { keyPath, autoIncrement }
921+ let storeName' = IDBObjectStore.name store
922+ _ <- launchAff $ storeName `shouldEqual` storeName'
923+ pure unit
1141924
925+ db <- IDBFactory.open dbName Nothing
926+ { onUpgradeNeeded : Just callback
927+ , onBlocked : Nothing
928+ }
929+ tearDown dbName dbVersion db