blob: e44c5cbc37fd5a3af8079efebaf833f5d45048e3 [file] [log] [blame]
// Copyright 2021 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:cocoon_service/cocoon_service.dart';
import 'package:cocoon_service/src/model/appengine/commit.dart';
import 'package:cocoon_service/src/model/firestore/commit.dart' as firestore;
import 'package:cocoon_service/src/service/commit_service.dart';
import 'package:github/github.dart';
import 'package:googleapis/firestore/v1.dart' hide Status;
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'package:github/hooks.dart';
import 'package:cocoon_server/testing/mocks.dart';
import '../src/datastore/fake_datastore.dart';
import '../src/utilities/entity_generators.dart';
import '../src/utilities/mocks.mocks.dart';
import '../src/utilities/webhook_generators.dart';
void main() {
late MockConfig config;
late FakeDatastoreDB db;
late CommitService commitService;
late MockGithubService githubService;
late MockRepositoriesService repositories;
late MockGitHub github;
late MockFirestoreService mockFirestoreService;
const String owner = 'flutter';
const String repository = 'flutter';
const String branch = 'coolest-branch';
const String sha = '1234';
const String message = 'Adding null safety';
const String avatarUrl = 'https://avatars.githubusercontent.com/u/fake-user-num';
const String username = 'AwesomeGithubUser';
const String dateTimeAsString = '2023-08-18T19:27:00Z';
setUp(() {
db = FakeDatastoreDB();
github = MockGitHub();
githubService = MockGithubService();
mockFirestoreService = MockFirestoreService();
when(githubService.github).thenReturn(github);
repositories = MockRepositoriesService();
when(github.repositories).thenReturn(repositories);
config = MockConfig();
commitService = CommitService(config: config);
when(config.createDefaultGitHubService()).thenAnswer((_) async => githubService);
when(config.createFirestoreService()).thenAnswer((_) async => mockFirestoreService);
when(config.db).thenReturn(db);
});
group('handleCreateGithubRequest', () {
test('adds commit to db if it does not exist in the datastore', () async {
expect(db.values.values.whereType<Commit>().length, 0);
when(
mockFirestoreService.batchWriteDocuments(
captureAny,
captureAny,
),
).thenAnswer((Invocation invocation) {
return Future<BatchWriteResponse>.value(BatchWriteResponse());
});
when(githubService.getReference(RepositorySlug(owner, repository), 'heads/$branch'))
.thenAnswer((Invocation invocation) {
return Future<GitReference>.value(
GitReference(ref: 'refs/$branch', object: GitObject('', sha, '')),
);
});
when(repositories.getCommit(RepositorySlug(owner, repository), sha)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(
RepositoryCommit(
sha: sha,
author: User(
login: username,
avatarUrl: avatarUrl,
),
commit: GitCommit(message: message),
),
);
});
final CreateEvent createEvent = generateCreateBranchEvent(branch, '$owner/$repository');
await commitService.handleCreateGithubRequest(createEvent);
expect(db.values.values.whereType<Commit>().length, 1);
final Commit commit = db.values.values.whereType<Commit>().single;
expect(commit.repository, '$owner/$repository');
expect(commit.message, message);
expect(commit.key.id, '$owner/$repository/$branch/$sha');
expect(commit.sha, sha);
expect(commit.author, username);
expect(commit.authorAvatarUrl, avatarUrl);
expect(commit.branch, branch);
final List<dynamic> captured = verify(mockFirestoreService.batchWriteDocuments(captureAny, captureAny)).captured;
expect(captured.length, 2);
final BatchWriteRequest batchWriteRequest = captured[0] as BatchWriteRequest;
expect(batchWriteRequest.writes!.length, 1);
final Document insertedCommitDocument = batchWriteRequest.writes![0].update!;
expect(insertedCommitDocument.name, '$kDatabase/documents/${firestore.kCommitCollectionId}/$sha');
});
test('does not add commit to db if it exists in the datastore', () async {
final Commit existingCommit = generateCommit(
1,
sha: sha,
branch: branch,
owner: owner,
repo: repository,
timestamp: 0,
);
final List<Commit> datastoreCommit = <Commit>[existingCommit];
await config.db.commit(inserts: datastoreCommit);
expect(db.values.values.whereType<Commit>().length, 1);
when(githubService.getReference(RepositorySlug(owner, repository), 'heads/$branch'))
.thenAnswer((Invocation invocation) {
return Future<GitReference>.value(
GitReference(ref: 'refs/$branch', object: GitObject('', sha, '')),
);
});
when(repositories.getCommit(RepositorySlug(owner, repository), sha)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(
RepositoryCommit(
sha: sha,
author: User(
createdAt: DateTime.parse(dateTimeAsString),
login: username,
avatarUrl: avatarUrl,
),
commit: GitCommit(message: message),
),
);
});
final CreateEvent createEvent = generateCreateBranchEvent(branch, '$owner/$repository');
await commitService.handleCreateGithubRequest(createEvent);
expect(db.values.values.whereType<Commit>().length, 1);
final Commit commit = db.values.values.whereType<Commit>().single;
expect(commit, existingCommit);
});
});
group('handlePushGithubRequest', () {
test('adds commit to db if it does not exist in the datastore', () async {
expect(db.values.values.whereType<Commit>().length, 0);
final Map<String, dynamic> pushEvent = generatePushEvent(
branch,
owner,
repository,
message: message,
sha: sha,
avatarUrl: avatarUrl,
username: username,
);
await commitService.handlePushGithubRequest(pushEvent);
expect(db.values.values.whereType<Commit>().length, 1);
final Commit commit = db.values.values.whereType<Commit>().single;
expect(commit.repository, '$owner/$repository');
expect(commit.message, message);
expect(commit.key.id, '$owner/$repository/$branch/$sha');
expect(commit.sha, sha);
expect(commit.author, username);
expect(commit.authorAvatarUrl, avatarUrl);
expect(commit.branch, branch);
});
test('does not add commit to db if it exists in the datastore', () async {
final Commit existingCommit = generateCommit(
1,
sha: sha,
branch: branch,
owner: owner,
repo: repository,
timestamp: 0,
);
final List<Commit> datastoreCommit = <Commit>[existingCommit];
await config.db.commit(inserts: datastoreCommit);
expect(db.values.values.whereType<Commit>().length, 1);
final Map<String, dynamic> pushEvent = generatePushEvent(
branch,
owner,
repository,
message: message,
sha: sha,
avatarUrl: avatarUrl,
username: username,
);
await commitService.handlePushGithubRequest(pushEvent);
expect(db.values.values.whereType<Commit>().length, 1);
final Commit commit = db.values.values.whereType<Commit>().single;
expect(commit, existingCommit);
});
});
}