1/** 2 * Sample React Native App 3 * https://github.com/facebook/react-native 4 * 5 * @format 6 * @flow 7 */ 8 9import React, { Component } from 'react'; 10import { Button, StyleSheet, Text, View } from 'react-native'; 11import { EJDB2, JBE } from 'ejdb2_react_native'; 12 13const { assert } = require('chai'); 14const t = { 15 true: a => assert.isTrue(a), 16 is: (a, b) => assert.equal(a, b), 17 throwsAsync: (a, b) => a.catch(e => assert.deepInclude(e, b)), 18 deepEqual: (a, b) => assert.deepEqual(a, b), 19}; 20 21export default class App extends Component { 22 constructor(props) { 23 super(props); 24 this.state = { 25 status: 0, 26 } 27 } 28 29 async test() { 30 31 const db = await EJDB2.open('hello.db', { truncate: true }); 32 33 await db.createQuery('@mycoll/*').use(q => { 34 t.true(q != null); 35 t.is(q.collection, 'mycoll'); 36 t.true(q.db != null); 37 }); 38 39 let id = await db.put('mycoll', { 'foo': 'bar' }); 40 t.is(id, 1); 41 42 await t.throwsAsync(db.put('mycoll', '{"'), { 43 code: '76005', 44 message: 'com.softmotions.ejdb2.EJDB2Exception: @ejdb IWRC:76005 errno:0 Unquoted JSON string (JBL_ERROR_PARSE_UNQUOTED_STRING)' 45 }); 46 47 let doc = await db.get('mycoll', 1); 48 t.deepEqual(doc, { foo: 'bar' }); 49 50 await db.put('mycoll', { 'foo': 'baz' }); 51 52 const list = await db.createQuery('@mycoll/*').use(q => q.list({ limit: 1 })); 53 t.is(list.length, 1); 54 55 let first = await db.createQuery('@mycoll/*').use(q => q.first()); 56 t.true(first != null); 57 t.deepEqual(first.json, { foo: 'baz' }); 58 t.is(first._raw, null); 59 60 61 first = await db.createQuery('@mycoll/[zzz=bbb]').use(q => q.first()); 62 t.is(first, undefined); 63 64 let firstN = await db.createQuery('@mycoll/*').use(q => q.firstN(5)); 65 t.true(firstN != null && firstN.length == 2); 66 t.deepEqual(firstN[0].json, { foo: 'baz' }); 67 t.deepEqual(firstN[1].json, { foo: 'bar' }); 68 69 firstN = await db.createQuery('@mycoll/*').use(q => q.firstN(1)); 70 t.true(firstN != null && firstN.length == 1); 71 t.deepEqual(firstN[0].json, { foo: 'baz' }); 72 73 // Query 1 74 const rbuf = []; 75 await db.createQuery('@mycoll/*').withLimit(10).useExecute((doc) => { 76 rbuf.push(doc.id); 77 rbuf.push(doc._raw); 78 }); 79 t.is(rbuf.toString(), '2,{"foo":"baz"},1,{"foo":"bar"}'); 80 81 // Query 2 82 rbuf.length = 0; 83 await db.createQuery('@mycoll/[foo=:? and foo=:bar]') 84 .setString(0, 'baz') 85 .setString('bar', 'baz') 86 .useExecute((doc) => { 87 rbuf.push(doc.id); 88 rbuf.push(doc._raw); 89 }); 90 t.is(rbuf.toString(), '2,{"foo":"baz"}'); 91 92 93 let error = null; 94 try { 95 await db.createQuery('@mycoll/[').useExecute(); 96 } catch (e) { 97 error = e; 98 t.true(JBE.isInvalidQuery(e)); 99 } 100 t.true(error != null); 101 error = null; 102 103 let q = await db.createQuery('@mycoll/*'); 104 q.close(); 105 106 try { 107 await q.useExecute(); 108 } catch (e) { 109 error = e; 110 t.true(e.toString().indexOf('IllegalStateException') != -1); 111 } 112 t.true(error != null); 113 error = null; 114 115 let count = await db.createQuery('@mycoll/* | count').use(q => q.scalarInt()); 116 t.is(count, 2); 117 118 await db.del('mycoll', 1); 119 120 error = null; 121 try { 122 await db.get('mycoll', 1); 123 } catch (e) { 124 error = e; 125 t.true(JBE.isNotFound(e)); 126 } 127 t.true(error != null); 128 error = null; 129 130 count = await db.createQuery('@mycoll/* | count').use(q => q.scalarInt()); 131 t.is(count, 1); 132 133 // Patch 134 await db.patch('mycoll', '[{"op":"add", "path":"/baz", "value":"qux"}]', 2); 135 doc = await db.get('mycoll', 2); 136 t.deepEqual(doc, { foo: 'baz', baz: 'qux' }); 137 138 // DB Info 139 doc = await db.info(); 140 assert.deepNestedInclude(doc, { 141 'collections[0]': { 142 name: 'mycoll', 143 rnum: 1, 144 dbid: 3, 145 indexes: [] 146 } 147 }); 148 149 // Indexes 150 await db.ensureStringIndex('mycoll', '/foo', true); 151 doc = await db.info(); 152 assert.deepNestedInclude(doc, { 153 'collections[0].indexes[0]': { 154 ptr: '/foo', 155 mode: 5, 156 idbf: 0, 157 dbid: 4, 158 rnum: 1 159 } 160 }); 161 162 // Test JQL set 163 doc = await db.createQuery('@mycoll/[foo=:?]') 164 .setString(0, 'baz').use(q => q.first()); 165 assert.deepInclude(doc.json, { 166 foo: 'baz', 167 baz: 'qux' 168 }); 169 170 // Test explain log 171 let log; 172 q = await db.createQuery('@mycoll/[foo=:?]') 173 .setString(0, 'baz') 174 .withExplain(); 175 await q.useExecute(); 176 log = q.explainLog; 177 t.true(log.indexOf('[INDEX] MATCHED UNIQUE|STR|1 /foo EXPR1: \'foo = :?\' INIT: IWKV_CURSOR_EQ') != -1); 178 179 180 await db.createQuery('@mycoll/[foo=:?]') 181 .setString(0, 'baz') 182 .useExecute((jbdoc, jql) => { 183 t.true(jql != null); 184 q.explainLog; 185 t.true(log.indexOf('[INDEX] MATCHED UNIQUE|STR|1 /foo EXPR1: \'foo = :?\' INIT: IWKV_CURSOR_EQ') != -1); 186 }); 187 188 doc = await db.createQuery('@mycoll/[foo=:?] and /[baz=:?]') 189 .setString(0, 'baz') 190 .setString(1, 'qux') 191 .use(q => q.first()); 192 193 assert.deepInclude(doc.json, { 194 foo: 'baz', 195 baz: 'qux' 196 }); 197 198 199 doc = await db.createQuery('@mycoll/[foo re :?]').setRegexp(0, '.*').use(q => q.first()); 200 assert.deepInclude(doc.json, { 201 foo: 'baz', 202 baz: 'qux' 203 }); 204 205 doc = await db.createQuery('@mycoll/[foo re :?]').setRegexp(0, /.*/).use(q => q.first()); 206 assert.deepInclude(doc.json, { 207 foo: 'baz', 208 baz: 'qux' 209 }); 210 211 doc = await db.createQuery('@mycoll/* | /foo').use(q => q.first()); 212 assert.deepEqual(doc.json, { foo: 'baz' }); 213 214 await db.removeStringIndex('mycoll', '/foo', true); 215 doc = await db.info(); 216 217 const dbfile = doc.file; 218 t.true(typeof dbfile == 'string'); 219 220 assert.deepNestedInclude(doc, { 221 'collections[0].indexes': [] 222 }); 223 224 await db.removeCollection('mycoll'); 225 doc = await db.info(); 226 assert.deepNestedInclude(doc, { 227 'collections': [] 228 }); 229 230 q = db.createQuery('@c1/* | limit 2 skip 3'); 231 t.is(q.limit, 2); 232 t.is(q.skip, 3); 233 q.close(); 234 235 // Rename collection 236 id = await db.put('cc1', { 'foo': 1 }); 237 t.true(id > 0); 238 doc = await db.get('cc1', id); 239 t.deepEqual(doc, { 'foo': 1 }); 240 241 await db.renameCollection('cc1', 'cc2'); 242 doc = await db.get('cc2', id); 243 t.deepEqual(doc, { 'foo': 1 }); 244 245 246 let i = 0; 247 for (i = 0; i < 1023; ++i) { 248 await db.put('load', { 'name': `v${i}` }); 249 } 250 251 i = 0; 252 await db.createQuery('@load/* | inverse').useExecute(((jbdoc) => { 253 const json = jbdoc.json; 254 t.is(json.name, `v${i}`); 255 i++; 256 })); 257 t.is(i, 1023); 258 259 const ts0 = +new Date(); 260 const ts = await db.onlineBackup(`${dbfile}.bkp`); 261 t.true(ts0 < ts); 262 263 await db.close(); 264 265 // Restore from backup 266 const db2 = await EJDB2.open('hello.db.bkp', { truncate: false }); 267 doc = await db2.get('cc2', id); 268 t.deepEqual(doc, { 'foo': 1 }); 269 await db2.close(); 270 } 271 272 render() { 273 return ( 274 <View style={styles.container}> 275 {this.state.status 276 ? <Text testID="status">{this.state.status}</Text> 277 : <Button testID="run" title="Run tests" onPress={e => this.run()}></Button>} 278 </View> 279 ); 280 } 281 282 async run() { 283 try { 284 this.setState({ status: 'Testing' }); 285 286 await this.test(); 287 288 this.setState({ status: 'OK' }); 289 } catch (e) { 290 console.log('Error ', e); 291 this.setState({ status: `${e.code || ''} ${e}` }); 292 throw e; 293 } 294 } 295} 296 297const styles = StyleSheet.create({ 298 container: { 299 flex: 1, 300 justifyContent: 'center', 301 alignItems: 'center', 302 backgroundColor: '#F5FCFF', 303 }, 304}); 305