diff --git a/test/core/discovery_test.dart b/test/core/discovery_test.dart index e3f206a9..98286c5b 100644 --- a/test/core/discovery_test.dart +++ b/test/core/discovery_test.dart @@ -25,6 +25,8 @@ final directoryTestUri1 = Uri.parse('$testUriScheme://[::3]/.well-known/wot'); final directoryTestThingsUri1 = Uri.parse('$testUriScheme://[::3]/things'); final directoryTestUri2 = Uri.parse('$testUriScheme://[::4]/.well-known/wot'); final directoryTestThingsUri2 = Uri.parse('$testUriScheme://[::4]/things'); +final directoryTestUri3 = Uri.parse('$testUriScheme://[::5]/.well-known/wot'); +final directoryTestThingsUri3 = Uri.parse('$testUriScheme://[::5]/things'); const validTestTitle1 = 'Test TD 1'; const validTestThingDescription = ''' @@ -63,7 +65,7 @@ final directoryThingDescription1 = ''' } '''; -const validDirectoryTestTitle2 = 'Test TD 2'; +const validDirectoryTestTitle2 = 'Test TD 3'; final directoryThingDescription2 = ''' { "@context": [ @@ -88,119 +90,36 @@ final directoryThingDescription2 = ''' } '''; +const validDirectoryTestTitle3 = 'Test TD 2'; +final directoryThingDescription3 = ''' +{ + "@context": [ + "https://www.w3.org/2022/wot/td/v1.1", + "https://www.w3.org/2022/wot/discovery" + ], + "@type": "ThingDirectory", + "title": "$validDirectoryTestTitle3", + "security": "nosec_sc", + "securityDefinitions": { + "nosec_sc": {"scheme": "nosec"} + }, + "properties": { + "things": { + "forms": [ + { + "href": "$directoryTestThingsUri3" + } + ] + } + } +} +'''; + const invalidTestThingDescription1 = '"Hi there!"'; const invalidTestThingDescription2 = ''' {"foo": "bar"} '''; -void main() { - group('requestThingDescription()', () { - test('should be able to retrieve a valid TD', () async { - final servient = Servient( - clientFactories: [ - _MockedProtocolClientFactory(), - ], - ); - - final wot = await servient.start(); - final thingDescription = - await wot.requestThingDescription(validTestDiscoveryUri); - - expect(thingDescription.title, validTestTitle1); - }); - - test( - 'should throw an exception when an invalid TD is retrieved', - () async { - final servient = Servient( - clientFactories: [ - _MockedProtocolClientFactory(), - ], - ); - - final wot = await servient.start(); - await expectLater( - wot.requestThingDescription(invalidTestDiscoveryUri), - // TODO: Refine error handling - throwsA(isA()), - ); - }, - ); - }); - - group('exploreDirectory()', () { - test('should be able to discover valid TDs from a TD directory', () async { - final servient = Servient( - clientFactories: [ - _MockedProtocolClientFactory(), - ], - ); - - final wot = await servient.start(); - final thingDiscoveryProcess = - await wot.exploreDirectory(directoryTestUri1); - - var counter = 0; - await for (final thingDescription in thingDiscoveryProcess) { - counter++; - expect(thingDescription.title, validTestTitle1); - } - expect(counter, 1); - expect(thingDiscoveryProcess.done, true); - }); - - test('should be able to handle invalid TDs during discovery', () async { - final servient = Servient( - clientFactories: [ - _MockedProtocolClientFactory(), - ], - ); - - final wot = await servient.start(); - final thingDiscoveryProcess = - await wot.exploreDirectory(directoryTestUri2); - - var counter = 0; - - final testCompleter = Completer(); - - thingDiscoveryProcess.listen( - (event) { - counter++; - }, - onError: (error, stackTrace) async {}, - onDone: () { - expect(counter, 0); - expect(thingDiscoveryProcess.done, true); - expect(thingDiscoveryProcess.error, isNotNull); - testCompleter.complete(); - }, - ); - - return testCompleter.future; - }); - - test('should be able to handle premature cancellation ', () async { - final servient = Servient( - clientFactories: [ - _MockedProtocolClientFactory(), - ], - ); - - final wot = await servient.start(); - final thingDiscoveryProcess = - await wot.exploreDirectory(directoryTestUri1); - - await thingDiscoveryProcess.stop(); - expect(thingDiscoveryProcess.done, true); - - // Cancelling twice should not change the state - await thingDiscoveryProcess.stop(); - expect(thingDiscoveryProcess.done, true); - }); - }); -} - class _MockedProtocolClient implements ProtocolClient { @override Stream discoverWithCoreLinkFormat(Uri uri) { @@ -225,6 +144,10 @@ class _MockedProtocolClient implements ProtocolClient { return '[$invalidTestThingDescription2]'.toContent('application/td+json'); } + if (href == directoryTestThingsUri3) { + return '$invalidTestThingDescription2'.toContent('application/td+json'); + } + throw StateError('Encountered an unknown URI $href.'); } @@ -246,6 +169,10 @@ class _MockedProtocolClient implements ProtocolClient { return directoryThingDescription2.toDiscoveryContent(url); } + if (url == directoryTestUri3) { + return directoryThingDescription3.toDiscoveryContent(url); + } + throw StateError('Encountered invalid URL.'); } @@ -317,3 +244,129 @@ extension _DiscoveryContentCreationExtension on String { return Content(type, _body); } } + +void main() { + group('requestThingDescription()', () { + test('should be able to retrieve a valid TD', () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + final thingDescription = + await wot.requestThingDescription(validTestDiscoveryUri); + + expect(thingDescription.title, validTestTitle1); + }); + + test( + 'should throw an exception when an invalid TD is retrieved', + () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + await expectLater( + wot.requestThingDescription(invalidTestDiscoveryUri), + // TODO: Refine error handling + throwsA(isA()), + ); + }, + ); + }); + + group('exploreDirectory()', () { + test('should be able to discover valid TDs from a TD directory', () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + final thingDiscoveryProcess = + await wot.exploreDirectory(directoryTestUri1); + + var counter = 0; + await for (final thingDescription in thingDiscoveryProcess) { + counter++; + expect(thingDescription.title, validTestTitle1); + } + expect(counter, 1); + expect(thingDiscoveryProcess.done, true); + }); + + test('should be able to handle an array of invalid TDs during discovery', + () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + final thingDiscoveryProcess = + await wot.exploreDirectory(directoryTestUri2); + + var counter = 0; + + final testCompleter = Completer(); + + thingDiscoveryProcess.listen( + (event) { + counter++; + }, + onError: (error, stackTrace) async {}, + onDone: () { + expect(counter, 0); + expect(thingDiscoveryProcess.done, true); + expect(thingDiscoveryProcess.error, isNotNull); + testCompleter.complete(); + }, + ); + + return testCompleter.future; + }); + + test( + 'should be able to handle an invalid non-array output during discovery', + () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + + expect( + () async => wot.exploreDirectory(directoryTestUri3), + throwsA(isException), + ); + }); + + test('should be able to handle premature cancellation', () async { + final servient = Servient( + clientFactories: [ + _MockedProtocolClientFactory(), + ], + ); + + final wot = await servient.start(); + final thingDiscoveryProcess = + await wot.exploreDirectory(directoryTestUri1); + + await thingDiscoveryProcess.stop(); + expect(thingDiscoveryProcess.done, true); + + // Cancelling twice should not change the state + await thingDiscoveryProcess.stop(); + expect(thingDiscoveryProcess.done, true); + }); + }); +}