Socket
Socket
Sign inDemoInstall

cordova-sqlite-storage

Package Overview
Dependencies
1
Maintainers
1
Versions
66
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.4.7 to 1.4.8

scripts/prepareSpec.js

2

AUTHORS.md

@@ -19,3 +19,3 @@ # Authors

## iOS version
## iOS/macOS version

@@ -22,0 +22,0 @@ - Original authors: @davibe (Davide Bertola <dade@dadeb.it>) and @joenoon (Joe Noon <joenoon@gmail.com>)

# Changes
### cordova-sqlite-storage 1.4.8
- selfTest function add string test and test of effects of location reload/change
- Support macOS ("osx" platform)
- Signal an error in case of SQL with too many parameter argument values on iOS (in addition to Android & Windows)
- Include proper SQL error code on Android (in certain cases)
- Fix reporting of SQL statement execution errors in Windows version
- Fix Windows version to report errors with a valid error code (0)
- Some doc fixes
### cordova-sqlite-storage 1.4.7

@@ -4,0 +14,0 @@

@@ -11,3 +11,3 @@ # Licenses

## iOS version
## iOS/macOS version

@@ -25,2 +25,1 @@ MIT only

MIT License
{
"name": "cordova-sqlite-storage",
"version": "1.4.7",
"version": "1.4.8",
"description": "Native interface to SQLite for PhoneGap/Cordova",

@@ -32,3 +32,9 @@ "cordova": {

"cordova-sqlite-storage-dependencies": "1.0.0"
},
"scripts": {
"start": "node scripts/prepareSpec.js"
},
"devDependencies": {
"shelljs": "^0.7.4"
}
}

@@ -7,12 +7,9 @@ /* 'use strict'; */

var isWP8 = /IEMobile/.test(navigator.userAgent); // Matches WP(7/8/8.1)
//var isWindows = /Windows NT/.test(navigator.userAgent); // Windows [NT] (8.1)
var isWindows = /Windows /.test(navigator.userAgent); // Windows (8.1)
//var isWindowsPC = /Windows NT/.test(navigator.userAgent); // Windows [NT] (8.1)
//var isWindowsPhone_8_1 = /Windows Phone 8.1/.test(navigator.userAgent); // Windows Phone 8.1
//var isIE = isWindows || isWP8 || isWindowsPhone_8_1;
var isIE = isWindows || isWP8;
var isWebKit = !isIE; // TBD [Android or iOS]
var isWindows = /Windows /.test(navigator.userAgent); // Windows 8.1/Windows Phone 8.1/Windows 10
var isMac = /Macintosh/.test(navigator.userAgent);
window.hasBrowser = true;
window.hasWebKitBrowser = isWebKit;
// XXX TODO rename to something like window.hasWebKitWebSQL here and
// in actual test scripts
window.hasWebKitBrowser = (!isWindows && !isWP8 && !isMac && (isAndroid || !(window.webkit && window.webkit.messageHandlers)));

