downgrade_test.dart 8.38 KB
Newer Older
1 2 3 4
// 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.

5 6
// @dart = 2.8

7 8 9 10 11 12 13 14
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/downgrade.dart';
import 'package:flutter_tools/src/persistent_tool_state.dart';
15
import 'package:test/fake.dart';
16 17 18

import '../../src/common.dart';
import '../../src/context.dart';
19
import '../../src/fakes.dart';
20
import '../../src/test_flutter_command_runner.dart';
21 22 23 24

void main() {
  FileSystem fileSystem;
  BufferLogger bufferLogger;
25
  FakeTerminal terminal;
26
  ProcessManager processManager;
27
  FakeStdio stdio;
28 29 30 31 32 33 34 35 36 37

  setUpAll(() {
    Cache.disableLocking();
  });

  tearDownAll(() {
    Cache.enableLocking();
  });

  setUp(() {
38
    stdio = FakeStdio();
39
    processManager = FakeProcessManager.any();
40
    terminal = FakeTerminal();
41
    fileSystem = MemoryFileSystem.test();
42
    bufferLogger = BufferLogger.test(terminal: terminal);
43 44 45
  });

  testUsingContext('Downgrade exits on unknown channel', () async {
46
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion();
47 48 49 50 51 52
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"invalid"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(directory: fileSystem.currentDirectory, logger: bufferLogger),
      processManager: processManager,
      terminal: terminal,
53
      stdio: stdio,
54
      flutterVersion: fakeFlutterVersion,
55 56 57 58 59 60 61 62
      logger: bufferLogger,
    );

    expect(createTestCommandRunner(command).run(const <String>['downgrade']),
      throwsToolExit(message: 'Flutter is not currently on a known channel.'));
  });

  testUsingContext('Downgrade exits on no recorded version', () async {
63
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'beta');
64 65 66 67 68 69 70
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"abcd"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(directory: fileSystem.currentDirectory, logger: bufferLogger),
      processManager: FakeProcessManager.list(<FakeCommand>[
        const FakeCommand(
          command: <String>[
71
            'git', 'describe', '--tags', 'abcd',
72
          ],
73 74
          stdout: 'v1.2.3',
        ),
75 76
      ]),
      terminal: terminal,
77
      stdio: stdio,
78
      flutterVersion: fakeFlutterVersion,
79 80 81 82 83
      logger: bufferLogger,
    );

    expect(createTestCommandRunner(command).run(const <String>['downgrade']),
      throwsToolExit(message:
84
        'There is no previously recorded version for channel "beta".\n'
85 86 87 88 89 90
        'Channel "master" was previously on: v1.2.3.'
      ),
    );
  });

  testUsingContext('Downgrade exits on unknown recorded version', () async {
91
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master');
92 93 94 95 96 97 98
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"invalid"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(directory: fileSystem.currentDirectory, logger: bufferLogger),
      processManager: FakeProcessManager.list(<FakeCommand>[
        const FakeCommand(
          command: <String>[
99
            'git', 'describe', '--tags', 'invalid',
100 101
          ],
          exitCode: 1,
102
        ),
103 104
      ]),
      terminal: terminal,
105
      stdio: stdio,
106
      flutterVersion: fakeFlutterVersion,
107 108 109 110 111 112 113 114
      logger: bufferLogger,
    );

    expect(createTestCommandRunner(command).run(const <String>['downgrade']),
      throwsToolExit(message: 'Failed to parse version for downgrade'));
  });

   testUsingContext('Downgrade prompts for user input when terminal is attached - y', () async {
115
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master');
116
    stdio.hasTerminal = true;
117 118 119 120 121 122
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(directory: fileSystem.currentDirectory, logger: bufferLogger),
      processManager: processManager,
      terminal: terminal,
123
      stdio: stdio,
124
      flutterVersion: fakeFlutterVersion,
125 126 127
      logger: bufferLogger,
    );

128
    terminal.addPrompt(const <String>['y', 'n'], 'y');
129 130 131 132 133 134 135

    await createTestCommandRunner(command).run(const <String>['downgrade']);

    expect(bufferLogger.statusText, contains('Success'));
  });

   testUsingContext('Downgrade prompts for user input when terminal is attached - n', () async {
136
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master');
137
    stdio.hasTerminal = true;
138 139 140 141 142 143
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(directory: fileSystem.currentDirectory, logger: bufferLogger),
      processManager: processManager,
      terminal: terminal,
144
      stdio: stdio,
145
      flutterVersion: fakeFlutterVersion,
146 147 148
      logger: bufferLogger,
    );

149
    terminal.addPrompt(const <String>['y', 'n'], 'n');
150 151 152 153 154 155 156

    await createTestCommandRunner(command).run(const <String>['downgrade']);

    expect(bufferLogger.statusText, isNot(contains('Success')));
  });

  testUsingContext('Downgrade does not prompt when there is no terminal', () async {
157
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master');
158
    stdio.hasTerminal = false;
159 160 161 162 163 164 165 166 167
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(
        directory: fileSystem.currentDirectory,
        logger: bufferLogger,
      ),
      processManager: processManager,
      terminal: terminal,
168
      stdio: stdio,
169
      flutterVersion: fakeFlutterVersion,
170 171 172 173 174 175 176 177 178
      logger: bufferLogger,
    );

    await createTestCommandRunner(command).run(const <String>['downgrade']);

    expect(bufferLogger.statusText, contains('Success'));
  });

  testUsingContext('Downgrade performs correct git commands', () async {
179
    final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master');
180
    stdio.hasTerminal = false;
181 182 183 184 185 186 187 188 189 190
    fileSystem.currentDirectory.childFile('.flutter_tool_state')
      .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
    final DowngradeCommand command = DowngradeCommand(
      persistentToolState: PersistentToolState.test(
        directory: fileSystem.currentDirectory,
        logger: bufferLogger,
      ),
      processManager: FakeProcessManager.list(<FakeCommand>[
        const FakeCommand(
          command: <String>[
191
            'git', 'describe', '--tags', 'g6b00b5e88',
192 193 194 195 196
          ],
          stdout: 'v1.2.3',
        ),
        const FakeCommand(
          command: <String>[
197
            'git', 'reset', '--hard', 'g6b00b5e88',
198 199 200 201
          ],
        ),
        const FakeCommand(
          command: <String>[
202 203
            'git', 'checkout', 'master', '--',
          ],
204 205 206
        ),
      ]),
      terminal: terminal,
207
      stdio: stdio,
208
      flutterVersion: fakeFlutterVersion,
209 210 211 212 213 214 215 216 217
      logger: bufferLogger,
    );

    await createTestCommandRunner(command).run(const <String>['downgrade']);

    expect(bufferLogger.statusText, contains('Success'));
  });
}

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
class FakeTerminal extends Fake implements Terminal {
  @override
  bool usesTerminalUi = false;

  void addPrompt(List<String> characters, String selected) {
    _characters = characters;
    _selected = selected;
  }

  List<String> _characters;
  String _selected;

  @override
  Future<String> promptForCharInput(List<String> acceptedCharacters, {Logger logger, String prompt, int defaultChoiceIndex, bool displayAcceptedCharacters = true}) async {
    expect(acceptedCharacters, _characters);
    return _selected;
  }
}

class FakeStdio extends Fake implements Stdio {
  @override
  bool hasTerminal = true;
}