// 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,
        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,
            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,
            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,
            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,
            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,
            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,
            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,
          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,
          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
    }
  ''';
}
