Need remove, sort, docs
This commit is contained in:
parent
ddd8fea18b
commit
7d54936623
6 changed files with 483 additions and 89 deletions
|
@ -1,10 +1,87 @@
|
||||||
library angel_mongo;
|
library angel_mongo;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:mirrors';
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:json_god/json_god.dart';
|
import 'package:json_god/json_god.dart' as god;
|
||||||
import 'package:merge_map/merge_map.dart';
|
import 'package:merge_map/merge_map.dart';
|
||||||
import 'package:mongo_dart/mongo_dart.dart';
|
import 'package:mongo_dart/mongo_dart.dart';
|
||||||
|
|
||||||
part 'mongo_service.dart';
|
part 'mongo_service.dart';
|
||||||
|
|
||||||
final _god = new God();
|
part 'mongo_service_typed.dart';
|
||||||
|
|
||||||
|
/// A data type that can be serialized to MongoDB.
|
||||||
|
class Model {
|
||||||
|
/// This instance's ID.
|
||||||
|
String id;
|
||||||
|
|
||||||
|
/// The time at which this instance was created.
|
||||||
|
DateTime createdAt;
|
||||||
|
|
||||||
|
/// The time at which this instance was last updated.
|
||||||
|
DateTime updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map _transformId(Map doc) {
|
||||||
|
Map result = mergeMap([doc]);
|
||||||
|
result['id'] = doc['_id'];
|
||||||
|
|
||||||
|
return result..remove('_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastItem(DbCollection collection, Function _jsonify, [Map params]) async {
|
||||||
|
return (await (await collection
|
||||||
|
.find(where.sortBy('\$natural', descending: true)))
|
||||||
|
.toList())
|
||||||
|
.map((x) => _jsonify(x, params))
|
||||||
|
.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectId _makeId(id) {
|
||||||
|
try {
|
||||||
|
return (id is ObjectId) ? id : new ObjectId.fromHexString(id.toString());
|
||||||
|
} catch (e) {
|
||||||
|
throw new AngelHttpException.BadRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map _removeSensitive(Map data) {
|
||||||
|
return data..remove('id')..remove('_id')..remove('createdAt')..remove(
|
||||||
|
'updatedAt');
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectorBuilder _makeQuery([Map params_]) {
|
||||||
|
Map params = params_ ?? {};
|
||||||
|
params = params..remove('provider');
|
||||||
|
SelectorBuilder result = where.exists('_id');
|
||||||
|
|
||||||
|
// You can pass a SelectorBuilder as 'query';
|
||||||
|
if (params['query'] != null && params['query'] is SelectorBuilder)
|
||||||
|
return params['query'];
|
||||||
|
|
||||||
|
for (var key in params.keys) {
|
||||||
|
if (key == r'$sort') {
|
||||||
|
if (params[key] is Map) {
|
||||||
|
// If they send a map, then we'll sort by every key in the map
|
||||||
|
for (String fieldName in params[key].keys.where((x) => x is String)) {
|
||||||
|
var sorter = params[key][fieldName];
|
||||||
|
if (sorter is num) {
|
||||||
|
result = result.sortBy(fieldName, descending: sorter == -1);
|
||||||
|
} else if (sorter is String) {
|
||||||
|
result = result.sortBy(fieldName, descending: sorter == "-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (params[key] is String) {
|
||||||
|
// If they send just a string, then we'll sort
|
||||||
|
// by that, ascending
|
||||||
|
result = result.sortBy(params[key]);
|
||||||
|
}
|
||||||
|
} else if (key is String) {
|
||||||
|
result = result.and(where.eq(key, params[key]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -1,29 +1,33 @@
|
||||||
part of angel_mongo;
|
part of angel_mongo;
|
||||||
|
|
||||||
|
/// Manipulates data from MongoDB as Maps.
|
||||||
class MongoService extends Service {
|
class MongoService extends Service {
|
||||||
DbCollection collection;
|
DbCollection collection;
|
||||||
|
|
||||||
MongoService(DbCollection this.collection);
|
MongoService(DbCollection this.collection):super();
|
||||||
|
|
||||||
Map _jsonify(Map doc) {
|
Map _transformId(Map doc) {
|
||||||
|
Map result = mergeMap([doc]);
|
||||||
|
result['id'] = doc['_id'];
|
||||||
|
|
||||||
|
return result..remove('_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
_jsonify(Map doc, [Map params]) {
|
||||||
Map result = {};
|
Map result = {};
|
||||||
for (var key in doc.keys) {
|
for (var key in doc.keys) {
|
||||||
if (doc[key] is ObjectId) {
|
if (doc[key] is ObjectId) {
|
||||||
result[key] = doc[key].toHexString();
|
result[key] = doc[key].toHexString();
|
||||||
} else result[key] = doc[key];
|
} else
|
||||||
}
|
result[key] = doc[key];
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastItem() async {
|
return _transformId(result);
|
||||||
return (await (await collection.find(
|
|
||||||
where.sortBy('\$natural', descending: true))).toList())
|
|
||||||
.map(_jsonify)
|
|
||||||
.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectorBuilder _makeQuery([Map params_]) {
|
SelectorBuilder _makeQuery([Map params_]) {
|
||||||
Map params = params_ ?? {};
|
Map params = params_ ?? {};
|
||||||
|
params = params..remove('provider');
|
||||||
SelectorBuilder result = where.exists('_id');
|
SelectorBuilder result = where.exists('_id');
|
||||||
|
|
||||||
for (var key in params.keys) {
|
for (var key in params.keys) {
|
||||||
|
@ -43,9 +47,7 @@ class MongoService extends Service {
|
||||||
// by that, ascending
|
// by that, ascending
|
||||||
result = result.sortBy(params[key]);
|
result = result.sortBy(params[key]);
|
||||||
}
|
}
|
||||||
}
|
} else if (key is String) {
|
||||||
|
|
||||||
else if (key is String) {
|
|
||||||
result = result.and(where.eq(key, params[key]));
|
result = result.and(where.eq(key, params[key]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,37 +58,70 @@ class MongoService extends Service {
|
||||||
@override
|
@override
|
||||||
Future<List> index([Map params]) async {
|
Future<List> index([Map params]) async {
|
||||||
return await (await collection.find(_makeQuery(params)))
|
return await (await collection.find(_makeQuery(params)))
|
||||||
.map(_jsonify)
|
.map((x) => _jsonify(x, params))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future create(data, [Map params]) async {
|
Future create(Map data, [Map params]) async {
|
||||||
Map item = (data is Map) ? data : _god.serializeToMap(data);
|
Map item = (data is Map) ? data : god.serializeObject(data);
|
||||||
item = mergeMap([item, params]);
|
item = _removeSensitive(item);
|
||||||
|
|
||||||
|
try {
|
||||||
item['createdAt'] = new DateTime.now();
|
item['createdAt'] = new DateTime.now();
|
||||||
await collection.insert(item);
|
await collection.insert(item);
|
||||||
return await _lastItem();
|
return await _lastItem(collection, _jsonify, params);
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e, stackTrace: st);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future read(id, [Map params]) async {
|
Future read(id, [Map params]) async {
|
||||||
ObjectId id_;
|
ObjectId _id = _makeId(id);
|
||||||
try {
|
Map found = await collection.findOne(where.id(_id).and(_makeQuery(params)));
|
||||||
id_ = (id is ObjectId) ? id : new ObjectId.fromHexString(
|
|
||||||
id.toString());
|
|
||||||
} catch (e) {
|
|
||||||
throw new AngelHttpException.BadRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map found = await collection.findOne(
|
|
||||||
where.id(id_).and(_makeQuery(params)));
|
|
||||||
|
|
||||||
if (found == null) {
|
if (found == null) {
|
||||||
throw new AngelHttpException.NotFound(
|
throw new AngelHttpException.NotFound(
|
||||||
message: 'No record found for ID ${id_.toHexString()}');
|
message: 'No record found for ID ${_id.toHexString()}');
|
||||||
}
|
}
|
||||||
|
|
||||||
return _jsonify(found);
|
return _jsonify(found, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future modify(id, Map data, [Map params]) async {
|
||||||
|
Map target = await read(id, params);
|
||||||
|
Map result = mergeMap([target, _removeSensitive(data)]);
|
||||||
|
result['updatedAt'] = new DateTime.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await collection.update(where.id(_makeId(id)), result);
|
||||||
|
result = _jsonify(result, params);
|
||||||
|
result['id'] = id;
|
||||||
|
return result;
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e, stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future update(id, data, [Map params]) async {
|
||||||
|
Map target = await read(id, params);
|
||||||
|
Map result = _removeSensitive(data);
|
||||||
|
result['_id'] = _makeId(id);
|
||||||
|
result['createdAt'] = target['createdAt'];
|
||||||
|
result['updatedAt'] = new DateTime.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await collection.update(where.id(_makeId(id)), result);
|
||||||
|
result = _jsonify(result, params);
|
||||||
|
result['id'] = id;
|
||||||
|
return result;
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e, stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
131
lib/mongo_service_typed.dart
Normal file
131
lib/mongo_service_typed.dart
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
part of angel_mongo;
|
||||||
|
|
||||||
|
/// Manipulates data from MongoDB by serializing BSON from and deserializing BSON to a target class.
|
||||||
|
class MongoTypedService<T> extends Service {
|
||||||
|
DbCollection collection;
|
||||||
|
|
||||||
|
MongoTypedService(DbCollection this.collection):super() {
|
||||||
|
if (!reflectType(T).isAssignableTo(reflectType(Model)))
|
||||||
|
throw new Exception(
|
||||||
|
"If you specify a type for MongoService, it must be dynamic, Map, or extend from Model.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map _transformId(Map doc) {
|
||||||
|
Map result = mergeMap([doc]);
|
||||||
|
result['id'] = doc['_id'];
|
||||||
|
|
||||||
|
return result..remove('_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
_jsonify(Map doc, [Map params]) {
|
||||||
|
Map result = {};
|
||||||
|
for (var key in doc.keys) {
|
||||||
|
if (doc[key] is ObjectId) {
|
||||||
|
result[key] = doc[key].toHexString();
|
||||||
|
} else
|
||||||
|
result[key] = doc[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
result = _transformId(result);
|
||||||
|
|
||||||
|
// Clients will always receive JSON.
|
||||||
|
if ((params != null && params['provider'] != null)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// However, when we run server-side, we should return a T, not a Map.
|
||||||
|
Model typedResult = god.deserializeDatum(result, outputType: T);
|
||||||
|
typedResult.createdAt = result['createdAt'];
|
||||||
|
typedResult.updatedAt = result['updatedAt'];
|
||||||
|
return typedResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List> index([Map params]) async {
|
||||||
|
return await (await collection.find(_makeQuery(params)))
|
||||||
|
.map((x) => _jsonify(x, params))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future create(data, [Map params]) async {
|
||||||
|
Map item;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Model target =
|
||||||
|
(data is T) ? data : god.deserializeDatum(data, outputType: T);
|
||||||
|
item = god.serializeObject(target);
|
||||||
|
item = _removeSensitive(item);
|
||||||
|
|
||||||
|
item['createdAt'] = new DateTime.now();
|
||||||
|
await collection.insert(item);
|
||||||
|
return await _lastItem(collection, _jsonify, params);
|
||||||
|
} catch (e, st) {
|
||||||
|
print(e);
|
||||||
|
print(st);
|
||||||
|
throw new AngelHttpException.BadRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future read(id, [Map params]) async {
|
||||||
|
ObjectId _id = _makeId(id);
|
||||||
|
|
||||||
|
Map found = await collection.findOne(where.id(_id).and(_makeQuery(params)));
|
||||||
|
|
||||||
|
if (found == null) {
|
||||||
|
throw new AngelHttpException.NotFound(
|
||||||
|
message: 'No record found for ID ${_id.toHexString()}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return _jsonify(found, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future modify(id, Map data, [Map params]) async {
|
||||||
|
ObjectId _id = _makeId(id);
|
||||||
|
try {
|
||||||
|
Map result = await collection.findOne(
|
||||||
|
where.id(_id).and(_makeQuery(params)));
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
throw new AngelHttpException.NotFound(
|
||||||
|
message: 'No record found for ID ${_id.toHexString()}');
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mergeMap([result, _removeSensitive(data)]);
|
||||||
|
result['_id'] = _id;
|
||||||
|
result['updatedAt'] = new DateTime.now();
|
||||||
|
|
||||||
|
await collection.update(where.id(_id), result);
|
||||||
|
return await read(_id, params);
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e, stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future update(id, _data, [Map params]) async {
|
||||||
|
try {
|
||||||
|
Model data = (_data is T) ? _data : god.deserializeDatum(
|
||||||
|
_data, outputType: T);
|
||||||
|
ObjectId _id = _makeId(id);
|
||||||
|
Map rawData = _removeSensitive(god.serializeObject(data));
|
||||||
|
rawData['_id'] = _id;
|
||||||
|
rawData['createdAt'] = data.createdAt;
|
||||||
|
rawData['updatedAt'] = new DateTime.now();
|
||||||
|
|
||||||
|
await collection.update(where.id(_id).and(_makeQuery(params)), rawData);
|
||||||
|
var result = _jsonify(rawData, params);
|
||||||
|
|
||||||
|
if (result is T) {
|
||||||
|
result.createdAt = data.createdAt;
|
||||||
|
result.updatedAt = rawData['updatedAt'];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (e, st) {
|
||||||
|
throw new AngelHttpException(e, stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,9 @@ description: Core libraries for the Angel framework.
|
||||||
author: Tobe O <thosakwe@gmail.com>
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
homepage: https://github.com/angel-dart/angel_framework
|
homepage: https://github.com/angel-dart/angel_framework
|
||||||
dependencies:
|
dependencies:
|
||||||
angel_framework: ">=0.0.0-dev.17 < 0.1.0"
|
angel_framework: ">=1.0.0-dev < 2.0.0"
|
||||||
json_god: ">=1.0.0 <2.0.0"
|
json_god: ">=2.0.0-beta <3.0.0"
|
||||||
mongo_dart: ">= 0.2.5+1 < 1.0.0"
|
mongo_dart: ">= 0.2.7 < 1.0.0"
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
http: ">= 0.11.3 < 0.12.0"
|
http: ">= 0.11.3 < 0.12.0"
|
||||||
test: ">= 0.12.13 < 0.13.0"
|
test: ">= 0.12.13 < 0.13.0"
|
|
@ -2,29 +2,27 @@ import 'dart:io';
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:angel_mongo/angel_mongo.dart';
|
import 'package:angel_mongo/angel_mongo.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:json_god/json_god.dart';
|
import 'package:json_god/json_god.dart' as god;
|
||||||
import 'package:mongo_dart/mongo_dart.dart';
|
import 'package:mongo_dart/mongo_dart.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
class Greeting {
|
|
||||||
final String to;
|
|
||||||
const Greeting(String this.to);
|
|
||||||
}
|
|
||||||
|
|
||||||
final headers = {
|
final headers = {
|
||||||
HttpHeaders.ACCEPT: ContentType.JSON.mimeType,
|
HttpHeaders.ACCEPT: ContentType.JSON.mimeType,
|
||||||
HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType
|
HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType
|
||||||
};
|
};
|
||||||
|
|
||||||
wireHooked(HookedService hooked) {
|
final Map testGreeting = {'to': 'world'};
|
||||||
hooked.onCreated.listen((item) {
|
|
||||||
print("Just created: $item");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wireGreeting(HookedService hooked) {
|
wireHooked(HookedService hooked) {
|
||||||
hooked.onCreated.listen((item) {
|
hooked
|
||||||
print("Greeting: $item");
|
..afterCreated.listen((HookedServiceEvent event) {
|
||||||
|
print("Just created: ${event.result}");
|
||||||
|
})
|
||||||
|
..afterModified.listen((HookedServiceEvent event) {
|
||||||
|
print("Just modified: ${event.result}");
|
||||||
|
})
|
||||||
|
..afterUpdated.listen((HookedServiceEvent event) {
|
||||||
|
print("Just updated: ${event.result}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,33 +30,25 @@ main() {
|
||||||
group('angel_mongo', () {
|
group('angel_mongo', () {
|
||||||
Angel app = new Angel();
|
Angel app = new Angel();
|
||||||
http.Client client;
|
http.Client client;
|
||||||
God god = new God();
|
|
||||||
Db db = new Db('mongodb://localhost:27017/angel_mongo');
|
Db db = new Db('mongodb://localhost:27017/angel_mongo');
|
||||||
DbCollection testData;
|
DbCollection testData;
|
||||||
DbCollection testGreetings;
|
|
||||||
String url;
|
String url;
|
||||||
|
HookedService Greetings;
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
client = new http.Client();
|
client = new http.Client();
|
||||||
await db.open();
|
await db.open();
|
||||||
testData = db.collection('test_data');
|
testData = db.collection('test_data');
|
||||||
testGreetings = db.collection('test_greetings');
|
|
||||||
// Delete anything before we start
|
// Delete anything before we start
|
||||||
await testData.remove();
|
await testData.remove();
|
||||||
await testGreetings.remove();
|
|
||||||
|
|
||||||
var service = new MongoService(testData);
|
var service = new MongoService(testData);
|
||||||
var hooked = new HookedService(service);
|
Greetings = new HookedService(service);
|
||||||
wireHooked(hooked);
|
wireHooked(Greetings);
|
||||||
|
|
||||||
var greetings = new MongoService<Greeting>(testGreetings);
|
app.use('/api', Greetings);
|
||||||
var hookedGreetings = new HookedService(greetings);
|
HttpServer server =
|
||||||
wireGreeting(hookedGreetings);
|
await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||||
|
|
||||||
app.use('/api', hooked);
|
|
||||||
app.use('/greetings', hookedGreetings);
|
|
||||||
HttpServer server = await app.startServer(
|
|
||||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
|
||||||
url = "http://${server.address.host}:${server.port}";
|
url = "http://${server.address.host}:${server.port}";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -69,13 +59,12 @@ main() {
|
||||||
await app.httpServer.close(force: true);
|
await app.httpServer.close(force: true);
|
||||||
client = null;
|
client = null;
|
||||||
url = null;
|
url = null;
|
||||||
|
Greetings = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('insert items', () async {
|
test('insert items', () async {
|
||||||
Map testUser = {'hello': 'world'};
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
var response = await client.post(
|
|
||||||
"$url/api", body: god.serialize(testUser), headers: headers);
|
|
||||||
expect(response.statusCode, equals(HttpStatus.OK));
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
|
||||||
response = await client.get("$url/api");
|
response = await client.get("$url/api");
|
||||||
|
@ -85,42 +74,56 @@ main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('read item', () async {
|
test('read item', () async {
|
||||||
Map testUser = {'hello': 'world'};
|
var response = await client.post("$url/api",
|
||||||
var response = await client.post(
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
"$url/api", body: god.serialize(testUser), headers: headers);
|
|
||||||
expect(response.statusCode, equals(HttpStatus.OK));
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
Map created = god.deserialize(response.body);
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
response = await client.get("$url/api/${created['_id']}");
|
response = await client.get("$url/api/${created['id']}");
|
||||||
expect(response.statusCode, equals(HttpStatus.OK));
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
Map read = god.deserialize(response.body);
|
Map read = god.deserialize(response.body);
|
||||||
expect(read['_id'], equals(created['_id']));
|
expect(read['id'], equals(created['id']));
|
||||||
expect(read['hello'], equals('world'));
|
expect(read['to'], equals('world'));
|
||||||
expect(read['createdAt'], isNot(null));
|
expect(read['createdAt'], isNot(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modify item', () async {
|
test('modify item', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
|
response = await client.patch(
|
||||||
|
"$url/api/${created['id']}", body: god.serialize({"to": "Mom"}),
|
||||||
|
headers: headers);
|
||||||
|
Map modified = god.deserialize(response.body);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
expect(modified['id'], equals(created['id']));
|
||||||
|
expect(modified['to'], equals('Mom'));
|
||||||
|
expect(modified['updatedAt'], isNot(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('update item', () async {
|
test('update item', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
|
response = await client.post(
|
||||||
|
"$url/api/${created['id']}", body: god.serialize({"to": "Updated"}),
|
||||||
|
headers: headers);
|
||||||
|
Map modified = god.deserialize(response.body);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
expect(modified['id'], equals(created['id']));
|
||||||
|
expect(modified['to'], equals('Updated'));
|
||||||
|
expect(modified['updatedAt'], isNot(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('remove item', () async {
|
test('remove item', () async {});
|
||||||
|
|
||||||
|
test(r'$sort', () async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sort by string', () async {
|
test('query parameters', () async {});
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test('sort by map', () async {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test('query parameters', () async {
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
|
import 'package:angel_mongo/angel_mongo.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:json_god/json_god.dart' as god;
|
||||||
|
import 'package:mongo_dart/mongo_dart.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
class Greeting extends Model {
|
||||||
|
String to;
|
||||||
|
|
||||||
|
Greeting({String this.to});
|
||||||
|
}
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
HttpHeaders.ACCEPT: ContentType.JSON.mimeType,
|
||||||
|
HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType
|
||||||
|
};
|
||||||
|
|
||||||
|
final Map testGreeting = {'to': 'world'};
|
||||||
|
|
||||||
|
wireHooked(HookedService hooked) {
|
||||||
|
hooked
|
||||||
|
..afterCreated.listen((HookedServiceEvent event) {
|
||||||
|
print("Just created: ${god.serialize(event.result)}");
|
||||||
|
})
|
||||||
|
..afterModified.listen((HookedServiceEvent event) {
|
||||||
|
print("Just modified: ${god.serialize(event.result)}");
|
||||||
|
})
|
||||||
|
..afterUpdated.listen((HookedServiceEvent event) {
|
||||||
|
print("Just updated: ${event.result}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('angel_mongo', () {
|
||||||
|
Angel app = new Angel();
|
||||||
|
http.Client client;
|
||||||
|
Db db = new Db('mongodb://localhost:27017/angel_mongo');
|
||||||
|
DbCollection testData;
|
||||||
|
String url;
|
||||||
|
Service Greetings;
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
client = new http.Client();
|
||||||
|
await db.open();
|
||||||
|
testData = db.collection('test_greetings');
|
||||||
|
// Delete anything before we start
|
||||||
|
await testData.remove();
|
||||||
|
|
||||||
|
var service = new MongoTypedService<Greeting>(testData);
|
||||||
|
Greetings = new HookedService(service);
|
||||||
|
wireHooked(Greetings);
|
||||||
|
|
||||||
|
app.use('/api', Greetings);
|
||||||
|
HttpServer server =
|
||||||
|
await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||||
|
url = "http://${server.address.host}:${server.port}";
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
// Delete anything left over
|
||||||
|
await testData.remove();
|
||||||
|
await db.close();
|
||||||
|
await app.httpServer.close(force: true);
|
||||||
|
client = null;
|
||||||
|
url = null;
|
||||||
|
Greetings = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('insert items', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
|
||||||
|
response = await client.get("$url/api");
|
||||||
|
expect(response.statusCode, 200);
|
||||||
|
List<Map> greetings = god.deserialize(response.body);
|
||||||
|
expect(greetings.length, equals(1));
|
||||||
|
|
||||||
|
Greeting greeting = new Greeting(to: "Mom");
|
||||||
|
await Greetings.create(greeting);
|
||||||
|
greetings = await (await testData.find()).toList();
|
||||||
|
expect(greetings.length, equals(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('read item', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
|
response = await client.get("$url/api/${created['id']}");
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map read = god.deserialize(response.body);
|
||||||
|
expect(read['id'], equals(created['id']));
|
||||||
|
expect(read['to'], equals('world'));
|
||||||
|
expect(read['createdAt'], isNot(null));
|
||||||
|
|
||||||
|
Greeting greeting = await Greetings.read(created['id']);
|
||||||
|
expect(greeting.id, equals(created['id']));
|
||||||
|
expect(greeting.to, equals('world'));
|
||||||
|
expect(greeting.createdAt, isNot(null));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('modify item', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
|
response = await client.patch(
|
||||||
|
"$url/api/${created['id']}", body: god.serialize({"to": "Mom"}),
|
||||||
|
headers: headers);
|
||||||
|
Map modified = god.deserialize(response.body);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
expect(modified['id'], equals(created['id']));
|
||||||
|
expect(modified['to'], equals('Mom'));
|
||||||
|
expect(modified['updatedAt'], isNot(null));
|
||||||
|
|
||||||
|
await Greetings.modify(created['id'], {"to": "Batman"});
|
||||||
|
Greeting greeting = await Greetings.read(created['id']);
|
||||||
|
expect(greeting.to, equals("Batman"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update item', () async {
|
||||||
|
var response = await client.post("$url/api",
|
||||||
|
body: god.serialize(testGreeting), headers: headers);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
Map created = god.deserialize(response.body);
|
||||||
|
|
||||||
|
response = await client.post(
|
||||||
|
"$url/api/${created['id']}", body: god.serialize({"to": "Updated"}),
|
||||||
|
headers: headers);
|
||||||
|
Map modified = god.deserialize(response.body);
|
||||||
|
expect(response.statusCode, equals(HttpStatus.OK));
|
||||||
|
expect(modified['id'], equals(created['id']));
|
||||||
|
expect(modified['to'], equals('Updated'));
|
||||||
|
expect(modified['updatedAt'], isNot(null));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('remove item', () async {});
|
||||||
|
|
||||||
|
test(r'$sort', () async {});
|
||||||
|
|
||||||
|
test('query parameters', () async {});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue