Skip to content

Commit

Permalink
refactor(nextcloud_test,nextcloud): run tests on web
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolas Rimikis <leptopoda@users.noreply.github.com>
  • Loading branch information
Leptopoda committed Sep 12, 2024
1 parent 115d63a commit bf07c99
Show file tree
Hide file tree
Showing 68 changed files with 2,105 additions and 376 deletions.
1 change: 1 addition & 0 deletions commitlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rules:
- news_app
- nextcloud
- nextcloud_test
- nextcloud_test_api
- nextcloud_test_presets
- notes_app
- notifications_app
Expand Down
16 changes: 16 additions & 0 deletions packages/nextcloud/dart_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
platforms:
- vm
- chrome

define_platforms:
chromium:
name: Chromium
extends: chrome
settings:
executable: chromium

override_platforms:
chrome:
settings:
arguments: --disable-web-security
executable: chromium
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
export 'src/fixtures.dart' hide appendFixture, validateFixture;
export 'src/presets.dart';
/// Nextcloud test library.
///
/// Handles the server setup and allows to run tests against different test presets.
/// All http requests of a test will be validated against predefined fixtures.
library;

export 'src/nextcloud_test.dart' show NextcloudTester, NextcloudTesterCallback, closeFixture, presets, resetFixture;

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export 'nextcloud_test/fixture_interceptor.dart';
export 'nextcloud_test/fixtures.dart';
export 'nextcloud_test/nextcloud_tester.dart';
export 'nextcloud_test/presets.dart';
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import 'package:built_collection/built_collection.dart';
import 'package:meta/meta.dart';
import 'package:nextcloud/webdav.dart';
import 'package:nextcloud_test/src/models/models.dart';
import 'package:nextcloud_test_api/client.dart';
import 'package:test/expect.dart';
// ignore: implementation_imports
import 'package:test_api/src/backend/invoker.dart';
import 'package:universal_io/io.dart';

