ide_config_test.dart 11.2 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// 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
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/ide_config.dart';
11
import 'package:flutter_tools/src/globals.dart' as globals;
12
import 'package:flutter_tools/src/template.dart';
13

14 15
import '../../src/common.dart';
import '../../src/context.dart';
16
import '../../src/test_flutter_command_runner.dart';
17 18 19

void main() {
  group('ide_config', () {
20
    Directory tempDir;
21 22 23 24
    Directory templateDir;
    Directory intellijDir;
    Directory toolsDir;

25
    Map<String, String> _getFilesystemContents([ Directory root ]) {
26
      final String tempPath = tempDir.absolute.path;
27
      final List<String> paths =
28
        (root ?? tempDir).listSync(recursive: true).map((FileSystemEntity entity) {
29
          final String relativePath = globals.fs.path.relative(entity.path, from: tempPath);
30 31
          return relativePath;
        }).toList();
32
      final Map<String, String> contents = <String, String>{};
33
      for (final String path in paths) {
34 35
        final String absPath = globals.fs.path.join(tempPath, path);
        if (globals.fs.isDirectorySync(absPath)) {
36
          contents[path] = 'dir';
37 38
        } else if (globals.fs.isFileSync(absPath)) {
          contents[path] = globals.fs.file(absPath).readAsStringSync();
39 40 41 42 43
        }
      }
      return contents;
    }

44
    Map<String, String> _getManifest(Directory base, String marker, { bool isTemplate = false }) {
45
      final String basePath = globals.fs.path.relative(base.path, from: tempDir.absolute.path);
46 47
      final String suffix = isTemplate ? Template.copyTemplateExtension : '';
      return <String, String>{
48 49 50 51 52 53 54 55
        globals.fs.path.join(basePath, '.idea'): 'dir',
        globals.fs.path.join(basePath, '.idea', 'modules.xml$suffix'): 'modules $marker',
        globals.fs.path.join(basePath, '.idea', 'vcs.xml$suffix'): 'vcs $marker',
        globals.fs.path.join(basePath, '.idea', '.name$suffix'): 'codeStyleSettings $marker',
        globals.fs.path.join(basePath, '.idea', 'runConfigurations'): 'dir',
        globals.fs.path.join(basePath, '.idea', 'runConfigurations', 'hello_world.xml$suffix'): 'hello_world $marker',
        globals.fs.path.join(basePath, 'flutter.iml$suffix'): 'flutter $marker',
        globals.fs.path.join(basePath, 'packages', 'new', 'deep.iml$suffix'): 'deep $marker',
56
        globals.fs.path.join(basePath, 'example', 'gallery', 'android.iml$suffix'): 'android $marker',
57 58 59 60
      };
    }

    void _populateDir(Map<String, String> manifest) {
61
      for (final String key in manifest.keys) {
62
        if (manifest[key] == 'dir') {
63
          tempDir.childDirectory(key).createSync(recursive: true);
64 65
        }
      }
66
      for (final String key in manifest.keys) {
67
        if (manifest[key] != 'dir') {
68
          tempDir.childFile(key)
69 70 71 72 73 74 75
            ..createSync(recursive: true)
            ..writeAsStringSync(manifest[key]);
        }
      }
    }

    bool _fileOrDirectoryExists(String path) {
76 77
      final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
      return globals.fs.file(absPath).existsSync() || globals.fs.directory(absPath).existsSync();
78 79
    }

80
    Future<void> _updateIdeConfig({
81 82 83 84 85
      Directory dir,
      List<String> args = const <String>[],
      Map<String, String> expectedContents = const <String, String>{},
      List<String> unexpectedPaths = const <String>[],
    }) async {
86
      dir ??= tempDir;
87
      Cache.flutterRoot = tempDir.absolute.path;
88
      final IdeConfigCommand command = IdeConfigCommand();
89
      final CommandRunner<void> runner = createTestCommandRunner(command);
90 91 92 93
      await runner.run(<String>[
        'ide-config',
        ...args,
      ]);
94

95
      for (final String path in expectedContents.keys) {
96 97
        final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
        expect(_fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), true,
98
            reason: "$path doesn't exist");
99 100
        if (globals.fs.file(absPath).existsSync()) {
          expect(globals.fs.file(absPath).readAsStringSync(), equals(expectedContents[path]),
101 102 103
              reason: "$path contents don't match");
        }
      }
104
      for (final String path in unexpectedPaths) {
105
        expect(_fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), false, reason: '$path exists');
106 107 108 109 110 111 112 113
      }
    }

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

    setUp(() {
114
      tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_ide_config_test.');
115
      final Directory packagesDir = tempDir.childDirectory('packages')..createSync(recursive: true);
116 117 118 119 120 121
      toolsDir = packagesDir.childDirectory('flutter_tools')..createSync();
      templateDir = toolsDir.childDirectory('ide_templates')..createSync();
      intellijDir = templateDir.childDirectory('intellij')..createSync();
    });

    tearDown(() {
122
      tryToDelete(tempDir);
123 124 125 126 127 128 129 130 131
    });

    testUsingContext("doesn't touch existing files without --overwrite", () async {
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = _getManifest(
132
        tempDir,
133 134 135 136 137 138 139 140
        'existing',
      );
      _populateDir(templateManifest);
      _populateDir(flutterManifest);
      final Map<String, String> expectedContents = _getFilesystemContents();
      return _updateIdeConfig(
        expectedContents: expectedContents,
      );
141
    });
142 143 144 145 146 147 148 149

    testUsingContext('creates non-existent files', () async {
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = _getManifest(
150
        tempDir,
151 152 153
        'template',
      );
      _populateDir(templateManifest);
154 155 156 157
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...flutterManifest,
      };
158 159 160
      return _updateIdeConfig(
        expectedContents: expectedContents,
      );
161
    });