@@ -28,3 +25,3 @@ describe('check startup', function() {

it('has openDatabase', function() {
if (isWebKit) expect(window.openDatabase).toBeDefined();
if (window.hasWebKitBrowser) expect(window.openDatabase).toBeDefined();
expect(window.sqlitePlugin).toBeDefined();

@@ -31,0 +28,0 @@ expect(window.sqlitePlugin.openDatabase).toBeDefined();

@@ -743,4 +743,4 @@ /* 'use strict'; */

test_it(suiteName + ' database.close (immediately after open) calls its success callback', function () {
// XXX POSSIBLY BROKEN on iOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('POSSIBLY BROKEN on iOS (background processing implementation)');
// XXX POSSIBLY BROKEN on iOS/macOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('POSSIBLY BROKEN on iOS/macOS (background processing implementation)');

@@ -958,3 +958,3 @@ // asynch test coming up

stop(1);
var dbName = "Database-Close-and-Reopen";

@@ -981,3 +981,3 @@

// or commit will fail
db.close();
db.close();
});

@@ -1050,4 +1050,4 @@ }, function (error) {

// XXX POSSIBLY BROKEN on iOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('POSSIBLY BROKEN on iOS (background processing implementation)');
// XXX POSSIBLY BROKEN on iOS/macOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('POSSIBLY BROKEN on iOS/macOS (background processing implementation)');

@@ -1196,4 +1196,4 @@ var dbName = "Immediate-close-delete-Reopen.db";

test_it(suiteName + ' repeatedly open and close database faster (5x)', function () {
// XXX CURRENTLY BROKEN on iOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('CURRENTLY BROKEN on iOS (background processing implementation)');
// XXX CURRENTLY BROKEN on iOS/macOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('CURRENTLY BROKEN on iOS/macOS (background processing implementation)');

@@ -1318,4 +1318,4 @@ var dbName = "repeatedly-open-and-close-faster-5x.db";

test_it(suiteName + ' repeatedly open and delete database faster (5x)', function () {
// XXX CURRENTLY BROKEN on iOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('CURRENTLY BROKEN on iOS (background processing implementation)');
// XXX CURRENTLY BROKEN on iOS/macOS due to current background processing implementation
if (!(isAndroid || isIE)) pending('CURRENTLY BROKEN on iOS/macOS (background processing implementation)');

@@ -1322,0 +1322,0 @@ var dbName = "repeatedly-open-and-delete-faster-5x.db";

@@ -10,4 +10,2 @@ /* 'use strict'; */

var isAndroid = !isWindows && /Android/.test(navigator.userAgent);
var isIE = isWindows || isWP8;
var isWebKit = !isIE; // TBD [Android or iOS]

@@ -53,5 +51,7 @@ // NOTE: In the common storage-master branch there is no difference between the

it(suiteName + 'US-ASCII String manipulation test', function(done) {
var db = openDatabase("ASCII-string-test.db", "1.0", "Demo", DEFAULT_SIZE);
describe(suiteName + 'basic string binding/manipulation tests', function() {
it(suiteName + 'Inline US-ASCII String manipulation test with empty ([]) parameter list', function(done) {
var db = openDatabase("Inline-US-ASCII-string-test-with-empty-parameter-list.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();

@@ -71,2 +71,36 @@

it(suiteName + 'Inline US-ASCII String manipulation test with null parameter list', function(done) {
var db = openDatabase("Inline-US-ASCII-string-test-with-null-parameter-list.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql("SELECT UPPER('Some US-ASCII text') AS uppertext", null, function(tx, res) {
expect(res.rows.item(0).uppertext).toBe("SOME US-ASCII TEXT");
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'Inline US-ASCII String manipulation test with undefined parameter list', function(done) {
var db = openDatabase("Inline-US-ASCII-string-test-with-undefined-parameter-list.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql("SELECT UPPER('Some US-ASCII text') AS uppertext", undefined, function(tx, res) {
expect(res.rows.item(0).uppertext).toBe("SOME US-ASCII TEXT");
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'US-ASCII String binding test', function(done) {

@@ -101,5 +135,5 @@ var db = openDatabase("ASCII-string-binding-test.db", "1.0", "Demo", DEFAULT_SIZE);

it(suiteName + 'String encoding test with UNICODE \\u0000', function (done) {
if (isWindows) pending('BROKEN for Windows'); // XXX
if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] UNICODE characters not working with WP(8)
if (isAndroid && !isWebSql && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)'); // XXX
if (isWindows) pending('BROKEN for Windows'); // [FUTURE TBD, already documented]
if (!isWebSql && isAndroid && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)'); // [FUTURE TBD (documented)]

@@ -238,2 +272,88 @@ var dbName = "Unicode-hex-test";

// NOTE On Windows [using a customized version of the SQLite3-WinRT component] and
// default Android-sqlite-connector implementations it is possible to manipulate,
// store, and retrieve a text string with 4-octet UTF-8 characters such as emojis.
// However HEX manipulations do not work the same as Android/iOS WebKit Web SQL,
// iOS plugin, or Android plugin with androidDatabaseImplementation : 2 setting.
// This linkely indicates that such characters are stored differently
// due to UTF-8 string handling limitations of Android-sqlite-connector
// and Windows (SQLite3-WinRT) versions. ref: litehelpers/Cordova-sqlite-storage#564
it(suiteName + 'Inline emoji string manipulation test: SELECT UPPER("a\\uD83D\\uDE03.") [\\u1F603 SMILING FACE (MOUTH OPEN)]', function(done) {
var db = openDatabase("Inline-emoji-hex-test.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql('SELECT UPPER("a\uD83D\uDE03.") AS uppertext', [], function(tx, res) {
expect(res.rows.item(0).uppertext).toBe('A\uD83D\uDE03.');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'Inline emoji HEX test: SELECT HEX("@\\uD83D\\uDE03!") [\\u1F603 SMILING FACE (MOUTH OPEN)]', function(done) {
if (isWP8) pending('BROKEN for WP8');
if (isAndroid && !isWebSql && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)');
if (isWindows) pending('BROKEN for Windows');
var db = openDatabase("Inline-emoji-hex-test.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql('SELECT HEX("@\uD83D\uDE03!") AS hexvalue', [], function(tx, res) {
expect(res.rows.item(0).hexvalue).toBe('40F09F988321');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + "Inline BLOB with emoji string manipulation test: SELECT LOWER(X'41F09F9883') [A\uD83D\uDE03] [\\u1F603 SMILING FACE (MOUTH OPEN)]", function(done) {
if (isWP8) pending('BROKEN for WP8'); // [CRASH with uncaught exception]
if (isAndroid && !isWebSql && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)'); // CRASH on Android 5.x
if (isWindows) pending('BROKEN for Windows');
var db = openDatabase("Inline-emoji-select-lower-result-test.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql("SELECT LOWER(X'41F09F9883') AS lowertext", [], function(ignored, res) {
expect(res).toBeDefined();
expect(res.rows.item(0).lowertext).toBe('a\uD83D\uDE03');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'emoji SELECT HEX(?) parameter value test: "@\\uD83D\\uDE03!" [\\u1F603 SMILING FACE (MOUTH OPEN)]', function(done) {
if (isWP8) pending('BROKEN for WP8');
if (isAndroid && !isWebSql && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)');
if (isWindows) pending('BROKEN for Windows');
var db = openDatabase("String-emoji-parameter-value-test.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql('SELECT HEX(?) AS hexvalue', ['@\uD83D\uDE03!'], function(tx, res) {
expect(res.rows.item(0).hexvalue).toBe('40F09F988321');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
// NOTE: the next two tests show that for iOS:

@@ -265,5 +385,4 @@ // - UNICODE \u2028 line separator from Javascript to Objective-C is working ok

it(suiteName + ' handles UNICODE \\u2028 line separator correctly [string test]', function (done) {
if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] UNICODE characters not working with WP(8)
if (!(isWebSql || isAndroid || isIE)) pending('BROKEN for iOS'); // XXX [BUG #147] (no callback received)
if (!isWebSql && !isAndroid && !isWindows && !isWP8) pending('BROKEN for iOS/macOS plugin'); // [BUG #147] (no callback received)

@@ -295,3 +414,3 @@ // NOTE: since the above test shows the UNICODE line separator (\u2028)

// ref: litehelpers/Cordova-sqlite-storage#147
it(suiteName + "UNICODE \\u2029 line separator string length", function(done) {
it(suiteName + "UNICODE \\u2029 paragraph separator string length", function(done) {
if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] Certain UNICODE characters not working with WP(8)

@@ -318,6 +437,5 @@

it(suiteName + ' handles UNICODE \\u2029 line separator correctly [string test]', function (done) {
it(suiteName + ' handles UNICODE \\u2029 paragraph separator correctly [string test]', function (done) {
if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] UNICODE characters not working with WP(8)
if (!(isWebSql || isAndroid || isIE)) pending('BROKEN for iOS'); // XXX [BUG #147] (no callback received)
if (!isWebSql && !isAndroid && !isWindows && !isWP8) pending('BROKEN for iOS/macOS plugin'); // [BUG #147] (no callback received)

@@ -352,4 +470,6 @@ // NOTE: since the above test shows the UNICODE paragraph separator (\u2029)

tx.executeSql("SELECT UPPER('Test ¢ é €') AS upper_result", [], function(ignored, rs) {
if (isAndroid && isWebSql) expect(rs.rows.item(0).upper_result).toBe('TEST ¢ É €');
else expect(rs.rows.item(0).upper_result).toBe('TEST ¢ é €');
if (isAndroid && (isWebSql || (isImpl2 && /Android [5-9]/.test(navigator.userAgent))))
expect(rs.rows.item(0).upper_result).toBe('TEST ¢ É €');
else
expect(rs.rows.item(0).upper_result).toBe('TEST ¢ é €');

@@ -370,4 +490,6 @@ // Close (plugin only) & finish:

tx.executeSql('SELECT UPPER(?) AS upper_result', ['Test ¢ é €'], function(ignored, rs) {
if (isAndroid && isWebSql) expect(rs.rows.item(0).upper_result).toBe('TEST ¢ É €');
else expect(rs.rows.item(0).upper_result).toBe('TEST ¢ é €');
if (isAndroid && (isWebSql || (isImpl2 && /Android [5-9]/.test(navigator.userAgent))))
expect(rs.rows.item(0).upper_result).toBe('TEST ¢ É €');
else
expect(rs.rows.item(0).upper_result).toBe('TEST ¢ é €');

@@ -436,2 +558,20 @@ // Close (plugin only) & finish:

});
describe(suiteName + 'string test with non-primitive parameter values', function() {
it(suiteName + 'String test with array parameter value', function(done) {
var db = openDatabase("String-test-with-array-parameter-value.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('SELECT UPPER(?) AS upper_result', [['Test',null,123.456,789]], function(ignored, rs) {
expect(rs.rows.item(0).upper_result).toBe('TEST,,123.456,789');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'String test with new String object', function(done) {

@@ -451,9 +591,9 @@ var db = openDatabase("String-object-string-test.db", "1.0", "Demo", DEFAULT_SIZE);

it(suiteName + 'String test with custom object', function(done) {
// MyCustomObject "class":
function MyCustomObject() {};
MyCustomObject.prototype.toString = function() {return 'toString result';};
MyCustomObject.prototype.valueOf = function() {return 'valueOf result';};
it(suiteName + 'String test with custom object parameter value', function(done) {
// MyCustomParameterObject "class":
function MyCustomParameterObject() {};
MyCustomParameterObject.prototype.toString = function() {return 'toString result';};
MyCustomParameterObject.prototype.valueOf = function() {return 'valueOf result';};
var myObject = new MyCustomObject();
var myObject = new MyCustomParameterObject();
// Check myObject:

@@ -475,4 +615,63 @@ expect(myObject.toString()).toBe('toString result');

}, MYTIMEOUT);
});
it(suiteName + 'String test with custom object in place of sql', function(done) {
describe(suiteName + 'string test with [non-primitive] values for SQL', function() {
it(suiteName + 'String test with new String for SQL', function(done) {
var myNewString = new String("SELECT UPPER('Alice') as u1");
var db = openDatabase("New-string-for-sql-test.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql(myNewString, [], function(tx_ignored, resultSet) {
// EXPECTED RESULT:
expect(true).toBe(true);
expect(resultSet).toBeDefined();
expect(resultSet.rows).toBeDefined();
expect(resultSet.rows.length).toBe(1);
expect(resultSet.rows.item(0)).toBeDefined();
expect(resultSet.rows.item(0).u1).toBeDefined();
expect(resultSet.rows.item(0).u1).toBe('ALICE');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(tx_ignored, error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'String test with single element array for SQL', function(done) {
var db = openDatabase("String-test-with-single-element-array-for-sql.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql(["SELECT UPPER('Alice') as u1"], [], function(tx_ignored, resultSet) {
// EXPECTED RESULT:
expect(true).toBe(true);
expect(resultSet).toBeDefined();
expect(resultSet.rows).toBeDefined();
expect(resultSet.rows.length).toBe(1);
expect(resultSet.rows.item(0)).toBeDefined();
expect(resultSet.rows.item(0).u1).toBeDefined();
expect(resultSet.rows.item(0).u1).toBe('ALICE');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(tx_ignored, error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);
it(suiteName + 'String test with custom object for SQL', function(done) {
// MyCustomObject "class":

@@ -488,6 +687,4 @@ function MyCustomObject() {};

var db = openDatabase("Custom-sql-object-test.db", "1.0", "Demo", DEFAULT_SIZE);
var db = openDatabase("Custom-object-for-sql-test.db", "1.0", "Demo", DEFAULT_SIZE);
var check1 = false;
db.transaction(function(tx) {

@@ -517,2 +714,186 @@ tx.executeSql(myObject, [], function(tx_ignored, resultSet) {

});
describe(suiteName + 'string test with dynamically changing objects', function() {
it(suiteName + 'String test with dynamically changing object for SQL', function(done) {
// MyDynamicObject "class":
function MyDynamicObject() { this.name = 'Alice'; };
MyDynamicObject.prototype.toString = function() {return "SELECT UPPER('" + this.name + "') as uppertext";}
var myObject = new MyDynamicObject();
// Check myObject:
expect(myObject.toString()).toBe("SELECT UPPER('Alice') as uppertext");
var db = openDatabase("Dynamic-object-for-sql-test.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
myObject.name = 'Betty';
tx.executeSql(myObject, [], function(ignored, rs) {
// EXPECTED RESULT:
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
expect(rs.rows.item(0)).toBeDefined();
expect(rs.rows.item(0).uppertext).toBe('BETTY');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(tx_ignored, error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
myObject.name = 'Carol';
});
}, MYTIMEOUT);
it(suiteName + 'String test with dynamically changing object parameter arg value', function(done) {
// MyDynamicParameterObject "class":
function MyDynamicParameterObject() {this.name='Alice';};
MyDynamicParameterObject.prototype.toString = function() {return this.name;};
var myObject = new MyDynamicParameterObject();
// Check myObject:
expect(myObject.toString()).toBe('Alice');
var db = openDatabase("Dynamic-object-arg-string-test.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
myObject.name = 'Betty';
tx.executeSql('SELECT UPPER(?) AS uppertext', [myObject], function(ignored, rs) {
// EXPECTED RESULT:
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
expect(rs.rows.item(0)).toBeDefined();
expect(rs.rows.item(0).uppertext).toBeDefined();
expect(rs.rows.item(0).uppertext).toBe('BETTY');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
myObject.name = 'Carol';
});
}, MYTIMEOUT);
});
describe(suiteName + 'string test with Array "subclass" for SQL parameter arg values array', function() {
;
it(suiteName + 'SELECT UPPER(?) AS upper1, UPPER(?) AS upper2 with "naive" Array subclass (constructor NOT explicitly set) as value arguments array', function(done) {
var db = openDatabase('SELECT-multi-upper-on-array-subclass.db');
expect(db).toBeDefined();
// Variation on the "naive approach" described in
// http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
function F() {}
F.prototype = Array.prototype;
function MyArraySubclass() {}
MyArraySubclass.prototype = new F();
myObject = new MyArraySubclass();
myObject.push('s1', 's2');
expect(myObject.length).toBe(2);
expect(myObject[0]).toBe('s1');
expect(myObject[1]).toBe('s2');
expect(myObject.constructor).toBe(Array);
db.transaction(function(tx) {
tx.executeSql('SELECT UPPER(?) AS upper1, UPPER(?) AS upper2', myObject, function(ignored, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
expect(rs.rows.item(0).upper1).toBe('S1');
expect(rs.rows.item(0).upper2).toBe('S2');
done();
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
it(suiteName + 'SELECT UPPER(?) AS upper1, UPPER(?) AS upper2 with "naive" Array subclass (constructor explicitly set to subclasss) as value arguments array [SQL argument values IGNORED by plugin]', function(done) {
var db = openDatabase('SELECT-multi-upper-on-array-subclass-explicit-constructor.db');
expect(db).toBeDefined();
// Variation on the "naive approach" described in
// http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
function F() {}
F.prototype = Array.prototype;
function MyArraySubclass() {}
MyArraySubclass.prototype = new F();
myObject = new MyArraySubclass();
myObject.push('s1', 's2');
expect(myObject.length).toBe(2);
expect(myObject[0]).toBe('s1');
expect(myObject[1]).toBe('s2');
expect(myObject.constructor).toBe(Array);
myObject.constructor = MyArraySubclass;
expect(myObject.constructor).toBe(MyArraySubclass);
db.transaction(function(tx) {
tx.executeSql('SELECT UPPER(?) AS upper1, UPPER(?) AS upper2', myObject, function(ignored, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
if (isWebSql) {
expect(rs.rows.item(0).upper1).toBe('S1');
expect(rs.rows.item(0).upper2).toBe('S2');
} else {
expect(rs.rows.item(0).upper1).toBeNull();
expect(rs.rows.item(0).upper2).toBeNull();
}
done();
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
xit(suiteName + 'Blank string test with null/undefined callback functions', function(done) {
var db = openDatabase("Inline-US-ASCII-string-test-with-undefined-parameter-list.db", "1.0", "Demo", DEFAULT_SIZE);
expect(db).toBeDefined();
db.transaction(function(tx) {
expect(tx).toBeDefined();
tx.executeSql("SELECT ''", null, null);
tx.executeSql("SELECT ''", undefined, undefined);
tx.executeSql("SELECT ''", null, undefined);
tx.executeSql("SELECT ''", undefined, null);
tx.executeSql("SELECT ''", function(ignored, rs) {
expect(rs).toBeDefined();
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
});
describe(suiteName + 'BLOB string test(s)', function() {
it(suiteName + "SELECT HEX(X'010203') [BLOB value test]", function(done) {

@@ -523,7 +904,7 @@ var db = openDatabase("SELECT-HEX-BLOB-test.db", "1.0", "Demo", DEFAULT_SIZE);

tx.executeSql("SELECT HEX(X'010203') AS hex_value", [], function(ignored, rs) {
tx.executeSql("SELECT HEX(X'010203') AS hexvalue", [], function(ignored, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
expect(rs.rows.item(0).hex_value).toBe('010203');
expect(rs.rows.item(0).hexvalue).toBe('010203');

@@ -536,2 +917,4 @@ // Close (plugin only) & finish:

});
});

@@ -538,0 +921,0 @@

@@ -36,4 +36,4 @@ /* 'use strict'; */

var isAndroid = !isWindows && /Android/.test(navigator.userAgent);
var isIE = isWindows || isWP8;
var isWebKit = !isIE; // TBD [Android or iOS]
var isMac = /Macintosh/.test(navigator.userAgent);
var isWKWebView = !isWindows && !isAndroid && !isWP8 && !isMac && !!window.webkit && !!window.webkit.messageHandlers;

@@ -55,11 +55,11 @@ // NOTE: In the core-master branch there is no difference between the default

describe(scenarioList[i] + ': tx value bindings test(s)', function() {
describe(scenarioList[i] + ': tx INSERT value bindings test(s)', function() {
var scenarioName = scenarioList[i];
var suiteName = scenarioName + ': ';
var isWebSql = (i === 1);
var isOldImpl = (i === 2);
var isImpl2 = (i === 2);
// NOTE: MUST be defined in function scope, NOT outer scope:
var openDatabase = function(name, ignored1, ignored2, ignored3) {
if (isOldImpl) {
if (isImpl2) {
return window.sqlitePlugin.openDatabase({

@@ -80,6 +80,109 @@ // prevent reuse of database from default db implementation:

describe(suiteName + 'transaction column value bindings semantics test(s)', function() {
describe(suiteName + 'transaction column value insertion test(s)', function() {
it(suiteName + "all columns should be included in result set (including 'null' columns)", function(done) {
it(suiteName + 'INSERT with null parameter argument value and check stored data', function(done) {
var db = openDatabase('INSERT-null-arg-value-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (data1, data2)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?,?)', [null, 'test-string'], function(ignored, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(ignored, rs2) {
var row = rs2.rows.item(0);
expect(row.data1).toBeNull();
expect(row.data2).toBe('test-string');
tx.executeSql('SELECT TYPEOF(data1) AS t1, TYPEOF(data2) AS t2 FROM test_table', null, function(ignored, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
expect(rs3.rows.item(0).t1).toBe('null');
expect(rs3.rows.item(0).t2).toBe('text');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + 'INSERT with undefined parameter argument value (inserted as null) and check stored data [BROKEN for Windows: Unsupported argument type ERROR]', function(done) {
if (isWP8) pending('SKIP for WP8'); // SKIP for now
var db = openDatabase('INSERT-undefined-arg-value-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (data1, data2)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?,?)', [undefined, 'test-string'], function(ignored, rs1) {
if (isWindows) expect('Windows plugin version FIXED please update this test').toBe('--');
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(ignored, rs2) {
var row = rs2.rows.item(0);
if (isWebSql && isAndroid)
expect(row.data1).toBe('undefined');
else
expect(row.data1).toBeNull();
expect(row.data2).toBe('test-string');
tx.executeSql('SELECT TYPEOF(data1) AS t1, TYPEOF(data2) AS t2 FROM test_table', null, function(ignored, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
if (isWebSql && isAndroid)
expect(rs3.rows.item(0).t1).toBe('text');
else
expect(rs3.rows.item(0).t1).toBe('null');
expect(rs3.rows.item(0).t2).toBe('text');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// ERROR in case of Windows:
if (isWindows) {
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
expect(error.code).toBe(0);
expect(error.message).toMatch(/a statement with no error handler failed: Unsupported argument type: undefined/);
return done();
}
// OTHERWISE
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + "all columns should be included in result set including id integer primary key & 'null' columns", function(done) {
var db = openDatabase('all-result-columns-including-null-columns.db', '1.0', 'Demo', DEFAULT_SIZE);

@@ -119,6 +222,262 @@

});
it(suiteName + 'INSERT integer value (42) with no/INTEGER/NUMERIC/REAL/TEXT affinity & check stored data [TBD Plugin vs (WebKit) Web SQL]', function(done) {
var db = openDatabase("INTEGER-INSERT-value-bindings.db", "1.0", "Demo", DEFAULT_SIZE);
describe(scenarioList[i] + ': tx column value insertion test(s)', function() {
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS tt');
tx.executeSql('CREATE TABLE IF NOT EXISTS tt (data1, data2 INTEGER, data3 NUMERIC, data4 REAL, data5 TEXT)', null, function(ignored1, ignored2) {
tx.executeSql('INSERT INTO tt VALUES (?,?,?,?,?)',
[42, 42, 42, 42, 42], function(ignored, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
expect(rs1.insertId).toBe(1);
tx.executeSql('SELECT * FROM tt', [], function(ignored, rs2) {
// CHECK BIG INTEGER number was inserted properly:
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBe(1);
var row = rs2.rows.item(0);
expect(row.data1).toBe(42);
expect(row.data2).toBe(42);
expect(row.data3).toBe(42);
expect(row.data4).toBe(42);
if (isWebSql || isMac || isWKWebView)
expect(row.data5).toBe('42.0');
else
expect(row.data5).toBe('42');
tx.executeSql('SELECT TYPEOF(data1) AS t1, TYPEOF(data2) AS t2, TYPEOF(data3) AS t3, TYPEOF(data4) AS t4, TYPEOF(data5) AS t5 FROM tt', [], function(ignored, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
var row = rs3.rows.item(0);
if (isWebSql || isMac || isWKWebView)
expect(row.t1).toBe('real');
else
expect(row.t1).toBe('integer');
expect(row.t2).toBe('integer');
expect(row.t3).toBe('integer');
expect(row.t4).toBe('real');
expect(row.t5).toBe('text');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + 'INSERT Infinity with no/NUMERIC/REAL/INTEGER/TEXT type affinity and check stored data [Android/iOS Plugin BROKEN: stored with null value]', function(done) {
if (isWP8) pending('SKIP for WP8'); // SKIP for now
if (isMac) pending('SKIP for macOS [CRASH]'); // FUTURE TBD
var db = openDatabase('INSERT-Infinity-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE test_table (data, data_num NUMERIC, data_real REAL, data_int INTEGER, data_text TEXT)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?,?,?,?,?)', [Infinity, Infinity, Infinity, Infinity, Infinity], function(ignored, res) {
expect(res).toBeDefined();
expect(res.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(tx, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBeDefined();
var row = rs.rows.item(0);
expect(row).toBeDefined();
if (!isWebSql && !isWindows) {
// Android/iOS plugin issue
expect(row.data).toBe(null);
expect(row.data_num).toBe(null);
expect(row.data_real).toBe(null);
expect(row.data_int).toBe(null);
expect(row.data_text).toBe(null);
} else {
expect(row.data).toBe(Infinity);
expect(row.data_num).toBe(Infinity);
expect(row.data_real).toBe(Infinity);
expect(row.data_int).toBe(Infinity);
expect(row.data_text).toBe('Inf');
}
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + 'INSERT -Infinity with no/NUMERIC/REAL/INTEGER/TEXT type affinity and check stored data [Android/iOS Plugin BROKEN: stored with null value]', function(done) {
if (isWP8) pending('SKIP for WP8'); // SKIP for now
if (isMac) pending('SKIP for macOS [CRASH]'); // FUTURE TBD
var db = openDatabase('INSERT-minus-Infinity-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE test_table (data, data_num NUMERIC, data_real REAL, data_int INTEGER, data_text TEXT)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?,?,?,?,?)', [-Infinity, -Infinity, -Infinity, -Infinity, -Infinity], function(ignored, res) {
expect(res).toBeDefined();
expect(res.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(tx, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBeDefined();
var row = rs.rows.item(0);
expect(row).toBeDefined();
if (!isWebSql && !isWindows) {
// Android/iOS plugin issue
expect(row.data).toBe(null);
expect(row.data_num).toBe(null);
expect(row.data_real).toBe(null);
expect(row.data_int).toBe(null);
expect(row.data_text).toBe(null);
} else {
expect(row.data).toBe(-Infinity);
expect(row.data_num).toBe(-Infinity);
expect(row.data_real).toBe(-Infinity);
expect(row.data_int).toBe(-Infinity);
expect(row.data_text).toBe('-Inf');
}
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + 'INSERT NaN with no/NUMERIC/REAL/INTEGER/TEXT type affinity and check stored data', function(done) {
var db = openDatabase('INSERT-minus-Infinity-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE test_table (data, data_num NUMERIC, data_real REAL, data_int INTEGER, data_text TEXT)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?,?,?,?,?)', [NaN, NaN, NaN, NaN, NaN], function(ignored, res) {
expect(res).toBeDefined();
expect(res.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(tx, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBeDefined();
var row = rs.rows.item(0);
expect(row).toBeDefined();
expect(row.data).toBe(null);
expect(row.data_num).toBe(null);
expect(row.data_real).toBe(null);
expect(row.data_int).toBe(null);
expect(row.data_text).toBe(null);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
// NOTE: emojis and other 4-octet UTF-8 characters apparently not stored
// properly by Android-sqlite-connector/Windows ref: litehelpers/Cordova-sqlite-storage#564
it(suiteName + 'INSERT TEXT string with emoji [\\u1F603 SMILING FACE (MOUTH OPEN)], SELECT the data, and check' +
((!isWebSql && (isWindows || (isAndroid && !isImpl2))) ?
' [BROKEN: SELECT HEX(data) result on Android-sqlite-connector/Windows]' : ''), function(done) {
if (isWP8) pending('SKIP for WP8'); // [TBD CRASH with uncaught exception]
var db = openDatabase('INSERT-emoji-and-check.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (data)', [], function(ignored1, ignored2) {
tx.executeSql('INSERT INTO test_table VALUES (?)', ['@\uD83D\uDE03!'], function(tx, res) {
expect(res).toBeDefined();
expect(res.rowsAffected).toBe(1);
tx.executeSql('SELECT * FROM test_table', [], function(tx, res) {
var row = res.rows.item(0);
// Full object check:
expect(row).toEqual({data: '@\uD83D\uDE03!'});
// Check individual members:
expect(row.data).toBe('@\uD83D\uDE03!');
tx.executeSql('SELECT HEX(data) AS hexvalue FROM test_table', [], function(tx, res) {
// BROKEN: INCORRECT value Android-sqlite-connector/Windows
if (!isWebSql && !isWindows && !isWP8 && !(isAndroid && !isImpl2))
expect(res.rows.item(0).hexvalue).toBe('40F09F988321');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + "number values inserted using number bindings", function(done) {

@@ -147,2 +506,3 @@

expect(row.id).toBe(1);
expect(row.data_text1).toBe("314159"); // (data_text1 should have inserted data as text)

@@ -158,2 +518,16 @@

(isWebSql) ? done() : db.close(done, done);
tx.executeSql('SELECT TYPEOF(data_text1) AS t1, TYPEOF(data_text2) AS t2, data_int AS t3, data_real AS t4', null, function(ignored, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
expect(rs3.rows.item(0).t1).toBe('text');
expect(rs3.rows.item(0).t2).toBe('text');
expect(rs3.rows.item(0).t2).toBe('integer');
expect(rs3.rows.item(0).t2).toBe('real');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});

@@ -165,28 +539,31 @@ });

it(suiteName + "Big [integer] value bindings", function(done) {
if (isWP8) pending('BROKEN for WP(8)'); // XXX [BUG #195]
it(suiteName + 'BIG INTEGER INSERT value bindings', function(done) {
var db = openDatabase("BIG-INTEGER-INSERT-value-bindings.db", "1.0", "Demo", DEFAULT_SIZE);
var db = openDatabase("Big-int-bindings.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS tt');
tx.executeSql('CREATE TABLE IF NOT EXISTS tt (test_date INTEGER, test_text TEXT)');
}, function(err) {
expect(false).toBe(true);
expect(err.message).toBe('---');
// NOTE: DATETIME is same as NUMERIC ref:
// https://www.sqlite.org/datatype3.html#affinity_name_examples
tx.executeSql('CREATE TABLE IF NOT EXISTS tt (data1, test_int INTEGER, test_num NUMERIC, test_date DATETIME, test_text TEXT)', null, function(ignored1, ignored2) {
tx.executeSql('INSERT INTO tt VALUES (?,?,?,?,?)',
[1424174959894, 1424174959894, 1424174959894, 1424174959894, 1424174959894], function(ignored, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
expect(rs1.insertId).toBe(1);
}, function() {
db.transaction(function(tx) {
tx.executeSql("insert into tt (test_date, test_text) VALUES (?,?)",
[1424174959894, 1424174959894], function(tx, res) {
expect(res).toBeDefined();
expect(res.rowsAffected).toBe(1);
tx.executeSql("select * from tt", [], function(tx, res) {
// (Big integer number inserted properly)
var row = res.rows.item(0);
tx.executeSql('SELECT * FROM tt', [], function(ignored, rs2) {
// CHECK BIG INTEGER number was inserted properly:
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBe(1);
var row = rs2.rows.item(0);
expect(row.data1).toBe(1424174959894);
expect(row.test_int).toBe(1424174959894);
expect(row.test_num).toBe(1424174959894);
expect(row.test_date).toBe(1424174959894);
// NOTE: storing big integer in TEXT field WORKING OK with WP(8) version.
// It is now suspected that the issue lies with the results handling.
// XXX Brody TODO: storing big number in TEXT field is different for Plugin vs. Web SQL!
if (isWebSql)
// NOTE: big number apparently stored in field with TEXT affinity with slightly
// different conversion in plugin vs. WebKit Web SQL!
if (isWebSql || isMac || isWKWebView)
expect(row.test_text).toBe("1424174959894.0"); // ([Big] number inserted as string ok)

@@ -196,9 +573,32 @@ else

// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
tx.executeSql('SELECT TYPEOF(data1) AS t1, TYPEOF(test_int) AS t2, TYPEOF(test_num) AS t3, TYPEOF(test_date) AS t4, TYPEOF(test_text) AS t5 FROM tt', [], function(ignored, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
var row = rs3.rows.item(0);
if (isWebSql || isMac || isWKWebView)
expect(row.t1).toBe('real');
else
expect(row.t1).toBe('integer');
expect(row.t2).toBe('integer');
expect(row.t3).toBe('integer');
expect(row.t4).toBe('integer');
expect(row.t5).toBe('text');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
}, MYTIMEOUT);

@@ -233,2 +633,53 @@ it(suiteName + "Double precision decimal number insertion", function(done) {

it(suiteName + 'BIG REAL INSERT value bindings', function(done) {
var db = openDatabase("BIG-REAL-INSERT-value-bindings.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS tt');
tx.executeSql('CREATE TABLE IF NOT EXISTS tt (data1 REAL, data2 NUMERIC, data3 INTEGER, data4 TEXT)', null, function(ignored1, ignored2) {
tx.executeSql('INSERT INTO tt VALUES (?,?,?,?)',
[1234567890123.4, 1234567890123.4, 1234567890123.4, 1234567890123.4], function(tx, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
expect(rs1.insertId).toBe(1);
tx.executeSql('SELECT * FROM tt', [], function(tx, rs2) {
// CHECK BIG INTEGER number was inserted properly:
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBe(1);
var row = rs2.rows.item(0);
expect(row.data1).toBe(1234567890123.4);
expect(row.data2).toBe(1234567890123.4);
expect(row.data3).toBe(1234567890123.4);
expect(row.data4).toBe('1234567890123.4');
tx.executeSql('SELECT TYPEOF(data1) AS t1, TYPEOF(data2) AS t2, TYPEOF(data3) AS t3, TYPEOF(data4) AS t4 FROM tt', [], function(tx, rs3) {
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBe(1);
var row = rs3.rows.item(0);
expect(row.t1).toBe('real');
expect(row.t2).toBe('real');
expect(row.t3).toBe('real');
expect(row.t4).toBe('text');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);
it(suiteName + "executeSql parameter as array", function(done) {

@@ -282,2 +733,3 @@ var db = openDatabase("array-parameter.db", "1.0", "Demo", DEFAULT_SIZE);

expect(rs2.rows.length).toBe(1);
expect(rs2.rows.item(0).id).toBe(1);
expect(rs2.rows.item(0).data1).toBe('true');

@@ -294,3 +746,72 @@ expect(rs2.rows.item(0).data2).toBe('false');

it(suiteName + "executeSql with not enough parameters", function(done) {
it(suiteName + "INSERT inline BLOB value (X'40414243') and check stored data [SELECT BLOB ISSUE with androidDatabaseImplementation: 2 & Windows/WP8]", function(done) {
var db = openDatabase('INSERT-inline-BLOB-value-and-check-stored-data.db', '1.0', 'Demo', DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (data)', [], function(ignored1, ignored2) {
tx.executeSql("INSERT INTO test_table VALUES (X'40414243')", [], function(ignored, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
tx.executeSql('SELECT HEX(data) AS hexValue FROM test_table', [], function(ignored, rs2) {
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBeDefined();
var row = rs2.rows.item(0);
expect(row).toBeDefined();
expect(row.hexValue).toBe('40414243');
if (isWP8) return done(); // STOP CRASH on WP8
tx.executeSql('SELECT * FROM test_table', [], function(ignored, rs3) {
if (!isWebSql && isAndroid && isImpl2) expect('Behavior changed please update this test').toBe('--');
expect(rs3).toBeDefined();
expect(rs3.rows).toBeDefined();
expect(rs3.rows.length).toBeDefined();
var row = rs3.rows.item(0);
expect(row).toBeDefined();
expect(row.data).toBe('@ABC');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(ignored, error) {
if (!isWebSql && isWindows || (isAndroid && isImpl2)) {
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
expect(error.code).toBe(0);
if (isWindows)
expect(error.message).toMatch(/Unsupported column type in column 0/);
else
expect(error.message).toMatch(/unknown error.*code 0.*Unable to convert BLOB to string/);
} else {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
}
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
});
});
}, MYTIMEOUT);
});
describe(suiteName + 'parameter count mismatch tests', function() {
it(suiteName + 'executeSql with not enough parameters (Plugin DEVIATION: does not reject such SQL statements)', function(done) {
var db = openDatabase("not-enough-parameters.db", "1.0", "Demo", DEFAULT_SIZE);

@@ -301,14 +822,5 @@

// CREATE columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data1, data2)');
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function() {
db.transaction(function(tx) {
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first'], function(tx, rs1) {
// ACTUAL for plugin (Android/iOS/Windows):
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (data1, data2)', [], function(ignored1, ignored2) {
tx.executeSql("INSERT INTO test_table VALUES (?,?)", ['first'], function(tx, rs1) {
// ACTUAL BEHAVIOR for plugin (Android/iOS/Windows):
if (isWebSql) expect('RESULT NOT EXPECTED for Web SQL').toBe('--');

@@ -318,6 +830,7 @@ expect(rs1).toBeDefined();

tx.executeSql("select * from test_table", [], function(tx, rs2) {
tx.executeSql('SELECT * FROM test_table', [], function(tx, rs2) {
expect(rs2.rows.length).toBe(1);
expect(rs2.rows.item(0).data1).toBe('first');
expect(rs2.rows.item(0).data2).toBeNull();
// Close (plugin only) & finish:

@@ -327,6 +840,16 @@ (isWebSql) ? done() : db.close(done, done);

}, function(error) {
}, function(ignored, error) {
// CORRECT (Web SQL):
if (!isWebSql) expect('Plugin behavior changed please update this test').toBe('--');
expect(true).toBe(true);
if (!isWebSql) expect('Plugin behavior changed, please update this test').toBe('--');
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
// WebKit Web SQL reports correct error code (5 - SYNTAX_ERR) in this case.
expect(error.code).toBe(5);
// WebKit Web SQL error message (Android/iOS):
expect(error.message).toMatch(/number of '\?'s in statement string does not match argument count/);
// Close (plugin only) & finish:

@@ -337,7 +860,9 @@ (isWebSql) ? done() : db.close(done, done);

});
});
}, MYTIMEOUT);
it(suiteName + "executeSql with too many parameters", function(done) {
var db = openDatabase("too-many-parameters.db", "1.0", "Demo", DEFAULT_SIZE);
it(suiteName + 'executeSql with too many parameters [extra TEXT string]', function(done) {
if (isWP8) pending('SKIP for WP8'); // TBD BROKEN on WP8
var db = openDatabase("too-many-parameters-extra-text-string.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {

@@ -356,20 +881,31 @@ tx.executeSql('DROP TABLE IF EXISTS test_table');

db.transaction(function(tx) {
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first', 'second', 'third'], function(tx, rs1) {
// ACTUAL for iOS plugin:
if (isWebSql) expect('RESULT NOT EXPECTED for Web SQL').toBe('--');
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first', 'second', 'third'], function(ignored1, ignored2) {
// NOT EXPECTED:
expect(false).toBe(true);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
tx.executeSql("select * from test_table", [], function(tx, rs2) {
expect(rs2.rows.length).toBe(1);
expect(rs2.rows.item(0).data1).toBe('first');
expect(rs2.rows.item(0).data2).toBe('second');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, function(ignored, error) {
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
}, function(error) {
// CORRECT (Web SQL; Android & Windows plugin):
if (!isWebSql && !isAndroid && !isWindows) expect('Plugin behavior changed please update this test').toBe('--');
expect(true).toBe(true);
// PLUGIN BROKEN: reports INCORRECT error code: 0 (SQLite.UNKNOWN_ERR)
// WebKit Web SQL reports correct error code: 5 (SQLite.SYNTAX_ERR) in this case.
// ref: https://www.w3.org/TR/webdatabase/#dom-sqlexception-code-syntax
if (isWebSql)
expect(error.code).toBe(5);
else
expect(error.code).toBe(0);
// WebKit Web SQL vs plugin error message
// FUTURE TBD plugin error message subject to change
if (isWebSql)
expect(error.message).toMatch(/number of '\?'s in statement string does not match argument count/);
else if (isWindows)
expect(error.message).toMatch(/Error 25 when binding argument to SQL query/);
else
expect(error.message).toMatch(/index.*out of range/);
// Close (plugin only) & finish:

@@ -380,4 +916,166 @@ (isWebSql) ? done() : db.close(done, done);

});
});
}, MYTIMEOUT);
it(suiteName + 'executeSql with too many parameters [extra REAL value]', function(done) {
if (isWP8) pending('SKIP for WP8'); // TBD BROKEN on WP8
var db = openDatabase("too-many-parameters-extra-real-value.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
// CREATE columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data1, data2)');
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function() {
db.transaction(function(tx) {
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first', 'second', 123.456], function(ignored1, ignored2) {
// NOT EXPECTED:
expect(false).toBe(true);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(ignored, error) {
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
// PLUGIN BROKEN: reports INCORRECT error code: 0 (SQLite.UNKNOWN_ERR)
// WebKit Web SQL reports correct error code: 5 (SQLite.SYNTAX_ERR) in this case.
// ref: https://www.w3.org/TR/webdatabase/#dom-sqlexception-code-syntax
if (isWebSql)
expect(error.code).toBe(5);
else
expect(error.code).toBe(0);
// WebKit Web SQL vs plugin error message
// FUTURE TBD plugin error message subject to change
if (isWebSql)
expect(error.message).toMatch(/number of '\?'s in statement string does not match argument count/);
else if (isWindows)
expect(error.message).toMatch(/Error 25 when binding argument to SQL query/);
else
expect(error.message).toMatch(/index.*out of range/);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, MYTIMEOUT);
it(suiteName + 'executeSql with too many parameters [extra INTEGER value]', function(done) {
if (isWP8) pending('SKIP for WP8'); // TBD BROKEN on WP8
var db = openDatabase("too-many-parameters-extra-integer-value.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
// CREATE columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data1, data2)');
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function() {
db.transaction(function(tx) {
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first', 'second', 789], function(ignored1, ignored2) {
// NOT EXPECTED:
expect(false).toBe(true);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(ignored, error) {
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
// PLUGIN BROKEN: reports INCORRECT error code: 0 (SQLite.UNKNOWN_ERR)
// WebKit Web SQL reports correct error code: 5 (SQLite.SYNTAX_ERR) in this case.
// ref: https://www.w3.org/TR/webdatabase/#dom-sqlexception-code-syntax
if (isWebSql)
expect(error.code).toBe(5);
else
expect(error.code).toBe(0);
// WebKit Web SQL vs plugin error message
// FUTURE TBD plugin error message subject to change
if (isWebSql)
expect(error.message).toMatch(/number of '\?'s in statement string does not match argument count/);
else if (isWindows)
expect(error.message).toMatch(/Error 25 when binding argument to SQL query/);
else
expect(error.message).toMatch(/index.*out of range/);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, MYTIMEOUT);
it(suiteName + 'executeSql with too many parameters [extra NULL value]', function(done) {
if (isWP8) pending('SKIP for WP8'); // TBD BROKEN on WP8
var db = openDatabase("too-many-parameters-extra-null-value.db", "1.0", "Demo", DEFAULT_SIZE);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
// CREATE columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data1, data2)');
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function() {
db.transaction(function(tx) {
tx.executeSql("INSERT INTO test_table (data1, data2) VALUES (?,?)", ['first', 'second', null], function(ignored1, ignored2) {
// NOT EXPECTED:
expect(false).toBe(true);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
}, function(ignored, error) {
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
// PLUGIN BROKEN: reports INCORRECT error code: 0 (SQLite.UNKNOWN_ERR)
// WebKit Web SQL reports correct error code: 5 (SQLite.SYNTAX_ERR) in this case.
// ref: https://www.w3.org/TR/webdatabase/#dom-sqlexception-code-syntax
if (isWebSql)
expect(error.code).toBe(5);
else
expect(error.code).toBe(0);
// WebKit Web SQL vs plugin error message
// FUTURE TBD plugin error message subject to change
if (isWebSql)
expect(error.message).toMatch(/number of '\?'s in statement string does not match argument count/);
else if (isWindows)
expect(error.message).toMatch(/Error 25 when binding argument to SQL query/);
else
expect(error.message).toMatch(/index.*out of range/);
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, MYTIMEOUT);
});

@@ -390,5 +1088,5 @@

test_it(suiteName + ' stores [Unicode] string with \\u0000 correctly', function () {
if (isWindows) pending('BROKEN on Windows'); // XXX
if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] UNICODE characters not working with WP(8)
if (isAndroid && !isWebSql && !isOldImpl) pending('BROKEN for Android (default sqlite-connector version)'); // XXX
if (isWindows) pending('BROKEN on Windows'); // [FUTURE TBD, already documented]
if (!isWebSql && isAndroid && !isImpl2) pending('BROKEN for Android (default sqlite-connector version)'); // [FUTURE TBD (documented)]

@@ -492,3 +1190,3 @@ stop();

equal(name.length, 0, 'length of field === 0');
equal(name.length, 0, 'length of field === 0');
start();

@@ -521,3 +1219,3 @@ return;

if (isWP8) pending('BROKEN for WP(8)'); // [BUG #202] UNICODE characters not working with WP(8)
if (!(isWebSql || isAndroid || isIE)) pending('BROKEN for iOS'); // XXX [BUG #147] (no callback received)
if (!isWebSql && !isAndroid && !isWindows && !isWP8) pending('BROKEN for iOS/macOS plugin'); // [BUG #147] (no callback received)

@@ -524,0 +1222,0 @@ var dbName = "Unicode-line-separator.db";

@@ -47,3 +47,3 @@ /* 'use strict'; */

if (!isWebSql && isAndroid) pending('SKIP for android.database'); // TBD (SKIP for Android plugin for now)
if (!isAndroid && !isWindows && !isWP8) pending('SKIP for iOS');
if (!isAndroid && !isWindows && !isWP8) pending('SKIP for iOS/macOS');

@@ -50,0 +50,0 @@ var db = openDatabase('simple-regexp-test.db', '1.0', 'test', DEFAULT_SIZE);

@@ -10,2 +10,4 @@ /* 'use strict'; */

var isAndroid = !isWindows && /Android/.test(navigator.userAgent);
var isMac = /Macintosh/.test(navigator.userAgent);
var isWKWebView = !isWindows && !isAndroid && !isWP8 && !isMac && !!window.webkit && !!window.webkit.messageHandlers;

@@ -51,3 +53,2 @@ // NOTE: In the common storage-master branch there is no difference between the

var db = openDatabase('Single-column-batch-sql-test.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();

@@ -57,7 +58,217 @@

'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (SampleColumn)',
'CREATE TABLE MyTable (data)',
[ 'INSERT INTO MyTable VALUES (?)', ['test-value'] ],
], function() {
db.executeSql('SELECT * FROM MyTable', [], function (rs) {
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);
expect(rs.rows.item(0).data).toBe('test-value');
done();
});
}, function(error) {
expect(true).toBe(false);
done();
});
}, MYTIMEOUT);
it(suiteName + 'Single-column batch sql test values: INSERT INTEGER/REAL number values and check stored data', function(done) {
var db = openDatabase('Single-column-batch-sql-test-number-values.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (data)',
[ 'INSERT INTO MyTable VALUES (?)', [101] ],
[ 'INSERT INTO MyTable VALUES (?)', [-101] ],
[ 'INSERT INTO MyTable VALUES (?)', [123.456] ],
[ 'INSERT INTO MyTable VALUES (?)', [-123.456] ],
[ 'INSERT INTO MyTable VALUES (?)', [1234567890123] ],
[ 'INSERT INTO MyTable VALUES (?)', [-1234567890123] ],
[ 'INSERT INTO MyTable VALUES (?)', [0] ],
], function() {
db.executeSql('SELECT data AS d1, TYPEOF(data) AS t1, ABS(data) AS a1, UPPER(data) as u1 FROM MyTable', [], function (rs) {
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(7);
expect(rs.rows.item(0).d1).toBe(101);
if (isMac || isWKWebView)
expect(rs.rows.item(0).t1).toBe('real');
else
expect(rs.rows.item(0).t1).toBe('integer');
expect(rs.rows.item(0).a1).toBe(101);
if (isMac || isWKWebView)
expect(rs.rows.item(0).u1).toBe('101.0');
else
expect(rs.rows.item(0).u1).toBe('101');
expect(rs.rows.item(1).d1).toBe(-101);
if (isMac || isWKWebView)
expect(rs.rows.item(1).t1).toBe('real');
else
expect(rs.rows.item(1).t1).toBe('integer');
expect(rs.rows.item(1).a1).toBe(101);
if (isMac || isWKWebView)
expect(rs.rows.item(1).u1).toBe('-101.0');
else
expect(rs.rows.item(1).u1).toBe('-101');
expect(rs.rows.item(2).d1).toBe(123.456);
expect(rs.rows.item(2).t1).toBe('real');
expect(rs.rows.item(2).a1).toBe(123.456);
expect(rs.rows.item(2).u1).toBe('123.456');
expect(rs.rows.item(3).d1).toBe(-123.456);
expect(rs.rows.item(3).t1).toBe('real');
expect(rs.rows.item(3).a1).toBe(123.456);
expect(rs.rows.item(3).u1).toBe('-123.456');
expect(rs.rows.item(4).d1).toBe(1234567890123);
if (isMac || isWKWebView)
expect(rs.rows.item(4).t1).toBe('real');
else
expect(rs.rows.item(4).t1).toBe('integer');
expect(rs.rows.item(4).a1).toBe(1234567890123);
if (isMac || isWKWebView)
expect(rs.rows.item(4).u1).toBe('1234567890123.0');
else
expect(rs.rows.item(4).u1).toBe('1234567890123');
expect(rs.rows.item(5).d1).toBe(-1234567890123);
if (isMac || isWKWebView)
expect(rs.rows.item(5).t1).toBe('real');
else
expect(rs.rows.item(5).t1).toBe('integer');
expect(rs.rows.item(5).a1).toBe(1234567890123);
if (isMac || isWKWebView)
expect(rs.rows.item(5).u1).toBe('-1234567890123.0');
else
expect(rs.rows.item(5).u1).toBe('-1234567890123');
expect(rs.rows.item(6).d1).toBe(0);
if (isMac || isWKWebView)
expect(rs.rows.item(6).t1).toBe('real');
else
expect(rs.rows.item(6).t1).toBe('integer');
expect(rs.rows.item(6).a1).toBe(0);
if (isMac || isWKWebView)
expect(rs.rows.item(6).u1).toBe('0.0');
else
expect(rs.rows.item(6).u1).toBe('0');
done();
});
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
it(suiteName + 'Single-column batch sql test values: INSERT null/undefined values and check stored data [BROKEN on Windows]', function(done) {
if (isWP8) pending('SKIP for WP8'); // SKIP for now
var db = openDatabase('Single-column-batch-sql-test-null-undefined-values.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (data)',
[ 'INSERT INTO MyTable VALUES (?)', [null] ],
[ 'INSERT INTO MyTable VALUES (?)', [undefined] ],
], function() {
if (isWindows) expect('Windows plugin version FIXED please update this test').toBe('--');
db.executeSql('SELECT data AS d1, TYPEOF(data) AS t1, ABS(data) AS a1, UPPER(data) as u1 FROM MyTable', [], function (rs) {
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(2);
expect(rs.rows.item(0).d1).toBe(null);
expect(rs.rows.item(0).t1).toBe('null');
expect(rs.rows.item(0).a1).toBe(null);
expect(rs.rows.item(0).u1).toBe(null);
expect(rs.rows.item(1).d1).toBe(null);
expect(rs.rows.item(1).t1).toBe('null');
expect(rs.rows.item(1).a1).toBe(null);
expect(rs.rows.item(1).u1).toBe(null);
done();
});
}, function(error) {
// ERROR in case of Windows:
if (isWindows) {
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
expect(error.code).toBe(0);
expect(error.message).toMatch(/a statement with no error handler failed: Unsupported argument type: undefined/);
return done();
}
// OTHERWISE
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
it(suiteName + 'Single-column batch sql test values: INSERT +/- Infinity & NaN values and check stored data [TBD Android/iOS/macOS plugin result for +/- Infinity]', function(done) {
if (isWP8) pending('SKIP for WP8'); // SKIP for now
if (isMac) pending('SKIP for macOS [CRASH]'); // FUTURE TBD
var db = openDatabase('Single-column-batch-sql-test-infinity-nan-values.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (data)',
[ 'INSERT INTO MyTable VALUES (?)', [Infinity] ],
[ 'INSERT INTO MyTable VALUES (?)', [-Infinity] ],
[ 'INSERT INTO MyTable VALUES (?)', [NaN] ],
], function() {
db.executeSql('SELECT data AS d1, TYPEOF(data) AS t1, ABS(data) AS a1, UPPER(data) as u1 FROM MyTable', [], function (rs) {
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(3);
if (isWindows) {
expect(rs.rows.item(0).d1).toBe(Infinity);
expect(rs.rows.item(0).t1).toBe('real');
expect(rs.rows.item(0).a1).toBe(Infinity);
expect(rs.rows.item(0).u1).toBe('INF');
expect(rs.rows.item(1).d1).toBe(-Infinity);
expect(rs.rows.item(1).t1).toBe('real');
expect(rs.rows.item(1).a1).toBe(Infinity);
expect(rs.rows.item(1).u1).toBe('-INF');
} else {
expect(rs.rows.item(0).d1).toBe(null);
expect(rs.rows.item(0).t1).toBe('null');
expect(rs.rows.item(0).a1).toBe(null);
expect(rs.rows.item(0).u1).toBe(null);
expect(rs.rows.item(1).d1).toBe(null);
expect(rs.rows.item(1).t1).toBe('null');
expect(rs.rows.item(1).a1).toBe(null);
expect(rs.rows.item(1).u1).toBe(null);
}
expect(rs.rows.item(2).d1).toBe(null);
expect(rs.rows.item(2).t1).toBe('null');
expect(rs.rows.item(2).a1).toBe(null);
expect(rs.rows.item(2).u1).toBe(null);
done();
});
}, function(error) {
expect(false).toBe(true);
expect(error.message).toBe('--');
done();
});
}, MYTIMEOUT);
it(suiteName + 'batch sql with dynamic object for SQL [INCONSISTENT BEHAVIOR]', function(done) {
// MyDynamicObject "class":
function MyDynamicObject() { this.name = 'Alice'; };
MyDynamicObject.prototype.toString = function() {return "INSERT INTO MyTable VALUES ('" + this.name + "')";}
var myObject = new MyDynamicObject();
// Check myObject:
expect(myObject.toString()).toBe("INSERT INTO MyTable VALUES ('Alice')");
var db = openDatabase('batch-sql-with-dynamic-object-for-sql.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
myObject.name = 'Betty';
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (data)',
myObject
], function() {
db.executeSql('SELECT * FROM MyTable', [], function (res) {
expect(res.rows.item(0).SampleColumn).toBe('test-value');
expect(res.rows.item(0).data).toBe('Carol');
done();

@@ -69,4 +280,63 @@ });

});
myObject.name = 'Carol';
}, MYTIMEOUT);
it(suiteName + 'batch sql with dynamic object for SQL arg value [INCONSISTENT BEHAVIOR]', function(done) {
// MyDynamicParameterObject "class":
function MyDynamicParameterObject() {this.name='Alice';};
MyDynamicParameterObject.prototype.toString = function() {return this.name;};
var myObject = new MyDynamicParameterObject();
// Check myObject:
expect(myObject.toString()).toBe('Alice');
var db = openDatabase('batch-sql-with-dynamic-object-for-sql-arg-value.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
myObject.name = 'Betty';
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (data)',
[ 'INSERT INTO MyTable VALUES (?)', [myObject] ],
], function() {
db.executeSql('SELECT * FROM MyTable', [], function (res) {
expect(res.rows.item(0).data).toBe('Carol');
done();
});
}, function(error) {
expect(true).toBe(false);
done();
});
myObject.name = 'Carol';
}, MYTIMEOUT);
it(suiteName + 'Multi-row INSERT with parameters in batch sql test', function(done) {
if (isWP8) pending('SKIP: NOT SUPPORTED for WP8');
var db = openDatabase('Multi-row-INSERT-with-parameters-batch-sql-test.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (x,y)',
[ 'INSERT INTO MyTable VALUES (?,?),(?,?)', ['a',1,'b',2] ],
], function() {
db.executeSql('SELECT * FROM MyTable', [], function (resultSet) {
// EXPECTED: CORRECT RESULT:
expect(resultSet.rows.length).toBe(2);
expect(resultSet.rows.item(0).x).toBe('a');
expect(resultSet.rows.item(0).y).toBe(1);
expect(resultSet.rows.item(1).x).toBe('b');
expect(resultSet.rows.item(1).y).toBe(2);
done();
});
}, function(error) {
expect(true).toBe(false);
done();
});
}, MYTIMEOUT);
it(suiteName + 'batch sql with syntax error', function(done) {

@@ -83,8 +353,25 @@ var db = openDatabase('batch-sql-syntax-error-test.db', '1.0', 'Test', DEFAULT_SIZE);

], function() {
// not expected:
// NOT EXPECTED:
expect(true).toBe(false);
done();
}, function(error) {
// expected:
expect(true).toBe(true);
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
if (isWP8)
expect(true).toBe(true); // SKIP for now
else if (isWindows || (isAndroid && isImpl2))
expect(error.code).toBe(0);
else
expect(error.code).toBe(5);
if (isWP8)
expect(true).toBe(true); // SKIP for now
else if (isWindows)
expect(error.message).toMatch(/a statement with no error handler failed: Error preparing an SQLite statement/);
else
expect(error.message).toMatch(/a statement with no error handler failed.*near \"CRETE\": syntax error/);
done();

@@ -94,2 +381,41 @@ });

it(suiteName + 'batch sql with constraint violation (check error code & basic error message pattern)', function(done) {
var db = openDatabase('batch-sql-constraint-violation-test.db', '1.0', 'Test', DEFAULT_SIZE);
expect(db).toBeDefined();
db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
// syntax error below:
'CREATE TABLE MyTable (data UNIQUE)',
[ 'INSERT INTO MyTable VALUES (?)', [123] ],
[ 'INSERT INTO MyTable VALUES (?)', [123] ],
], function() {
// NOT EXPECTED:
expect(false).toBe(true);
done();
}, function(error) {
// EXPECTED RESULT:
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
if (isWP8)
expect(true).toBe(true); // SKIP for now
else if (isWindows)
expect(error.code).toBe(0);
else
expect(error.code).toBe(6);
if (isWP8)
expect(true).toBe(true); // SKIP for now
else if (isWindows)
expect(error.message).toMatch(/a statement with no error handler failed: SQLite3 step error result code: 1/);
else
expect(error.message).toMatch(/a statement with no error handler failed.*constraint fail/);
done();
});
}, MYTIMEOUT);
it(suiteName + 'batch sql failure-safe semantics', function(done) {

@@ -96,0 +422,0 @@ var db = openDatabase('batch-sql-failure-safe-test.db', '1.0', 'Test', DEFAULT_SIZE);

@@ -379,4 +379,3 @@ /* 'use strict'; */

test_it(suiteName + "exception from transaction handler causes failure", function() {
stop();
it(suiteName + 'exception from transaction handler causes failure', function(done) {
var db = openDatabase("exception-causes-failure.db", "1.0", "Demo", DEFAULT_SIZE);

@@ -387,22 +386,64 @@

throw new Error("boom");
}, function(err) {
expect(err).toBeDefined();
expect(err.hasOwnProperty('message')).toBe(true);
}, function(error) {
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
if (!isWebSql) expect(err.message).toEqual('boom');
expect(error.code).toBe(0);
start();
if (isWebSql)
expect(error.message).toMatch(/the SQLTransactionCallback was null or threw an exception/);
else
expect(error.message).toBe('boom');
done();
}, function() {
// transaction success callback not expected
expect(false).toBe(true);
start();
done();
});
ok(true, "db.transaction() did not throw an error");
} catch(err) {
} catch(ex) {
// exception not expected here
expect(false).toBe(true);
start();
done();
}
});
it(suiteName + 'exception with code from transaction handler', function(done) {
var db = openDatabase("exception-with-code.db", "1.0", "Demo", DEFAULT_SIZE);
try {
db.transaction(function(tx) {
var e = new Error("boom");
e.code = 3;
throw e;
}, function(error) {
expect(error).toBeDefined();
expect(error.code).toBeDefined();
expect(error.message).toBeDefined();
if (isWebSql)
expect(error.code).toBe(0);
else
expect(error.code).toBe(3);
if (isWebSql)
expect(error.message).toMatch(/the SQLTransactionCallback was null or threw an exception/);
else
expect(error.message).toBe('boom');
done();
}, function() {
// transaction success callback not expected
expect(false).toBe(true);
done();
});
} catch(ex) {
// exception not expected here
expect(false).toBe(true);
done();
}
});
test_it(suiteName + "error handler returning true causes rollback", function() {

@@ -504,7 +545,7 @@ stop();

});
test_it(suiteName + "executeSql fails outside transaction", function() {
withTestTable(function(db) {
expect(4);
ok(!!db, "db ok");
ok(!!db, "db ok");
var txg;

@@ -533,3 +574,3 @@ stop(2);

start(1);
});
});
});

@@ -536,0 +577,0 @@ });

@@ -707,5 +707,56 @@ # SQLite plugin in Markdown (litcoffee)

(-> SelfTest.start2(successcb, errorcb))
return
start2: (successcb, errorcb) ->
SQLiteFactory.openDatabase {name: SelfTest.DBNAME, location: 'default'}, (db) ->
check1 = false
db.transaction (tx) ->
tx.executeSql 'SELECT UPPER("Test") AS upperText', [], (ignored, resutSet) ->
if !resutSet.rows
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows'
if !resutSet.rows.length
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows.length'
if resutSet.rows.length isnt 1
return SelfTest.finishWithError errorcb,
"Incorrect resutSet.rows.length value: #{resutSet.rows.length} (expected: 1)"
if !resutSet.rows.item(0).upperText
return SelfTest.finishWithError errorcb,
'Missing resutSet.rows.item(0).upperText'
if resutSet.rows.item(0).upperText isnt 'TEST'
return SelfTest.finishWithError errorcb,
"Incorrect resutSet.rows.item(0).upperText value: #{resutSet.rows.item(0).data} (expected: 'TEST')"
check1 = true
return
, (sql_err) ->
SelfTest.finishWithError errorcb, "SQL error: #{sql_err}"
return
, (tx_err) ->
SelfTest.finishWithError errorcb, "TRANSACTION error: #{tx_err}"
return
, () ->
if !check1
return SelfTest.finishWithError errorcb,
'Did not get expected upperText result data'
# DELETE INTERNAL STATE to simulate the effects of location refresh or change:
delete db.openDBs[SelfTest.DBNAME]
delete txLocks[SelfTest.DBNAME]
SelfTest.start3 successcb, errorcb
return
, (open_err) ->
SelfTest.finishWithError errorcb, "Open database error: #{open_err}"
return
start3: (successcb, errorcb) ->
SQLiteFactory.openDatabase {name: SelfTest.DBNAME, location: 'default'}, (db) ->
db.sqlBatch [

@@ -839,2 +890,3 @@ 'CREATE TABLE TestTable(id integer primary key autoincrement unique, data);'

SelfTest.finishWithError errorcb, "Open database error: #{open_err}"
return

@@ -845,2 +897,3 @@ finishWithError: (errorcb, message) ->

, (err2)-> errorcb newSQLError "Cleanup error: #{err2} for error: #{message}"
return

@@ -874,2 +927,1 @@ ## Exported API:

#### vim: set expandtab :

@@ -7,2 +7,3 @@ var dbmap = {};

/* **
function handle(p, win, fail) {

@@ -22,2 +23,3 @@ if (p)

}
// */

@@ -34,3 +36,5 @@ module.exports = {

function openImmediate(dbname) {
//var dbname = options.name;
// STOP with success if db is already open:
if (!!dbmap[dbname]) return nextTick(win);
// from @EionRobb / phonegap-win8-sqlite:

@@ -111,3 +115,3 @@ var opendbname = Windows.Storage.ApplicationData.current.localFolder.path + "\\" + dbname;

type: "error",
result: { code: -1, message: ex.message }
result: { message: ex.message, code: 0 }
});

@@ -114,0 +118,0 @@ }

@@ -75,5 +75,12 @@ (function () {

each: function (callback) {
while (this.statement.step() === SQLite3.ResultCode.row) {
var resultCode = this.statement.step();
while (resultCode === SQLite3.ResultCode.row) {
callback(this._getRow());
resultCode = this.statement.step();
}
if (resultCode !== SQLite3.ResultCode.done && resultCode !== SQLite3.ResultCode.ok) {
throw new Error("SQLite3 step error result code: " + resultCode);
}
},

@@ -80,0 +87,0 @@ map: function (callback) {

@@ -627,3 +627,3 @@ (function() {

start: function(successcb, errorcb) {
return SQLiteFactory.deleteDatabase({
SQLiteFactory.deleteDatabase({
name: SelfTest.DBNAME,

@@ -638,6 +638,48 @@ location: 'default'

start2: function(successcb, errorcb) {
return SQLiteFactory.openDatabase({
SQLiteFactory.openDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function(db) {
var check1;
check1 = false;
return db.transaction(function(tx) {
return tx.executeSql('SELECT UPPER("Test") AS upperText', [], function(ignored, resutSet) {
if (!resutSet.rows) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows');
}
if (!resutSet.rows.length) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length');
}
if (resutSet.rows.length !== 1) {
return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.length value: " + resutSet.rows.length + " (expected: 1)");
}
if (!resutSet.rows.item(0).upperText) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.item(0).upperText');
}
if (resutSet.rows.item(0).upperText !== 'TEST') {
return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.item(0).upperText value: " + (resutSet.rows.item(0).data) + " (expected: 'TEST')");
}
check1 = true;
}, function(sql_err) {
SelfTest.finishWithError(errorcb, "SQL error: " + sql_err);
});
}, function(tx_err) {
SelfTest.finishWithError(errorcb, "TRANSACTION error: " + tx_err);
}, function() {
if (!check1) {
return SelfTest.finishWithError(errorcb, 'Did not get expected upperText result data');
}
delete db.openDBs[SelfTest.DBNAME];
delete txLocks[SelfTest.DBNAME];
SelfTest.start3(successcb, errorcb);
});
}, function(open_err) {
return SelfTest.finishWithError(errorcb, "Open database error: " + open_err);
});
},
start3: function(successcb, errorcb) {
SQLiteFactory.openDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function(db) {
return db.sqlBatch(['CREATE TABLE TestTable(id integer primary key autoincrement unique, data);', ['INSERT INTO TestTable (data) VALUES (?);', ['test-value']]], function() {

@@ -776,3 +818,3 @@ var firstid;

finishWithError: function(errorcb, message) {
return SQLiteFactory.deleteDatabase({
SQLiteFactory.deleteDatabase({
name: SelfTest.DBNAME,

@@ -779,0 +821,0 @@ location: 'default'

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc