From bbce0224f90d7b529f8caf0585186afb089afaff Mon Sep 17 00:00:00 2001 From: Client Date: Tue, 18 Aug 2020 19:19:06 +0000 Subject: [PATCH] PubNub SDK v1.4.4 release. --- .pubnub.yml | 22 +++- CHANGELOG.md | 9 ++ lib/pubnub.dart | 8 ++ lib/src/core/core.dart | 2 +- lib/src/dx/_endpoints/history.dart | 54 ++++++++-- lib/src/dx/_utils/custom_flow.dart | 19 ++-- lib/src/dx/_utils/ensure.dart | 2 +- lib/src/dx/batch/batch.dart | 61 ++++++++--- lib/src/dx/message_action/message_action.dart | 1 + lib/src/net/net.dart | 3 +- pubspec.lock | 16 ++- pubspec.yaml | 3 +- test/dx/fixtures/history.dart | 102 ++++++++++++++++++ test/dx/history_test.dart | 74 ++++++++++++- test/dx/message_action_test.dart | 21 ++-- 15 files changed, 353 insertions(+), 44 deletions(-) diff --git a/.pubnub.yml b/.pubnub.yml index 6163e3e3..9e826f2c 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -3,7 +3,20 @@ changelog: - changes: - - text: "Fixes issue of exception from server when publishKey os null with publish call." + text: "Add flags in history v3 for including messageType and uuid." + type: feature + - + text: "Add support for fetch history with message actions." + type: feature + - + text: "Refactor for error message parsing for files." + type: improvement + date: Aug 19, 20 + version: v1.4.4 + - + changes: + - + text: "Fixes issue of exception from server when publishKey is null with publish call." type: bug - text: "Fixes missing url component in file publish message for sendFile and support for message encryption." @@ -211,6 +224,11 @@ features: - STORAGE-MESSAGE-COUNT - STORAGE-HISTORY-WITH-META - STORAGE-FETCH-WITH-META + - STORAGE-FETCH-WITH-MESSAGE-ACTIONS + - STORAGE-HISTORY-WITH-INCLUDE-MESSAGE-TYPE + - STORAGE-HISTORY-WITH-INCLUDE-UUID + - STORAGE-FETCH-WITH-INCLUDE-MESSAGE-TYPE + - STORAGE-FETCH-WITH-INCLUDE-UUID subscribe: - SUBSCRIBE-CHANNELS - SUBSCRIBE-CHANNEL-GROUPS @@ -266,4 +284,4 @@ supported-platforms: platforms: - "Dart SDK >=2.6.0 <3.0.0" version: "PubNub Dart SDK" -version: "1.4.3" +version: "1.4.4" diff --git a/CHANGELOG.md b/CHANGELOG.md index ef75544e..8c4f2e1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [v1.4.4](https://github.com/pubnub/dart/releases/tag/v1.4.4) +August 19 2020 + +[Full Changelog](https://github.com/pubnub/dart/compare/v1.4.3...v1.4.4) + +- 🌟️ Add flags in history v3 for including messageType and uuid. +- 🌟️ Add support for fetch history with message actions. Fixed the following issues reported by [@edissonaguilar](https://github.com/edissonaguilar): [#12](https://github.com/pubnub/dart/issues/12). +- ⭐️️ Refactor for error message parsing for files. + ## [v1.4.3](https://github.com/pubnub/dart/releases/tag/v1.4.3) August 5 2020 diff --git a/lib/pubnub.dart b/lib/pubnub.dart index 7530972d..5ac8ac6f 100644 --- a/lib/pubnub.dart +++ b/lib/pubnub.dart @@ -17,6 +17,7 @@ export './src/dx/_endpoints/file.dart' PublishFileMessageResult, ListFilesResult, DeleteFileResult, + FileDetail, DownloadFileResult; export './src/dx/_endpoints/presence.dart' show HeartbeatResult, LeaveResult, HereNowResult, StateInfo; @@ -25,6 +26,13 @@ export './src/dx/_endpoints/channel_group.dart' ChannelGroupChangeChannelsResult, ChannelGroupListChannelsResult, ChannelGroupDeleteResult; +export './src/dx/_endpoints/history.dart' + show + FetchHistoryResult, + BatchHistoryResult, + BatchHistoryResultEntry, + CountMessagesResult, + DeleteMessagesResult; export './src/dx/_endpoints/signal.dart' show SignalResult; export './src/dx/_endpoints/push.dart' show diff --git a/lib/src/core/core.dart b/lib/src/core/core.dart index edf4d937..250a87b1 100644 --- a/lib/src/core/core.dart +++ b/lib/src/core/core.dart @@ -23,7 +23,7 @@ class Core { ParserModule parser; CryptoModule crypto; - static String version = '1.4.3'; + static String version = '1.4.4'; Core( {Keyset defaultKeyset, diff --git a/lib/src/dx/_endpoints/history.dart b/lib/src/dx/_endpoints/history.dart index a6842737..1c3fde3e 100644 --- a/lib/src/dx/_endpoints/history.dart +++ b/lib/src/dx/_endpoints/history.dart @@ -1,5 +1,7 @@ import 'package:pubnub/src/core/core.dart'; import 'package:pubnub/src/dx/_utils/utils.dart'; +import 'package:pubnub/src/dx/subscribe/envelope.dart' + show MessageType, fromInt; typedef decryptFunction = List Function(CipherKey key, String data); @@ -78,16 +80,26 @@ class BatchHistoryParams extends Parameters { Timetoken start; Timetoken end; bool includeMeta; + bool includeMessageActions; + bool includeUUID; + bool includeMessageType; BatchHistoryParams(this.keyset, this.channels, - {this.max, this.reverse, this.start, this.end, this.includeMeta}) + {this.max, + this.reverse, + this.start, + this.end, + this.includeMeta, + this.includeMessageActions, + this.includeMessageType, + this.includeUUID}) : assert(channels.isNotEmpty); @override Request toRequest() { var pathSegments = [ 'v3', - 'history', + includeMessageActions == true ? 'history-with-actions' : 'history', 'sub-key', keyset.subscribeKey, 'channel', @@ -100,6 +112,9 @@ class BatchHistoryParams extends Parameters { if (start != null) 'start': '$start', if (end != null) 'end': '$end', if (includeMeta != null) 'include-_meta': '$includeMeta', + if (includeMessageType != null) + 'include_message_type': '{$includeMessageType}', + if (includeUUID != null) 'include_uuid': '{$includeUUID}', if (keyset.authKey != null) 'auth': '${keyset.authKey}', if (keyset.uuid != null) 'uuid': '${keyset.uuid}' }; @@ -112,6 +127,9 @@ class BatchHistoryParams extends Parameters { class BatchHistoryResultEntry { dynamic message; Timetoken timetoken; + String uuid; + MessageType messageType; + Map actions; BatchHistoryResultEntry._(); @@ -119,29 +137,53 @@ class BatchHistoryResultEntry { {CipherKey cipherKey, Function decryptFunction}) { return BatchHistoryResultEntry._() ..timetoken = Timetoken(object['timestamp'] as int) + ..uuid = object['uuid'] + ..messageType = (object['message_type'] is int) + ? fromInt(object['message_type']) + : null ..message = cipherKey == null ? object['message'] - : decryptFunction(cipherKey, object['message']); + : decryptFunction(cipherKey, object['message']) + ..actions = object['actions']; } } class BatchHistoryResult extends Result { Map> channels; + MoreHistory more; - BatchHistoryResult._(); + BatchHistoryResult(); factory BatchHistoryResult.fromJson(Map object, {CipherKey cipherKey, Function decryptFunction}) { var result = DefaultResult.fromJson(object); - return BatchHistoryResult._() + return BatchHistoryResult() ..channels = (result.otherKeys['channels'] as Map).map( (key, value) => MapEntry( key, (value as List) .map((entry) => BatchHistoryResultEntry.fromJson(entry, cipherKey: cipherKey, decryptFunction: decryptFunction)) - .toList())); + .toList())) + ..more = result.otherKeys['more'] != null + ? MoreHistory.fromJson(result.otherKeys['more']) + : null; + } +} + +class MoreHistory { + String url; + String start; + int count; + + MoreHistory(); + + factory MoreHistory.fromJson(dynamic object) { + return MoreHistory() + ..url = object['url'] as String + ..start = object['start'] as String + ..count = object['limit'] as int; } } diff --git a/lib/src/dx/_utils/custom_flow.dart b/lib/src/dx/_utils/custom_flow.dart index 9662c9d2..e13ac1c1 100644 --- a/lib/src/dx/_utils/custom_flow.dart +++ b/lib/src/dx/_utils/custom_flow.dart @@ -1,3 +1,5 @@ +import 'dart:convert' show utf8; +import 'package:xml/xml.dart' show XmlDocument; import 'package:meta/meta.dart'; import 'package:pubnub/src/core/core.dart'; @@ -21,12 +23,17 @@ Future customFlow

( return result; } on PubNubRequestFailureException catch (exception) { - var error = await core.parser.decode(exception.responseData); - - if (error is Map) { - error = DefaultResult.fromJson(error); + var responseData = exception.responseData; + if (responseData.data != null) { + var details = utf8.decode(exception.responseData.data); + var messageNode = + XmlDocument.parse(details).rootElement.getElement('Message'); + if (messageNode != null) { + details = messageNode.text; + } + throw PubNubException( + '${responseData.statusCode}\n${responseData.statusMessage}\n${exception.message}\n$details'); } - - throw getExceptionFromAny(error); + throw PubNubException('${responseData.statusCode}'); } } diff --git a/lib/src/dx/_utils/ensure.dart b/lib/src/dx/_utils/ensure.dart index 3849ce89..4f92ba73 100644 --- a/lib/src/dx/_utils/ensure.dart +++ b/lib/src/dx/_utils/ensure.dart @@ -47,6 +47,6 @@ class Ensure { return; } - throw InvariantException('is-equal', what); + throw InvariantException('is-equal', what, ['$otherValue']); } } diff --git a/lib/src/dx/batch/batch.dart b/lib/src/dx/batch/batch.dart index d5676fef..7935e983 100644 --- a/lib/src/dx/batch/batch.dart +++ b/lib/src/dx/batch/batch.dart @@ -1,3 +1,4 @@ +import 'package:pubnub/pubnub.dart'; import 'package:pubnub/src/core/core.dart'; import 'package:pubnub/src/dx/_utils/utils.dart'; import 'package:pubnub/src/dx/_endpoints/history.dart'; @@ -13,25 +14,57 @@ class BatchDx { Future fetchMessages(Set channels, {Keyset keyset, String using, - int count, + int count = 25, Timetoken start, Timetoken end, bool reverse, - bool includeMeta}) async { + bool includeMeta, + bool includeMessageActions = false, + bool includeMessageType = true, + bool includeUUID = true}) async { keyset ??= _core.keysets.get(using, defaultIfNameIsNull: true); - return defaultFlow( - logger: _logger, - core: _core, - params: BatchHistoryParams(keyset, channels, - max: count, - start: start, - end: end, - reverse: reverse, - includeMeta: includeMeta), - serialize: (object, [_]) => BatchHistoryResult.fromJson(object, - cipherKey: keyset.cipherKey, - decryptFunction: _core.crypto.decrypt)); + if (includeMessageActions == true) { + Ensure(channels.length).isEqual(1, + 'History can return actions data for a single channel only. Either pass a single channel or disable the includeMessageActions flag.'); + } + var fetchMessagesResult = BatchHistoryResult()..channels = {}; + BatchHistoryResult loopResult; + do { + loopResult = await defaultFlow( + logger: _logger, + core: _core, + params: BatchHistoryParams(keyset, channels, + max: count, + start: start, + end: end, + reverse: reverse, + includeMeta: includeMeta, + includeMessageActions: includeMessageActions, + includeMessageType: includeMessageType, + includeUUID: includeUUID), + serialize: (object, [_]) => BatchHistoryResult.fromJson(object, + cipherKey: keyset.cipherKey, + decryptFunction: _core.crypto.decrypt)); + loopResult.channels.forEach((channel, messages) => { + if (fetchMessagesResult.channels[channel] == null) + { + fetchMessagesResult.channels[channel] = + loopResult.channels[channel] + } + else + { + fetchMessagesResult.channels[channel] + .addAll(loopResult.channels[channel]) + } + }); + if (loopResult.more != null) { + var moreHistory = loopResult.more; + start = Timetoken(int.parse(moreHistory.start)); + count = moreHistory.count; + } + } while (loopResult.more != null); + return fetchMessagesResult; } /// Get multiple channels' message count using one REST call. diff --git a/lib/src/dx/message_action/message_action.dart b/lib/src/dx/message_action/message_action.dart index 0e9b4ec2..bf88c30c 100644 --- a/lib/src/dx/message_action/message_action.dart +++ b/lib/src/dx/message_action/message_action.dart @@ -76,6 +76,7 @@ mixin MessageActionDx on Core { Ensure(type).isNotEmpty('message action type'); Ensure(value).isNotEmpty('message action value'); Ensure(timetoken).isNotNull('message timetoken'); + Ensure(keyset.uuid).isNotNull('uuid'); var addMessageActionBody = await super.parser.encode({'type': type, 'value': value}); diff --git a/lib/src/net/net.dart b/lib/src/net/net.dart index 0840c958..d91a2722 100644 --- a/lib/src/net/net.dart +++ b/lib/src/net/net.dart @@ -155,8 +155,7 @@ class CustomRequestHandler extends RequestHandler { _contents.completeError(PubNubRequestTimeoutException()); break; case DioErrorType.RESPONSE: - _contents - .completeError(PubNubRequestFailureException(e.response.data)); + _contents.completeError(PubNubRequestFailureException(e.response)); break; case DioErrorType.DEFAULT: default: diff --git a/pubspec.lock b/pubspec.lock index 3f5cedfe..426d3b96 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -196,7 +196,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.2.2" mime: dependency: transitive description: @@ -260,6 +260,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" pointycastle: dependency: transitive description: @@ -414,6 +421,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + xml: + dependency: "direct main" + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6152abc1..e37acc0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pubnub description: PubNub SDK v5 for Dart lang (with Flutter support) that allows you to create real-time applications -version: 1.4.3 +version: 1.4.4 homepage: https://www.pubnub.com/docs environment: @@ -14,6 +14,7 @@ dependencies: cbor: ^3.1.0 encrypt: ^4.0.2 convert: ^2.0.0 + xml: ^4.3.0 dev_dependencies: pedantic: 1.9.0 test: 1.11.1 diff --git a/test/dx/fixtures/history.dart b/test/dx/fixtures/history.dart index 1fb155b5..398add89 100644 --- a/test/dx/fixtures/history.dart +++ b/test/dx/fixtures/history.dart @@ -13,3 +13,105 @@ final _batchCountMessagesSuccessResponse = '''{ "error_message": "", "channels": {"test-1": 42, "test-2": 10} }'''; + +final _batchFetchMessagesWithActionSuccessResponse = '''{ + "status": 200, + "error": false, + "error_message": "", + "channels": { + "demo-channel": [ + { + "message": "Hi", + "timetoken": 15610547826970040, + "actions": { + "receipt": { + "read": [ + { + "uuid": "user-7", + "actionTimetoken": 15610547826970044 + } + ] + } + } + }, + { + "message": "Hello", + "timetoken": 15610547826970000, + "actions": { + "reaction": { + "smiley_face": [ + { + "uuid": "user-456", + "actionTimetoken": 15610547826970050 + } + ], + "poop_pile": [ + { + "uuid": "user-789", + "actionTimetoken": 15610547826980050 + }, + { + "uuid": "user-567", + "actionTimetoken": 15610547826970000 + } + ] + } + } + } + ] + } +}'''; + +final _batchFetchMessagesWithActionsWithMore = '''{ + "status": 200, + "error": false, + "error_message": "", + "channels": { + "demo-channel": [ + { + "message": "Hi", + "timetoken": 15610547826970040, + "actions": { + "receipt": { + "read": [ + { + "uuid": "user-7", + "actionTimetoken": 15610547826970044 + } + ] + } + } + }, + { + "message": "Hello", + "timetoken": 15610547826970000, + "actions": { + "reaction": { + "smiley_face": [ + { + "uuid": "user-456", + "actionTimetoken": 15610547826970050 + } + ], + "poop_pile": [ + { + "uuid": "user-789", + "actionTimetoken": 15610547826980050 + }, + { + "uuid": "user-567", + "actionTimetoken": 15610547826970000 + } + ] + } + } + } + ] + }, + "more": { + "url": "/v1/history-with-actions/s/channel/c?start=15610547826970000&limit=98", + "start": "15610547826970000", + "limit": 98 + } +} +'''; diff --git a/test/dx/history_test.dart b/test/dx/history_test.dart index 17dd2f88..5daca097 100644 --- a/test/dx/history_test.dart +++ b/test/dx/history_test.dart @@ -1,7 +1,6 @@ import 'package:test/test.dart'; import 'package:pubnub/pubnub.dart'; -import 'package:pubnub/src/dx/_endpoints/history.dart'; import '../net/fake_net.dart'; part './fixtures/history.dart'; @@ -18,7 +17,7 @@ void main() { test('.batch#fetchMessages correctly fetches messages', () async { when( path: - 'v3/history/sub-key/test/channel/test-1,test-2?max=10&pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v3/history/sub-key/test/channel/test-1,test-2?max=10&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', method: 'GET', ).then(status: 200, body: _batchFetchMessagesSuccessResponse); @@ -47,5 +46,76 @@ void main() { expect(result.channels['test-1'], equals(42)); expect(result.channels['test-2'], equals(10)); }); + + test('.batch#fetchMessages with messageActions', () async { + when( + path: + 'v3/history-with-actions/sub-key/test/channel/demo-channel?max=10&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', + method: 'GET', + ).then(status: 200, body: _batchFetchMessagesWithActionSuccessResponse); + + var result = await pubnub.batch.fetchMessages({'demo-channel'}, + includeMessageActions: true, count: 10); + + expect(result.channels['demo-channel'], + isA>()); + expect(result.channels['demo-channel'][0].actions, + isA>()); + expect(result.channels['demo-channel'][0].actions['receipt']['read'], + isA()); + }); + test('.batch#fetchMessagesWith Message Actions for multiple channels', + () async { + when( + path: + 'v3/history-with-actions/sub-key/test/channel/demo-channel?max=10&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', + method: 'GET', + ).then(status: 200, body: _batchFetchMessagesWithActionsWithMore); + + expect( + pubnub.batch.fetchMessages({'demo-channel', 'channel_2'}, + includeMessageActions: true, count: 10), + throwsA(TypeMatcher())); + }); + test('.batch#fetchMessages with messageActions', () async { + when( + path: + 'v3/history-with-actions/sub-key/test/channel/demo-channel?max=10&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', + method: 'GET', + ).then(status: 200, body: _batchFetchMessagesWithActionSuccessResponse); + + var result = await pubnub.batch.fetchMessages({'demo-channel'}, + includeMessageActions: true, count: 10); + + expect(result.channels['demo-channel'], + isA>()); + expect(result.channels['demo-channel'][0].actions, + isA>()); + expect(result.channels['demo-channel'][0].actions['receipt']['read'], + isA()); + }); + + test('.batch#fetchMessages with more messages', () async { + when( + path: + 'v3/history-with-actions/sub-key/test/channel/demo-channel?max=10&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', + method: 'GET', + ).then(status: 200, body: _batchFetchMessagesWithActionsWithMore); + + when( + path: + 'v3/history-with-actions/sub-key/test/channel/demo-channel?max=98&start=15610547826970000&include_message_type=%7Btrue%7D&include_uuid=%7Btrue%7D&pnsdk=PubNub-Dart%2F${PubNub.version}', + method: 'GET', + ).then(status: 200, body: _batchFetchMessagesWithActionSuccessResponse); + + var result = await pubnub.batch.fetchMessages({'demo-channel'}, + includeMessageActions: true, count: 10); + + expect(result.channels['demo-channel'], + isA>()); + expect(result.channels['demo-channel'].length, equals(4)); + expect(result.channels['demo-channel'][1].actions['reaction'].length, + equals(2)); + }); }); } diff --git a/test/dx/message_action_test.dart b/test/dx/message_action_test.dart index 03d7e0a8..5fccfa61 100644 --- a/test/dx/message_action_test.dart +++ b/test/dx/message_action_test.dart @@ -14,8 +14,13 @@ void main() { group('DX [messageAction]', () { setUp(() { pubnub = PubNub(networking: FakeNetworkingModule()) - ..keysets.add(Keyset(subscribeKey: 'test', publishKey: 'test'), - name: 'default', useAsDefault: true); + ..keysets.add( + Keyset( + subscribeKey: 'test', + publishKey: 'test', + uuid: UUID('test-uuid')), + name: 'default', + useAsDefault: true); }); test('add message action throws when type is empty', () async { var messageTimetoken = Timetoken(15610547826970050); @@ -60,7 +65,7 @@ void main() { when( method: 'POST', path: - 'v1/message-actions/test/channel/test/message/15610547826970050?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', body: _addMessageActionBody, ).then(status: 200, body: _addMessageActionResponse); expect( @@ -76,7 +81,7 @@ void main() { when( method: 'POST', path: - 'v1/message-actions/test/channel/test/message/15610547826970050?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', body: _addMessageActionBody, ).then(status: 200, body: _failedToPublishErrorResponse); var response = await pubnub.addMessageAction( @@ -91,7 +96,7 @@ void main() { when( method: 'POST', path: - 'v1/message-actions/test/channel/test/message/15610547826970050?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', body: _addMessageActionBody, ).then(status: 200, body: _invalidParameterErrorResponse); var response = await pubnub.addMessageAction( @@ -105,7 +110,7 @@ void main() { when( method: 'POST', path: - 'v1/message-actions/test/channel/test/message/15610547826970050?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', body: _addMessageActionBody, ).then(status: 200, body: _unauthorizeErrorResponse); var response = await pubnub.addMessageAction( @@ -206,7 +211,7 @@ void main() { when( method: 'DELETE', path: - 'v1/message-actions/test/channel/test/message/15610547826970050/action/15645905639093361?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050/action/15645905639093361?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', ).then(status: 200, body: _deleteMessageActionResponse); expect( @@ -222,7 +227,7 @@ void main() { when( method: 'DELETE', path: - 'v1/message-actions/test/channel/test/message/15610547826970050/action/15645905639093361?pnsdk=PubNub-Dart%2F${PubNub.version}', + 'v1/message-actions/test/channel/test/message/15610547826970050/action/15645905639093361?uuid=test-uuid&pnsdk=PubNub-Dart%2F${PubNub.version}', ).then(status: 200, body: _unauthorizeErrorResponse); var response = await pubnub.deleteMessageAction( channel, messageTimetoken, actionTimetoken);