|
| 1 | +import 'package:built_collection/built_collection.dart'; |
| 2 | +import 'package:collection/collection.dart'; |
| 3 | +import 'package:http/http.dart' as http; |
| 4 | +// ignore: implementation_imports |
| 5 | +import 'package:matcher/src/expect/async_matcher.dart'; |
| 6 | +import 'package:nextcloud/webdav.dart'; |
| 7 | +import 'package:nextcloud_test/src/models/models.dart'; |
| 8 | +import 'package:test/test.dart'; |
| 9 | +import 'package:xml/xml.dart'; |
| 10 | + |
| 11 | +class _ContainsAllAvailableProps extends AsyncMatcher { |
| 12 | + _ContainsAllAvailableProps( |
| 13 | + this.tester, |
| 14 | + this.uri, |
| 15 | + ); |
| 16 | + |
| 17 | + final NextcloudTester tester; |
| 18 | + final PathUri uri; |
| 19 | + |
| 20 | + @override |
| 21 | + Description describe(Description description) { |
| 22 | + return description; |
| 23 | + } |
| 24 | + |
| 25 | + @override |
| 26 | + Future<String?> matchAsync(dynamic item) async { |
| 27 | + if (item is! XmlElement) { |
| 28 | + return 'Expected XmlElement, got ${item.runtimeType}.'; |
| 29 | + } |
| 30 | + |
| 31 | + final parsedProps = _getMultistatusPropNames(item); |
| 32 | + if (parsedProps.isEmpty) { |
| 33 | + return 'Parsed props were empty'; |
| 34 | + } |
| 35 | + |
| 36 | + final streamedResponse = await tester.client.webdav.httpClient.send(tester.client.webdav.propfind_Request(uri)); |
| 37 | + if (streamedResponse.statusCode != 207) { |
| 38 | + return 'PROPFIND response status code was not 207'; |
| 39 | + } |
| 40 | + final rawResponse = await http.Response.fromStream(streamedResponse); |
| 41 | + |
| 42 | + final expectedProps = _getMultistatusPropNames(XmlDocument.parse(rawResponse.body).rootElement); |
| 43 | + if (expectedProps.isEmpty) { |
| 44 | + return 'Expected props were empty'; |
| 45 | + } |
| 46 | + |
| 47 | + if (parsedProps != expectedProps) { |
| 48 | + return 'Missing props: ${expectedProps.where((p) => !parsedProps.contains(p)).join(', ')}'; |
| 49 | + } |
| 50 | + |
| 51 | + return null; |
| 52 | + } |
| 53 | + |
| 54 | + BuiltList<String> _getMultistatusPropNames(XmlElement root) { |
| 55 | + return root.firstElementChild!.childElements |
| 56 | + .singleWhere( |
| 57 | + (node) => |
| 58 | + node.name.local == 'propstat' && |
| 59 | + node.childElements.singleWhere((node) => node.name.local == 'status').innerText.contains('200 OK'), |
| 60 | + ) |
| 61 | + .childElements |
| 62 | + .singleWhere((node) => node.name.local == 'prop') |
| 63 | + .childElements |
| 64 | + .map((el) => '{${el.name.namespaceUri}}${el.name.local}') |
| 65 | + .toList() |
| 66 | + .sorted() |
| 67 | + .toBuiltList(); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +/// Checks that all props have been parsed, by comparing them to a raw PROPFIND response of a request to [uri]. |
| 72 | +Matcher containsAllAvailableProps(NextcloudTester tester, PathUri uri) => _ContainsAllAvailableProps(tester, uri); |
0 commit comments