Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
3c83c526
Unverified
Commit
3c83c526
authored
Aug 07, 2018
by
Mikkel Nygaard Ravn
Committed by
GitHub
Aug 07, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
FlutterProject refactoring and test coverage (#20296)
parent
e60087a1
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
266 additions
and
143 deletions
+266
-143
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+8
-4
xcodeproj.dart
packages/flutter_tools/lib/src/ios/xcodeproj.dart
+1
-21
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+3
-3
project.dart
packages/flutter_tools/lib/src/project.dart
+88
-87
project_test.dart
packages/flutter_tools/test/project_test.dart
+166
-28
No files found.
packages/flutter_tools/lib/src/android/gradle.dart
View file @
3c83c526
...
...
@@ -200,22 +200,26 @@ distributionUrl=https\\://services.gradle.org/distributions/gradle-$gradleVersio
}
}
/// Overwrite android/local.properties in the specified Flutter project, if needed.
/// Overwrite local.properties in the specified Flutter project's Android
/// sub-project, if needed.
///
/// Throws
, if `pubspec.yaml` or Android SDK cannot be locate
d.
/// Throws
tool exit, if `pubspec.yaml` is invali
d.
///
/// If [requireSdk] is `true` this will fail with a tool
-
exit if no Android Sdk
/// If [requireSdk] is `true` this will fail with a tool
exit if no Android Sdk
/// is found.
Future
<
void
>
updateLocalProperties
({
@required
FlutterProject
project
,
BuildInfo
buildInfo
,
bool
requireAndroidSdk
=
true
,
})
async
{
if
(
project
.
manifest
==
null
)
{
throwToolExit
(
'Invalid `pubspec.yaml`'
);
}
if
(
requireAndroidSdk
&&
androidSdk
==
null
)
{
throwToolExit
(
'Unable to locate Android SDK. Please run `flutter doctor` for more details.'
);
}
final
File
localProperties
=
project
.
android
L
ocalPropertiesFile
;
final
File
localProperties
=
project
.
android
.
l
ocalPropertiesFile
;
bool
changed
=
false
;
SettingsFile
settings
;
...
...
packages/flutter_tools/lib/src/ios/xcodeproj.dart
View file @
3c83c526
...
...
@@ -15,7 +15,6 @@ import '../base/process.dart';
import
'../base/process_manager.dart'
;
import
'../base/utils.dart'
;
import
'../build_info.dart'
;
import
'../bundle.dart'
as
bundle
;
import
'../cache.dart'
;
import
'../flutter_manifest.dart'
;
import
'../globals.dart'
;
...
...
@@ -28,25 +27,6 @@ String flutterFrameworkDir(BuildMode mode) {
return
fs
.
path
.
normalize
(
fs
.
path
.
dirname
(
artifacts
.
getArtifactPath
(
Artifact
.
flutterFramework
,
TargetPlatform
.
ios
,
mode
)));
}
/// Writes default Xcode properties files in the Flutter project at [projectPath],
/// if project is an iOS project and such files are out of date or do not
/// already exist.
Future
<
void
>
generateXcodeProperties
({
FlutterProject
project
})
async
{
if
(
project
.
manifest
.
isModule
||
project
.
ios
.
directory
.
existsSync
())
{
if
(!
Cache
.
instance
.
fileOlderThanToolsStamp
(
project
.
generatedXcodePropertiesFile
))
{
return
;
}
await
updateGeneratedXcodeProperties
(
project:
project
,
buildInfo:
BuildInfo
.
debug
,
targetOverride:
bundle
.
defaultMainPath
,
previewDart2:
true
,
);
}
}
/// Writes or rewrites Xcode property files with the specified information.
///
/// targetOverride: Optional parameter, if null or unspecified the default value
...
...
@@ -119,7 +99,7 @@ Future<void> updateGeneratedXcodeProperties({
localsBuffer
.
writeln
(
'TRACK_WIDGET_CREATION=true'
);
}
final
File
generatedXcodePropertiesFile
=
project
.
generatedXcodePropertiesFile
;
final
File
generatedXcodePropertiesFile
=
project
.
ios
.
generatedXcodePropertiesFile
;
generatedXcodePropertiesFile
.
createSync
(
recursive:
true
);
generatedXcodePropertiesFile
.
writeAsStringSync
(
localsBuffer
.
toString
());
}
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
3c83c526
...
...
@@ -158,7 +158,7 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
};
final
String
javaSourcePath
=
fs
.
path
.
join
(
project
.
android
P
luginRegistrantHost
.
path
,
project
.
android
.
p
luginRegistrantHost
.
path
,
'src'
,
'main'
,
'java'
,
...
...
@@ -247,8 +247,8 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
'plugins'
:
iosPlugins
,
};
final
String
registryDirectory
=
project
.
ios
P
luginRegistrantHost
.
path
;
if
(
project
.
manifest
.
isModule
)
{
final
String
registryDirectory
=
project
.
ios
.
p
luginRegistrantHost
.
path
;
if
(
project
.
isModule
)
{
final
String
registryClassesDirectory
=
fs
.
path
.
join
(
registryDirectory
,
'Classes'
);
_renderTemplateToFile
(
_iosPluginRegistrantPodspecTemplate
,
...
...
packages/flutter_tools/lib/src/project.dart
View file @
3c83c526
...
...
@@ -5,8 +5,11 @@
import
'dart:async'
;
import
'dart:convert'
;
import
'package:meta/meta.dart'
;
import
'android/gradle.dart'
as
gradle
;
import
'base/file_system.dart'
;
import
'build_info.dart'
;
import
'bundle.dart'
as
bundle
;
import
'cache.dart'
;
import
'flutter_manifest.dart'
;
...
...
@@ -16,21 +19,27 @@ import 'template.dart';
/// Represents the contents of a Flutter project at the specified [directory].
///
/// Instances should be treated as immutable snapshots, to be replaced by new
/// instances on changes to `pubspec.yaml` files.
/// [FlutterManifest] information is read from `pubspec.yaml` and
/// `example/pubspec.yaml` files on construction of a [FlutterProject] instance.
/// The constructed instance carries an immutable snapshot representation of the
/// presence and content of those files. Accordingly, [FlutterProject] instances
/// should be discarded upon changes to the `pubspec.yaml` files, but can be
/// used across changes to other files, as no other file-level information is
/// cached.
class
FlutterProject
{
FlutterProject
.
_
(
this
.
directory
,
this
.
manifest
,
this
.
_exampleManifest
);
@visibleForTesting
FlutterProject
(
this
.
directory
,
this
.
manifest
,
this
.
_exampleManifest
);
/// Returns a future that completes with a FlutterProject view of the given directory.
static
Future
<
FlutterProject
>
fromDirectory
(
Directory
directory
)
async
{
final
FlutterManifest
manifest
=
await
FlutterManifest
.
createFromPath
(
directory
.
childFile
(
bundle
.
defaultManifestPath
).
path
,
);
final
Directory
exampleDirectory
=
directory
.
childDirectory
(
'example'
);
final
Directory
exampleDirectory
=
_exampleDirectory
(
directory
);
final
FlutterManifest
exampleManifest
=
await
FlutterManifest
.
createFromPath
(
exampleDirectory
.
childFile
(
bundle
.
defaultManifestPath
).
path
,
);
return
new
FlutterProject
.
_
(
directory
,
manifest
,
exampleManifest
);
return
new
FlutterProject
(
directory
,
manifest
,
exampleManifest
);
}
/// Returns a future that completes with a FlutterProject view of the current directory.
...
...
@@ -73,83 +82,56 @@ class FlutterProject {
}
/// The iOS sub project of this project.
IosProject
get
ios
=>
new
IosProject
(
directory
.
childDirectory
(
'ios'
)
);
IosProject
get
ios
=>
new
IosProject
.
_
(
this
);
/// The Android sub project of this project.
AndroidProject
get
android
{
if
(
manifest
.
isModule
)
{
return
new
AndroidProject
(
directory
.
childDirectory
(
'.android'
));
}
return
new
AndroidProject
(
directory
.
childDirectory
(
'android'
));
}
/// The generated AndroidModule sub project of this module project.
AndroidModuleProject
get
androidModule
=>
new
AndroidModuleProject
(
directory
.
childDirectory
(
'.android'
));
/// The generated IosModule sub project of this module project.
IosModuleProject
get
iosModule
=>
new
IosModuleProject
(
directory
.
childDirectory
(
'.ios'
));
File
get
androidLocalPropertiesFile
{
return
directory
.
childDirectory
(
manifest
.
isModule
?
'.android'
:
'android'
)
.
childFile
(
'local.properties'
);
}
File
get
generatedXcodePropertiesFile
{
return
directory
.
childDirectory
(
manifest
.
isModule
?
'.ios'
:
'ios'
)
.
childDirectory
(
'Flutter'
)
.
childFile
(
'Generated.xcconfig'
);
}
AndroidProject
get
android
=>
new
AndroidProject
.
_
(
this
);
File
get
flutterPluginsFile
=>
directory
.
childFile
(
'.flutter-plugins'
);
Directory
get
androidPluginRegistrantHost
{
return
manifest
.
isModule
?
directory
.
childDirectory
(
'.android'
).
childDirectory
(
'Flutter'
)
:
directory
.
childDirectory
(
'android'
).
childDirectory
(
'app'
);
}
Directory
get
iosPluginRegistrantHost
{
// In a module create the GeneratedPluginRegistrant as a pod to be included
// from a hosting app.
// For a non-module create the GeneratedPluginRegistrant as source files
// directly in the iOS project.
return
manifest
.
isModule
?
directory
.
childDirectory
(
'.ios'
).
childDirectory
(
'Flutter'
).
childDirectory
(
'FlutterPluginRegistrant'
)
:
directory
.
childDirectory
(
'ios'
).
childDirectory
(
'Runner'
);
}
/// The example sub-project of this project.
FlutterProject
get
example
=>
new
FlutterProject
.
_
(
_exampleDirectory
,
_exampleManifest
,
FlutterManifest
.
empty
());
FlutterProject
get
example
=>
new
FlutterProject
(
_exampleDirectory
(
directory
),
_exampleManifest
,
FlutterManifest
.
empty
(),
);
bool
get
isModule
=>
manifest
!=
null
&&
manifest
.
isModule
;
/// True, if this project has an example application
bool
get
hasExampleApp
=>
_exampleDirectory
.
childFile
(
'pubspec.yaml'
).
existsSync
();
/// True, if this project has an example application
.
bool
get
hasExampleApp
=>
_exampleDirectory
(
directory
).
existsSync
();
/// The directory that will contain the example if an example exists.
Directory
get
_exampleDirectory
=>
directory
.
childDirectory
(
'example'
);
static
Directory
_exampleDirectory
(
Directory
directory
)
=>
directory
.
childDirectory
(
'example'
);
/// Generates project files necessary to make Gradle builds work on Android
/// and CocoaPods+Xcode work on iOS, for app and module projects only.
Future
<
void
>
ensureReadyForPlatformSpecificTooling
()
async
{
if
(!
directory
.
existsSync
()
||
hasExampleApp
)
{
if
(!
directory
.
existsSync
()
||
hasExampleApp
)
return
;
}
if
(
manifest
.
isModule
)
{
await
androidModule
.
ensureReadyForPlatformSpecificTooling
(
this
);
await
iosModule
.
ensureReadyForPlatformSpecificTooling
();
}
await
xcode
.
generateXcodeProperties
(
project:
this
);
await
android
.
ensureReadyForPlatformSpecificTooling
();
await
ios
.
ensureReadyForPlatformSpecificTooling
();
await
injectPlugins
(
this
);
}
}
/// Represents the contents of the ios/ folder of a Flutter project.
/// Represents the iOS sub-project of a Flutter project.
///
/// Instances will reflect the contents of the `ios/` sub-folder of
/// Flutter applications and the `.ios/` sub-folder of Flutter modules.
class
IosProject
{
static
final
RegExp
_productBundleIdPattern
=
new
RegExp
(
r'^\s*PRODUCT_BUNDLE_IDENTIFIER\s*=\s*(.*);\s*$'
);
IosProject
(
this
.
directory
);
final
Directory
directory
;
IosProject
.
_
(
this
.
parent
);
/// The parent of this project.
final
FlutterProject
parent
;
/// The directory of this project.
Directory
get
directory
=>
parent
.
directory
.
childDirectory
(
isModule
?
'.ios'
:
'ios'
);
/// True, if the parent Flutter project is a module.
bool
get
isModule
=>
parent
.
isModule
;
/// The xcode config file for [mode].
File
xcodeConfigFor
(
String
mode
)
=>
directory
.
childDirectory
(
'Flutter'
).
childFile
(
'
$mode
.xcconfig'
);
...
...
@@ -167,33 +149,55 @@ class IosProject {
final
File
projectFile
=
directory
.
childDirectory
(
'Runner.xcodeproj'
).
childFile
(
'project.pbxproj'
);
return
_firstMatchInFile
(
projectFile
,
_productBundleIdPattern
).
then
((
Match
match
)
=>
match
?.
group
(
1
));
}
}
/// Represents the contents of the .ios/ folder of a Flutter module
/// project.
class
IosModuleProject
{
IosModuleProject
(
this
.
directory
);
final
Directory
directory
;
Future
<
void
>
ensureReadyForPlatformSpecificTooling
()
async
{
if
(
_shouldRegener
ate
())
{
if
(
isModule
&&
_shouldRegenerateFromTempl
ate
())
{
final
Template
template
=
new
Template
.
fromName
(
fs
.
path
.
join
(
'module'
,
'ios'
));
template
.
render
(
directory
,
<
String
,
dynamic
>{},
printStatusWhenWriting:
false
);
}
if
(!
directory
.
existsSync
())
return
;
if
(
Cache
.
instance
.
fileOlderThanToolsStamp
(
generatedXcodePropertiesFile
))
{
await
xcode
.
updateGeneratedXcodeProperties
(
project:
parent
,
buildInfo:
BuildInfo
.
debug
,
targetOverride:
bundle
.
defaultMainPath
,
previewDart2:
true
,
);
}
}
bool
_shouldRegenerate
()
{
bool
_shouldRegenerate
FromTemplate
()
{
return
Cache
.
instance
.
fileOlderThanToolsStamp
(
directory
.
childFile
(
'podhelper.rb'
));
}
File
get
generatedXcodePropertiesFile
=>
directory
.
childDirectory
(
'Flutter'
).
childFile
(
'Generated.xcconfig'
);
Directory
get
pluginRegistrantHost
{
return
isModule
?
directory
.
childDirectory
(
'Flutter'
).
childDirectory
(
'FlutterPluginRegistrant'
)
:
directory
.
childDirectory
(
'Runner'
);
}
}
/// Represents the contents of the android/ folder of a Flutter project.
/// Represents the Android sub-project of a Flutter project.
///
/// Instances will reflect the contents of the `android/` sub-folder of
/// Flutter applications and the `.android/` sub-folder of Flutter modules.
class
AndroidProject
{
static
final
RegExp
_applicationIdPattern
=
new
RegExp
(
'^
\\
s*applicationId
\\
s+[
\'\"
](.*)[
\'\"
]
\\
s*
\$
'
);
static
final
RegExp
_groupPattern
=
new
RegExp
(
'^
\\
s*group
\\
s+[
\'\"
](.*)[
\'\"
]
\\
s*
\$
'
);
AndroidProject
(
this
.
directory
);
AndroidProject
.
_
(
this
.
parent
);
/// The parent of this project.
final
FlutterProject
parent
;
/// The directory of this project.
Directory
get
directory
=>
parent
.
directory
.
childDirectory
(
isModule
?
'.android'
:
'android'
);
/// True, if the parent Flutter project is a module.
bool
get
isModule
=>
parent
.
isModule
;
File
get
gradleManifestFile
{
return
isUsingGradle
()
...
...
@@ -211,8 +215,6 @@ class AndroidProject {
return
directory
.
childFile
(
'build.gradle'
).
existsSync
();
}
final
Directory
directory
;
Future
<
String
>
applicationId
()
{
final
File
gradleFile
=
directory
.
childDirectory
(
'app'
).
childFile
(
'build.gradle'
);
return
_firstMatchInFile
(
gradleFile
,
_applicationIdPattern
).
then
((
Match
match
)
=>
match
?.
group
(
1
));
...
...
@@ -222,32 +224,31 @@ class AndroidProject {
final
File
gradleFile
=
directory
.
childFile
(
'build.gradle'
);
return
_firstMatchInFile
(
gradleFile
,
_groupPattern
).
then
((
Match
match
)
=>
match
?.
group
(
1
));
}
}
/// Represents the contents of the .android/ folder of a Flutter module project.
class
AndroidModuleProject
{
AndroidModuleProject
(
this
.
directory
);
final
Directory
directory
;
Future
<
void
>
ensureReadyForPlatformSpecificTooling
(
FlutterProject
project
)
async
{
if
(
_shouldRegenerate
())
{
Future
<
void
>
ensureReadyForPlatformSpecificTooling
()
async
{
if
(
isModule
&&
_shouldRegenerateFromTemplate
())
{
final
Template
template
=
new
Template
.
fromName
(
fs
.
path
.
join
(
'module'
,
'android'
));
template
.
render
(
directory
,
<
String
,
dynamic
>{
'androidIdentifier'
:
p
rojec
t
.
manifest
.
androidPackage
,
'androidIdentifier'
:
p
aren
t
.
manifest
.
androidPackage
,
},
printStatusWhenWriting:
false
,
);
gradle
.
injectGradleWrapper
(
directory
);
}
await
gradle
.
updateLocalProperties
(
project:
project
,
requireAndroidSdk:
false
);
if
(!
directory
.
existsSync
())
return
;
await
gradle
.
updateLocalProperties
(
project:
parent
,
requireAndroidSdk:
false
);
}
bool
_shouldRegenerate
()
{
bool
_shouldRegenerate
FromTemplate
()
{
return
Cache
.
instance
.
fileOlderThanToolsStamp
(
directory
.
childFile
(
'build.gradle'
));
}
File
get
localPropertiesFile
=>
directory
.
childFile
(
'local.properties'
);
Directory
get
pluginRegistrantHost
=>
directory
.
childDirectory
(
isModule
?
'Flutter'
:
'app'
);
}
/// Asynchronously returns the first line-based match for [regExp] in [file].
...
...
packages/flutter_tools/test/project_test.dart
View file @
3c83c526
...
...
@@ -3,12 +3,14 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter_tools/src/base/context.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/flutter_manifest.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:test/test.dart'
;
import
'package:file/file.dart'
;
import
'package:file/memory.dart'
;
import
'src/context.dart'
;
void
main
(
)
{
...
...
@@ -23,73 +25,151 @@ void main() {
(
await
FlutterProject
.
fromPath
(
directory
.
path
)).
directory
.
absolute
.
path
,
directory
.
absolute
.
path
,
);
expect
(
(
await
FlutterProject
.
current
()).
directory
.
absolute
.
path
,
fs
.
currentDirectory
.
absolute
.
path
,
);
});
group
(
'ensure ready for platform-specific tooling'
,
()
{
testInMemory
(
'does nothing, if project is not created'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
new
FlutterProject
(
fs
.
directory
(
'not_created'
),
FlutterManifest
.
empty
(),
FlutterManifest
.
empty
(),
);
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
directory
.
existsSync
(),
isFalse
);
});
testInMemory
(
'does nothing in plugin or package root project'
,
()
async
{
final
FlutterProject
project
=
a
wait
a
PluginProject
();
final
FlutterProject
project
=
aPluginProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isFalse
);
expect
(
project
.
android
.
directory
.
childFile
(
'app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java'
,
).
existsSync
(),
isFalse
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isFalse
);
expect
(
project
.
android
.
directory
.
childFile
(
'local.properties'
).
existsSync
(),
isFalse
);
});
testInMemory
(
'injects plugins'
,
()
async
{
final
FlutterProject
project
=
await
aProjectWithIos
();
testInMemory
(
'injects plugins
for iOS
'
,
()
async
{
final
FlutterProject
project
=
someProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isTrue
);
});
testInMemory
(
'generates Xcode configuration'
,
()
async
{
final
FlutterProject
project
=
await
aProjectWithIos
();
testInMemory
(
'generates Xcode configuration
for iOS
'
,
()
async
{
final
FlutterProject
project
=
someProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isTrue
);
});
testInMemory
(
'injects plugins for Android'
,
()
async
{
final
FlutterProject
project
=
someProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
android
.
directory
.
childFile
(
'app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java'
,
).
existsSync
(),
isTrue
);
});
testInMemory
(
'updates local properties for Android'
,
()
async
{
final
FlutterProject
project
=
someProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
android
.
directory
.
childFile
(
'local.properties'
).
existsSync
(),
isTrue
);
});
testInMemory
(
'creates Android library in module'
,
()
async
{
final
FlutterProject
project
=
aModuleProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
android
.
directory
.
childFile
(
'template_content'
).
existsSync
(),
isTrue
);
expect
(
project
.
android
.
directory
.
childFile
(
'local.properties'
).
existsSync
(),
isTrue
);
expect
(
project
.
android
.
directory
.
childFile
(
'Flutter/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java'
,
).
existsSync
(),
isTrue
);
});
testInMemory
(
'creates iOS pod in module'
,
()
async
{
final
FlutterProject
project
=
aModuleProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
final
Directory
flutter
=
project
.
ios
.
directory
.
childDirectory
(
'Flutter'
);
expect
(
flutter
.
childFile
(
'template_content'
).
existsSync
(),
isTrue
);
expect
(
flutter
.
childFile
(
'Generated.xcconfig'
).
existsSync
(),
isTrue
);
expect
(
flutter
.
childFile
(
'FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.h'
,
).
existsSync
(),
isTrue
);
expect
(
flutter
.
childFile
(
'FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.m'
,
).
existsSync
(),
isTrue
);
});
});
group
(
'module status'
,
()
{
testInMemory
(
'is known for module'
,
()
async
{
final
FlutterProject
project
=
aModuleProject
();
expect
(
project
.
isModule
,
isTrue
);
expect
(
project
.
android
.
isModule
,
isTrue
);
expect
(
project
.
ios
.
isModule
,
isTrue
);
expect
(
project
.
android
.
directory
.
path
,
startsWith
(
'module_project/.android'
));
expect
(
project
.
ios
.
directory
.
path
,
startsWith
(
'module_project/.ios'
));
});
testInMemory
(
'is known for non-module'
,
()
async
{
final
FlutterProject
project
=
someProject
();
expect
(
project
.
isModule
,
isFalse
);
expect
(
project
.
android
.
isModule
,
isFalse
);
expect
(
project
.
ios
.
isModule
,
isFalse
);
expect
(
project
.
android
.
directory
.
path
,
startsWith
(
'some_project/android'
));
expect
(
project
.
ios
.
directory
.
path
,
startsWith
(
'some_project/ios'
));
});
});
group
(
'example'
,
()
{
testInMemory
(
'exists for plugin'
,
()
async
{
final
FlutterProject
project
=
aPluginProject
();
expect
(
project
.
hasExampleApp
,
isTrue
);
});
testInMemory
(
'does not exist for non-plugin'
,
()
async
{
final
FlutterProject
project
=
someProject
();
expect
(
project
.
hasExampleApp
,
isFalse
);
});
});
group
(
'organization names set'
,
()
{
testInMemory
(
'is empty, if project not created'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
expect
(
await
project
.
organizationNames
(),
isEmpty
);
});
testInMemory
(
'is empty, if no platform folders exist'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
project
.
directory
.
createSync
();
expect
(
await
project
.
organizationNames
(),
isEmpty
);
});
testInMemory
(
'is populated from iOS bundle identifier'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is populated from Android application ID'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is populated from iOS bundle identifier in plugin example'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addIosWithBundleId
(
project
.
example
.
directory
,
'io.flutter.someProject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is populated from Android application ID in plugin example'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addAndroidWithApplicationId
(
project
.
example
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is populated from Android group in plugin'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addAndroidWithGroup
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is singleton, if sources agree'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
testInMemory
(
'is non-singleton, if sources disagree'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.clutter.someproject'
);
expect
(
...
...
@@ -101,30 +181,88 @@ void main() {
});
}
Future
<
FlutterProject
>
someProject
()
=>
FlutterProject
.
fromPath
(
'some_project'
);
Future
<
FlutterProject
>
aProjectWithIos
()
{
final
Directory
directory
=
fs
.
directory
(
'ios_project'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
FlutterProject
someProject
(
)
{
final
Directory
directory
=
fs
.
directory
(
'some_project'
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
FlutterProject
.
fromDirectory
(
directory
);
directory
.
childDirectory
(
'android'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
,
FlutterManifest
.
empty
(),
FlutterManifest
.
empty
(),
);
}
Future
<
FlutterProject
>
aPluginProject
()
{
final
Directory
directory
=
fs
.
directory
(
'plugin_project/example'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
FlutterProject
aPluginProject
(
)
{
final
Directory
directory
=
fs
.
directory
(
'plugin_project'
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
FlutterProject
.
fromDirectory
(
directory
.
parent
);
directory
.
childDirectory
(
'android'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'example'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
,
FlutterManifest
.
mock
(
const
<
String
,
dynamic
>{
'flutter'
:
<
String
,
dynamic
>{
'plugin'
:
<
String
,
dynamic
>{}
}
}),
FlutterManifest
.
empty
(),
);
}
FlutterProject
aModuleProject
(
)
{
final
Directory
directory
=
fs
.
directory
(
'module_project'
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
,
FlutterManifest
.
mock
(
const
<
String
,
dynamic
>{
'flutter'
:
<
String
,
dynamic
>{
'module'
:
<
String
,
dynamic
>{
'androidPackage'
:
'com.example'
}
}
}),
FlutterManifest
.
empty
(),
);
}
void
testInMemory
(
String
description
,
Future
<
Null
>
testMethod
())
{
Cache
.
flutterRoot
=
'flutter'
;
final
FileSystem
fs
=
new
MemoryFileSystem
();
// Pretend we have a Flutter module project template.
fs
.
directory
(
Cache
.
flutterRoot
)
.
childDirectory
(
'packages'
)
.
childDirectory
(
'flutter_tools'
)
.
childDirectory
(
'templates'
)
.
childDirectory
(
'module'
)
.
childDirectory
(
'android'
)
.
childFile
(
'template_content.copy.tmpl'
)
.
createSync
(
recursive:
true
);
fs
.
directory
(
Cache
.
flutterRoot
)
.
childDirectory
(
'packages'
)
.
childDirectory
(
'flutter_tools'
)
.
childDirectory
(
'templates'
)
.
childDirectory
(
'module'
)
.
childDirectory
(
'ios'
)
.
childDirectory
(
'Flutter.tmpl'
)
.
childFile
(
'template_content.copy.tmpl'
)
.
createSync
(
recursive:
true
);
// Sets up cache in a test execution context where `fs` is the file system.
Cache
cacheCreator
()
{
final
Cache
cache
=
new
Cache
(
rootOverride:
fs
.
directory
(
'flutter'
));
cache
.
getArtifactDirectory
(
'gradle_wrapper'
)
.
childDirectory
(
'gradle'
)
.
childDirectory
(
'wrapper'
)
.
childFile
(
'gradle-wrapper.properties'
)
.
createSync
(
recursive:
true
);
return
cache
;
}
testUsingContext
(
description
,
testMethod
,
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
new
MemoryFileSystem
(),
FileSystem:
()
=>
fs
,
Cache:
cacheCreator
,
},
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment