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 5 6 7 8
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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';
9
import 'package:flutter_tools/src/globals.dart' as globals;
10
import 'package:flutter_tools/src/template.dart';
11

12 13
import '../../src/common.dart';
import '../../src/context.dart';
14
import '../../src/test_flutter_command_runner.dart';
15 16 17

void main() {
  group('ide_config', () {
18 19 20 21
    late Directory tempDir;
    late Directory templateDir;
    late Directory intellijDir;
    late Directory toolsDir;
22

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

42
    Map<String, String> getManifest(Directory base, String marker, { bool isTemplate = false }) {
43
      final String basePath = globals.fs.path.relative(base.path, from: tempDir.absolute.path);
44 45
      final String suffix = isTemplate ? Template.copyTemplateExtension : '';
      return <String, String>{
46 47 48 49 50 51 52 53
        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',
54
        globals.fs.path.join(basePath, 'example', 'gallery', 'android.iml$suffix'): 'android $marker',
55 56 57
      };
    }

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

73
    bool fileOrDirectoryExists(String path) {
74 75
      final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
      return globals.fs.file(absPath).existsSync() || globals.fs.directory(absPath).existsSync();
76 77
    }

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

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

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

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

    tearDown(() {
120
      tryToDelete(tempDir);
121 122 123
    });

    testUsingContext("doesn't touch existing files without --overwrite", () async {
124
      final Map<String, String> templateManifest = getManifest(
125 126 127 128
        intellijDir,
        'template',
        isTemplate: true,
      );
129
      final Map<String, String> flutterManifest = getManifest(
130
        tempDir,
131 132
        'existing',
      );
133 134 135 136
      populateDir(templateManifest);
      populateDir(flutterManifest);
      final Map<String, String> expectedContents = getFilesystemContents();
      return updateIdeConfig(
137 138
        expectedContents: expectedContents,
      );
139
    });
140 141

    testUsingContext('creates non-existent files', () async {
142
      final Map<String, String> templateManifest = getManifest(
143 144 145 146
        intellijDir,
        'template',
        isTemplate: true,
      );
147
      final Map<String, String> flutterManifest = getManifest(
148
        tempDir,
149 150
        'template',
      );
151
      populateDir(templateManifest);
152 153 154 155
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...flutterManifest,
      };
156
      return updateIdeConfig(
157 158
        expectedContents: expectedContents,
      );
159
    });
160 161

    testUsingContext('overwrites existing files with --overwrite', () async {
162
      final Map<String, String> templateManifest = getManifest(
163 164 165 166
        intellijDir,
        'template',
        isTemplate: true,
      );
167
      final Map<String, String> flutterManifest = getManifest(
168
        tempDir,
169 170
        'existing',
      );
171 172 173
      populateDir(templateManifest);
      populateDir(flutterManifest);
      final Map<String, String> overwrittenManifest = getManifest(
174
        tempDir,
175 176
        'template',
      );
177 178 179 180
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...overwrittenManifest,
      };
181
      return updateIdeConfig(
182 183 184
        args: <String>['--overwrite'],
        expectedContents: expectedContents,
      );
185
    });
186 187

    testUsingContext('only adds new templates without --overwrite', () async {
188
      final Map<String, String> templateManifest = getManifest(
189 190 191 192
        intellijDir,
        'template',
        isTemplate: true,
      );
193
      final String flutterIml = globals.fs.path.join(
194 195 196 197 198 199 200
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij',
        'flutter.iml${Template.copyTemplateExtension}',
      );
      templateManifest.remove(flutterIml);
201
      populateDir(templateManifest);
202
      templateManifest[flutterIml] = 'flutter existing';
203
      final Map<String, String> flutterManifest = getManifest(
204
        tempDir,
205 206
        'existing',
      );
207
      populateDir(flutterManifest);
208 209 210 211
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...templateManifest,
      };
212
      return updateIdeConfig(
213 214 215
        args: <String>['--update-templates'],
        expectedContents: expectedContents,
      );
216
    });
217 218

    testUsingContext('update all templates with --overwrite', () async {
219
      final Map<String, String> templateManifest = getManifest(
220 221 222 223
        intellijDir,
        'template',
        isTemplate: true,
      );
224 225
      populateDir(templateManifest);
      final Map<String, String> flutterManifest = getManifest(
226
        tempDir,
227 228
        'existing',
      );
229 230
      populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = getManifest(
231 232 233 234
        intellijDir,
        'existing',
        isTemplate: true,
      );
235 236 237 238
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
239
      return updateIdeConfig(
240 241 242
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
243
    });
244

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

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

  });
}