From 9d1b368d5b1e293f85af808b5f069e9d0756538f Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 5 Jan 2019 21:08:31 -0500 Subject: [PATCH] 2.0.0 --- CHANGELOG.md | 5 + analysis_options.yaml | 5 +- example/main.dart | 21 ++++ lib/angel_client.dart | 102 ++++++++++++---- lib/auth_types.dart | 7 +- lib/base_angel_client.dart | 235 +++++++++++++++++-------------------- lib/browser.dart | 35 ++---- lib/flutter.dart | 5 +- lib/io.dart | 11 +- pubspec.yaml | 11 +- test/all_test.dart | 11 +- test/common.dart | 2 +- web/main.dart | 2 +- 13 files changed, 248 insertions(+), 204 deletions(-) create mode 100644 example/main.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index b5c510a5..6cb5ffd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.0.0 +* Deprecate `basePath` in favor of `baseUrl`. +* `Angel` now extends `http.Client`. +* Deprecate `auth_types`. + # 2.0.0-alpha.2 * Make Service `index` always return `List`. * Add `Service.map`. diff --git a/analysis_options.yaml b/analysis_options.yaml index 3e203853..a146a9e6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,5 +1,6 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false - exclude: - - test/io_test.dart \ No newline at end of file + errors: + unawaited_futures: ignore \ No newline at end of file diff --git a/example/main.dart b/example/main.dart new file mode 100644 index 00000000..d237c4bb --- /dev/null +++ b/example/main.dart @@ -0,0 +1,21 @@ +import 'dart:async'; +import 'package:angel_client/angel_client.dart'; + +Future doSomething(Angel app) async { + var userService = app + .service>('api/users') + .map(User.fromMap, User.toMap); + + var users = await userService.index(); + print('Name: ${users.first.name}'); +} + +class User { + final String name; + + User({this.name}); + + static User fromMap(Map data) => User(name: data['name'] as String); + + static Map toMap(User user) => {'name': user.name}; +} diff --git a/lib/angel_client.dart b/lib/angel_client.dart index edcc52d1..f681786b 100644 --- a/lib/angel_client.dart +++ b/lib/angel_client.dart @@ -4,11 +4,12 @@ library angel_client; import 'dart:async'; import 'package:collection/collection.dart'; import 'dart:convert'; -import 'package:http/src/response.dart' as http; +import 'package:http/http.dart' as http; export 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:meta/meta.dart'; /// A function that configures an [Angel] client in some way. -typedef Future AngelConfigurer(Angel app); +typedef FutureOr AngelConfigurer(Angel app); /// A function that deserializes data received from the server. /// @@ -17,61 +18,110 @@ typedef Future AngelConfigurer(Angel app); typedef T AngelDeserializer(x); /// Represents an Angel server that we are querying. -abstract class Angel { +abstract class Angel extends http.BaseClient { + /// A mutable member. When this is set, it holds a JSON Web Token + /// that is automatically attached to every request sent. + /// + /// This is designed with `package:angel_auth` in mind. String authToken; - String basePath; - Angel(String this.basePath); + /// The root URL at which the target server. + final Uri baseUrl; + + Angel(baseUrl) + : this.baseUrl = baseUrl is Uri ? baseUrl : Uri.parse(baseUrl.toString()); + + /// Prefer to use [baseUrl] instead. + @deprecated + String get basePath => baseUrl.toString(); /// Fired whenever a WebSocket is successfully authenticated. Stream get onAuthenticated; + /// Authenticates against the server. + /// + /// This is designed with `package:angel_auth` in mind. + /// + /// The [type] is appended to the [authEndpoint], ex. `local` becomes `/auth/local`. + /// + /// The given [credentials] are sent to server as-is; the request body is sent as JSON. Future authenticate( - {String type, + {@required String type, credentials, - String authEndpoint: '/auth', - String reviveEndpoint: '/auth/token'}); + String authEndpoint = '/auth', + @deprecated String reviveEndpoint = '/auth/token'}); + + /// Shorthand for authenticating via a JWT string. + Future reviveJwt(String token, + {String authEndpoint = '/auth'}) { + return authenticate( + type: 'token', + credentials: {'token': token}, + authEndpoint: authEndpoint); + } /// Opens the [url] in a new window, and returns a [Stream] that will fire a JWT on successful authentication. - Stream authenticateViaPopup(String url, {String eventName: 'token'}); + Stream authenticateViaPopup(String url, {String eventName = 'token'}); - Future close(); + /// Disposes of any outstanding resources. + Future close(); /// Applies an [AngelConfigurer] to this instance. - Future configure(AngelConfigurer configurer) async { + Future configure(AngelConfigurer configurer) async { await configurer(this); } /// Logs the current user out of the application. - Future logout(); + FutureOr logout(); + /// Creates a [Service] instance that queries a given path on the server. + /// + /// This expects that there is an Angel `Service` mounted on the server. + /// + /// In other words, all endpoints will return [Data], except for the root of + /// [path], which returns a [List]. + /// + /// You can pass a custom [deserializer], which is typically necessary in cases where + /// `dart:mirrors` does not exist. Service service(String path, - {Type type, AngelDeserializer deserializer}); + {@deprecated Type type, AngelDeserializer deserializer}); - Future delete(String url, {Map headers}); + @override + Future delete(url, {Map headers}); - Future get(String url, {Map headers}); + @override + Future get(url, {Map headers}); - Future head(String url, {Map headers}); + @override + Future head(url, {Map headers}); - Future patch(String url, {body, Map headers}); + @override + Future patch(url, + {body, Map headers, Encoding encoding}); - Future post(String url, {body, Map headers}); + @override + Future post(url, + {body, Map headers, Encoding encoding}); - Future put(String url, {body, Map headers}); + @override + Future put(url, + {body, Map headers, Encoding encoding}); } /// Represents the result of authentication with an Angel server. class AngelAuthResult { String _token; final Map data = {}; + + /// The JSON Web token that was sent with this response. String get token => _token; - AngelAuthResult({String token, Map data: const {}}) { + AngelAuthResult({String token, Map data = const {}}) { _token = token; this.data.addAll(data ?? {}); } + /// Attempts to deserialize a response from a [Map]. factory AngelAuthResult.fromMap(Map data) { final result = new AngelAuthResult(); @@ -81,12 +131,22 @@ class AngelAuthResult { if (data is Map) result.data.addAll((data['data'] as Map) ?? {}); + if (result.token == null) { + throw new FormatException( + 'The required "token" field was not present in the given data.'); + } else if (data['data'] is! Map) { + throw new FormatException( + 'The required "data" field in the given data was not a map; instead, it was ${data['data']}.'); + } + return result; } + /// Attempts to deserialize a response from a [String]. factory AngelAuthResult.fromJson(String s) => new AngelAuthResult.fromMap(json.decode(s) as Map); + /// Converts this instance into a JSON-friendly representation. Map toJson() { return {'token': token, 'data': data}; } @@ -225,7 +285,7 @@ class ServiceList extends DelegatingList { final List _subs = []; - ServiceList(this.service, {this.idField, Equality equality}) + ServiceList(this.service, {this.idField = 'id', Equality equality}) : super([]) { _equality = equality; _equality ??= new EqualityBy((map) { diff --git a/lib/auth_types.dart b/lib/auth_types.dart index f28a06af..5b98fe57 100644 --- a/lib/auth_types.dart +++ b/lib/auth_types.dart @@ -1,5 +1,4 @@ -const String local = 'local'; - -/// Use [local] instead. @deprecated -const String LOCAL = local; +library auth_types; + +const String local = 'local', token = 'token'; diff --git a/lib/base_angel_client.dart b/lib/base_angel_client.dart index 4704085a..1b7f7f35 100644 --- a/lib/base_angel_client.dart +++ b/lib/base_angel_client.dart @@ -7,25 +7,17 @@ import 'package:http/src/base_request.dart' as http; import 'package:http/src/request.dart' as http; import 'package:http/src/response.dart' as http; import 'package:http/src/streamed_response.dart' as http; +import 'package:path/path.dart' as p; import 'angel_client.dart'; -final RegExp straySlashes = new RegExp(r"(^/)|(/+$)"); const Map _readHeaders = const {'Accept': 'application/json'}; const Map _writeHeaders = const { 'Accept': 'application/json', 'Content-Type': 'application/json' }; -_buildQuery(Map params) { - if (params == null || params.isEmpty || params['query'] is! Map) return ""; - - List query = []; - - params['query'].forEach((k, v) { - query.add('$k=${Uri.encodeQueryComponent(v.toString())}'); - }); - - return '?' + query.join('&'); +Map _buildQuery(Map params) { + return params?.map((k, v) => new MapEntry(k, v.toString())); } bool _invalid(http.Response response) => @@ -36,7 +28,7 @@ bool _invalid(http.Response response) => AngelHttpException failure(http.Response response, {error, String message, StackTrace stack}) { try { - final v = json.decode(response.body); + var v = json.decode(response.body); if (v is Map && (v['is_error'] == true) || v['isError'] == true) { return new AngelHttpException.fromMap(v as Map); @@ -71,89 +63,48 @@ abstract class BaseAngelClient extends Angel { Future authenticate( {String type, credentials, - String authEndpoint: '/auth', - String reviveEndpoint: '/auth/token'}) async { - if (type == null) { - final url = '$basePath$reviveEndpoint'; - String token; + String authEndpoint = '/auth', + @deprecated String reviveEndpoint = '/auth/token'}) async { + type ??= 'token'; - if (credentials is String) - token = credentials; - else if (credentials is Map && credentials.containsKey('token')) - token = credentials['token'].toString(); + var segments = baseUrl.pathSegments + .followedBy(p.split(authEndpoint)) + .followedBy([type]); + var url = baseUrl.replace(path: p.joinAll(segments)); + http.Response response; - if (token == null) { - throw new ArgumentError( - 'If `type` is not set, a JWT is expected as the `credentials` argument.'); - } - - final response = await client.post(url, headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token' - }); - - if (_invalid(response)) { - throw failure(response); - } - - try { - final v = json.decode(response.body); - - if (v is! Map || - !(v as Map).containsKey('data') || - !(v as Map).containsKey('token')) { - throw new AngelHttpException.notAuthenticated( - message: - "Auth endpoint '$url' did not return a proper response."); - } - - var r = new AngelAuthResult.fromMap(v as Map); - _onAuthenticated.add(r); - return r; - } on AngelHttpException { - rethrow; - } catch (e, st) { - throw failure(response, error: e, stack: st); - } + if (credentials != null) { + response = await post(url, + body: json.encode(credentials), headers: _writeHeaders); } else { - final url = '$basePath$authEndpoint/$type'; - http.Response response; + response = await post(url, headers: _writeHeaders); + } - if (credentials != null) { - response = await client.post(url, - body: json.encode(credentials), headers: _writeHeaders); - } else { - response = await client.post(url, headers: _writeHeaders); + if (_invalid(response)) { + throw failure(response); + } + + try { + var v = json.decode(response.body); + + if (v is! Map || + !(v as Map).containsKey('data') || + !(v as Map).containsKey('token')) { + throw new AngelHttpException.notAuthenticated( + message: "Auth endpoint '$url' did not return a proper response."); } - if (_invalid(response)) { - throw failure(response); - } - - try { - final v = json.decode(response.body); - - if (v is! Map || - !(v as Map).containsKey('data') || - !(v as Map).containsKey('token')) { - throw new AngelHttpException.notAuthenticated( - message: - "Auth endpoint '$url' did not return a proper response."); - } - - var r = new AngelAuthResult.fromMap(v as Map); - _onAuthenticated.add(r); - return r; - } on AngelHttpException { - rethrow; - } catch (e, st) { - throw failure(response, error: e, stack: st); - } + var r = new AngelAuthResult.fromMap(v as Map); + _onAuthenticated.add(r); + return r; + } on AngelHttpException { + rethrow; + } catch (e, st) { + throw failure(response, error: e, stack: st); } } - Future close() async { + Future close() async { client.close(); _onAuthenticated.close(); Future.wait(_services.map((s) => s.close())).then((_) { @@ -161,10 +112,17 @@ abstract class BaseAngelClient extends Angel { }); } - Future logout() async { + Future logout() async { authToken = null; } + @override + Future send(http.BaseRequest request) async { + if (authToken?.isNotEmpty == true) + request.headers['authorization'] ??= 'Bearer $authToken'; + return client.send(request); + } + /// Sends a non-streaming [Request] and returns a non-streaming [Response]. Future sendUnstreamed( String method, url, Map headers, @@ -174,80 +132,77 @@ abstract class BaseAngelClient extends Angel { if (headers != null) request.headers.addAll(headers); - if (authToken?.isNotEmpty == true) - request.headers['Authorization'] = 'Bearer $authToken'; - if (encoding != null) request.encoding = encoding; if (body != null) { if (body is String) { request.body = body; - } else if (body is List) { - request.bodyBytes = new List.from(body); - } else if (body is Map) { - request.bodyFields = new Map.from(body); + } else if (body is List) { + request.bodyBytes = new List.from(body); + } else if (body is Map) { + request.bodyFields = new Map.from(body); } else { - throw new ArgumentError('Invalid request body "$body".'); + throw new ArgumentError.value(body, 'body', + 'must be a String, List, or Map.'); } } - return http.Response.fromStream(await client.send(request)); + return http.Response.fromStream(await send(request)); } @override Service service(String path, {Type type, AngelDeserializer deserializer}) { - String uri = path.toString().replaceAll(straySlashes, ""); - var s = new BaseAngelService(client, this, '$basePath/$uri', + var url = baseUrl.replace(path: p.join(baseUrl.path, path)); + var s = new BaseAngelService(client, this, url, deserializer: deserializer); _services.add(s); return s; } - String _join(url) { - final head = basePath.replaceAll(new RegExp(r'/+$'), ''); - final tail = url.replaceAll(straySlashes, ''); - return '$head/$tail'; + Uri _join(url) { + var u = url is Uri ? url : Uri.parse(url.toString()); + if (u.hasScheme || u.hasAuthority) return u; + return baseUrl.replace(path: p.join(baseUrl.path, u.path)); } @override - Future delete(String url, - {Map headers}) async { + Future delete(url, {Map headers}) async { return sendUnstreamed('DELETE', _join(url), headers); } @override - Future get(String url, {Map headers}) async { + Future get(url, {Map headers}) async { return sendUnstreamed('GET', _join(url), headers); } @override - Future head(String url, {Map headers}) async { + Future head(url, {Map headers}) async { return sendUnstreamed('HEAD', _join(url), headers); } @override - Future patch(String url, - {body, Map headers}) async { - return sendUnstreamed('PATCH', _join(url), headers, body); + Future patch(url, + {body, Map headers, Encoding encoding}) async { + return sendUnstreamed('PATCH', _join(url), headers, body, encoding); } @override - Future post(String url, - {body, Map headers}) async { - return sendUnstreamed('POST', _join(url), headers, body); + Future post(url, + {body, Map headers, Encoding encoding}) async { + return sendUnstreamed('POST', _join(url), headers, body, encoding); } @override - Future put(String url, - {body, Map headers}) async { - return sendUnstreamed('PUT', _join(url), headers, body); + Future put(url, + {body, Map headers, Encoding encoding}) async { + return sendUnstreamed('PUT', _join(url), headers, body, encoding); } } class BaseAngelService extends Service { @override final BaseAngelClient app; - final String basePath; + final Uri baseUrl; final http.BaseClient client; final AngelDeserializer deserializer; @@ -286,7 +241,12 @@ class BaseAngelService extends Service { _onRemoved.close(); } - BaseAngelService(this.client, this.app, this.basePath, {this.deserializer}); + BaseAngelService(this.client, this.app, baseUrl, {this.deserializer}) + : this.baseUrl = baseUrl is Uri ? baseUrl : Uri.parse(baseUrl.toString()); + + /// Use [baseUrl] instead. + @deprecated + String get basePath => baseUrl.toString(); Data deserialize(x) { return deserializer != null ? deserializer(x) : x as Data; @@ -306,8 +266,8 @@ class BaseAngelService extends Service { @override Future> index([Map params]) async { - final response = await app.sendUnstreamed( - 'GET', '$basePath${_buildQuery(params)}', _readHeaders); + var url = baseUrl.replace(queryParameters: _buildQuery(params)); + var response = await app.sendUnstreamed('GET', url, _readHeaders); try { if (_invalid(response)) { @@ -317,7 +277,7 @@ class BaseAngelService extends Service { throw failure(response); } - final v = json.decode(response.body) as List; + var v = json.decode(response.body) as List; var r = v.map(deserialize).toList(); _onIndexed.add(r); return r; @@ -333,8 +293,11 @@ class BaseAngelService extends Service { @override Future read(id, [Map params]) async { - final response = await app.sendUnstreamed( - 'GET', '$basePath/$id${_buildQuery(params)}', _readHeaders); + var url = baseUrl.replace( + path: p.join(baseUrl.path, id.toString()), + queryParameters: _buildQuery(params)); + + var response = await app.sendUnstreamed('GET', url, _readHeaders); try { if (_invalid(response)) { @@ -359,8 +322,9 @@ class BaseAngelService extends Service { @override Future create(data, [Map params]) async { - final response = await app.sendUnstreamed('POST', - '$basePath/${_buildQuery(params)}', _writeHeaders, makeBody(data)); + var url = baseUrl.replace(queryParameters: _buildQuery(params)); + var response = + await app.sendUnstreamed('POST', url, _writeHeaders, makeBody(data)); try { if (_invalid(response)) { @@ -385,8 +349,12 @@ class BaseAngelService extends Service { @override Future modify(id, data, [Map params]) async { - final response = await app.sendUnstreamed('PATCH', - '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data)); + var url = baseUrl.replace( + path: p.join(baseUrl.path, id.toString()), + queryParameters: _buildQuery(params)); + + var response = + await app.sendUnstreamed('PATCH', url, _writeHeaders, makeBody(data)); try { if (_invalid(response)) { @@ -411,8 +379,12 @@ class BaseAngelService extends Service { @override Future update(id, data, [Map params]) async { - final response = await app.sendUnstreamed('POST', - '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data)); + var url = baseUrl.replace( + path: p.join(baseUrl.path, id.toString()), + queryParameters: _buildQuery(params)); + + var response = + await app.sendUnstreamed('POST', url, _writeHeaders, makeBody(data)); try { if (_invalid(response)) { @@ -437,8 +409,11 @@ class BaseAngelService extends Service { @override Future remove(id, [Map params]) async { - final response = await app.sendUnstreamed( - 'DELETE', '$basePath/$id${_buildQuery(params)}', _readHeaders); + var url = baseUrl.replace( + path: p.join(baseUrl.path, id.toString()), + queryParameters: _buildQuery(params)); + + var response = await app.sendUnstreamed('DELETE', url, _readHeaders); try { if (_invalid(response)) { diff --git a/lib/browser.dart b/lib/browser.dart index 54b67a80..5b25459a 100644 --- a/lib/browser.dart +++ b/lib/browser.dart @@ -15,42 +15,31 @@ export 'angel_client.dart'; class Rest extends BaseAngelClient { Rest(String basePath) : super(new http.BrowserClient(), basePath); - @override Future authenticate( {String type, credentials, - String authEndpoint: '/auth', - String reviveEndpoint: '/auth/token'}) async { - if (type == null) { + String authEndpoint = '/auth', + @deprecated String reviveEndpoint = '/auth/token'}) async { + if (type == null || type == 'token') { if (!window.localStorage.containsKey('token')) { throw new Exception( 'Cannot revive token from localStorage - there is none.'); } - try { - final result = await super.authenticate( - type: null, - credentials: {'token': json.decode(window.localStorage['token'])}, - reviveEndpoint: reviveEndpoint); - window.localStorage['token'] = json.encode(authToken = result.token); - window.localStorage['user'] = json.encode(result.data); - return result; - } catch (e, st) { - throw new AngelHttpException(e, - message: 'Failed to revive auth token.', stackTrace: st); - } - } else { - final result = await super.authenticate( - type: type, credentials: credentials, authEndpoint: authEndpoint); - window.localStorage['token'] = json.encode(authToken = result.token); - window.localStorage['user'] = json.encode(result.data); - return result; + var token = json.decode(window.localStorage['token']); + credentials ??= {'token': token}; } + + final result = await super.authenticate( + type: type, credentials: credentials, authEndpoint: authEndpoint); + window.localStorage['token'] = json.encode(authToken = result.token); + window.localStorage['user'] = json.encode(result.data); + return result; } @override Stream authenticateViaPopup(String url, - {String eventName: 'token', String errorMessage}) { + {String eventName = 'token', String errorMessage}) { var ctrl = new StreamController(); var wnd = window.open(url, 'angel_client_auth_popup'); diff --git a/lib/flutter.dart b/lib/flutter.dart index 83bfec5e..5e908fb5 100644 --- a/lib/flutter.dart +++ b/lib/flutter.dart @@ -11,8 +11,9 @@ class Rest extends BaseAngelClient { Rest(String basePath) : super(new http.Client() as http.BaseClient, basePath); @override - Stream authenticateViaPopup(String url, {String eventName: 'token'}) { + Stream authenticateViaPopup(String url, + {String eventName = 'token'}) { throw new UnimplementedError( - 'Opening popup windows is not supported in the `dart:io` client.'); + 'Opening popup windows is not supported in the `flutter` client.'); } } diff --git a/lib/io.dart b/lib/io.dart index cb50df37..85ad0822 100644 --- a/lib/io.dart +++ b/lib/io.dart @@ -4,6 +4,7 @@ library angel_client.cli; import 'dart:async'; import 'package:http/http.dart' as http; import 'package:json_god/json_god.dart' as god; +import 'package:path/path.dart' as p; import 'angel_client.dart'; import 'base_angel_client.dart'; export 'angel_client.dart'; @@ -17,14 +18,15 @@ class Rest extends BaseAngelClient { @override Service service(String path, {Type type, AngelDeserializer deserializer}) { - String uri = path.replaceAll(straySlashes, ""); - var s = new RestService(client, this, "$basePath/$uri", type); + var url = baseUrl.replace(path: p.join(baseUrl.path, path)); + var s = new RestService(client, this, url, type); _services.add(s); return s; } @override - Stream authenticateViaPopup(String url, {String eventName: 'token'}) { + Stream authenticateViaPopup(String url, + {String eventName = 'token'}) { throw new UnimplementedError( 'Opening popup windows is not supported in the `dart:io` client.'); } @@ -41,8 +43,7 @@ class Rest extends BaseAngelClient { class RestService extends BaseAngelService { final Type type; - RestService( - http.BaseClient client, BaseAngelClient app, String url, this.type) + RestService(http.BaseClient client, BaseAngelClient app, url, this.type) : super(client, app, url); @override diff --git a/pubspec.yaml b/pubspec.yaml index 5e8aa7b1..60056482 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_client -version: 2.0.0-alpha.2 +version: 2.0.0 description: Client library for the Angel framework. author: Tobe O homepage: https://github.com/angel-dart/angel_client @@ -8,13 +8,14 @@ environment: dependencies: angel_http_exception: ^1.0.0 collection: ^1.0.0 - http: ">=0.11.0 <2.0.0" + http: ^0.12.0 json_god: ">=2.0.0-beta <3.0.0" - merge_map: ^1.0.0 + path: ^1.0.0 dev_dependencies: angel_framework: ^2.0.0-alpha angel_model: ^1.0.0 - build_runner: ^0.10.0 - build_web_compilers: ^0.4.0 + build_runner: ^1.0.0 + build_web_compilers: ^1.0.0 mock_request: ^1.0.0 + pedantic: ^1.0.0 test: ^1.0.0 diff --git a/test/all_test.dart b/test/all_test.dart index 4816d38e..f80821bb 100644 --- a/test/all_test.dart +++ b/test/all_test.dart @@ -33,7 +33,7 @@ main() { expect(app.client.spec.method, 'POST'); expect(app.client.spec.headers['content-type'], startsWith('application/json')); - expect(app.client.spec.path, '/api/todos/'); + expect(app.client.spec.path, '/api/todos'); expect(await read(app.client.spec.request.finalize()), '{}'); }); @@ -63,10 +63,6 @@ main() { }); group('authentication', () { - test('no type, no token throws', () async { - expect(app.authenticate, throwsArgumentError); - }); - test('no type defaults to token', () async { await app.authenticate(credentials: ''); expect(app.client.spec.path, '/auth/token'); @@ -77,11 +73,6 @@ main() { expect(app.client.spec.path, '/auth/local'); }); - test('token sends headers', () async { - await app.authenticate(credentials: ''); - expect(app.client.spec.headers['authorization'], 'Bearer '); - }); - test('credentials send right body', () async { await app .authenticate(type: 'local', credentials: {'username': 'password'}); diff --git a/test/common.dart b/test/common.dart index bc54f5cf..8d7e2c90 100644 --- a/test/common.dart +++ b/test/common.dart @@ -15,7 +15,7 @@ class MockAngel extends BaseAngelClient { MockAngel() : super(null, 'http://localhost:3000'); @override - authenticateViaPopup(String url, {String eventName: 'token'}) { + authenticateViaPopup(String url, {String eventName = 'token'}) { throw new UnsupportedError('Nope'); } } diff --git a/web/main.dart b/web/main.dart index 4cd7910d..9e12ec08 100644 --- a/web/main.dart +++ b/web/main.dart @@ -4,5 +4,5 @@ import 'package:angel_client/browser.dart'; /// Dummy app to ensure client works with DDC. main() { var app = new Rest(window.location.origin); - window.alert(app.basePath); + window.alert(app.baseUrl.toString()); }