| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:args/args.dart'; |
| import 'package:conductor_core/src/globals.dart'; |
| import 'package:conductor_core/src/proto/conductor_state.pb.dart' as pb; |
| |
| import './common.dart'; |
| |
| void main() { |
| test('assertsEnabled returns true in test suite', () { |
| expect(assertsEnabled(), true); |
| }); |
| |
| group('getNewPrLink', () { |
| const String userName = 'flutterer'; |
| const String releaseChannel = 'beta'; |
| const String releaseVersion = '1.2.0-3.4.pre'; |
| const String candidateBranch = 'flutter-1.2-candidate.3'; |
| const String workingBranch = 'cherrypicks-$candidateBranch'; |
| const String dartRevision = 'fe9708ab688dcda9923f584ba370a66fcbc3811f'; |
| const String engineCherrypick1 = 'a5a25cd702b062c24b2c67b8d30b5cb33e0ef6f0'; |
| const String engineCherrypick2 = '94d06a2e1d01a3b0c693b94d70c5e1df9d78d249'; |
| const String frameworkCherrypick = |
| 'a5a25cd702b062c24b2c67b8d30b5cb33e0ef6f0'; |
| |
| final RegExp titlePattern = RegExp(r'&title=(.*)&'); |
| final RegExp bodyPattern = RegExp(r'&body=(.*)$'); |
| |
| late pb.ConductorState state; |
| |
| setUp(() { |
| state = pb.ConductorState( |
| engine: pb.Repository( |
| candidateBranch: candidateBranch, |
| cherrypicks: <pb.Cherrypick>[ |
| pb.Cherrypick(trunkRevision: engineCherrypick1), |
| pb.Cherrypick(trunkRevision: engineCherrypick2), |
| ], |
| dartRevision: dartRevision, |
| workingBranch: workingBranch, |
| ), |
| framework: pb.Repository( |
| candidateBranch: candidateBranch, |
| cherrypicks: <pb.Cherrypick>[ |
| pb.Cherrypick(trunkRevision: frameworkCherrypick), |
| ], |
| workingBranch: workingBranch, |
| ), |
| releaseChannel: releaseChannel, |
| releaseVersion: releaseVersion, |
| ); |
| }); |
| |
| test('throws on an invalid repoName', () { |
| expect( |
| () => getNewPrLink( |
| repoName: 'flooter', |
| userName: userName, |
| state: state, |
| ), |
| throwsExceptionWith( |
| 'Expected repoName to be one of flutter or engine but got flooter.', |
| ), |
| ); |
| }); |
| |
| test('returns a valid URL for engine', () { |
| final String link = getNewPrLink( |
| repoName: 'engine', |
| userName: userName, |
| state: state, |
| ); |
| expect( |
| link, |
| contains('https://github.com/flutter/engine/compare/'), |
| ); |
| expect( |
| link, |
| contains('$candidateBranch...$userName:$workingBranch?expand=1'), |
| ); |
| expect( |
| Uri.decodeQueryComponent( |
| titlePattern.firstMatch(link)?.group(1) ?? ''), |
| '[flutter_releases] Flutter $releaseChannel $releaseVersion Engine Cherrypicks'); |
| final String expectedBody = ''' |
| # Flutter $releaseChannel $releaseVersion Engine |
| |
| ## Scheduled Cherrypicks |
| |
| - Roll dart revision: dart-lang/sdk@${dartRevision.substring(0, 9)} |
| - commit: flutter/engine@${engineCherrypick1.substring(0, 9)} |
| - commit: flutter/engine@${engineCherrypick2.substring(0, 9)} |
| '''; |
| expect( |
| Uri.decodeQueryComponent(bodyPattern.firstMatch(link)?.group(1) ?? ''), |
| expectedBody, |
| ); |
| }); |
| |
| test('returns a valid URL for framework', () { |
| final String link = getNewPrLink( |
| repoName: 'flutter', |
| userName: userName, |
| state: state, |
| ); |
| expect( |
| link, |
| contains('https://github.com/flutter/flutter/compare/'), |
| ); |
| expect( |
| link, |
| contains('$candidateBranch...$userName:$workingBranch?expand=1'), |
| ); |
| expect( |
| Uri.decodeQueryComponent( |
| titlePattern.firstMatch(link)?.group(1) ?? ''), |
| '[flutter_releases] Flutter $releaseChannel $releaseVersion Framework Cherrypicks'); |
| final String expectedBody = ''' |
| # Flutter $releaseChannel $releaseVersion Framework |
| |
| ## Scheduled Cherrypicks |
| |
| - commit: ${frameworkCherrypick.substring(0, 9)} |
| '''; |
| expect( |
| Uri.decodeQueryComponent(bodyPattern.firstMatch(link)?.group(1) ?? ''), |
| expectedBody, |
| ); |
| }); |
| }); |
| |
| group('getBoolFromEnvOrArgs', () { |
| const String flagName = 'a-cli-flag'; |
| |
| test('prefers env over argResults', () { |
| final ArgResults argResults = FakeArgs(results: <String, Object>{ |
| flagName: false, |
| }); |
| final Map<String, String> env = <String, String>{'A_CLI_FLAG': 'TRUE'}; |
| final bool result = getBoolFromEnvOrArgs( |
| flagName, |
| argResults, |
| env, |
| ); |
| expect(result, true); |
| }); |
| |
| test('falls back to argResults if env is empty', () { |
| final ArgResults argResults = FakeArgs(results: <String, Object>{ |
| flagName: false, |
| }); |
| final Map<String, String> env = <String, String>{}; |
| final bool result = getBoolFromEnvOrArgs( |
| flagName, |
| argResults, |
| env, |
| ); |
| expect(result, false); |
| }); |
| }); |
| } |
| |
| class FakeArgs implements ArgResults { |
| FakeArgs({ |
| this.arguments = const <String>[], |
| this.name = 'fake-command', |
| this.results = const <String, Object>{}, |
| }); |
| |
| final Map<String, Object> results; |
| |
| @override |
| final List<String> arguments; |
| |
| @override |
| final String name; |
| |
| @override |
| ArgResults? get command => throw Exception('Unimplemented'); |
| |
| @override |
| List<String> get rest => throw Exception('Unimplemented'); |
| |
| @override |
| Iterable<String> get options => throw Exception('Unimplemented'); |
| |
| @override |
| bool wasParsed(String name) { |
| return results[name] != null; |
| } |
| |
| @override |
| Object? operator[](String name) { |
| return results[name]; |
| } |
| } |