682 lines
21 KiB
Dart
682 lines
21 KiB
Dart
import 'package:platform_driver_rethinkdb/platform_driver_rethinkdb.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
main() {
|
|
var r = RethinkDb() as dynamic;
|
|
String? databaseName;
|
|
String? tableName;
|
|
String? testDbName;
|
|
bool shouldDropTable = false;
|
|
Connection? connection;
|
|
|
|
setUp(() async {
|
|
connection = await r.connect();
|
|
|
|
if (testDbName == null) {
|
|
String useDb = await r.uuid().run(connection);
|
|
testDbName = 'unit_test_db${useDb.replaceAll("-", "")}';
|
|
await r.dbCreate(testDbName).run(connection);
|
|
}
|
|
|
|
if (databaseName == null) {
|
|
String dbName = await r.uuid().run(connection);
|
|
databaseName = "test_database_${dbName.replaceAll("-", "")}";
|
|
}
|
|
|
|
if (tableName == null) {
|
|
String tblName = await r.uuid().run(connection);
|
|
tableName = "test_table_${tblName.replaceAll("-", "")}";
|
|
}
|
|
connection!.use(testDbName!);
|
|
});
|
|
|
|
tearDown(() async {
|
|
if (shouldDropTable) {
|
|
shouldDropTable = false;
|
|
await r.tableDrop(tableName).run(connection);
|
|
}
|
|
connection!.close();
|
|
});
|
|
|
|
test("r.db throws an error if a bad database name is given", () async {
|
|
try {
|
|
await r.db('fake2834723895').tableList().run(connection);
|
|
} catch (err) {
|
|
expect(err is Exception, equals(true));
|
|
expect(err.toString().split("\n")[2],
|
|
equals('Database `fake2834723895` does not exist.'));
|
|
}
|
|
});
|
|
|
|
group("dbCreate command -> ", () {
|
|
test("r.dbCreate will create a new database", () async {
|
|
Map response = await r.dbCreate(databaseName).run(connection);
|
|
|
|
expect(response.keys.length, equals(2));
|
|
expect(response.containsKey('config_changes'), equals(true));
|
|
expect(response['dbs_created'], equals(1));
|
|
|
|
Map configChanges = response['config_changes'][0];
|
|
expect(configChanges.keys.length, equals(2));
|
|
expect(configChanges['old_val'], equals(null));
|
|
Map newVal = configChanges['new_val'];
|
|
expect(newVal.containsKey('id'), equals(true));
|
|
expect(newVal.containsKey('name'), equals(true));
|
|
expect(newVal['name'], equals(databaseName));
|
|
});
|
|
|
|
test("r.dbCreate will throw an error if the database exists", () async {
|
|
try {
|
|
await r.dbCreate(databaseName).run(connection);
|
|
} catch (err) {
|
|
expect(err is Exception, equals(true));
|
|
expect(
|
|
err.toString().split("\n")[2],
|
|
// ignore: unnecessary_brace_in_string_interps
|
|
equals('Database `${databaseName}` already exists.'));
|
|
}
|
|
});
|
|
});
|
|
|
|
group("dbDrop command -> ", () {
|
|
test("r.dbDrop should drop a database", () async {
|
|
Map response = await r.dbDrop(databaseName).run(connection);
|
|
|
|
expect(response.keys.length, equals(3));
|
|
expect(response.containsKey('config_changes'), equals(true));
|
|
expect(response['dbs_dropped'], equals(1));
|
|
expect(response['tables_dropped'], equals(0));
|
|
|
|
Map configChanges = response['config_changes'][0];
|
|
expect(configChanges.keys.length, equals(2));
|
|
expect(configChanges['new_val'], equals(null));
|
|
Map oldVal = configChanges['old_val'];
|
|
expect(oldVal.containsKey('id'), equals(true));
|
|
expect(oldVal.containsKey('name'), equals(true));
|
|
expect(oldVal['name'], equals(databaseName));
|
|
});
|
|
|
|
test("r.dbDrop should error if the database does not exist", () async {
|
|
try {
|
|
await r.dbDrop(databaseName).run(connection);
|
|
} catch (err) {
|
|
expect(err.toString().split("\n")[2],
|
|
equals('Database `$databaseName` does not exist.'));
|
|
}
|
|
});
|
|
});
|
|
|
|
test("r.dbList should list all databases", () async {
|
|
List response = await r.dbList().run(connection);
|
|
|
|
expect(response.indexOf('rethinkdb'), greaterThan(-1));
|
|
});
|
|
|
|
group("range command -> ", () {
|
|
test("r.range() with no arguments should return a stream", () async {
|
|
Cursor cur = await r.range().run(connection);
|
|
|
|
List item = await cur.take(17).toList();
|
|
expect(item,
|
|
equals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]));
|
|
});
|
|
|
|
test("r.range() should accept a single end arguement", () async {
|
|
Cursor cur = await r.range(10).run(connection);
|
|
|
|
List l = await cur.toList();
|
|
expect(l, equals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
|
});
|
|
|
|
test("r.range() should accept a start and end arguement", () async {
|
|
Cursor cur = await r.range(7, 10).run(connection);
|
|
List l = await cur.toList();
|
|
expect(l, equals([7, 8, 9]));
|
|
});
|
|
});
|
|
|
|
group("table command -> ", () {
|
|
test("table should return a cursor containing all records for a table",
|
|
() async {
|
|
Cursor cur = await r.db('rethinkdb').table('stats').run(connection);
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should allow for `read_mode: single` option", () async {
|
|
Cursor cur = await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'read_mode': 'single'}).run(connection);
|
|
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should allow for `read_mode: majority` option", () async {
|
|
Cursor cur = await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'read_mode': 'majority'}).run(connection);
|
|
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should allow for `read_mode: outdated` option", () async {
|
|
Cursor cur = await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'read_mode': 'outdated'}).run(connection);
|
|
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should catch invalid read_mode option", () async {
|
|
try {
|
|
await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'read_mode': 'badReadMode'}).run(connection);
|
|
} catch (err) {
|
|
expect(
|
|
err.toString().split("\n")[2],
|
|
equals(
|
|
'Read mode `badReadMode` unrecognized (options are "majority", "single", and "outdated").'));
|
|
}
|
|
});
|
|
|
|
test("table should allow for `identifier_format: name` option", () async {
|
|
Cursor cur = await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'identifier_format': 'name'}).run(connection);
|
|
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should allow for `identifier_format: uuid` option", () async {
|
|
Cursor cur = await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'identifier_format': 'uuid'}).run(connection);
|
|
|
|
await for (Map item in cur) {
|
|
expect(item.containsKey('id'), equals(true));
|
|
expect(item.containsKey('query_engine'), equals(true));
|
|
}
|
|
});
|
|
|
|
test("table should catch invalid identifier_format option", () async {
|
|
try {
|
|
await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'identifier_format': 'badFormat'}).run(connection);
|
|
} catch (err) {
|
|
expect(
|
|
err.toString().split("\n")[2],
|
|
equals(
|
|
'Identifier format `badFormat` unrecognized (options are "name" and "uuid").'));
|
|
}
|
|
});
|
|
|
|
test("table should catch bad options", () async {
|
|
try {
|
|
await r
|
|
.db('rethinkdb')
|
|
.table('stats', {'fake_option': 'bad_value'}).run(connection);
|
|
} catch (err) {
|
|
expect(err.toString().split("\n")[2],
|
|
equals('Unrecognized optional argument `fake_option`.'));
|
|
}
|
|
});
|
|
});
|
|
|
|
group("time command -> ", () {
|
|
test(
|
|
"should return a time object if given a year, month, day, and timezone",
|
|
() async {
|
|
DateTime obj = await r.time(2010, 12, 29, timezone: 'Z').run(connection);
|
|
|
|
expect(obj.runtimeType, equals(DateTime));
|
|
expect(obj.isBefore(DateTime.now()), equals(true));
|
|
expect(obj.minute, equals(0));
|
|
expect(obj.second, equals(0));
|
|
});
|
|
|
|
test(
|
|
"should return a time object if given a year, month, day, hour, minute, second, and timezone",
|
|
() async {
|
|
DateTime obj = await r
|
|
.time(2010, 12, 29, hour: 7, minute: 33, second: 45, timezone: 'Z')
|
|
.run(connection);
|
|
|
|
expect(obj.runtimeType, equals(DateTime));
|
|
expect(obj.isBefore(DateTime.now()), equals(true));
|
|
expect(obj.minute, equals(33));
|
|
expect(obj.second, equals(45));
|
|
});
|
|
});
|
|
|
|
test(
|
|
"nativeTime command -> should turn a native dart DateTime to a reql time",
|
|
() async {
|
|
DateTime dt = DateTime.now();
|
|
DateTime rqlDt = await r.nativeTime(dt).run(connection);
|
|
|
|
expect(dt.year, equals(rqlDt.year));
|
|
expect(dt.month, equals(rqlDt.month));
|
|
expect(dt.day, equals(rqlDt.day));
|
|
expect(dt.hour, equals(rqlDt.hour));
|
|
expect(dt.minute, equals(rqlDt.minute));
|
|
expect(dt.second, equals(rqlDt.second));
|
|
});
|
|
|
|
group("ISO8601 command -> ", () {
|
|
test("should take an ISO8601 string and convert it to a DateTime object",
|
|
() async {
|
|
DateTime dt =
|
|
await r.ISO8601('1986-11-03T08:30:00-07:00').run(connection);
|
|
|
|
expect(dt.year, equals(1986));
|
|
expect(dt.month, equals(11));
|
|
expect(dt.day, equals(3));
|
|
expect(dt.minute, equals(30));
|
|
});
|
|
|
|
test("should accept a timezone argument as well", () async {
|
|
DateTime dt =
|
|
await r.ISO8601('1986-11-03T08:30:00-07:00', 'MST').run(connection);
|
|
|
|
expect(dt.year, equals(1986));
|
|
expect(dt.month, equals(11));
|
|
expect(dt.day, equals(3));
|
|
expect(dt.minute, equals(30));
|
|
});
|
|
});
|
|
|
|
test("epochTime command -> should take a timestamp and return a time object",
|
|
() async {
|
|
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(531360000000);
|
|
|
|
DateTime dt = await r.epochTime(531360000).run(connection);
|
|
|
|
expect(dt.month, equals(dateTime.month));
|
|
expect(dt.day, equals(dateTime.day));
|
|
expect(dt.hour, equals(dateTime.hour));
|
|
expect(dt.minute, equals(dateTime.minute));
|
|
expect(dt.second, equals(dateTime.second));
|
|
});
|
|
|
|
test("now command -> should return current DateTime object", () async {
|
|
DateTime dt = await r.now().run(connection);
|
|
|
|
await Future.delayed(Duration(milliseconds: 1));
|
|
|
|
//expect(dt is DateTime, equals(true));
|
|
expect(DateTime.now().difference(dt).inSeconds == 0, equals(true));
|
|
});
|
|
|
|
group("rqlDo command -> ", () {
|
|
test("should accept a single argument and function", () async {
|
|
bool i = await r.rqlDo(3, (item) => item > 4).run(connection);
|
|
|
|
expect(i, equals(false));
|
|
});
|
|
|
|
test("should accept a many arguments and a function", () async {
|
|
num i = await r
|
|
.rqlDo(
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
(item1, item2, item3, item4, item5) =>
|
|
item1 + item2 + item3 + item4 + item5)
|
|
.run(connection);
|
|
|
|
expect(i, equals(25));
|
|
});
|
|
|
|
test("should accept many args and an expression", () async {
|
|
Cursor cur = await r.rqlDo(3, 7, r.range).run(connection);
|
|
|
|
List list = await cur.toList();
|
|
expect(list, equals([3, 4, 5, 6]));
|
|
});
|
|
});
|
|
|
|
group("branch command -> ", () {
|
|
test("should accept a true test and return the true branch value",
|
|
() async {
|
|
String val = await r.branch(3 < 4, 'isTrue', 'isFalse').run(connection);
|
|
|
|
expect(val, equals('isTrue'));
|
|
});
|
|
|
|
test("should accept a false test and return the false branch value",
|
|
() async {
|
|
String val = await r.branch(3 > 4, 'isTrue', 'isFalse').run(connection);
|
|
|
|
expect(val, equals('isFalse'));
|
|
});
|
|
|
|
test("should accept multiple tests and actions", () async {
|
|
String val = await r
|
|
.branch(1 > 4, 'isTrue', 0 < 1, 'elseTrue', 'isFalse')
|
|
.run(connection);
|
|
|
|
expect(val, equals('elseTrue'));
|
|
});
|
|
});
|
|
|
|
test("error command -> should create a custom error", () async {
|
|
try {
|
|
await r.error('This is my Error').run(connection);
|
|
} catch (err) {
|
|
expect(err.runtimeType, equals(ReqlUserError));
|
|
expect(err.toString().split("\n")[2], equals('This is my Error'));
|
|
}
|
|
});
|
|
|
|
group("js command -> ", () {
|
|
test("should run custom javascript", () async {
|
|
String jsString = """
|
|
function concatStrs(){
|
|
return 'firstHalf' + '_' + 'secondHalf';
|
|
}
|
|
concatStrs();
|
|
""";
|
|
|
|
String str = await r.js(jsString).run(connection);
|
|
|
|
expect(str, equals('firstHalf_secondHalf'));
|
|
});
|
|
|
|
//TODO: fix test
|
|
|
|
// test("should accept a timeout option", () async {
|
|
// String jsString = """
|
|
// function concatStrs(){
|
|
// return 'firstHalf' + '_' + 'secondHalf';
|
|
// }
|
|
// while(true){
|
|
// concatStrs();
|
|
// }
|
|
// """;
|
|
// int timeout = 3;
|
|
// try {
|
|
// await r.js(jsString, {'timeout': timeout}).run(connection);
|
|
// } catch (err) {
|
|
// expect(
|
|
// err.toString(),
|
|
// equals(
|
|
// 'JavaScript query `$jsString` timed out after $timeout.000 seconds.'));
|
|
// }
|
|
// });
|
|
});
|
|
|
|
group("json command -> ", () {
|
|
test("should parse a json string", () async {
|
|
String jsonString = "[1,2,3,4]";
|
|
List obj = await r.json(jsonString).run(connection);
|
|
|
|
expect([1, 2, 3, 4], equals(obj));
|
|
});
|
|
|
|
test("should throw error if jsonString is invalid", () async {
|
|
String jsonString = "1,2,3,4]";
|
|
try {
|
|
await r.json(jsonString).run(connection);
|
|
} catch (err) {
|
|
expect(
|
|
err.toString().split("\n")[2],
|
|
equals(
|
|
'Failed to parse "$jsonString" as JSON: The document root must not follow by other values.'));
|
|
}
|
|
});
|
|
});
|
|
|
|
group("object command -> ", () {
|
|
test("should create an object from an array of values", () async {
|
|
Map obj = await r
|
|
.object('key', 'val', 'listKey', [1, 2, 3, 4], 'objKey', {'a': 'b'})
|
|
.run(connection);
|
|
|
|
//expect(obj is Map, equals(true));
|
|
expect(obj['key'], equals('val'));
|
|
expect(obj['listKey'], equals([1, 2, 3, 4]));
|
|
expect(obj['objKey']['a'], equals('b'));
|
|
});
|
|
|
|
test("should throw an error if params cannot be parsed into a map",
|
|
() async {
|
|
try {
|
|
await r
|
|
.object('key', 'val', 'listKey', [1, 2, 3, 4], 'objKey', {'a': 'b'},
|
|
'odd')
|
|
.run(connection);
|
|
} catch (err) {
|
|
expect(
|
|
err.toString().split("\n")[2],
|
|
equals(
|
|
'OBJECT expects an even number of arguments (but found 7).'));
|
|
}
|
|
});
|
|
});
|
|
|
|
test("args command -> should accept an array", () async {
|
|
List l = await r.args([1, 2]).run(connection);
|
|
|
|
expect(l, equals([1, 2]));
|
|
});
|
|
|
|
group("random command -> ", () {
|
|
test("should generate a random number if no parameters are provided",
|
|
() async {
|
|
double number = await r.random().run(connection);
|
|
|
|
expect(number, lessThanOrEqualTo(1));
|
|
expect(number, greaterThanOrEqualTo(0));
|
|
});
|
|
|
|
test(
|
|
"should generate a positive random int no greater than the single argument",
|
|
() async {
|
|
int number = await r.random(50).run(connection);
|
|
|
|
expect(number, lessThanOrEqualTo(50));
|
|
expect(number, greaterThanOrEqualTo(0));
|
|
});
|
|
|
|
test("should generate a random int between the two arguments", () async {
|
|
int number = await r.random(50, 55).run(connection);
|
|
|
|
expect(number, lessThanOrEqualTo(55));
|
|
expect(number, greaterThanOrEqualTo(50));
|
|
});
|
|
|
|
test("should generate a random float between the two arguments", () async {
|
|
double number = await r.random(50, 55, {'float': true}).run(connection);
|
|
expect(number, lessThanOrEqualTo(55));
|
|
expect(number, greaterThanOrEqualTo(50));
|
|
});
|
|
});
|
|
|
|
group("not command -> ", () {
|
|
test("should return false if given no arguements", () async {
|
|
bool val = await r.not().run(connection);
|
|
|
|
expect(val, equals(false));
|
|
});
|
|
|
|
test("should return the inverse of the argument provided", () async {
|
|
bool val = await r.not(false).run(connection);
|
|
|
|
expect(val, equals(true));
|
|
});
|
|
});
|
|
|
|
group("map command -> ", () {
|
|
test("should map over an array", () async {
|
|
List arr =
|
|
await r.map([1, 2, 3, 4, 5], (item) => item * 2).run(connection);
|
|
expect(arr, equals([2, 4, 6, 8, 10]));
|
|
});
|
|
|
|
test("should map over multiple arrays", () async {
|
|
List arr = await r.map([1, 2, 3, 4, 5], [10, 9, 8, 7],
|
|
(item, item2) => item + item2).run(connection);
|
|
|
|
//notice that the first array is longer but we
|
|
//only map the length of the shortest array
|
|
expect(arr, equals([11, 11, 11, 11]));
|
|
});
|
|
|
|
test("should map a sequence", () async {
|
|
List arr = await r
|
|
.map(
|
|
r.expr({
|
|
'key': [1, 2, 3, 4, 5]
|
|
}).getField('key'),
|
|
(item) => item + 1)
|
|
.run(connection);
|
|
|
|
expect(arr, equals([2, 3, 4, 5, 6]));
|
|
});
|
|
|
|
test("should map over multiple sequences", () async {
|
|
List arr = await r
|
|
.map(
|
|
r.expr({
|
|
'key': [1, 2, 3, 4, 5]
|
|
}).getField('key'),
|
|
r.expr({
|
|
'key': [1, 2, 3, 4, 5]
|
|
}).getField('key'),
|
|
(item, item2) => item + item2)
|
|
.run(connection);
|
|
|
|
expect(arr, equals([2, 4, 6, 8, 10]));
|
|
});
|
|
});
|
|
|
|
group("and command -> ", () {
|
|
test("should and two values together", () async {
|
|
bool val = await r.and(true, true).run(connection);
|
|
|
|
expect(val, equals(true));
|
|
});
|
|
test("should and more than two values together", () async {
|
|
bool val = await r.and(true, true, false).run(connection);
|
|
|
|
expect(val, equals(false));
|
|
});
|
|
});
|
|
|
|
group("or command -> ", () {
|
|
test("should or two values together", () async {
|
|
bool val = await r.or(true, false).run(connection);
|
|
|
|
expect(val, equals(true));
|
|
});
|
|
|
|
test("should and more than two values together", () async {
|
|
bool val = await r.or(false, false, false).run(connection);
|
|
|
|
expect(val, equals(false));
|
|
});
|
|
});
|
|
|
|
group("binary command -> ", () {
|
|
test("should convert string to binary", () async {
|
|
List data = await r.binary('billysometimes').run(connection);
|
|
|
|
expect(
|
|
data,
|
|
equals([
|
|
98,
|
|
105,
|
|
108,
|
|
108,
|
|
121,
|
|
115,
|
|
111,
|
|
109,
|
|
101,
|
|
116,
|
|
105,
|
|
109,
|
|
101,
|
|
115
|
|
]));
|
|
});
|
|
});
|
|
|
|
group("uuid command -> ", () {
|
|
test("should create a unique uuid", () async {
|
|
String val = await r.uuid().run(connection);
|
|
|
|
expect(val, isNotNull);
|
|
});
|
|
|
|
test("should create a uuid based on a string key", () async {
|
|
String key = "billysometimes";
|
|
String val = await r.uuid(key).run(connection);
|
|
|
|
expect(val, equals('b3f5029e-f777-572f-a85d-5529b74fd99b'));
|
|
});
|
|
});
|
|
|
|
group("expr command -> ", () {
|
|
test("expr should convert native string to rql string", () async {
|
|
String str = await r.expr('string').run(connection);
|
|
expect(str, equals('string'));
|
|
});
|
|
|
|
test("expr should convert native int to rql int", () async {
|
|
int str = await r.expr(3).run(connection);
|
|
expect(str, equals(3));
|
|
});
|
|
test("expr should convert native double to rql float", () async {
|
|
double str = await r.expr(3.14).run(connection);
|
|
expect(str, equals(3.14));
|
|
});
|
|
test("expr should convert native bool to rql bool", () async {
|
|
bool str = await r.expr(true).run(connection);
|
|
expect(str, equals(true));
|
|
});
|
|
test("expr should convert native list to rql array", () async {
|
|
List str = await r.expr([1, 2, 3]).run(connection);
|
|
expect(str, equals([1, 2, 3]));
|
|
});
|
|
test("expr should convert native object to rql object", () async {
|
|
Map str = await r.expr({'a': 'b'}).run(connection);
|
|
expect(str, equals({'a': 'b'}));
|
|
});
|
|
});
|
|
|
|
test("remove the test database", () async {
|
|
Map response = await r.dbDrop(testDbName).run(connection);
|
|
|
|
expect(response.containsKey('config_changes'), equals(true));
|
|
expect(response['dbs_dropped'], equals(1));
|
|
expect(response['tables_dropped'], equals(0));
|
|
});
|
|
|
|
/// TO TEST:
|
|
/// test with orderby: r.asc(attr)
|
|
/// test with orderby: r.desc(attr)
|
|
/// r.http(url)
|
|
///
|
|
/// test with filter or something: r.row;
|
|
/// test with time: r.monday ... r.sunday;
|
|
/// test with time: r.january .. r.december;
|
|
}
|