162 163 164 165 166 167 168 169

    testUsingContext('overwrites existing files with --overwrite', () async {
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = _getManifest(
170
        tempDir,
171 172 173 174 175
        'existing',
      );
      _populateDir(templateManifest);
      _populateDir(flutterManifest);
      final Map<String, String> overwrittenManifest = _getManifest(
176
        tempDir,
177 178
        'template',
      );
179 180 181 182
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...overwrittenManifest,
      };
183 184 185 186
      return _updateIdeConfig(
        args: <String>['--overwrite'],
        expectedContents: expectedContents,
      );
187
    });
188 189 190 191 192 193 194

    testUsingContext('only adds new templates without --overwrite', () async {
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
195
      final String flutterIml = globals.fs.path.join(
196 197 198 199 200 201 202 203 204 205
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij',
        'flutter.iml${Template.copyTemplateExtension}',
      );
      templateManifest.remove(flutterIml);
      _populateDir(templateManifest);
      templateManifest[flutterIml] = 'flutter existing';
      final Map<String, String> flutterManifest = _getManifest(
206
        tempDir,
207 208 209
        'existing',
      );
      _populateDir(flutterManifest);
210 211 212 213
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...templateManifest,
      };
214 215 216 217
      return _updateIdeConfig(
        args: <String>['--update-templates'],
        expectedContents: expectedContents,
      );
218
    });
219 220 221 222 223 224 225 226 227

    testUsingContext('update all templates with --overwrite', () async {
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      _populateDir(templateManifest);
      final Map<String, String> flutterManifest = _getManifest(
228
        tempDir,
229 230 231 232 233 234 235 236
        'existing',
      );
      _populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = _getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
237 238 239 240
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
241 242 243 244
      return _updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
245
    });
246

247
    testUsingContext('removes deleted imls with --overwrite', () async {
248 249 250 251 252 253 254
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      _populateDir(templateManifest);
      final Map<String, String> flutterManifest = _getManifest(
255
        tempDir,
256 257 258 259 260 261 262 263 264
        'existing',
      );
      flutterManifest.remove('flutter.iml');
      _populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = _getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
265
      final String flutterIml = globals.fs.path.join(
266 267 268 269 270 271 272
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij',
        'flutter.iml${Template.copyTemplateExtension}',
      );
      updatedTemplates.remove(flutterIml);
273 274 275 276
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
277 278 279 280
      return _updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
281
    });
282

283
    testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async {
284 285 286 287 288 289 290
      final Map<String, String> templateManifest = _getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      _populateDir(templateManifest);
      final Map<String, String> flutterManifest = _getManifest(
291
        tempDir,
292 293
        'existing',
      );
294
      flutterManifest.remove(globals.fs.path.join('packages', 'new', 'deep.iml'));
295 296 297 298 299 300
      _populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = _getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
301
      String deepIml = globals.fs.path.join(
302 303 304 305 306 307
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij');
      // Remove the all the dir entries too.
      updatedTemplates.remove(deepIml);
308
      deepIml = globals.fs.path.join(deepIml, 'packages');
309
      updatedTemplates.remove(deepIml);
310
      deepIml = globals.fs.path.join(deepIml, 'new');
311
      updatedTemplates.remove(deepIml);
312
      deepIml = globals.fs.path.join(deepIml, 'deep.iml');
313
      updatedTemplates.remove(deepIml);
314 315 316 317
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
318 319 320 321
      return _updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
322
    });
323 324 325

  });
}