Compare commits

..

3 Commits

Author SHA1 Message Date
renovate[bot] 275a130b0f
chore(deps): lock file maintenance (#1188) 1 year ago
Kate e22b6f3ca2
Merge pull request #1184 from nextcloud/test/nextcloud/version-check 1 year ago
jld3103 805db1a0fc
test(nextcloud): Ensure versions for version checks are parsed correctly 1 year ago
  1. 1
      commitlint.yaml
  2. 2
      cspell.json
  3. 60
      packages/app/pubspec.lock
  4. 4
      packages/nextcloud/pubspec.yaml
  5. 4
      packages/nextcloud/pubspec_overrides.yaml
  6. 11
      packages/nextcloud/test/core_test.dart
  7. 10
      packages/nextcloud/test/dashboard_test.dart
  8. 227
      packages/nextcloud/test/helper.dart
  9. 11
      packages/nextcloud/test/news_test.dart
  10. 11
      packages/nextcloud/test/notes_test.dart
  11. 26
      packages/nextcloud/test/notifications_test.dart
  12. 10
      packages/nextcloud/test/provisioning_api_test.dart
  13. 10
      packages/nextcloud/test/settings_test.dart
  14. 44
      packages/nextcloud/test/spreed_test.dart
  15. 10
      packages/nextcloud/test/uppush_test.dart
  16. 10
      packages/nextcloud/test/user_status_test.dart
  17. 23
      packages/nextcloud/test/webdav_test.dart
  18. 1
      packages/nextcloud_test/LICENSE
  19. 3
      packages/nextcloud_test/README.md
  20. 1
      packages/nextcloud_test/analysis_options.yaml
  21. 3
      packages/nextcloud_test/lib/nextcloud_test.dart
  22. 7
      packages/nextcloud_test/lib/src/defaults.dart
  23. 112
      packages/nextcloud_test/lib/src/docker_container.dart
  24. 79
      packages/nextcloud_test/lib/src/test_client.dart
  25. 21
      packages/nextcloud_test/pubspec.yaml
  26. 8
      packages/nextcloud_test/pubspec_overrides.yaml
  27. 2
      tool/Dockerfile.dev
  28. 2
      tool/build-dev-container.sh
  29. 0
      tool/dev/static/nasa.xml
  30. 0
      tool/dev/static/wikipedia.xml

1
commitlint.yaml

@ -25,5 +25,4 @@ rules:
- neon_notifications
- neon_lints
- nextcloud
- nextcloud_test
- sort_box

2
cspell.json

@ -14,7 +14,7 @@
"packages/dynamite/dynamite_petstore_example/lib",
"packages/file_icons/lib/src/data.dart",
"packages/neon_lints/lib",
"packages/nextcloud_test/docker/static"
"tool/dev/static"
],
"dictionaries": [
"bash",

60
packages/app/pubspec.lock

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
ansicolor:
dependency: transitive
description:
name: ansicolor
sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
archive:
dependency: transitive
description:
@ -61,10 +69,10 @@ packages:
dependency: transitive
description:
name: built_value
sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e"
sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2"
url: "https://pub.dev"
source: hosted
version: "8.7.0"
version: "8.8.0"
camera:
dependency: transitive
description:
@ -157,10 +165,10 @@ packages:
dependency: transitive
description:
name: cross_file
sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c"
sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5"
url: "https://pub.dev"
source: hosted
version: "0.3.3+6"
version: "0.3.3+7"
crypto:
dependency: transitive
description:
@ -349,10 +357,10 @@ packages:
dependency: transitive
description:
name: flutter_local_notifications
sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3"
sha256: bb5cd63ff7c91d6efe452e41d0d0ae6348925c82eafd10ce170ef585ea04776e
url: "https://pub.dev"
source: hosted
version: "16.1.0"
version: "16.2.0"
flutter_local_notifications_linux:
dependency: transitive
description:
@ -394,10 +402,10 @@ packages:
dependency: transitive
description:
name: flutter_native_splash
sha256: d93394f22f73e810bda59e11ebe83329c5511d6460b6b7509c4e1f3c92d6d625
sha256: c4d899312b36e7454bedfd0a4740275837b99e532d81c8477579d8183db1de6c
url: "https://pub.dev"
source: hosted
version: "2.3.5"
version: "2.3.6"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@ -822,42 +830,50 @@ packages:
dependency: transitive
description:
name: permission_handler
sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78"
url: "https://pub.dev"
source: hosted
version: "11.0.1"
version: "11.1.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6"
url: "https://pub.dev"
source: hosted
version: "11.1.0"
version: "12.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306"
url: "https://pub.dev"
source: hosted
version: "9.1.4"
version: "9.2.0"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: d96ff56a757b7f04fa825c469d296c5aebc55f743e87bd639fef91a466a24da8
url: "https://pub.dev"
source: hosted
version: "0.1.0+1"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1
url: "https://pub.dev"
source: hosted
version: "3.12.0"
version: "4.0.2"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
version: "0.2.0"
petitparser:
dependency: transitive
description:
@ -1314,10 +1330,10 @@ packages:
dependency: transitive
description:
name: url_launcher_web
sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2"
sha256: "138bd45b3a456dcfafc46d1a146787424f8d2edfbf2809c9324361e58f851cf7"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
version: "2.2.1"
url_launcher_windows:
dependency: transitive
description:
@ -1434,10 +1450,10 @@ packages:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f"
sha256: adb8c03c2be231bea5a8ed0e9039e9d18dbb049603376beaefa15393ede468a5
url: "https://pub.dev"
source: hosted
version: "2.6.0"
version: "2.7.0"
webview_flutter_wkwebview:
dependency: transitive
description:

4
packages/nextcloud/pubspec.yaml

@ -37,10 +37,6 @@ dev_dependencies:
git:
url: https://github.com/nextcloud/neon
path: packages/neon_lints
nextcloud_test:
git:
url: https://github.com/nextcloud/neon
path: packages/nextcloud_test
path: ^1.8.3
process_run: ^0.13.3
test: ^1.24.9

4
packages/nextcloud/pubspec_overrides.yaml

@ -1,4 +1,4 @@
# melos_managed_dependency_overrides: dynamite,dynamite_runtime,neon_lints,nextcloud_test
# melos_managed_dependency_overrides: dynamite,dynamite_runtime,neon_lints
dependency_overrides:
dynamite:
path: ../dynamite/dynamite
@ -6,5 +6,3 @@ dependency_overrides:
path: ../dynamite/dynamite_runtime
neon_lints:
path: ../neon_lints
nextcloud_test:
path: ../nextcloud_test

11
packages/nextcloud/test/core_test.dart

@ -1,17 +1,18 @@
import 'package:nextcloud/core.dart' as core;
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'core',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());
@ -22,6 +23,8 @@ void main() {
expect(() => response.headers, isA<void>());
final result = client.core.getVersionCheck(response.body.ocs.data);
expect(result.versions, isNotNull);
expect(result.versions, isNotEmpty);
expect(result.isSupported, isTrue);
});

