text: Mocking SQLite Native Plugin in Ionic 4 & Angular
  Receive new Ionic 4 tutorials.
  In this tutorial, we'll learn how to mock the SQLite native plugin in Ionic 4 & Angular projects.
  Thanks to Ionic Native, we can now mock native plugins to provide a fake class that has the same API as the native wrapper for a specific Cordova plugin.
  You may use simple mocks which only return some supplied values or you can build fully working mocks that port the functionality of a specific native plugin to the browser by taking advantage of an equivalent browser API or a JavaScript library.
  So let's get started by creating a new Ionic 4 project based on Angular and install the Ionic native SQLite wrapper.
  Creating a New Ionic 4 Project
  Open your terminal/command prompt and run the following command:
  ionic start native-sqlite-mock blank --type=angular
  Note: Please note that we are using the Ionic CLI 5 which is the latest version. You can install via npm by running the
  npm install -g ionic@latest.
  Once your project is fully created, navigate inside of it and run the following command to install the Ionic native SQLite plugin:
  cd native-sqlite-mock npm install --save @ionic-native/sqlite@4
  Note: We don't need to add a Cordova platform or add the Cordova SQLite plugin since we are not going to develop on the real device for now.
  After installing the native plugin, open the
  src/app/app.module.ts file and add it to the list of providers:
  import { SQLite } from '@ionic-native/sqlite'; @NgModule({ declarations: [ MyApp ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp ], providers: [ StatusBar, SplashScreen, SQLite ] }) export class AppModule {}
  Creating a SQLite Database
  Now, let's create our SQLite database. Open the
  src/pages/home/home.ts file and let's do the following things:
  - Inject the SQLite plugin,
  - Declare an object of the
  SQLiteObjecttype,
  - Add an array for storing your data and a variable of the number type that will be used as a counter.
  - Finally, create a SQLite database.
  Open the
  src/app/pages/home/home.page.ts file and the following changes:
  import { Component, OnInit } from '@angular/core'; import { SQLite, SQLiteObject } from '@ionic-native/sqlite'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'] }) export class HomePage { public database: SQLiteObject; public invoices: Array<Object>; // our data public counter : number = 0; constructor(private sqlite : SQLite) { } ngOnInit() { this.sqlite.create({name: "data.db", location: "default"}) .then((db : SQLiteObject) => { this.database = db; }, (error) => { console.log("ERROR: ", error); }); } }
  Head back to your terminal and run the following command to serve your app locally:
  $ ionic serve
  Next, go to the address for playing with your app in the browser.
  Open the browser's console, you should cordova is not available message.
  That's because, unlike real devices, in the browser environment Cordova is not avialble.
  This means, the
  create() method will fail to create a SQLite database. let's change that!
  Mocking the SQLite Plugin
  We want to use the SQLite API methods when developing on the browser without having to change anything when we switch back to a real device. This is why we need to create a mock which has the same API.
  The most used methods of the SQlite plugin are:
  - The
  create()method for creating SQLite databases.
  - The
  executeSql()method for executing SQL statements against the created database.
  We need to create a mock that at least provides these two methods.
  Open the
  src/app/app.module.ts file and add the following TypeScript class:
  import { SQLite , SQLiteDatabaseConfig , SQLiteObject } from '@ionic-native/sqlite'; class SQLiteMock { public create(config: SQLiteDatabaseConfig): Promise<SQLiteObject> { return new Promise((resolve,reject)=>{ resolve(new SQLiteObject(new Object())); }); } }
  Next, add the
  SQLiteMock class under the
  useClass property of the SQLite provider:
  providers: [ StatusBar, SplashScreen, {provide: SQLite, useClass: SQLiteMock}, {provide: ErrorHandler, useClass: IonicErrorHandler} ] })
  That's it! You have created a basic mock for the SQLite plugin. Now if you go back to your application, you will not get the Cordova Not Available method since we are using the
  create() method of our mock class instead of the original one.
  But this mock doesn't actually create any database, so we can't simulate the same environment as if we are developing on a real device, let's change that!
  Since the browser has no supported way to use SQLite, we will use a JavaScript library which provides an in memory SQLite database i.e the database and all its content will live in the memory.
  So go ahead and grab the library then include
  it with using a
  <script> tag in
  index.html file of your project just before Ionic files:
  <script src="assets/sql.js"></script>
  Since this is a JavaScript library, add the following statement in the
  src/app/app.module.ts to be able to use it:
  declare var SQL;
  Implementing the
  create() Method of SQLite
  Now let's implement the
  create() method of our mock class:
  class SQLiteMock { public create(config: SQLiteDatabaseConfig): Promise<SQLiteObject> { //since this is an in memory database we can ignore the config parameters var db = new SQL.Database(); return new Promise((resolve,reject)=>{ resolve(new SQLiteObject(db)); }); } }
  Implementing
  SQLiteObject and
  executeSql()
  Until now, we are using the original
  SQLiteObject but we need to use our own so we can provide an
  implementation of
  executeSql() method.
  So go ahead and remove the import statement of
  SQLiteObject and create a new class which has a constructor that
  takes a database object we have in the
  create() method.
  The
  executeSql() method needs to return a Promise that can be either rejected with an error string or resolved
  with a payload:
  var payload = { rows: { item: function(i) { return rows[i]; }, length: rows.length }, rowsAffected: this._objectInstance.getRowsModified() || 0, insertId: this._objectInstance.insertId || void 0 };
  And here is the full class:
  class SQLiteObject{ _objectInstance: any; constructor(_objectInstance: any){ this._objectInstance = _objectInstance; }; }; resolve(payload); } catch(e){ reject(e); } }); }; }
  Note: Both the
  create()and
  executeSql()methods should have the exact same parameters and return types as the original ones. So we can get the same behavior, when we swap back the original plugin on the real device
  You can look at the Ionic Native wrapper of SQLite and also the SQLite Cordova plugin to get the exact signatures and return types of these methods.
  Testing the Mocked SQLite Plugin
  Now, let's test our fake SQLite plugin.
  Creating a SQL Table
  Let's add a
  createTable() method to create an
  invoices table:
  public createTable(){ this.database.executeSql('create table if not exists invoices(name VARCHAR(32))', {}) .then(() => { console.log('Table Invoice created !'); }) .catch(e => console.log(e)); }
  Inserting Data in the SQL Table
  Next, add a method to insert some invoices into the created table:
  public counter : number = 0; public insertInvoice(){ var c = 'INV' + this.counter; this.database.executeSql("INSERT INTO invoices (name) VALUES (?)", [c]).then((data) => { console.log("INSERTED: "); this.counter++; this.showInvoices(); }, (error) => { console.log("ERROR: " + JSON.stringify(error.err)); }); }
  List the Table Data
  Create the
  showInvoices() method which list all the inserted invoices:
  public invoices: Array<Object>; public showInvoices(){ this.database.executeSql("SELECT * FROM invoices", []).then((data) => { this.invoices = []; if(data.rows.length > 0) { for(var i = 0 ; i < data.rows.length ; i++) { this.invoices.push({ name: data.rows.item(i).name }); } } }, (error) => { console.log("ERROR: " + JSON.stringify(error)); }); }
  Next, chnage the code inside the
  ngOnInit() method as follows:
  ngOnInit(){ this.sqlite.create({name: "data.db", location: "default"}).then((db : SQLiteObject) => { this.database = db; this.createTable(); }, (error) => { console.log("ERROR: ", error); }); }
  Note: Don't forget to inject the SQLite provider via home page constructor.
  Finally, open the
  src/app/pages/home/home.page.html file and add a button to trigger the method to insert invoices and a list to show the invoices in our SQLite database
  <ion-content padding> <button ion-button (click)="insertInvoice()">Insert Invoice</button> <ion-list> <ion-item * </ion-item> </ion-list> </ion-content>
  Saving the SQLite Database
  Since we are using an in memory SQLite database, when our app reloads, the content of the database gets lost.
  This is not a problem because this is just test data but to avoid re-entering the data every time the app reloads let's save the SQLite database and reload it back when the app reloads.
  Fortunately for us, our JavaScript library has an export method to export the in memory database to an Array of bytes.
  You can use either the local storage or the IndexedDB database in the browser to save the in memory database every time the
  executeSql() method is invoked.
  Change the
  executeSql() as follows: }; //save database after each sql query var arr : ArrayBuffer = this._objectInstance.export(); localStorage.setItem("database",String(arr)); resolve(payload); } catch(e){ reject(e); } }); };
  Next, change the
  create() method of
  SQLiteMock as follows:
  class SQLiteMock { public create(config: SQLiteDatabaseConfig): Promise<SQLiteObject> { var db; var storeddb = localStorage.getItem("database"); var arr = storeddb.split(','); if(storeddb) { db = new SQL.Database(arr); } else { db = new SQL.Database(); } return new Promise((resolve,reject)=>{ resolve(new SQLiteObject(db)); }); } }
  The method looks for a database item in the local storage. If it exists, it gets passed to
  SQL.Database().
  The database is saved as a string so it gets parsed back to an array of bytes.
  Conclusion
  Now you can develop Ionic 4 apps which make use of the native SQLite plugin entirely in the browser thanks to Ionic Native mocks.<<