| // Copyright 2019 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/src/model/appengine/github_build_status_update.dart'; |
| import 'package:cocoon_service/src/request_handlers/push_build_status_to_github.dart'; |
| import 'package:cocoon_service/src/request_handling/body.dart'; |
| import 'package:cocoon_service/src/service/build_status_provider.dart'; |
| import 'package:cocoon_service/src/service/config.dart'; |
| import 'package:cocoon_service/src/service/datastore.dart'; |
| import 'package:gcloud/db.dart'; |
| import 'package:github/github.dart'; |
| import 'package:googleapis/bigquery/v2.dart' hide Model; |
| import 'package:mockito/mockito.dart'; |
| import 'package:test/test.dart'; |
| |
| import '../src/bigquery/fake_tabledata_resource.dart'; |
| import '../src/datastore/fake_config.dart'; |
| import '../src/datastore/fake_datastore.dart'; |
| import '../src/request_handling/api_request_handler_tester.dart'; |
| import '../src/request_handling/fake_authentication.dart'; |
| import '../src/service/fake_build_status_provider.dart'; |
| import '../src/service/fake_github_service.dart'; |
| import '../src/utilities/entity_generators.dart'; |
| import '../src/utilities/mocks.dart'; |
| |
| void main() { |
| group('PushStatusToGithub', () { |
| late FakeBuildStatusService buildStatusService; |
| late FakeClientContext clientContext; |
| late FakeConfig config; |
| late FakeDatastoreDB db; |
| late ApiRequestHandlerTester tester; |
| late FakeAuthenticatedContext authContext; |
| late FakeTabledataResource tabledataResourceApi; |
| late PushBuildStatusToGithub handler; |
| late MockGitHub github; |
| late MockPullRequestsService pullRequestsService; |
| late MockIssuesService issuesService; |
| late MockRepositoriesService repositoriesService; |
| late FakeGithubService githubService; |
| |
| GithubBuildStatusUpdate newStatusUpdate(PullRequest pr, BuildStatus status) { |
| return GithubBuildStatusUpdate( |
| key: db.emptyKey.append(GithubBuildStatusUpdate, id: pr.number), |
| repository: Config.flutterSlug.fullName, |
| status: status.githubStatus, |
| pr: pr.number!, |
| head: pr.head!.sha, |
| updates: 0, |
| ); |
| } |
| |
| setUp(() async { |
| clientContext = FakeClientContext(); |
| authContext = FakeAuthenticatedContext(clientContext: clientContext); |
| clientContext.isDevelopmentEnvironment = false; |
| buildStatusService = FakeBuildStatusService(); |
| githubService = FakeGithubService(); |
| tabledataResourceApi = FakeTabledataResource(); |
| db = FakeDatastoreDB(); |
| github = MockGitHub(); |
| pullRequestsService = MockPullRequestsService(); |
| issuesService = MockIssuesService(); |
| repositoriesService = MockRepositoriesService(); |
| config = FakeConfig( |
| tabledataResource: tabledataResourceApi, |
| githubService: githubService, |
| dbValue: db, |
| githubClient: github, |
| ); |
| tester = ApiRequestHandlerTester(context: authContext); |
| handler = PushBuildStatusToGithub( |
| config: config, |
| authenticationProvider: FakeAuthenticationProvider(clientContext: clientContext), |
| buildStatusServiceProvider: (_) => buildStatusService, |
| datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5), |
| ); |
| |
| when(github.pullRequests).thenReturn(pullRequestsService); |
| when(github.issues).thenReturn(issuesService); |
| when(github.repositories).thenReturn(repositoriesService); |
| when(repositoriesService.createStatus(any, any, any)).thenAnswer( |
| (_) async => RepositoryStatus(), |
| ); |
| }); |
| |
| test('development environment does nothing', () async { |
| clientContext.isDevelopmentEnvironment = true; |
| config.githubClient = ThrowingGitHub(); |
| db.onCommit = (List<Model<dynamic>> insert, List<Key<dynamic>> deletes) => throw AssertionError(); |
| db.addOnQuery<GithubBuildStatusUpdate>((Iterable<GithubBuildStatusUpdate> results) { |
| throw AssertionError(); |
| }); |
| final Body body = await tester.get<Body>(handler); |
| expect(body, same(Body.empty)); |
| }); |
| |
| group('does not update anything', () { |
| setUp(() { |
| db.onCommit = (List<Model<dynamic>> insert, List<Key<dynamic>> deletes) => throw AssertionError(); |
| when(repositoriesService.createStatus(any, any, any)).thenThrow(AssertionError()); |
| }); |
| |
| test('if there are no PRs', () async { |
| when(pullRequestsService.list(any, base: anyNamed('base'))) |
| .thenAnswer((_) => const Stream<PullRequest>.empty()); |
| buildStatusService.cumulativeStatus = BuildStatus.success(); |
| final Body body = await tester.get<Body>(handler); |
| final TableDataList tableDataList = await tabledataResourceApi.list('test', 'test', 'test'); |
| expect(body, same(Body.empty)); |
| |
| // Test for BigQuery insert |
| expect(tableDataList.totalRows, '1'); |
| }); |
| |
| test('only if pull request is for the default branch', () async { |
| when(pullRequestsService.list(any)).thenAnswer( |
| (_) => Stream<PullRequest>.value( |
| generatePullRequest( |
| id: 1, |
| branch: 'flutter-2.15-candidate.3', |
| ), |
| ), |
| ); |
| buildStatusService.cumulativeStatus = BuildStatus.success(); |
| await tester.get<Body>(handler); |
| verifyNever(repositoriesService.createStatus(any, any, any)); |
| }); |
| |
| test('if status has not changed since last update', () async { |
| final PullRequest pr = generatePullRequest(id: 1, sha: '1'); |
| when(pullRequestsService.list(any, base: anyNamed('base'))).thenAnswer((_) => Stream<PullRequest>.value(pr)); |
| buildStatusService.cumulativeStatus = BuildStatus.success(); |
| final GithubBuildStatusUpdate status = newStatusUpdate(pr, BuildStatus.success()); |
| db.values[status.key] = status; |
| final Body body = await tester.get<Body>(handler); |
| expect(body, same(Body.empty)); |
| expect(status.updates, 0); |
| }); |
| |
| test('if there is no pr found for a targeted branch', () async { |
| final PullRequest pr = generatePullRequest(id: 1, sha: '1'); |
| when(pullRequestsService.list(any, base: anyNamed('base'))).thenAnswer((_) => Stream<PullRequest>.value(pr)); |
| buildStatusService.cumulativeStatus = BuildStatus.success(); |
| final GithubBuildStatusUpdate status = |
| newStatusUpdate(pr, BuildStatus.failure(const <String>['failed_task_1'])); |
| db.values[status.key] = status; |
| final Body body = await tester.get<Body>(handler); |
| expect(body, same(Body.empty)); |
| expect(status.updates, 0); |
| expect(status.status, BuildStatus.failure().githubStatus); |
| }); |
| }); |
| |
| test('updates github and datastore if status has changed since last update', () async { |
| final PullRequest pr = generatePullRequest(id: 1, sha: '1'); |
| when(pullRequestsService.list(any, base: anyNamed('base'))).thenAnswer((_) => Stream<PullRequest>.value(pr)); |
| buildStatusService.cumulativeStatus = BuildStatus.success(); |
| final GithubBuildStatusUpdate status = newStatusUpdate(pr, BuildStatus.failure(const <String>['failed_test_1'])); |
| db.values[status.key] = status; |
| final Body body = await tester.get<Body>(handler); |
| expect(body, same(Body.empty)); |
| expect(status.updates, 1); |
| expect(status.updateTimeMillis, isNotNull); |
| expect(status.status, BuildStatus.success().githubStatus); |
| }); |
| }); |
| } |