10
packages/nextcloud/test/dashboard_test.dart

@ -1,17 +1,17 @@
import 'package:nextcloud/dashboard.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'dashboard',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());

227
packages/nextcloud/test/helper.dart

@ -0,0 +1,227 @@
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:nextcloud/core.dart' as core;
import 'package:nextcloud/nextcloud.dart';
import 'package:process_run/cmd_run.dart';
import 'package:test/test.dart';
import 'package:universal_io/io.dart';
const retryCount = 3;
const timeout = Timeout(Duration(seconds: 30));
class DockerContainer {
DockerContainer({
required this.id,
required this.port,
});
final String id;
final int port;
Future<void> runOccCommand(final List<String> args) async {
final result = await runExecutableArguments(
'docker',
[
'exec',
id,
'php',
'-f',
'occ',
...args,
],
stdout: stdout,
stderr: stderr,
);
if (result.exitCode != 0) {
throw Exception('Failed to run occ command');
}
}
void destroy() => unawaited(
runExecutableArguments(
'docker',
[
'kill',
id,
],
),
);
Future<String> serverLogs() async => (await runExecutableArguments(
'docker',
[
'logs',
id,
],
stdoutEncoding: utf8,
))
.stdout as String;
Future<String> nextcloudLogs() async => (await runExecutableArguments(
'docker',
[
'exec',
id,
'cat',
'data/nextcloud.log',
],
stdoutEncoding: utf8,
))
.stdout as String;
Future<String> allLogs() async => '${await serverLogs()}\n\n${await nextcloudLogs()}';
}
class TestNextcloudClient extends NextcloudClient {
TestNextcloudClient(
super.baseURL, {
super.loginName,
super.password,
super.appPassword,
super.language,
super.appType,
super.userAgentOverride,
super.cookieJar,
});
}
Future<TestNextcloudClient> getTestClient(
final DockerContainer container, {
final String? username = 'user1',
final AppType appType = AppType.unknown,
final String? userAgentOverride,
}) async {
String? appPassword;
if (username != null) {
final inputStream = StreamController<List<int>>();
final process = runExecutableArguments(
'docker',
[
'exec',
'-i',
container.id,
'php',
'-f',
'occ',
'user:add-app-password',
username,
],
stdin: inputStream.stream,
);
inputStream.add(utf8.encode(username));
await inputStream.close();
final result = await process;
if (result.exitCode != 0) {
throw Exception('Failed to run generate app password command\n${result.stderr}\n${result.stdout}');
}
appPassword = (result.stdout as String).split('\n')[1];
}
final client = TestNextcloudClient(
Uri(
scheme: 'http',
host: 'localhost',
port: container.port,
),
loginName: username,
password: username,
appPassword: appPassword,
appType: appType,
userAgentOverride: userAgentOverride,
cookieJar: CookieJar(),
);
var i = 0;
while (true) {
try {
await client.core.getStatus();
break;
} catch (error) {
if (error is HttpException || error is DynamiteApiException) {
i++;
await Future<void>.delayed(const Duration(milliseconds: 100));
if (i >= 300) {
throw TimeoutException('Failed to get the status of the Server. $error');
}
} else {
rethrow;
}
}
}
return client;
}
Future<DockerContainer> getDockerContainer() async {
const dockerImageName = 'ghcr.io/nextcloud/neon/dev';
var result = await runExecutableArguments(
'docker',
[
'images',
'-q',
dockerImageName,
],
);
if (result.exitCode != 0) {
throw Exception('Querying docker image failed: ${result.stderr}');
}
if (result.stdout.toString().isEmpty) {
throw Exception('Missing docker image $dockerImageName. Please build it using ./tool/build-dev-container.sh');
}
late int port;
while (true) {
port = randomPort();
result = await runExecutableArguments(
'docker',
[
'run',
'--rm',
'-d',
'--add-host',
'host.docker.internal:host-gateway',
'-p',
'$port:80',
dockerImageName,
],
);
// 125 means the docker run command itself has failed which indicated the port is already used
if (result.exitCode != 125) {
break;
}
}
if (result.exitCode != 0) {
throw Exception('Failed to run docker container: ${result.stderr}');
}
return DockerContainer(
id: result.stdout.toString().replaceAll('\n', ''),
port: port,
);
}
class TestNextcloudUser {
TestNextcloudUser(
this.username,
this.password, {
this.displayName,
});
final String username;
final String password;
final String? displayName;
}
int randomPort() => 1024 + Random().nextInt(65535 - 1024);
void expectDateInReasonableTimeRange(final DateTime actual, final DateTime expected) {
const duration = Duration(seconds: 10);
expect(actual.isAfter(expected.subtract(duration)), isTrue);
expect(actual.isBefore(expected.add(duration)), isTrue);
}

