@Retry(3) library news_test; import 'dart:async'; import 'dart:io'; import 'package:nextcloud/nextcloud.dart'; import 'package:test/test.dart'; import 'helper.dart'; void main() { group('news', () { late DockerImage image; late HttpServer rssServer; setUpAll(() async { image = await getDockerImage(); rssServer = await getRssServer(); }); tearDownAll(() async => rssServer.close(force: true)); late DockerContainer container; late TestNextcloudClient client; setUp(() async { container = await getDockerContainer(image); client = await getTestClient(container); }); tearDown(() => container.destroy()); Future addWikipediaFeed([final int? folderID]) async => client.news.addFeed( url: 'http://host.docker.internal:${rssServer.port}/wikipedia.xml', folderId: folderID, ); Future addNasaFeed() async => client.news.addFeed( url: 'http://host.docker.internal:${rssServer.port}/nasa.xml', ); test('Is supported', () async { final (supported, _) = await client.news.isSupported(); expect(supported, isTrue); }); test('Add feed', () async { var response = await client.news.listFeeds(); expect(response.starredCount, 0); expect(response.newestItemId, null); expect(response.feeds, hasLength(0)); response = await addWikipediaFeed(); expect(response.starredCount, null); expect(response.newestItemId, isNotNull); expect(response.feeds, hasLength(1)); expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); response = await client.news.listFeeds(); expect(response.starredCount, 0); expect(response.newestItemId, isNotNull); expect(response.feeds, hasLength(1)); expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); }); test('Rename feed', () async { var response = await addWikipediaFeed(); expect(response.feeds[0].title, 'Wikipedia featured articles feed'); await client.news.renameFeed( feedId: 1, feedTitle: 'test1', ); response = await client.news.listFeeds(); expect(response.feeds[0].title, 'test1'); }); test('Move feed to folder', () async { await client.news.createFolder(name: 'test1'); await addWikipediaFeed(); await client.news.moveFeed( feedId: 1, folderId: 1, ); final response = await client.news.listFolders(); expect(response.folders, hasLength(1)); expect(response.folders[0].id, 1); expect(response.folders[0].name, 'test1'); expect(response.folders[0].opened, true); expect(response.folders[0].feeds, hasLength(0)); }); test('Mark feed as read', () async { final feedsResponse = await addWikipediaFeed(); var articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); expect(articlesResponse.items.length, greaterThan(0)); await client.news.markFeedAsRead( feedId: feedsResponse.feeds[0].id, newestItemId: feedsResponse.newestItemId!, ); articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); expect(articlesResponse.items, hasLength(0)); }); test('List articles', () async { var response = await client.news.listArticles(); expect(response.items, hasLength(0)); await addWikipediaFeed(); response = await client.news.listArticles(); expect(response.items.length, greaterThan(0)); expect(response.items[0].body, isNotNull); expect(response.items[0].feedId, 1); expect(response.items[0].unread, true); expect(response.items[0].starred, false); }); test('List updated articles', () async { // Testing this is not easy, because we can't depend on an external source to update the feed // Therefore we just add a second feed and check that the articles returned after a certain modified timestamp // are exactly those of the new feed. // Now that I think of it, maybe we could host our own feed and update that way, but this works for now. await addWikipediaFeed(); var response = await client.news.listArticles(); final wikipediaArticles = response.items.length; expect(wikipediaArticles, greaterThan(0)); await addNasaFeed(); response = await client.news.listArticles(); final nasaArticles = response.items.length - wikipediaArticles; expect(nasaArticles, greaterThan(0)); response = await client.news.listUpdatedArticles( lastModified: response.items[response.items.length - 1 - nasaArticles].lastModified, ); expect(response.items, hasLength(nasaArticles)); }); test('Mark article as read', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.unread.index); final unreadArticles = response.items.length; expect(unreadArticles, greaterThan(0)); await client.news.markArticleAsRead( itemId: response.items[0].id, ); response = await client.news.listArticles(type: NewsListType.unread.index); expect(response.items, hasLength(unreadArticles - 1)); }); test('Mark article as unread', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.unread.index); final readArticle = response.items[0]; await client.news.markArticleAsRead(itemId: readArticle.id); response = await client.news.listArticles(type: NewsListType.unread.index); final unreadArticles = response.items.length; expect(unreadArticles, greaterThan(0)); await client.news.markArticleAsUnread(itemId: readArticle.id); response = await client.news.listArticles(type: NewsListType.unread.index); expect(response.items, hasLength(unreadArticles + 1)); }); test('Star article', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.starred.index); final starredArticles = response.items.length; expect(starredArticles, 0); response = await client.news.listArticles(); await client.news.starArticle( itemId: response.items[0].id, ); response = await client.news.listArticles(type: NewsListType.starred.index); expect(response.items, hasLength(1)); }); test('Unstar article', () async { await addWikipediaFeed(); var response = await client.news.listArticles(); final item = response.items[0]; await client.news.starArticle( itemId: item.id, ); response = await client.news.listArticles(type: NewsListType.starred.index); expect(response.items, hasLength(1)); await client.news.unstarArticle( itemId: item.id, ); response = await client.news.listArticles(type: NewsListType.starred.index); expect(response.items, hasLength(0)); }); test('Create folder', () async { var response = await client.news.listFolders(); expect(response.folders, hasLength(0)); response = await client.news.createFolder(name: 'test1'); expect(response.folders, hasLength(1)); expect(response.folders[0].id, 1); expect(response.folders[0].name, 'test1'); expect(response.folders[0].opened, true); expect(response.folders[0].feeds, hasLength(0)); response = await client.news.listFolders(); expect(response.folders, hasLength(1)); expect(response.folders[0].id, 1); expect(response.folders[0].name, 'test1'); expect(response.folders[0].opened, true); expect(response.folders[0].feeds, hasLength(0)); }); test('List folders', () async { var response = await client.news.listFolders(); expect(response.folders, hasLength(0)); await client.news.createFolder(name: 'test1'); await client.news.createFolder(name: 'test2'); response = response = await client.news.listFolders(); expect(response.folders, hasLength(2)); expect(response.folders[0].id, 1); expect(response.folders[0].name, 'test1'); expect(response.folders[0].opened, true); expect(response.folders[0].feeds, hasLength(0)); expect(response.folders[1].id, 2); expect(response.folders[1].name, 'test2'); expect(response.folders[1].opened, true); expect(response.folders[1].feeds, hasLength(0)); }); test('Add feed to folder', () async { await client.news.createFolder(name: 'test1'); final response = await addWikipediaFeed(1); expect(response.starredCount, null); expect(response.newestItemId, isNotNull); expect(response.feeds, hasLength(1)); expect(response.feeds[0].folderId, 1); expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); }); test('Mark folder as read', () async { final foldersResponse = await client.news.createFolder(name: 'test1'); final feedsResponse = await addWikipediaFeed(1); var articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); expect(articlesResponse.items.length, greaterThan(0)); await client.news.markFolderAsRead( folderId: foldersResponse.folders[0].id, newestItemId: feedsResponse.newestItemId!, ); articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); expect(articlesResponse.items, hasLength(0)); }); }); } Future getRssServer() async { final wikipediaRss = File('test/files/wikipedia.xml').readAsStringSync(); final nasaRss = File('test/files/nasa.xml').readAsStringSync(); while (true) { try { final port = randomPort(); final server = await HttpServer.bind(InternetAddress.anyIPv6, port); unawaited( server.forEach((final request) async { switch (request.uri.path) { case '/wikipedia.xml': request.response.write(wikipediaRss); case '/nasa.xml': request.response.write(nasaRss); default: request.response.statusCode = HttpStatus.badRequest; } await request.response.close(); }), ); return server; } catch (_) {} } }