var _closed = false;
final _fixture = <String>[];
Expand All @@ -31,9 +29,9 @@ void resetFixture() {

/// Validates that the requests match the stored fixtures.
///
/// If there is no stored fixture a new one is created.
/// If there is no stored fixture an empty one is created.
@internal
void validateFixture(NextcloudTester tester) {
Future<void> validateFixture(NextcloudTestApiClient client, Preset preset) async {
if (_fixture.isEmpty) {
return;
}
Expand All @@ -55,37 +53,31 @@ void validateFixture(NextcloudTester tester) {

// Remove the groups that are the preset name and the preset version and the app is kept.
for (var i = 0; i <= 2; i++) {
if (groups[i] == '${tester.version.major}.${tester.version.minor}') {
if (groups[i] == '${preset.version.major}.${preset.version.minor}') {
groups.removeAt(i);
break;
}
}

final fixturesPath = PathUri(
isAbsolute: false,
isDirectory: true,
pathSegments: BuiltList.from([
'test',
'fixtures',
...groups.map(_formatName),
]),
final fixtureName = _formatName(Invoker.current!.liveTest.individualName);

final fixturePath = [
...groups.map(_formatName),
'$fixtureName.regexp',
];

final response = await client.validateFixture(
fixturePath: fixturePath,
);
final fixturesDir = Directory(fixturesPath.path);
if (!fixturesDir.existsSync()) {
fixturesDir.createSync(recursive: true);
}
final pattern = response.fixture;

final fixtureName = _formatName(Invoker.current!.liveTest.individualName.toLowerCase());
final fixtureFile = File(fixturesPath.join(PathUri.parse('$fixtureName.regexp')).path);
if (fixtureFile.existsSync()) {
final pattern = fixtureFile.readAsStringSync();
final hasMatch = RegExp('^$pattern\$').hasMatch(data);
if (!hasMatch) {
throw Exception('$data\ndoes not match\n$pattern');
}
} else {
fixtureFile.writeAsStringSync(RegExp.escape(data));
throw Exception('Missing fixture $fixtureFile');
if (pattern == null) {
fail(
'Missing fixture: '
'$data',
);
} else if (!RegExp('^$pattern\$').hasMatch(data)) {
fail('$data\ndoes not match\n$pattern');
}

_closed = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import 'dart:async';

import 'package:built_collection/built_collection.dart';
import 'package:cookie_store/cookie_store.dart';
import 'package:http/http.dart' as http;
import 'package:interceptor_http_client/interceptor_http_client.dart';
import 'package:meta/meta.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:nextcloud_test/src/nextcloud_test.dart';
import 'package:nextcloud_test_api/client.dart';

/// The shared base http client.
///
/// Both the nextcloud communication and the communication to the test manager
/// are handled through this client.
@internal
final http.Client httpClient = http.Client();

/// Class that manages the creation of nextcloud api clients and the test environment.
final class NextcloudTester {
/// Creates a new Nextcloud tester for the given [preset] with the initial [username].
NextcloudTester({
required NextcloudTestApiClient testClient,
required Preset preset,
required String username,
}) : _preset = preset,
_username = username,
_testClient = testClient;

Preset _preset;

final String _username;

final NextcloudTestApiClient _testClient;

late Uri _hostURL;

/// URL where the target is available from itself.
late Uri targetURL;

/// The Nextcloud api client for the default user.
///
/// Use [createClient] to create a separate one.
late NextcloudClient client;

/// The app version tested.
Version get version => _preset.version;

/// Creates a new [NextcloudClient] for a given [username].
///
/// It is expected that the password of the user matches its [username].
Future<NextcloudClient> createClient({String username = 'user1'}) async {
final appPassword = await _testClient.createAppPassword(
preset: _preset,
username: username,
);

final interceptedClient = InterceptorHttpClient(
baseClient: httpClient,
interceptors: BuiltList([
CookieStoreInterceptor(
cookieStore: CookieStore(),
),
const FixtureInterceptor(appendFixture: appendFixture),
]),
);

return NextcloudClient(
_hostURL,
loginName: username,
password: username,
appPassword: appPassword,
httpClient: interceptedClient,
);
}

/// Initializes the tester creating the target and default client.
Future<void> init(String platform) async {
_preset = _preset.rebuild((b) {
b.platform = platform;
});

final response = await _testClient.setup(
preset: _preset,
);
_hostURL = response.hostURL;
targetURL = response.targetURL;

client = await createClient(username: _username);
}

/// Closes the tester.
Future<void> close() async {
await _testClient.tearDown(
preset: _preset,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import 'dart:convert';

import 'package:meta/meta.dart';
import 'package:nextcloud_test/src/nextcloud_test.dart';
import 'package:nextcloud_test_api/client.dart';
import 'package:test/test.dart';
// ignore: implementation_imports
import 'package:test_api/src/backend/invoker.dart';

/// Signature for callback to [presets].
typedef NextcloudTesterCallback = void Function(NextcloudTester tester);

final _testClient = NextcloudTestApiClient.localhost(
httpClient: httpClient,
);

/// All tests for apps that depend on the server version must be wrapped with this method and pass along the preset.
@isTestGroup
Future<void> presets(
String presetGroup,
String app,
NextcloudTesterCallback body, {
String username = defaultTestUsername,
String? testOn,
Timeout? timeout,
Object? skip,
Object? tags,
Map<String, dynamic>? onPlatform,
int? retry,
}) async {
final response = await _testClient.getPresets(group: presetGroup);
final presets = response.presets;

if (presets.isEmpty) {
throw Exception('Unknown preset type "$presetGroup"');
}

group(
presetGroup,
() {
void innerBody() {
for (final version in presets) {
group('${version.major}.${version.minor}', () {
final preset = Preset((b) {
b
..groupName = presetGroup
..appName = app
..version = version;
});

final tester = NextcloudTester(
preset: preset,
username: username,
testClient: _testClient,
);

setUpAll(() async {
final platform = jsonEncode(
Invoker.current!.liveTest.suite.platform.serialize(),
);

await tester.init(platform);
});

tearDownAll(() async {
await tester.close();
});

tearDown(() async {
await validateFixture(_testClient, preset);
});

body(tester);
});
}
}

if (app != presetGroup) {
group(app, innerBody);
} else {
innerBody();
}
},
testOn: testOn,
timeout: timeout,
skip: skip,
tags: tags,
onPlatform: onPlatform,
retry: retry,
);
}
Loading

0 comments on commit bf07c99

Please sign in to comment.