11
packages/nextcloud/test/news_test.dart

@ -2,18 +2,19 @@ import 'dart:async';
import 'package:nextcloud/news.dart' as news;
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'news',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());
@ -29,6 +30,8 @@ void main() {
test('Is supported', () async {
final result = await client.news.getVersionCheck();
expect(result.versions, isNotNull);
expect(result.versions, isNotEmpty);
expect(result.isSupported, isTrue);
});

11
packages/nextcloud/test/notes_test.dart

@ -1,18 +1,19 @@
import 'package:nextcloud/core.dart' as core;
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/notes.dart' as notes;
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'notes',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());
@ -22,6 +23,8 @@ void main() {
expect(() => response.headers, isA<void>());
final result = client.notes.getVersionCheck(response.body.ocs.data);
expect(result.versions, isNotNull);
expect(result.versions, isNotEmpty);
expect(result.isSupported, isTrue);
});

26
packages/nextcloud/test/notifications_test.dart

@ -1,17 +1,17 @@
import 'dart:async';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/notifications.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group('notifications', () {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(
container = await getDockerContainer();
client = await getTestClient(
container,
username: 'admin',
);
@ -42,10 +42,7 @@ void main() {
expect(response.ocs.data[0].notificationId, 2);
expect(response.ocs.data[0].app, 'admin_notifications');
expect(response.ocs.data[0].user, 'admin');
expect(
DateTime.parse(response.ocs.data[0].datetime).millisecondsSinceEpoch,
closeTo(startTime.millisecondsSinceEpoch, 10E3),
);
expectDateInReasonableTimeRange(DateTime.parse(response.ocs.data[0].datetime), startTime);
expect(response.ocs.data[0].objectType, 'admin_notifications');
expect(response.ocs.data[0].objectId, isNotNull);
expect(response.ocs.data[0].subject, '123');
@ -70,10 +67,7 @@ void main() {
expect(response.body.ocs.data.notificationId, 2);
expect(response.body.ocs.data.app, 'admin_notifications');
expect(response.body.ocs.data.user, 'admin');
expect(
DateTime.parse(response.body.ocs.data.datetime).millisecondsSinceEpoch,
closeTo(startTime.millisecondsSinceEpoch, 10E3),
);
expectDateInReasonableTimeRange(DateTime.parse(response.body.ocs.data.datetime), startTime);
expect(response.body.ocs.data.objectType, 'admin_notifications');
expect(response.body.ocs.data.objectId, isNotNull);
expect(response.body.ocs.data.subject, '123');
@ -107,10 +101,10 @@ void main() {
group('Push', () {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(
container = await getDockerContainer();
client = await getTestClient(
container,
username: 'admin',
);

10
packages/nextcloud/test/provisioning_api_test.dart

@ -1,17 +1,17 @@
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/provisioning_api.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'provisioning_api',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(
container = await getDockerContainer();
client = await getTestClient(
container,
username: 'admin',
);

10
packages/nextcloud/test/settings_test.dart

@ -1,19 +1,19 @@
import 'dart:convert';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/settings.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'settings',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(
container = await getDockerContainer();
client = await getTestClient(
container,
username: 'admin',
);

44
packages/nextcloud/test/spreed_test.dart

@ -3,20 +3,20 @@ import 'dart:convert';
import 'package:built_value/json_object.dart';
import 'package:nextcloud/core.dart' as core;
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/spreed.dart' as spreed;
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'spreed',
() {
late DockerContainer container;
late NextcloudClient client1;
late TestNextcloudClient client1;
setUp(() async {
container = await DockerContainer.create();
client1 = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client1 = await getTestClient(container);
});
tearDown(() => container.destroy());
@ -35,6 +35,8 @@ void main() {
expect(() => response.headers, isA<void>());
final result = client1.spreed.getVersionCheck(response.body.ocs.data);
expect(result.versions, isNotNull);
expect(result.versions, isNotEmpty);
expect(result.isSupported, isTrue);
});
@ -183,7 +185,10 @@ void main() {
expect(response.body.ocs.data!.actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data!.actorId, 'user1');
expect(response.body.ocs.data!.actorDisplayName, 'User One');
expect(response.body.ocs.data!.timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data!.timestamp * 1000),
startTime,
);
expect(response.body.ocs.data!.message, 'bla');
expect(response.body.ocs.data!.messageType, spreed.MessageType.comment.name);
});
@ -224,7 +229,10 @@ void main() {
expect(response.body.ocs.data[0].actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data[0].actorId, 'user1');
expect(response.body.ocs.data[0].actorDisplayName, 'User One');
expect(response.body.ocs.data[0].timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].timestamp * 1000),
startTime,
);
expect(response.body.ocs.data[0].message, '123');
expect(response.body.ocs.data[0].messageType, spreed.MessageType.comment.name);
@ -232,7 +240,10 @@ void main() {
expect(response.body.ocs.data[0].parent!.actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data[0].parent!.actorId, 'user1');
expect(response.body.ocs.data[0].parent!.actorDisplayName, 'User One');
expect(response.body.ocs.data[0].parent!.timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].parent!.timestamp * 1000),
startTime,
);
expect(response.body.ocs.data[0].parent!.message, 'bla');
expect(response.body.ocs.data[0].parent!.messageType, spreed.MessageType.comment.name);
@ -240,7 +251,10 @@ void main() {
expect(response.body.ocs.data[1].actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data[1].actorId, 'user1');
expect(response.body.ocs.data[1].actorDisplayName, 'User One');
expect(response.body.ocs.data[1].timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[1].timestamp * 1000),
startTime,
);
expect(response.body.ocs.data[1].message, 'bla');
expect(response.body.ocs.data[1].messageType, spreed.MessageType.comment.name);
@ -248,7 +262,10 @@ void main() {
expect(response.body.ocs.data[2].actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data[2].actorId, 'user1');
expect(response.body.ocs.data[2].actorDisplayName, 'User One');
expect(response.body.ocs.data[2].timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[2].timestamp * 1000),
startTime,
);
expect(response.body.ocs.data[2].message, 'You created the conversation');
expect(response.body.ocs.data[2].systemMessage, 'conversation_created');
expect(response.body.ocs.data[2].messageType, spreed.MessageType.system.name);
@ -285,7 +302,10 @@ void main() {
expect(response.body.ocs.data[0].actorType, spreed.ActorType.users.name);
expect(response.body.ocs.data[0].actorId, 'user1');
expect(response.body.ocs.data[0].actorDisplayName, 'User One');
expect(response.body.ocs.data[0].timestamp * 1000, closeTo(startTime.millisecondsSinceEpoch, 10E3));
expectDateInReasonableTimeRange(
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].timestamp * 1000),
startTime,
);
expect(response.body.ocs.data[0].message, '123');
expect(response.body.ocs.data[0].messageType, spreed.MessageType.comment.name);
});
@ -359,7 +379,7 @@ void main() {
final room1 = (await client1.spreed.room.joinRoom(token: room.token)).body.ocs.data;
await client1.spreed.call.joinCall(token: room.token);
final client2 = await TestNextcloudClient.create(
final client2 = await getTestClient(
container,
username: 'user2',
);

10
packages/nextcloud/test/uppush_test.dart

@ -1,17 +1,17 @@
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/uppush.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'uppush',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(
container = await getDockerContainer();
client = await getTestClient(
container,
username: 'admin',
);

10
packages/nextcloud/test/user_status_test.dart

@ -1,17 +1,17 @@
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud/user_status.dart' as user_status;
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'helper.dart';
void main() {
group(
'user_status',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());

23
packages/nextcloud/test/webdav_test.dart

@ -3,10 +3,11 @@ import 'dart:math';
import 'dart:typed_data';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/nextcloud_test.dart';
import 'package:test/test.dart';
import 'package:universal_io/io.dart';
import 'helper.dart';
void main() {
group('constructUri', () {
for (final values in [
@ -138,11 +139,11 @@ void main() {
'webdav',
() {
late DockerContainer container;
late NextcloudClient client;
late TestNextcloudClient client;
setUp(() async {
container = await DockerContainer.create();
client = await TestNextcloudClient.create(container);
container = await getDockerContainer();
client = await getTestClient(container);
});
tearDown(() => container.destroy());
@ -280,18 +281,12 @@ void main() {
expect(response.isCollection, isTrue);
expect(response.mimeType, isNull);
expect(response.size, data.lengthInBytes);
expect(
response.lastModified!.millisecondsSinceEpoch,
closeTo(DateTime.now().millisecondsSinceEpoch, 10E3),
);
expectDateInReasonableTimeRange(response.lastModified!, DateTime.now());
expect(response.name, 'test');
expect(response.isDirectory, isTrue);
expect(response.props.davgetcontenttype, isNull);
expect(
webdavDateFormat.parseUtc(response.props.davgetlastmodified!).millisecondsSinceEpoch,
closeTo(DateTime.now().millisecondsSinceEpoch, 10E3),
);
expectDateInReasonableTimeRange(webdavDateFormat.parseUtc(response.props.davgetlastmodified!), DateTime.now());
expect(response.props.davresourcetype!.collection, isNotNull);
expect(response.props.ocsize, data.lengthInBytes);
});
@ -360,8 +355,8 @@ void main() {
.prop;
expect(props.ocfavorite, 1);
expect(webdavDateFormat.parseUtc(props.davgetlastmodified!), lastModifiedDate);
expect(props.nccreationtime! * 1000, createdDate.millisecondsSinceEpoch);
expect(props.ncuploadtime! * 1000, closeTo(uploadTime.millisecondsSinceEpoch, 10E3));
expect(DateTime.fromMillisecondsSinceEpoch(props.nccreationtime! * 1000).isAtSameMomentAs(createdDate), isTrue);
expectDateInReasonableTimeRange(DateTime.fromMillisecondsSinceEpoch(props.ncuploadtime! * 1000), uploadTime);
});
test('Remove properties', () async {

1
packages/nextcloud_test/LICENSE

@ -1 +0,0 @@
../../assets/AGPL-3.0.txt

3
packages/nextcloud_test/README.md

@ -1,3 +0,0 @@
# nextcloud_test
A helper package for running tests in the [nextcloud](../nextcloud) package.

1
packages/nextcloud_test/analysis_options.yaml

@ -1 +0,0 @@
include: package:neon_lints/dart.yaml

3
packages/nextcloud_test/lib/nextcloud_test.dart

@ -1,3 +0,0 @@
export 'src/defaults.dart';
export 'src/docker_container.dart';
export 'src/test_client.dart';

7
packages/nextcloud_test/lib/src/defaults.dart

@ -1,7 +0,0 @@
import 'package:test/test.dart';
/// Default retry count for test groups.
const retryCount = 3;
/// Default timeout for test groups.
const timeout = Timeout(Duration(seconds: 30));

112
packages/nextcloud_test/lib/src/docker_container.dart

@ -1,112 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:process_run/process_run.dart';
int _randomPort() => 1024 + Random().nextInt(65535 - 1024);
/// Represents a docker container on the system.
class DockerContainer {
DockerContainer._({
required this.id,
required this.port,
});
/// Creates a new docker container and returns its representation.
static Future<DockerContainer> create() async {
const dockerImageName = 'ghcr.io/nextcloud/neon/dev';
var result = await runExecutableArguments(
'docker',
[
'images',
'-q',
dockerImageName,
],
);
if (result.exitCode != 0) {
throw Exception('Querying docker image failed: ${result.stderr}');
}
if (result.stdout.toString().isEmpty) {
throw Exception('Missing docker image $dockerImageName. Please build it using ./tool/build-dev-container.sh');
}
late int port;
while (true) {
port = _randomPort();
result = await runExecutableArguments(
'docker',
[
'run',
'--rm',
'-d',
'--add-host',
'host.docker.internal:host-gateway',
'-p',
'$port:80',
dockerImageName,
],
);
// 125 means the docker run command itself has failed which indicated the port is already used
if (result.exitCode != 125) {
break;
}
}
if (result.exitCode != 0) {
throw Exception('Failed to run docker container: ${result.stderr}');
}
return DockerContainer._(
id: result.stdout.toString().replaceAll('\n', ''),
port: port,
);
}
/// ID of the docker container.
final String id;
/// Assigned port of docker container.
final int port;
/// Removes the docker container from the system.
void destroy() => unawaited(
runExecutableArguments(
'docker',
[
'kill',
id,
],
),
);
/// Reads the server logs.
Future<String> serverLogs() async => (await runExecutableArguments(
'docker',
[
'logs',
id,
],
stdoutEncoding: utf8,
))
.stdout as String;
/// Reads the Nextcloud logs.
Future<String> nextcloudLogs() async => (await runExecutableArguments(
'docker',
[
'exec',
id,
'cat',
'data/nextcloud.log',
],
stdoutEncoding: utf8,
))
.stdout as String;
/// Reads all logs.
///
/// Combines the output of [serverLogs] and [nextcloudLogs].
Future<String> allLogs() async => '${await serverLogs()}\n\n${await nextcloudLogs()}';
}

79
packages/nextcloud_test/lib/src/test_client.dart

@ -1,79 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'package:nextcloud/core.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/src/docker_container.dart';
import 'package:process_run/process_run.dart';
import 'package:universal_io/io.dart';
/// An extension for creating [NextcloudClient]s based on [DockerContainer]s.
extension TestNextcloudClient on NextcloudClient {
/// Creates a new [NextcloudClient] for a given [container] and [username].
///
/// It is expected that the password of the user matches the its [username].
/// This is the case for the available test docker containers.
static Future<NextcloudClient> create(
final DockerContainer container, {
final String? username = 'user1',
}) async {
String? appPassword;
if (username != null) {
final inputStream = StreamController<List<int>>();
final process = runExecutableArguments(
'docker',
[
'exec',
'-i',
container.id,
'php',
'-f',
'occ',
'user:add-app-password',
username,
],
stdin: inputStream.stream,
);
inputStream.add(utf8.encode(username));
await inputStream.close();
final result = await process;
if (result.exitCode != 0) {
throw Exception('Failed to run generate app password command\n${result.stderr}\n${result.stdout}');
}
appPassword = (result.stdout as String).split('\n')[1];
}
final client = NextcloudClient(
Uri(
scheme: 'http',
host: 'localhost',
port: container.port,
),
loginName: username,
password: username,
appPassword: appPassword,
cookieJar: CookieJar(),
);
var i = 0;
while (true) {
try {
await client.core.getStatus();
break;
} catch (error) {
if (error is HttpException || error is DynamiteApiException) {
i++;
await Future<void>.delayed(const Duration(milliseconds: 100));
if (i >= 300) {
throw TimeoutException('Failed to get the status of the Server. $error');
}
} else {
rethrow;
}
}
}
return client;
}
}

21
packages/nextcloud_test/pubspec.yaml

@ -1,21 +0,0 @@
name: nextcloud_test
version: 1.0.0
publish_to: none
environment:
sdk: '>=3.1.0 <4.0.0'
dependencies:
nextcloud:
git:
url: https://github.com/nextcloud/neon
path: packages/nextcloud
process_run: ^0.13.0
test: ^1.24.0
universal_io: ^2.0.0
dev_dependencies:
neon_lints:
git:
url: https://github.com/nextcloud/neon
path: packages/neon_lints

8
packages/nextcloud_test/pubspec_overrides.yaml

@ -1,8 +0,0 @@
# melos_managed_dependency_overrides: dynamite_runtime,neon_lints,nextcloud
dependency_overrides:
dynamite_runtime:
path: ../dynamite/dynamite_runtime
neon_lints:
path: ../neon_lints
nextcloud:
path: ../nextcloud

2
packages/nextcloud_test/docker/Dockerfile → tool/Dockerfile.dev

@ -18,7 +18,7 @@ RUN (sh /entrypoint.sh php -S 0.0.0.0:80 &) && \
# Do not setup the demo user here
for user in admin user1 user2; do curl -u "$user:$user" -H "ocs-apirequest: true" -s -o /dev/null http://localhost/ocs/v2.php/cloud/user; done
COPY static /usr/src/nextcloud/static
COPY dev/static /usr/src/nextcloud/static
ENV PHP_CLI_SERVER_WORKERS=10
CMD ["php", "-S", "0.0.0.0:80"]

2
tool/build-dev-container.sh

@ -6,4 +6,4 @@ source tool/common.sh
tag="$(image_tag "dev:latest")"
# shellcheck disable=SC2046
docker buildx build --tag "$tag" $(cache_build_args "$tag") -f - ./packages/nextcloud_test/docker < packages/nextcloud_test/docker/Dockerfile
docker buildx build --tag "$tag" $(cache_build_args "$tag") -f - ./tool < tool/Dockerfile.dev

0
packages/nextcloud_test/docker/static/nasa.xml → tool/dev/static/nasa.xml

0
packages/nextcloud_test/docker/static/wikipedia.xml → tool/dev/static/wikipedia.xml

Loading…
Cancel
Save