In-line the package:stagehand templates into 'dart create'.

Change-Id: I717f0970314700b123b750fcfe7ed066ba88d2e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192944
Commit-Queue: Devon Carew <devoncarew@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Devon Carew
2021-03-25 18:05:09 +00:00
committed by commit-bot@chromium.org
parent e9d7ad78e4
commit f6ce7a829f
16 changed files with 787 additions and 39 deletions
+1 -7
View File
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
"generated": "2021-03-24T12:15:31.538873",
"generated": "2021-03-24T13:42:28.071470",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -637,12 +637,6 @@
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "stagehand",
"rootUri": "../third_party/pkg/stagehand",
"packageUri": "lib/",
"languageVersion": "2.10"
},
{
"name": "status_file",
"rootUri": "../pkg/status_file",
-1
View File
@@ -95,7 +95,6 @@ source_maps:third_party/pkg/source_maps/lib
source_span:third_party/pkg/source_span/lib
sse:third_party/pkg/sse/lib
stack_trace:third_party/pkg/stack_trace/lib
stagehand:third_party/pkg/stagehand/lib
status_file:pkg/status_file/lib
stream_channel:third_party/pkg/stream_channel/lib
string_scanner:third_party/pkg/string_scanner/lib
-3
View File
@@ -152,7 +152,6 @@ vars = {
"source_span_rev": "1be3c44045a06dff840d2ed3a13e6082d7a03a23",
"sse_tag": "5da8fedcdc56f306933d202e2d204753eecefd36",
"stack_trace_tag": "6788afc61875079b71b3d1c3e65aeaa6a25cbc2f",
"stagehand_rev": "e64ac90cac508981011299c4ceb819149e71f1bd",
"stream_channel_tag": "d7251e61253ec389ee6e045ee1042311bced8f1d",
"string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
"sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
@@ -430,8 +429,6 @@ deps = {
Var("dart_git") + "sse.git" + "@" + Var("sse_tag"),
Var("dart_root") + "/third_party/pkg/stack_trace":
Var("dart_git") + "stack_trace.git" + "@" + Var("stack_trace_tag"),
Var("dart_root") + "/third_party/pkg/stagehand":
Var("dart_git") + "stagehand.git" + "@" + Var("stagehand_rev"),
Var("dart_root") + "/third_party/pkg/stream_channel":
Var("dart_git") + "stream_channel.git" +
"@" + Var("stream_channel_tag"),
+11 -21
View File
@@ -8,10 +8,10 @@ import 'dart:io' as io;
import 'dart:math' as math;
import 'package:path/path.dart' as p;
import 'package:stagehand/stagehand.dart' as stagehand;
import '../core.dart';
import '../sdk.dart';
import '../templates.dart';
/// A command to create a new project from a set of templates.
class CreateCommand extends DartdevCommand {
@@ -19,18 +19,8 @@ class CreateCommand extends DartdevCommand {
static String defaultTemplateId = 'console-simple';
static List<String> legalTemplateIds = [
'console-simple',
'console-full',
'package-simple',
'web-simple'
];
static Iterable<stagehand.Generator> get generators =>
legalTemplateIds.map(retrieveTemplateGenerator);
static stagehand.Generator retrieveTemplateGenerator(String templateId) =>
stagehand.getGenerator(templateId);
static final List<String> legalTemplateIds =
generators.map((generator) => generator.id).toList();
CreateCommand({bool verbose = false})
: super(cmdName, 'Create a new Dart project.') {
@@ -91,8 +81,8 @@ class CreateCommand extends DartdevCommand {
);
log.stdout('');
var generator = retrieveTemplateGenerator(templateId);
await generator.generate(
var generator = getGenerator(templateId);
generator.generate(
p.basename(dir),
DirectoryGeneratorTarget(generator, io.Directory(dir)),
);
@@ -151,7 +141,7 @@ class CreateCommand extends DartdevCommand {
}
String _availableTemplatesJson() {
var items = generators.map((stagehand.Generator generator) {
var items = generators.map((Generator generator) {
var m = {
'name': generator.id,
'label': generator.label,
@@ -171,8 +161,8 @@ class CreateCommand extends DartdevCommand {
}
}
class DirectoryGeneratorTarget extends stagehand.GeneratorTarget {
final stagehand.Generator generator;
class DirectoryGeneratorTarget extends GeneratorTarget {
final Generator generator;
final io.Directory dir;
DirectoryGeneratorTarget(this.generator, this.dir) {
@@ -180,13 +170,13 @@ class DirectoryGeneratorTarget extends stagehand.GeneratorTarget {
}
@override
Future createFile(String path, List<int> contents) async {
void createFile(String path, List<int> contents) {
io.File file = io.File(p.join(dir.path, path));
String name = p.relative(file.path, from: dir.path);
log.stdout(' $name');
await file.create(recursive: true);
await file.writeAsBytes(contents);
file.createSync(recursive: true);
file.writeAsBytesSync(contents);
}
}
+195
View File
@@ -0,0 +1,195 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert' show utf8;
import 'package:meta/meta.dart';
import 'templates/console_full.dart';
import 'templates/console_simple.dart';
import 'templates/package_simple.dart';
import 'templates/server_simple.dart';
import 'templates/web_simple.dart';
final _substituteRegExp = RegExp(r'__([a-zA-Z]+)__');
final _nonValidSubstituteRegExp = RegExp('[^a-zA-Z]');
final List<Generator> generators = [
ConsoleSimpleGenerator(),
ConsoleFullGenerator(),
PackageSimpleGenerator(),
ServerSimpleGenerator(),
WebSimpleGenerator(),
];
Generator getGenerator(String id) =>
generators.firstWhere((g) => g.id == id, orElse: () => null);
/// An abstract class which both defines a template generator and can generate a
/// user project based on this template.
abstract class Generator implements Comparable<Generator> {
final String id;
final String label;
final String description;
final List<String> categories;
final List<TemplateFile> files = [];
TemplateFile _entrypoint;
Generator(
this.id,
this.label,
this.description, {
this.categories = const [],
});
/// The entrypoint of the application; the main file for the project, which an
/// IDE might open after creating the project.
TemplateFile get entrypoint => _entrypoint;
TemplateFile addFile(String path, String contents) {
return addTemplateFile(TemplateFile(path, contents));
}
/// Add a new template file.
TemplateFile addTemplateFile(TemplateFile file) {
files.add(file);
return file;
}
/// Return the template file wih the given [path].
TemplateFile getFile(String path) =>
files.firstWhere((file) => file.path == path, orElse: () => null);
/// Set the main entrypoint of this template. This is the 'most important'
/// file of this template. An IDE might use this information to open this file
/// after the user's project is generated.
void setEntrypoint(TemplateFile entrypoint) {
if (_entrypoint != null) throw StateError('entrypoint already set');
if (entrypoint == null) throw StateError('entrypoint is null');
_entrypoint = entrypoint;
}
void generate(
String projectName,
GeneratorTarget target, {
Map<String, String> additionalVars,
}) {
final vars = {
'projectName': projectName,
'description': description,
'year': DateTime.now().year.toString(),
'author': '<your name>',
if (additionalVars != null) ...additionalVars,
};
for (TemplateFile file in files) {
final resultFile = file.runSubstitution(vars);
final filePath = resultFile.path;
target.createFile(filePath, resultFile.content);
}
}
int numFiles() => files.length;
@override
int compareTo(Generator other) =>
id.toLowerCase().compareTo(other.id.toLowerCase());
/// Return some user facing instructions about how to finish installation of
/// the template.
String getInstallInstructions() => '';
@override
String toString() => '[$id: $description]';
}
/// An abstract implementation of a [Generator].
abstract class DefaultGenerator extends Generator {
DefaultGenerator(
String id,
String label,
String description, {
List<String> categories = const [],
}) : super(id, label, description, categories: categories);
}
/// A target for a [Generator]. This class knows how to create files given a
/// path for the file (relative to the particular [GeneratorTarget] instance),
/// and the binary content for the file.
abstract class GeneratorTarget {
/// Create a file at the given path with the given contents.
void createFile(String path, List<int> contents);
}
/// This class represents a file in a generator template. The contents could
/// either be binary or text. If text, the contents may contain mustache
/// variables that can be substituted (`__myVar__`).
class TemplateFile {
final String path;
final String content;
TemplateFile(this.path, this.content);
FileContents runSubstitution(Map<String, String> parameters) {
if (path == 'pubspec.yaml' && parameters['author'] == '<your name>') {
parameters = Map.from(parameters);
parameters['author'] = 'Your Name';
}
final newPath = substituteVars(path, parameters);
final newContents = _createContent(parameters);
return FileContents(newPath, newContents);
}
List<int> _createContent(Map<String, String> vars) {
return utf8.encode(substituteVars(content, vars));
}
}
class FileContents {
final String path;
final List<int> content;
FileContents(this.path, this.content);
}
/// Given a `String` [str] with mustache templates, and a [Map] of String key /
/// value pairs, substitute all instances of `__key__` for `value`. I.e.,
///
/// ```
/// Foo __projectName__ baz.
/// ```
///
/// and
///
/// ```
/// {'projectName': 'bar'}
/// ```
///
/// becomes:
///
/// ```
/// Foo bar baz.
/// ```
///
/// A key value can only be an ASCII string made up of letters: A-Z, a-z.
/// No whitespace, numbers, or other characters are allowed.
@visibleForTesting
String substituteVars(String str, Map<String, String> vars) {
if (vars.keys.any((element) => element.contains(_nonValidSubstituteRegExp))) {
throw ArgumentError('vars.keys can only contain letters.');
}
return str.replaceAllMapped(_substituteRegExp, (match) {
final item = vars[match[1]];
if (item == null) {
return match[0];
} else {
return item;
}
});
}
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
final String gitignore = '''
# Files and directories created by pub.
.dart_tool/
.packages
# Conventional directory for build output.
build/
''';
final String analysisOptions = '''
# Defines a default set of lint rules enforced for projects at Google. For
# details and rationale, see
# https://github.com/dart-lang/pedantic#enabled-lints.
include: package:pedantic/analysis_options.yaml
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
# Uncomment to specify additional rules.
# linter:
# rules:
# - camel_case_types
# analyzer:
# exclude:
# - path/to/excluded/files/**
''';
final String changelog = '''
## 1.0.0
- Initial version.
''';
@@ -0,0 +1,76 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import '../templates.dart';
import 'common.dart' as common;
/// A generator for a hello world command-line application.
class ConsoleFullGenerator extends DefaultGenerator {
ConsoleFullGenerator()
: super('console-full', 'Console Application',
'A command-line application sample.',
categories: const ['dart', 'console']) {
addFile('.gitignore', common.gitignore);
addFile('analysis_options.yaml', common.analysisOptions);
addFile('CHANGELOG.md', common.changelog);
addFile('pubspec.yaml', _pubspec);
addFile('README.md', _readme);
setEntrypoint(
addFile('bin/__projectName__.dart', _mainDart),
);
addFile('lib/__projectName__.dart', _libDart);
addFile('test/__projectName___test.dart', _testDart);
}
@override
String getInstallInstructions() => '${super.getInstallInstructions()}\n'
'run your app using `dart ${entrypoint.path}`.';
}
final String _pubspec = '''
name: __projectName__
description: A sample command-line application.
version: 1.0.0
# homepage: https://www.example.com
environment:
sdk: '>=2.12.0 <3.0.0'
# dependencies:
# path: ^1.8.0
dev_dependencies:
pedantic: ^1.10.0
test: ^1.16.0
''';
final String _readme = '''
A sample command-line application with an entrypoint in `bin/`, library code
in `lib/`, and example unit test in `test/`.
''';
final String _mainDart = r'''
import 'package:__projectName__/__projectName__.dart' as __projectName__;
void main(List<String> arguments) {
print('Hello world: ${__projectName__.calculate()}!');
}
''';
final String _libDart = '''
int calculate() {
return 6 * 7;
}
''';
final String _testDart = '''
import 'package:__projectName__/__projectName__.dart';
import 'package:test/test.dart';
void main() {
test('calculate', () {
expect(calculate(), 42);
});
}
''';
@@ -0,0 +1,53 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import '../templates.dart';
import 'common.dart' as common;
/// A generator for a simple command-line application.
class ConsoleSimpleGenerator extends DefaultGenerator {
ConsoleSimpleGenerator()
: super('console-simple', 'Simple Console Application',
'A simple command-line application.',
categories: const ['dart', 'console']) {
addFile('.gitignore', common.gitignore);
addFile('analysis_options.yaml', common.analysisOptions);
addFile('CHANGELOG.md', common.changelog);
addFile('pubspec.yaml', _pubspec);
addFile('README.md', _readme);
setEntrypoint(
addFile('bin/__projectName__.dart', main),
);
}
@override
String getInstallInstructions() => '${super.getInstallInstructions()}\n'
'run your app using `dart ${entrypoint.path}`.';
}
final String _pubspec = '''
name: __projectName__
description: A simple command-line application.
version: 1.0.0
# homepage: https://www.example.com
environment:
sdk: '>=2.12.0 <3.0.0'
# dependencies:
# path: ^1.8.0
dev_dependencies:
pedantic: ^1.10.0
''';
final String _readme = '''
A simple command-line application.
''';
final String main = '''
void main(List<String> arguments) {
print('Hello world!');
}
''';
@@ -0,0 +1,130 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import '../templates.dart';
import 'common.dart' as common;
/// A generator for a simple command-line application.
class PackageSimpleGenerator extends DefaultGenerator {
PackageSimpleGenerator()
: super('package-simple', 'Dart Package',
'A starting point for Dart libraries or applications.',
categories: const ['dart']) {
addFile('.gitignore', _gitignore);
addFile('analysis_options.yaml', common.analysisOptions);
addFile('CHANGELOG.md', common.changelog);
addFile('pubspec.yaml', _pubspec);
addFile('README.md', _readme);
addFile('example/__projectName___example.dart', _exampleDart);
setEntrypoint(
addFile('lib/__projectName__.dart', _libDart),
);
addFile('lib/src/__projectName___base.dart', _libSrcDart);
addFile('test/__projectName___test.dart', _testDart);
}
@override
String getInstallInstructions() => '${super.getInstallInstructions()}\n'
'run your app using `dart ${entrypoint.path}`.';
}
final String _gitignore = '''
# Files and directories created by pub.
.dart_tool/
.packages
# Conventional directory for build outputs.
build/
# Omit committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
''';
final String _pubspec = '''
name: __projectName__
description: A starting point for Dart libraries or applications.
version: 1.0.0
# homepage: https://www.example.com
environment:
sdk: '>=2.12.0 <3.0.0'
# dependencies:
# path: ^1.8.0
dev_dependencies:
pedantic: ^1.10.0
test: ^1.16.0
''';
final String _readme = '''
A library for Dart developers.
## Usage
A simple usage example:
```dart
import 'package:__projectName__/__projectName__.dart';
main() {
var awesome = new Awesome();
}
```
## Features and bugs
Please file feature requests and bugs at the [issue tracker][tracker].
[tracker]: http://example.com/issues/replaceme
''';
final String _exampleDart = r'''
import 'package:__projectName__/__projectName__.dart';
void main() {
var awesome = Awesome();
print('awesome: ${awesome.isAwesome}');
}
''';
final String _libDart = '''
/// Support for doing something awesome.
///
/// More dartdocs go here.
library __projectName__;
export 'src/__projectName___base.dart';
// TODO: Export any libraries intended for clients of this package.
''';
final String _libSrcDart = '''
// TODO: Put public facing types in this file.
/// Checks if you are awesome. Spoiler: you are.
class Awesome {
bool get isAwesome => true;
}
''';
final String _testDart = '''
import 'package:__projectName__/__projectName__.dart';
import 'package:test/test.dart';
void main() {
group('A group of tests', () {
final awesome = Awesome();
setUp(() {
// Additional setup goes here.
});
test('First Test', () {
expect(awesome.isAwesome, isTrue);
});
});
}
''';
@@ -0,0 +1,85 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import '../templates.dart';
import 'common.dart' as common;
/// A generator for a server app built on `package:shelf`.
class ServerSimpleGenerator extends DefaultGenerator {
ServerSimpleGenerator()
: super('server-simple', 'Web Server',
'A web server built using package:shelf.',
categories: const ['dart', 'server']) {
addFile('.gitignore', common.gitignore);
addFile('analysis_options.yaml', common.analysisOptions);
addFile('CHANGELOG.md', common.changelog);
addFile('pubspec.yaml', _pubspec);
addFile('README.md', _readme);
setEntrypoint(
addFile('bin/server.dart', _main),
);
}
@override
String getInstallInstructions() => '${super.getInstallInstructions()}\n'
'run your app using `dart ${entrypoint.path}`.';
}
final String _pubspec = '''
name: __projectName__
description: A web server built using the shelf package.
version: 1.0.0
# homepage: https://www.example.com
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
args: ^2.0.0
shelf: ^1.1.0
dev_dependencies:
pedantic: ^1.10.0
''';
final String _readme = '''
A web server built using [Shelf](https://pub.dev/packages/shelf).
''';
final String _main = r'''
import 'dart:io';
import 'package:args/args.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
// For Google Cloud Run, set _hostname to '0.0.0.0'.
const _hostname = 'localhost';
void main(List<String> args) async {
var parser = ArgParser()..addOption('port', abbr: 'p');
var result = parser.parse(args);
// For Google Cloud Run, we respect the PORT environment variable
var portStr = result['port'] ?? Platform.environment['PORT'] ?? '8080';
var port = int.tryParse(portStr);
if (port == null) {
stdout.writeln('Could not parse port value "$portStr" into a number.');
// 64: command line usage error
exitCode = 64;
return;
}
var handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);
var server = await io.serve(handler, _hostname, port);
print('Serving at http://${server.address.host}:${server.port}');
}
shelf.Response _echoRequest(shelf.Request request) =>
shelf.Response.ok('Request for "${request.url}"');
''';
@@ -0,0 +1,94 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import '../templates.dart';
import 'common.dart' as common;
/// A generator for a uber-simple web application.
class WebSimpleGenerator extends DefaultGenerator {
WebSimpleGenerator()
: super('web-simple', 'Bare-bones Web App',
'A web app that uses only core Dart libraries.',
categories: const ['dart', 'web']) {
addFile('.gitignore', common.gitignore);
addFile('analysis_options.yaml', common.analysisOptions);
addFile('CHANGELOG.md', common.changelog);
addFile('pubspec.yaml', _pubspec);
addFile('README.md', _readme);
addFile('web/index.html', _index);
setEntrypoint(
addFile('web/main.dart', _main),
);
addFile('web/styles.css', _styles);
}
}
final String _pubspec = '''
name: __projectName__
description: An absolute bare-bones web app.
version: 1.0.0
# homepage: https://www.example.com
environment:
sdk: '>=2.10.0 <3.0.0'
# dependencies:
# path: ^1.7.0
dev_dependencies:
build_runner: ^1.10.0
build_web_compilers: ^2.11.0
pedantic: ^1.9.0
''';
final String _readme = '''
An absolute bare-bones web app.
''';
final String _index = '''
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="scaffolded-by" content="https://github.com/dart-lang/sdk">
<title>__projectName__</title>
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart.js"></script>
</head>
<body>
<div id="output"></div>
</body>
</html>
''';
final String _main = '''
import 'dart:html';
void main() {
querySelector('#output').text = 'Your Dart app is running.';
}
''';
final String _styles = '''
@import url(https://fonts.googleapis.com/css?family=Roboto);
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
}
#output {
padding: 20px;
text-align: center;
}
''';
-1
View File
@@ -27,7 +27,6 @@ dependencies:
path: ^1.0.0
pedantic: ^1.9.0
pub: any
stagehand: any
telemetry:
path: ../telemetry
usage: ^3.4.0
@@ -0,0 +1,54 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:dartdev/src/commands/create.dart';
import 'package:test/test.dart';
import '../utils.dart';
void main() {
group('create integration', defineCreateTests, timeout: longTimeout);
}
void defineCreateTests() {
TestProject p;
setUp(() => p = null);
tearDown(() => p?.dispose());
// Create tests for each template.
for (String templateId in CreateCommand.legalTemplateIds) {
test(templateId, () {
p = project();
ProcessResult createResult = p.runSync([
'create',
'--force',
'--template',
templateId,
p.dir.path,
]);
expect(createResult.exitCode, 0, reason: createResult.stderr);
// Validate that the project analyzes cleanly.
// TODO: Should we use --fatal-infos here?
ProcessResult analyzeResult =
p.runSync(['analyze'], workingDir: p.dir.path);
expect(analyzeResult.exitCode, 0, reason: analyzeResult.stdout);
// Validate that the code is well formatted.
ProcessResult formatResult = p.runSync([
'format',
'--output',
'none',
'--set-exit-if-changed',
p.dir.path,
]);
expect(formatResult.exitCode, 0, reason: formatResult.stdout);
});
}
}
+10 -4
View File
@@ -6,6 +6,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:dartdev/src/commands/create.dart';
import 'package:dartdev/src/templates.dart' as templates;
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -77,14 +78,19 @@ void defineCreateTests() {
test('create $templateId', () {
p = project();
ProcessResult result = p
.runSync(['create', '--force', '--template', templateId, p.dir.path]);
ProcessResult result = p.runSync([
'create',
'--force',
'--no-pub',
'--template',
templateId,
p.dir.path,
]);
expect(result.exitCode, 0);
String projectName = path.basename(p.dir.path);
String entry =
CreateCommand.retrieveTemplateGenerator(templateId).entrypoint.path;
String entry = templates.getGenerator(templateId).entrypoint.path;
entry = entry.replaceAll('__projectName__', projectName);
File entryFile = File(path.join(p.dir.path, entry));
+40
View File
@@ -0,0 +1,40 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. 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:dartdev/src/templates.dart';
import 'package:test/test.dart';
void main() {
group('templates', () {
group('substituteVars', () {
test('simple', () {
_expect('foo __bar__ baz', {'bar': 'baz'}, 'foo baz baz');
});
test('nosub', () {
_expect('foo __bar__ baz', {'aaa': 'bbb'}, 'foo __bar__ baz');
});
test('matching input', () {
_expect('foo __bar__ baz', {'bar': '__baz__', 'baz': 'foo'},
'foo __baz__ baz');
});
test('vars must be alpha + numeric', () {
expect(() => substituteVars('str', {'with space': 'noop'}),
throwsArgumentError);
expect(() => substituteVars('str', {'with!symbols': 'noop'}),
throwsArgumentError);
expect(() => substituteVars('str', {'with1numbers': 'noop'}),
throwsArgumentError);
expect(() => substituteVars('str', {'with_under': 'noop'}),
throwsArgumentError);
});
});
});
}
void _expect(String original, Map<String, String> vars, String result) {
expect(substituteVars(original, vars), result);
}
+1 -2
View File
@@ -7,7 +7,6 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
/// A long [Timeout] is provided for tests that start a process on
@@ -54,7 +53,7 @@ class TestProject {
this.name = _defaultProjectName,
this.logAnalytics = false,
this.sdkConstraint}) {
dir = Directory.systemTemp.createTempSync(name);
dir = Directory.systemTemp.createTempSync('a');
file('pubspec.yaml', '''
name: $name
environment: