// Copyright 2020 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 'dart:async';
import 'dart:io';

import 'package:cocoon_service/src/model/appengine/github_gold_status_update.dart';
import 'package:cocoon_service/src/request_handlers/push_gold_status_to_github.dart';
import 'package:cocoon_service/src/request_handling/body.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:cocoon_service/src/service/logging.dart';
import 'package:gcloud/db.dart' as gcloud_db;
import 'package:gcloud/db.dart';
import 'package:github/github.dart';
import 'package:graphql/client.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:logging/logging.dart';
import 'package:mockito/mockito.dart';
import 'package:retry/retry.dart';
import 'package:test/test.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_graphql_client.dart';
import '../src/utilities/mocks.dart';

void main() {
  const String kGoldenFileLabel = 'will affect goldens';

  group('PushGoldStatusToGithub', () {
    late FakeConfig config;
    late FakeClientContext clientContext;
    FakeAuthenticatedContext authContext;
    late FakeAuthenticationProvider auth;
    late FakeDatastoreDB db;
    late ApiRequestHandlerTester tester;
    late PushGoldStatusToGithub handler;
    FakeGraphQLClient githubGraphQLClient;
    List<dynamic> checkRuns = <dynamic>[];
    List<dynamic> engineCheckRuns = <dynamic>[];
    late MockClient mockHttpClient;
    late RepositorySlug slug;
    late RepositorySlug engineSlug;
    late RetryOptions retryOptions;

    final List<LogRecord> records = <LogRecord>[];

    setUp(() {
      clientContext = FakeClientContext();
      authContext = FakeAuthenticatedContext(clientContext: clientContext);
      auth = FakeAuthenticationProvider(clientContext: clientContext);
      githubGraphQLClient = FakeGraphQLClient();
      db = FakeDatastoreDB();
      config = FakeConfig(
        dbValue: db,
      );
      tester = ApiRequestHandlerTester(context: authContext);
      mockHttpClient = MockClient((_) async => http.Response('{}', HttpStatus.ok));
      retryOptions = const RetryOptions(
        delayFactor: Duration(microseconds: 1),
        maxDelay: Duration(microseconds: 2),
        maxAttempts: 2,
      );

      githubGraphQLClient.mutateResultForOptions = (MutationOptions options) => createFakeQueryResult();
      githubGraphQLClient.queryResultForOptions = (QueryOptions options) {
        if (options.variables['sRepoName'] == slug.name) {
          return createGithubQueryResult(checkRuns);
        }
        if (options.variables['sRepoName'] == engineSlug.name) {
          return createGithubQueryResult(engineCheckRuns);
        }
        return createGithubQueryResult(<dynamic>[]);
      };
      config.githubGraphQLClient = githubGraphQLClient;
      config.flutterGoldPendingValue = 'pending';
      config.flutterGoldChangesValue = 'changes';
      config.flutterGoldSuccessValue = 'success';
      config.flutterGoldAlertConstantValue = 'flutter gold alert';
      config.flutterGoldInitialAlertValue = 'initial';
      config.flutterGoldFollowUpAlertValue = 'follow-up';
      config.flutterGoldDraftChangeValue = 'draft';
      config.flutterGoldStalePRValue = 'stale';

      handler = PushGoldStatusToGithub(
        config: config,
        authenticationProvider: auth,
        datastoreProvider: (DatastoreDB db) {
          return DatastoreService(
            db,
            5,
            retryOptions: retryOptions,
          );
        },
        goldClient: mockHttpClient,
        ingestionDelay: Duration.zero,
      );

      slug = RepositorySlug('flutter', 'flutter');
      engineSlug = RepositorySlug('flutter', 'engine');
      checkRuns.clear();
      engineCheckRuns.clear();
      records.clear();
      log.onRecord.listen((LogRecord record) => records.add(record));
    });

    group('in development environment', () {
      setUp(() {
        clientContext.isDevelopmentEnvironment = true;
      });

      test('Does nothing', () async {
        config.githubClient = ThrowingGitHub();
        db.onCommit =
            (List<gcloud_db.Model<dynamic>> insert, List<gcloud_db.Key<dynamic>> deletes) => throw AssertionError();
        db.addOnQuery<GithubGoldStatusUpdate>((Iterable<GithubGoldStatusUpdate> results) {
          throw AssertionError();
        });
        final Body body = await tester.get<Body>(handler);
        expect(body, same(Body.empty));
      });
    });

    group('in non-development environment', () {
      MockGitHub github;
      MockPullRequestsService pullRequestsService;
      late MockIssuesService issuesService;
      late MockRepositoriesService repositoriesService;
      List<PullRequest> prsFromGitHub = <PullRequest>[];
      List<PullRequest> enginePrsFromGitHub = <PullRequest>[];

      setUp(() {
        github = MockGitHub();
        pullRequestsService = MockPullRequestsService();
        issuesService = MockIssuesService();
        repositoriesService = MockRepositoriesService();
        when(github.pullRequests).thenReturn(pullRequestsService);
        when(github.issues).thenReturn(issuesService);
        when(github.repositories).thenReturn(repositoriesService);

        prsFromGitHub.clear();
        when(pullRequestsService.list(slug)).thenAnswer((Invocation _) {
          return Stream<PullRequest>.fromIterable(prsFromGitHub);
        });

        enginePrsFromGitHub.clear();
        when(pullRequestsService.list(engineSlug)).thenAnswer((Invocation _) {
          return Stream<PullRequest>.fromIterable(enginePrsFromGitHub);
        });

        when(repositoriesService.createStatus(any, any, any)).thenAnswer((_) async => RepositoryStatus());
        when(issuesService.createComment(any, any, any)).thenAnswer((_) async => IssueComment());
        when(issuesService.addLabelsToIssue(any, any, any)).thenAnswer((_) async => <IssueLabel>[]);
        config.githubClient = github;
        clientContext.isDevelopmentEnvironment = false;
      });

      GithubGoldStatusUpdate newStatusUpdate(
        RepositorySlug slug,
        PullRequest pr,
        String statusUpdate,
        String sha,
        String description,
      ) {
        return GithubGoldStatusUpdate(
          key: db.emptyKey.append(GithubGoldStatusUpdate, id: pr.number),
          status: statusUpdate,
          pr: pr.number!,
          head: sha,
          updates: 0,
          description: description,
          repository: slug.fullName,
        );
      }

      PullRequest newPullRequest(int number, String sha, String baseRef, {bool draft = false, DateTime? updated}) {
        return PullRequest()
          ..number = number
          ..head = (PullRequestHead()..sha = sha)
          ..base = (PullRequestHead()..ref = baseRef)
          ..draft = draft
          ..updatedAt = updated ?? DateTime.now();
      }

      group('does not update GitHub or Datastore', () {
        setUp(() {
          db.onCommit =
              (List<gcloud_db.Model<dynamic>> insert, List<gcloud_db.Key<dynamic>> deletes) => throw AssertionError();
          when(repositoriesService.createStatus(any, any, any)).thenThrow(AssertionError());
        });

        test('if there are no PRs', () async {
          prsFromGitHub = <PullRequest>[];
          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);
        });

        test('if there are no framework or web engine tests for this PR', () async {
          checkRuns = <dynamic>[
            <String, String>{'name': 'tool-test1', 'status': 'completed', 'conclusion': 'success'}
          ];
          final PullRequest flutterPr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[flutterPr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, flutterPr, '', '', '');
          db.values[status.key] = status;

          engineCheckRuns = <dynamic>[
            <String, String>{'name': 'linux-host1', 'status': 'completed', 'conclusion': 'success'}
          ];
          final PullRequest enginePr = newPullRequest(456, 'def', 'main');
          enginePrsFromGitHub = <PullRequest>[enginePr];
          final GithubGoldStatusUpdate engineStatus = newStatusUpdate(engineSlug, enginePr, '', '', '');
          db.values[engineStatus.key] = engineStatus;

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              flutterPr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );
          verifyNever(
            issuesService.addLabelsToIssue(
              engineSlug,
              enginePr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              flutterPr.number!,
              argThat(contains(config.flutterGoldCommentID(flutterPr))),
            ),
          );
          verifyNever(
            issuesService.createComment(
              engineSlug,
              enginePr.number!,
              argThat(contains(config.flutterGoldCommentID(enginePr))),
            ),
          );
        });

        test('if there are no framework tests for this PR, exclude web builds', () async {
          checkRuns = <dynamic>[
            <String, String>{'name': 'web-test1', 'status': 'completed', 'conclusion': 'success'}
          ];
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;
          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('same commit, checks running, last status running', () async {
          // Same commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(
            slug,
            pr,
            GithubGoldStatusUpdate.statusRunning,
            'abc',
            config.flutterGoldPendingValue!,
          );
          db.values[status.key] = status;

          // Checks still running
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'in_progress', 'conclusion': 'neutral'},
            <String, String>{'name': 'web engine', 'status': 'in_progress', 'conclusion': 'neutral'},
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('same commit, checks complete, last status complete', () async {
          // Same commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(
            slug,
            pr,
            GithubGoldStatusUpdate.statusCompleted,
            'abc',
            config.flutterGoldSuccessValue!,
          );
          db.values[status.key] = status;

          // Checks complete
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'},
            <String, String>{'name': 'web engine', 'status': 'completed', 'conclusion': 'success'},
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('same commit, checks complete, last status & gold status is running/awaiting triage, should not comment',
            () async {
          // Same commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(
            slug,
            pr,
            GithubGoldStatusUpdate.statusRunning,
            'abc',
            config.flutterGoldChangesValue!,
          );
          db.values[status.key] = status;

          final PullRequest enginePr = newPullRequest(456, 'def', 'main');
          enginePrsFromGitHub = <PullRequest>[enginePr];
          final GithubGoldStatusUpdate engineStatus = newStatusUpdate(
            engineSlug,
            enginePr,
            GithubGoldStatusUpdate.statusRunning,
            'def',
            config.flutterGoldChangesValue!,
          );
          db.values[engineStatus.key] = engineStatus;

          // Checks complete
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'},
          ];
          engineCheckRuns = <dynamic>[
            <String, String>{'name': 'web engine', 'status': 'completed', 'conclusion': 'success'},
          ];

          // Gold status is running
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobDigests(pr), HttpStatus.ok);
            }
            if (request.url.toString() ==
                'https://flutter-engine-gold.skia.org/json/v1/changelist_summary/github/${enginePr.number}') {
              return http.Response(tryjobDigests(enginePr), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          // Already commented for this commit.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = config.flutterGoldCommentID(pr),
            ),
          );
          when(issuesService.listCommentsByIssue(engineSlug, enginePr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = config.flutterGoldCommentID(enginePr),
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );
          verifyNever(
            issuesService.addLabelsToIssue(
              engineSlug,
              enginePr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
          verifyNever(
            issuesService.createComment(
              engineSlug,
              enginePr.number!,
              argThat(contains(config.flutterGoldCommentID(enginePr))),
            ),
          );
        });

        test('does nothing for branches not staged to land on main/master', () async {
          // New commit
          final PullRequest pr = newPullRequest(123, 'abc', 'release');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // All checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('does not post for draft PRs, does not query Gold', () async {
          // New commit, draft PR
          final PullRequest pr = newPullRequest(123, 'abc', 'master', draft: true);
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              any,
            ),
          );
        });

        test('does not post for draft PRs, does not query Gold', () async {
          // New commit, draft PR
          final PullRequest pr = newPullRequest(123, 'abc', 'master', draft: true);
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'Linux', 'status': 'completed', 'conclusion': 'success'}
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              any,
            ),
          );
        });

        test('does not post for stale PRs, does not query Gold, stale comment', () async {
          // New commit, draft PR
          final PullRequest pr =
              newPullRequest(123, 'abc', 'master', updated: DateTime.now().subtract(const Duration(days: 30)));
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Have not already commented for this commit.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels, should comment to update
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verify(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldStalePRValue)),
            ),
          ).called(1);
        });

        test('will only comment once on stale PRs', () async {
          // New commit, draft PR
          final PullRequest pr =
              newPullRequest(123, 'abc', 'master', updated: DateTime.now().subtract(const Duration(days: 30)));
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Already commented to update.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = config.flutterGoldStalePRValue,
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              any,
            ),
          );
        });

        test('will not fire off stale warning for non-framework PRs', () async {
          // New commit, draft PR
          final PullRequest pr =
              newPullRequest(123, 'abc', 'master', updated: DateTime.now().subtract(const Duration(days: 30)));
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'tool-test-1', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Already commented to update.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              any,
            ),
          );
        });
      });

      group('updates GitHub and/or Datastore', () {
        test('new commit, checks running', () async {
          // New commit
          final PullRequest flutterPr = newPullRequest(123, 'f-abc', 'master');
          prsFromGitHub = <PullRequest>[flutterPr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, flutterPr, '', '', '');

          final PullRequest enginePr = newPullRequest(567, 'e-abc', 'main');
          enginePrsFromGitHub = <PullRequest>[enginePr];
          final GithubGoldStatusUpdate engineStatus = newStatusUpdate(engineSlug, enginePr, '', '', '');

          db.values[status.key] = status;
          db.values[engineStatus.key] = engineStatus;

          // Checks running
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'in_progress', 'conclusion': 'neutral'},
          ];
          engineCheckRuns = <dynamic>[
            <String, String>{'name': 'web engine', 'status': 'in_progress', 'conclusion': 'neutral'},
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(status.status, GithubGoldStatusUpdate.statusRunning);
          expect(engineStatus.updates, 1);
          expect(engineStatus.status, GithubGoldStatusUpdate.statusRunning);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              flutterPr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );
          verifyNever(
            issuesService.addLabelsToIssue(
              engineSlug,
              enginePr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              flutterPr.number!,
              argThat(contains(config.flutterGoldCommentID(flutterPr))),
            ),
          );
          verifyNever(
            issuesService.createComment(
              engineSlug,
              enginePr.number!,
              argThat(contains(config.flutterGoldCommentID(enginePr))),
            ),
          );
        });

        test('new commit, checks complete, no changes detected', () async {
          // New commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Change detected by Gold
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobEmpty(), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(status.status, GithubGoldStatusUpdate.statusCompleted);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not label or comment
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('new commit, checks complete, change detected, should comment', () async {
          // New commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Change detected by Gold
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobDigests(pr), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          // Have not already commented for this commit.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(status.status, GithubGoldStatusUpdate.statusRunning);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should label and comment
          verify(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          ).called(1);

          verify(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          ).called(1);
        });

        test('same commit, checks complete, last status was waiting & gold status is needing triage, should comment',
            () async {
          // Same commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status =
              newStatusUpdate(slug, pr, GithubGoldStatusUpdate.statusRunning, 'abc', config.flutterGoldPendingValue!);
          db.values[status.key] = status;

          // Checks complete
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // Gold status is running
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobDigests(pr), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          // Have not already commented for this commit.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should apply labels and make comment
          verify(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          ).called(1);

          verify(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          ).called(1);
        });

        test('uses shorter comment after first comment to reduce noise', () async {
          // Same commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status =
              newStatusUpdate(slug, pr, GithubGoldStatusUpdate.statusRunning, 'abc', config.flutterGoldPendingValue!);
          db.values[status.key] = status;

          // Checks complete
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'completed': 'in_progress', 'conclusion': 'success'}
          ];

          // Gold status is running
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobDigests(pr), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          // Have not already commented for this commit.
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = config.flutterGoldInitialAlertValue,
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should apply labels and make comment
          verify(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          ).called(1);

          verify(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldFollowUpAlertValue)),
            ),
          ).called(1);
          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldInitialAlertValue)),
            ),
          );
          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldAlertConstantValue)),
            ),
          );
        });

        test('same commit, checks complete, new status, should not comment', () async {
          // Same commit: abc
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status =
              newStatusUpdate(slug, pr, GithubGoldStatusUpdate.statusRunning, 'abc', config.flutterGoldPendingValue!);
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];

          // New status: completed/triaged/no changes
          mockHttpClient = MockClient((http.Request request) async {
            if (request.url.toString() ==
                'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
              return http.Response(tryjobEmpty(), HttpStatus.ok);
            }
            throw const HttpException('Unexpected http request');
          });
          handler = PushGoldStatusToGithub(
            config: config,
            authenticationProvider: auth,
            datastoreProvider: (DatastoreDB db) {
              return DatastoreService(
                config.db,
                5,
                retryOptions: retryOptions,
              );
            },
            goldClient: mockHttpClient,
            ingestionDelay: Duration.zero,
          );

          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(status.status, GithubGoldStatusUpdate.statusCompleted);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not label or comment
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });

        test('will inform contributor of unresolved check for ATF draft status', () async {
          // New commit, draft PR
          final PullRequest pr = newPullRequest(123, 'abc', 'master', draft: true);
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status =
              newStatusUpdate(slug, pr, GithubGoldStatusUpdate.statusRunning, 'abc', config.flutterGoldPendingValue!);
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = 'some other comment',
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verify(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldDraftChangeValue)),
            ),
          ).called(1);
        });

        test('will only inform contributor of unresolved check for ATF draft status once', () async {
          // New commit, draft PR
          final PullRequest pr = newPullRequest(123, 'abc', 'master', draft: true);
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status =
              newStatusUpdate(slug, pr, GithubGoldStatusUpdate.statusRunning, 'abc', config.flutterGoldPendingValue!);
          db.values[status.key] = status;

          // Checks completed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
          ];
          when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
            (_) => Stream<IssueComment>.value(
              IssueComment()..body = config.flutterGoldDraftChangeValue,
            ),
          );

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 0);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldDraftChangeValue)),
            ),
          );
        });

        test('delivers pending state for failing checks, does not query Gold', () async {
          // New commit
          final PullRequest pr = newPullRequest(123, 'abc', 'master');
          prsFromGitHub = <PullRequest>[pr];
          final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
          db.values[status.key] = status;

          // Checks failed
          checkRuns = <dynamic>[
            <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'failure'}
          ];

          final Body body = await tester.get<Body>(handler);
          expect(body, same(Body.empty));
          expect(status.updates, 1);
          expect(status.status, GithubGoldStatusUpdate.statusRunning);
          expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
          expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

          // Should not apply labels or make comments
          verifyNever(
            issuesService.addLabelsToIssue(
              slug,
              pr.number!,
              <String>[
                kGoldenFileLabel,
              ],
            ),
          );

          verifyNever(
            issuesService.createComment(
              slug,
              pr.number!,
              argThat(contains(config.flutterGoldCommentID(pr))),
            ),
          );
        });
      });

      test('Completed pull request does not skip follow-up prs with early return', () async {
        final PullRequest completedPR = newPullRequest(123, 'abc', 'master');
        final PullRequest followUpPR = newPullRequest(456, 'def', 'master');
        prsFromGitHub = <PullRequest>[
          completedPR,
          followUpPR,
        ];
        final GithubGoldStatusUpdate completedStatus = newStatusUpdate(
          slug,
          completedPR,
          GithubGoldStatusUpdate.statusCompleted,
          'abc',
          config.flutterGoldSuccessValue!,
        );
        final GithubGoldStatusUpdate followUpStatus = newStatusUpdate(slug, followUpPR, '', '', '');
        db.values[completedStatus.key] = completedStatus;
        db.values[followUpStatus.key] = followUpStatus;

        // Checks completed
        checkRuns = <dynamic>[
          <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'}
        ];

        // New status: completed/triaged/no changes
        mockHttpClient = MockClient((http.Request request) async {
          if (request.url.toString() ==
              'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${completedPR.number}') {
            return http.Response(tryjobEmpty(), HttpStatus.ok);
          }
          if (request.url.toString() ==
              'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${followUpPR.number}') {
            return http.Response(tryjobEmpty(), HttpStatus.ok);
          }
          throw const HttpException('Unexpected http request');
        });
        handler = PushGoldStatusToGithub(
          config: config,
          authenticationProvider: auth,
          datastoreProvider: (DatastoreDB db) {
            return DatastoreService(
              config.db,
              5,
              retryOptions: retryOptions,
            );
          },
          goldClient: mockHttpClient,
          ingestionDelay: Duration.zero,
        );

        when(issuesService.listCommentsByIssue(slug, completedPR.number!)).thenAnswer(
          (_) => Stream<IssueComment>.value(
            IssueComment()..body = 'some other comment',
          ),
        );

        final Body body = await tester.get<Body>(handler);
        expect(body, same(Body.empty));
        expect(completedStatus.updates, 0);
        expect(followUpStatus.updates, 1);
        expect(completedStatus.status, GithubGoldStatusUpdate.statusCompleted);
        expect(followUpStatus.status, GithubGoldStatusUpdate.statusCompleted);
        expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
        expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);
      });

      test('accounts for null status description when parsing for Luci builds', () async {
        // Same commit
        final PullRequest pr = newPullRequest(123, 'abc', 'master');
        prsFromGitHub = <PullRequest>[pr];
        final GithubGoldStatusUpdate status = newStatusUpdate(
          slug,
          pr,
          GithubGoldStatusUpdate.statusRunning,
          'abc',
          config.flutterGoldPendingValue!,
        );
        db.values[status.key] = status;

        // null status for luci build
        checkRuns = <dynamic>[
          <String, String?>{
            'name': 'framework',
            'status': null,
            'conclusion': null,
          }
        ];

        final Body body = await tester.get<Body>(handler);
        expect(body, same(Body.empty));
        expect(status.updates, 0);
        expect(records.where((LogRecord record) => record.level == Level.WARNING), isEmpty);
        expect(records.where((LogRecord record) => record.level == Level.SEVERE), isEmpty);

        // Should not apply labels or make comments
        verifyNever(
          issuesService.addLabelsToIssue(
            slug,
            pr.number!,
            <String>[
              kGoldenFileLabel,
            ],
          ),
        );

        verifyNever(
          issuesService.createComment(
            slug,
            pr.number!,
            argThat(contains(config.flutterGoldCommentID(pr))),
          ),
        );
      });

      test('uses the correct Gold endpoint to get status', () async {
        // New commit
        final PullRequest pr = newPullRequest(123, 'abc', 'master');
        prsFromGitHub = <PullRequest>[pr];
        final GithubGoldStatusUpdate status = newStatusUpdate(slug, pr, '', '', '');
        db.values[status.key] = status;

        final PullRequest enginePr = newPullRequest(456, 'def', 'main');
        enginePrsFromGitHub = <PullRequest>[enginePr];
        final GithubGoldStatusUpdate engineStatus = newStatusUpdate(engineSlug, enginePr, '', '', '');
        db.values[engineStatus.key] = engineStatus;

        // Checks completed
        checkRuns = <dynamic>[
          <String, String>{'name': 'framework', 'status': 'completed', 'conclusion': 'success'},
        ];
        engineCheckRuns = <dynamic>[
          <String, String>{'name': 'web engine', 'status': 'completed', 'conclusion': 'success'},
        ];

        // Requests sent to Gold.
        final List<String> goldRequests = <String>[];
        mockHttpClient = MockClient((http.Request request) async {
          final String requestUrl = request.url.toString();
          goldRequests.add(requestUrl);

          final int prNumber = int.parse(requestUrl.split('/').last);
          final PullRequest requestedPr;
          if (prNumber == pr.number) {
            requestedPr = pr;
          } else if (prNumber == enginePr.number) {
            requestedPr = enginePr;
          } else {
            throw HttpException('Unexpected http request for PR#$prNumber');
          }
          return http.Response(tryjobDigests(requestedPr), HttpStatus.ok);
        });
        handler = PushGoldStatusToGithub(
          config: config,
          authenticationProvider: auth,
          datastoreProvider: (DatastoreDB db) {
            return DatastoreService(
              config.db,
              5,
              retryOptions: retryOptions,
            );
          },
          goldClient: mockHttpClient,
          ingestionDelay: Duration.zero,
        );

        // Have not already commented for this commit.
        when(issuesService.listCommentsByIssue(slug, pr.number!)).thenAnswer(
          (_) => Stream<IssueComment>.value(
            IssueComment()..body = 'some other comment',
          ),
        );
        when(issuesService.listCommentsByIssue(engineSlug, enginePr.number!)).thenAnswer(
          (_) => Stream<IssueComment>.value(
            IssueComment()..body = 'some other comment',
          ),
        );

        await tester.get<Body>(handler);

        expect(goldRequests, <String>[
          'https://flutter-gold.skia.org/json/v1/changelist_summary/github/${pr.number}',
          'https://flutter-engine-gold.skia.org/json/v1/changelist_summary/github/${enginePr.number}',
        ]);
      });
    });
  });
}

QueryResult createGithubQueryResult(List<dynamic> statuses) {
  return createFakeQueryResult(
    data: <String, dynamic>{
      'repository': <String, dynamic>{
        'pullRequest': <String, dynamic>{
          'commits': <String, dynamic>{
            'nodes': <dynamic>[
              <String, dynamic>{
                'commit': <String, dynamic>{
                  'checkSuites': <String, dynamic>{
                    'nodes': <dynamic>[
                      <String, dynamic>{
                        'checkRuns': <String, dynamic>{'nodes': statuses}
                      }
                    ]
                  }
                }
              }
            ],
          },
        },
      },
    },
  );
}

/// JSON response template for Skia Gold empty tryjob status request.
String tryjobEmpty() {
  return '''
    {
      "changelist_id": "123",
      "patchsets": [
        {
          "new_images": 0,
          "new_untriaged_images": 0,
          "total_untriaged_images": 0,
          "patchset_id": "abc",
          "patchset_order": 1
        }
      ],
      "outdated": false
    }
  ''';
}

/// JSON response template for Skia Gold untriaged tryjob status request.
String tryjobDigests(PullRequest pr) {
  return '''
    {
      "changelist_id": "${pr.number!}",
      "patchsets": [
        {
          "new_images": 1,
          "new_untriaged_images": 1,
          "total_untriaged_images": 1,
          "patchset_id": "${pr.head!.sha!}",
          "patchset_order": 1
        }
      ],
      "outdated": false
    }
  ''';
}
