From 3e0b3c0de1a158bd376a4fce8490f1f4587f37e8 Mon Sep 17 00:00:00 2001 From: saudademjj <128795969+saudademjj@users.noreply.github.com> Date: Sat, 21 Mar 2026 14:30:21 +0800 Subject: [PATCH 1/3] [mustache_template] Add example app and code excerpts Create a runnable example app and readme_excerpts.dart with #docregion markers for all README code examples. Migrate inline README code blocks to the system for CI validation. Fixes flutter/flutter#183936 --- script/configs/temp_exclude_excerpt.yaml | 1 - .../packages/mustache_template/README.md | 120 ++++++++++-------- .../mustache_template/example/lib/main.dart | 47 +++++++ .../example/lib/readme_excerpts.dart | 118 +++++++++++++++++ .../mustache_template/example/pubspec.yaml | 10 ++ 5 files changed, 243 insertions(+), 53 deletions(-) create mode 100644 third_party/packages/mustache_template/example/lib/main.dart create mode 100644 third_party/packages/mustache_template/example/lib/readme_excerpts.dart create mode 100644 third_party/packages/mustache_template/example/pubspec.yaml diff --git a/script/configs/temp_exclude_excerpt.yaml b/script/configs/temp_exclude_excerpt.yaml index 2dd229b184cf..3d39abc136bb 100644 --- a/script/configs/temp_exclude_excerpt.yaml +++ b/script/configs/temp_exclude_excerpt.yaml @@ -7,6 +7,5 @@ # https://github.com/flutter/flutter/issues/102679 - espresso - in_app_purchase/in_app_purchase -- mustache_template - pointer_interceptor - quick_actions/quick_actions diff --git a/third_party/packages/mustache_template/README.md b/third_party/packages/mustache_template/README.md index 7602c2755160..dcc2649669c0 100644 --- a/third_party/packages/mustache_template/README.md +++ b/third_party/packages/mustache_template/README.md @@ -1,3 +1,5 @@ + + # Mustache templates A Dart library to parse and render [mustache templates](https://mustache.github.io/). @@ -7,28 +9,32 @@ See the [mustache manual](http://mustache.github.com/mustache.5.html) for detail This library passes all [mustache specification](https://github.com/mustache/spec/tree/master/specs) tests. ## Example usage + + ```dart import 'package:mustache_template/mustache_template.dart'; -main() { - var source = ''' - {{# names }} -
{{ lastname }}, {{ firstname }}
- {{/ names }} - {{^ names }} -
No names.
- {{/ names }} - {{! I am a comment. }} - '''; - - var template = Template(source, name: 'template-filename.html'); - - var output = template.renderString({'names': [ - {'firstname': 'Greg', 'lastname': 'Lowe'}, - {'firstname': 'Bob', 'lastname': 'Johnson'} - ]}); - - print(output); +void main() { + const source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +{{! I am a comment. }} +'''; + + final template = Template(source, name: 'template-filename.html'); + + final output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], + }); + + print(output); } ``` @@ -53,65 +59,75 @@ By default all output from `{{variable}}` tags is html escaped, this behaviour c ## Nested paths + ```dart - var t = Template('{{ author.name }}'); - var output = template.renderString({'author': {'name': 'Greg Lowe'}}); +final t = Template('{{ author.name }}'); +final output = t.renderString({ + 'author': {'name': 'Greg Lowe'}, +}); ``` ## Partials - example usage + ```dart - -var partial = Template('{{ foo }}', name: 'partial'); - -var resolver = (String name) { - if (name == 'partial-name') { // Name of partial tag. - return partial; - } +final partial = Template('{{ foo }}', name: 'partial'); + +final resolver = (String name) { + if (name == 'partial-name') { + // Name of partial tag. + return partial; + } + return null; }; -var t = Template('{{> partial-name }}', partialResolver: resolver); - -var output = t.renderString({'foo': 'bar'}); // bar +final t = Template('{{> partial-name }}', partialResolver: resolver); +final output = t.renderString({'foo': 'bar'}); // bar ``` ## Lambdas - example usage + ```dart -var t = Template('{{# foo }}'); -var lambda = (_) => 'bar'; -t.renderString({'foo': lambda}); // bar -``` - -```dart -var t = Template('{{# foo }}hidden{{/ foo }}'); -var lambda = (_) => 'shown'; -t.renderString('foo': lambda); // shown +final t = Template('{{# foo }}{{/ foo }}'); +final lambda = (_) => 'bar'; +final output = t.renderString({'foo': lambda}); // bar ``` + ```dart -var t = Template('{{# foo }}oi{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda}); // OI +final t = Template('{{# foo }}hidden{{/ foo }}'); +final lambda = (_) => 'shown'; +final output = t.renderString({'foo': lambda}); // shown ``` + ```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB +final t = Template('{{# foo }}oi{{/ foo }}'); +final lambda = (LambdaContext ctx) => + '${ctx.renderString().toUpperCase()}'; +final output = t.renderString({'foo': lambda}); // OI ``` + ```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; -t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB +final t = Template('{{# foo }}{{bar}}{{/ foo }}'); +final lambda = (LambdaContext ctx) => + '${ctx.renderString().toUpperCase()}'; +final output = t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB ``` In the following example `LambdaContext.renderSource(source)` re-parses the source string in the current context, this is the default behaviour in many mustache implementations. Since re-parsing the content is slow, and often not required, this library makes this step optional. + ```dart -var t = Template('{{# foo }}{{bar}}{{/ foo }}'); -var lambda = (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}'); -t.renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); // pub build +final t = Template('{{# foo }}{{bar}}{{/ foo }}'); +final lambda = (LambdaContext ctx) => + ctx.renderSource('${ctx.source} {{cmd}}'); +final output = t.renderString({ + 'foo': lambda, + 'bar': 'pub', + 'cmd': 'build', +}); // pub build ``` diff --git a/third_party/packages/mustache_template/example/lib/main.dart b/third_party/packages/mustache_template/example/lib/main.dart new file mode 100644 index 000000000000..21892f55eca8 --- /dev/null +++ b/third_party/packages/mustache_template/example/lib/main.dart @@ -0,0 +1,47 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_print, prefer_function_declarations_over_variables + +import 'package:mustache_template/mustache_template.dart'; + +void main() { + // Basic template rendering with sections and inverted sections. + const source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +'''; + + final template = Template(source, name: 'example.html'); + + final String output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], + }); + + print('=== Basic Template ==='); + print(output); + + // Nested paths + final nested = Template('{{ author.name }}'); + print('=== Nested Paths ==='); + print( + nested.renderString({ + 'author': {'name': 'Greg Lowe'}, + }), + ); + + // Lambdas + final lambdaTemplate = Template('{{# transform }}hello{{/ transform }}'); + final String Function(LambdaContext) lambda = (LambdaContext ctx) => + ctx.renderString().toUpperCase(); + print('=== Lambdas ==='); + print(lambdaTemplate.renderString({'transform': lambda})); +} diff --git a/third_party/packages/mustache_template/example/lib/readme_excerpts.dart b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart new file mode 100644 index 000000000000..98129c76a332 --- /dev/null +++ b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart @@ -0,0 +1,118 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file exists solely to host compiled excerpts for README.md, and is not +// intended for use as an actual example application. + +// ignore_for_file: avoid_print, public_member_api_docs, unreachable_from_main +// ignore_for_file: prefer_function_declarations_over_variables +// ignore_for_file: specify_nonobvious_local_variable_types + +// #docregion ExampleUsage +import 'package:mustache_template/mustache_template.dart'; + +void main() { + const source = ''' +{{# names }} +
{{ lastname }}, {{ firstname }}
+{{/ names }} +{{^ names }} +
No names.
+{{/ names }} +{{! I am a comment. }} +'''; + + final template = Template(source, name: 'template-filename.html'); + + final output = template.renderString({ + 'names': [ + {'firstname': 'Greg', 'lastname': 'Lowe'}, + {'firstname': 'Bob', 'lastname': 'Johnson'}, + ], + }); + + print(output); +} +// #enddocregion ExampleUsage + +void nestedPathsExample() { + // #docregion NestedPaths + final t = Template('{{ author.name }}'); + final output = t.renderString({ + 'author': {'name': 'Greg Lowe'}, + }); + // #enddocregion NestedPaths + print(output); +} + +void partialsExample() { + // #docregion Partials + final partial = Template('{{ foo }}', name: 'partial'); + + final resolver = (String name) { + if (name == 'partial-name') { + // Name of partial tag. + return partial; + } + return null; + }; + + final t = Template('{{> partial-name }}', partialResolver: resolver); + + final output = t.renderString({'foo': 'bar'}); // bar + // #enddocregion Partials + print(output); +} + +void lambdaSimpleExample() { + // #docregion LambdaSimple + final t = Template('{{# foo }}{{/ foo }}'); + final lambda = (_) => 'bar'; + final output = t.renderString({'foo': lambda}); // bar + // #enddocregion LambdaSimple + print(output); +} + +void lambdaShownExample() { + // #docregion LambdaShown + final t = Template('{{# foo }}hidden{{/ foo }}'); + final lambda = (_) => 'shown'; + final output = t.renderString({'foo': lambda}); // shown + // #enddocregion LambdaShown + print(output); +} + +void lambdaRenderExample() { + // #docregion LambdaRender + final t = Template('{{# foo }}oi{{/ foo }}'); + final lambda = (LambdaContext ctx) => + '${ctx.renderString().toUpperCase()}'; + final output = t.renderString({'foo': lambda}); // OI + // #enddocregion LambdaRender + print(output); +} + +void lambdaRenderBarExample() { + // #docregion LambdaRenderBar + final t = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => + '${ctx.renderString().toUpperCase()}'; + final output = t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB + // #enddocregion LambdaRenderBar + print(output); +} + +void lambdaRenderSourceExample() { + // #docregion LambdaRenderSource + final t = Template('{{# foo }}{{bar}}{{/ foo }}'); + final lambda = (LambdaContext ctx) => + ctx.renderSource('${ctx.source} {{cmd}}'); + final output = t.renderString({ + 'foo': lambda, + 'bar': 'pub', + 'cmd': 'build', + }); // pub build + // #enddocregion LambdaRenderSource + print(output); +} diff --git a/third_party/packages/mustache_template/example/pubspec.yaml b/third_party/packages/mustache_template/example/pubspec.yaml new file mode 100644 index 000000000000..3dcf29ef1dc0 --- /dev/null +++ b/third_party/packages/mustache_template/example/pubspec.yaml @@ -0,0 +1,10 @@ +name: mustache_template_example +description: Example app for mustache_template package. +publish_to: none + +environment: + sdk: ^3.9.0 + +dependencies: + mustache_template: + path: ../ From 06fb272a086680ae0079dcd31b3bd6df36b1e83e Mon Sep 17 00:00:00 2001 From: saudademjj <128795969+saudademjj@users.noreply.github.com> Date: Sat, 21 Mar 2026 15:01:48 +0800 Subject: [PATCH 2/3] [mustache_template] Add regression tests for examples --- .../packages/mustache_template/test/all.dart | 2 + .../mustache_template/test/example_test.dart | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 third_party/packages/mustache_template/test/example_test.dart diff --git a/third_party/packages/mustache_template/test/all.dart b/third_party/packages/mustache_template/test/all.dart index 0e7d0e4cbb20..e50e87f1585a 100644 --- a/third_party/packages/mustache_template/test/all.dart +++ b/third_party/packages/mustache_template/test/all.dart @@ -1,8 +1,10 @@ +import 'example_test.dart' as example; import 'mustache_specs.dart' as specs; import 'mustache_test.dart' as test; import 'parser_test.dart' as parser; void main() { + example.main(); specs.main(); test.main(); parser.main(); diff --git a/third_party/packages/mustache_template/test/example_test.dart b/third_party/packages/mustache_template/test/example_test.dart new file mode 100644 index 000000000000..c14d19093568 --- /dev/null +++ b/third_party/packages/mustache_template/test/example_test.dart @@ -0,0 +1,107 @@ +// ignore_for_file: avoid_relative_lib_imports + +import 'dart:async'; + +import 'package:test/test.dart'; + +import '../example/lib/main.dart' as example_app; +import '../example/lib/readme_excerpts.dart' as readme_excerpts; + +Future> _capturePrints(FutureOr Function() body) async { + final output = []; + await runZoned( + () async => body(), + zoneSpecification: ZoneSpecification( + print: ( + Zone self, + ZoneDelegate parent, + Zone zone, + String line, + ) { + output.add(line); + }, + ), + ); + return output; +} + +void main() { + group('Example app', () { + test('main runs and prints the documented sections', () async { + final List output = await _capturePrints(example_app.main); + + expect(output, hasLength(6)); + expect(output[0], equals('=== Basic Template ===')); + expect(output[1], allOf(contains('Lowe, Greg'), contains('Johnson, Bob'))); + expect(output[2], equals('=== Nested Paths ===')); + expect(output[3], equals('Greg Lowe')); + expect(output[4], equals('=== Lambdas ===')); + expect(output[5], equals('HELLO')); + }); + }); + + group('README excerpts', () { + test('example usage renders both names', () async { + final List output = await _capturePrints(readme_excerpts.main); + + expect(output, hasLength(1)); + expect(output.single, allOf(contains('Lowe, Greg'), contains('Johnson, Bob'))); + }); + + test('nested paths example renders the nested value', () async { + final List output = await _capturePrints( + readme_excerpts.nestedPathsExample, + ); + + expect(output, equals(['Greg Lowe'])); + }); + + test('partials example renders the partial output', () async { + final List output = await _capturePrints( + readme_excerpts.partialsExample, + ); + + expect(output, equals(['bar'])); + }); + + test('simple lambda example renders the replacement text', () async { + final List output = await _capturePrints( + readme_excerpts.lambdaSimpleExample, + ); + + expect(output, equals(['bar'])); + }); + + test('lambda block example renders the alternate text', () async { + final List output = await _capturePrints( + readme_excerpts.lambdaShownExample, + ); + + expect(output, equals(['shown'])); + }); + + test('lambda render example uppercases the section body', () async { + final List output = await _capturePrints( + readme_excerpts.lambdaRenderExample, + ); + + expect(output, equals(['OI'])); + }); + + test('lambda render with context data includes the variable value', () async { + final List output = await _capturePrints( + readme_excerpts.lambdaRenderBarExample, + ); + + expect(output, equals(['PUB'])); + }); + + test('lambda renderSource example reparses in the current context', () async { + final List output = await _capturePrints( + readme_excerpts.lambdaRenderSourceExample, + ); + + expect(output, equals(['pub build'])); + }); + }); +} From cf5a0b66243e6d49ba8647383d81a8b3e8bc52ce Mon Sep 17 00:00:00 2001 From: saudademjj <128795969+saudademjj@users.noreply.github.com> Date: Sat, 21 Mar 2026 23:47:24 +0800 Subject: [PATCH 3/3] [mustache_template] Reduce excerpt duplication and simplify tests --- .../packages/mustache_template/CHANGELOG.md | 4 + .../packages/mustache_template/README.md | 5 +- .../mustache_template/example/lib/main.dart | 13 ++- .../example/lib/readme_excerpts.dart | 53 +++-------- .../packages/mustache_template/pubspec.yaml | 2 +- .../mustache_template/test/example_test.dart | 95 ++++--------------- 6 files changed, 49 insertions(+), 123 deletions(-) diff --git a/third_party/packages/mustache_template/CHANGELOG.md b/third_party/packages/mustache_template/CHANGELOG.md index 67f53c1a8fc9..5d58f3bb4bdd 100644 --- a/third_party/packages/mustache_template/CHANGELOG.md +++ b/third_party/packages/mustache_template/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.4 + +* Adds a runnable example app and refreshes README code samples. + ## 2.0.3 * Updates minimum supported SDK version to Flutter 3.35/Dart 3.9. diff --git a/third_party/packages/mustache_template/README.md b/third_party/packages/mustache_template/README.md index dcc2649669c0..469fca64a40c 100644 --- a/third_party/packages/mustache_template/README.md +++ b/third_party/packages/mustache_template/README.md @@ -10,7 +10,7 @@ This library passes all [mustache specification](https://github.com/mustache/spe ## Example usage - + ```dart import 'package:mustache_template/mustache_template.dart'; @@ -27,7 +27,7 @@ void main() { final template = Template(source, name: 'template-filename.html'); - final output = template.renderString({ + final String output = template.renderString({ 'names': [ {'firstname': 'Greg', 'lastname': 'Lowe'}, {'firstname': 'Bob', 'lastname': 'Johnson'}, @@ -36,6 +36,7 @@ void main() { print(output); } + ``` A template is parsed when it is created, after parsing it can be rendered any number of times with different values. A TemplateException is thrown if there is a problem parsing or rendering the template. diff --git a/third_party/packages/mustache_template/example/lib/main.dart b/third_party/packages/mustache_template/example/lib/main.dart index 21892f55eca8..e5b237e9b501 100644 --- a/third_party/packages/mustache_template/example/lib/main.dart +++ b/third_party/packages/mustache_template/example/lib/main.dart @@ -4,10 +4,15 @@ // ignore_for_file: avoid_print, prefer_function_declarations_over_variables +// #docregion ExampleUsage import 'package:mustache_template/mustache_template.dart'; void main() { + // #enddocregion ExampleUsage + print('=== Basic Template ==='); + // Basic template rendering with sections and inverted sections. + // #docregion ExampleUsage const source = ''' {{# names }}
{{ lastname }}, {{ firstname }}
@@ -15,9 +20,10 @@ void main() { {{^ names }}
No names.
{{/ names }} +{{! I am a comment. }} '''; - final template = Template(source, name: 'example.html'); + final template = Template(source, name: 'template-filename.html'); final String output = template.renderString({ 'names': [ @@ -26,8 +32,8 @@ void main() { ], }); - print('=== Basic Template ==='); print(output); + // #enddocregion ExampleUsage // Nested paths final nested = Template('{{ author.name }}'); @@ -44,4 +50,7 @@ void main() { ctx.renderString().toUpperCase(); print('=== Lambdas ==='); print(lambdaTemplate.renderString({'transform': lambda})); + // #docregion ExampleUsage } + +// #enddocregion ExampleUsage diff --git a/third_party/packages/mustache_template/example/lib/readme_excerpts.dart b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart index 98129c76a332..793d80186698 100644 --- a/third_party/packages/mustache_template/example/lib/readme_excerpts.dart +++ b/third_party/packages/mustache_template/example/lib/readme_excerpts.dart @@ -9,44 +9,19 @@ // ignore_for_file: prefer_function_declarations_over_variables // ignore_for_file: specify_nonobvious_local_variable_types -// #docregion ExampleUsage import 'package:mustache_template/mustache_template.dart'; -void main() { - const source = ''' -{{# names }} -
{{ lastname }}, {{ firstname }}
-{{/ names }} -{{^ names }} -
No names.
-{{/ names }} -{{! I am a comment. }} -'''; - - final template = Template(source, name: 'template-filename.html'); - - final output = template.renderString({ - 'names': [ - {'firstname': 'Greg', 'lastname': 'Lowe'}, - {'firstname': 'Bob', 'lastname': 'Johnson'}, - ], - }); - - print(output); -} -// #enddocregion ExampleUsage - -void nestedPathsExample() { +String nestedPathsExample() { // #docregion NestedPaths final t = Template('{{ author.name }}'); final output = t.renderString({ 'author': {'name': 'Greg Lowe'}, }); // #enddocregion NestedPaths - print(output); + return output; } -void partialsExample() { +String partialsExample() { // #docregion Partials final partial = Template('{{ foo }}', name: 'partial'); @@ -62,48 +37,48 @@ void partialsExample() { final output = t.renderString({'foo': 'bar'}); // bar // #enddocregion Partials - print(output); + return output; } -void lambdaSimpleExample() { +String lambdaSimpleExample() { // #docregion LambdaSimple final t = Template('{{# foo }}{{/ foo }}'); final lambda = (_) => 'bar'; final output = t.renderString({'foo': lambda}); // bar // #enddocregion LambdaSimple - print(output); + return output; } -void lambdaShownExample() { +String lambdaShownExample() { // #docregion LambdaShown final t = Template('{{# foo }}hidden{{/ foo }}'); final lambda = (_) => 'shown'; final output = t.renderString({'foo': lambda}); // shown // #enddocregion LambdaShown - print(output); + return output; } -void lambdaRenderExample() { +String lambdaRenderExample() { // #docregion LambdaRender final t = Template('{{# foo }}oi{{/ foo }}'); final lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; final output = t.renderString({'foo': lambda}); // OI // #enddocregion LambdaRender - print(output); + return output; } -void lambdaRenderBarExample() { +String lambdaRenderBarExample() { // #docregion LambdaRenderBar final t = Template('{{# foo }}{{bar}}{{/ foo }}'); final lambda = (LambdaContext ctx) => '${ctx.renderString().toUpperCase()}'; final output = t.renderString({'foo': lambda, 'bar': 'pub'}); // PUB // #enddocregion LambdaRenderBar - print(output); + return output; } -void lambdaRenderSourceExample() { +String lambdaRenderSourceExample() { // #docregion LambdaRenderSource final t = Template('{{# foo }}{{bar}}{{/ foo }}'); final lambda = (LambdaContext ctx) => @@ -114,5 +89,5 @@ void lambdaRenderSourceExample() { 'cmd': 'build', }); // pub build // #enddocregion LambdaRenderSource - print(output); + return output; } diff --git a/third_party/packages/mustache_template/pubspec.yaml b/third_party/packages/mustache_template/pubspec.yaml index 264e0ee0c4d4..8a8bdeae8b94 100644 --- a/third_party/packages/mustache_template/pubspec.yaml +++ b/third_party/packages/mustache_template/pubspec.yaml @@ -2,7 +2,7 @@ name: mustache_template description: A templating library that implements the Mustache template specification repository: https://github.com/flutter/packages/tree/main/third_party/packages/mustache_template issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+mustache_template%22 -version: 2.0.3 +version: 2.0.4 environment: sdk: ^3.9.0 diff --git a/third_party/packages/mustache_template/test/example_test.dart b/third_party/packages/mustache_template/test/example_test.dart index c14d19093568..091c5127f64d 100644 --- a/third_party/packages/mustache_template/test/example_test.dart +++ b/third_party/packages/mustache_template/test/example_test.dart @@ -1,107 +1,44 @@ // ignore_for_file: avoid_relative_lib_imports -import 'dart:async'; - import 'package:test/test.dart'; import '../example/lib/main.dart' as example_app; import '../example/lib/readme_excerpts.dart' as readme_excerpts; -Future> _capturePrints(FutureOr Function() body) async { - final output = []; - await runZoned( - () async => body(), - zoneSpecification: ZoneSpecification( - print: ( - Zone self, - ZoneDelegate parent, - Zone zone, - String line, - ) { - output.add(line); - }, - ), - ); - return output; -} - void main() { group('Example app', () { - test('main runs and prints the documented sections', () async { - final List output = await _capturePrints(example_app.main); - - expect(output, hasLength(6)); - expect(output[0], equals('=== Basic Template ===')); - expect(output[1], allOf(contains('Lowe, Greg'), contains('Johnson, Bob'))); - expect(output[2], equals('=== Nested Paths ===')); - expect(output[3], equals('Greg Lowe')); - expect(output[4], equals('=== Lambdas ===')); - expect(output[5], equals('HELLO')); + test('example app runs without error', () { + expect(example_app.main, returnsNormally); }); }); group('README excerpts', () { - test('example usage renders both names', () async { - final List output = await _capturePrints(readme_excerpts.main); - - expect(output, hasLength(1)); - expect(output.single, allOf(contains('Lowe, Greg'), contains('Johnson, Bob'))); - }); - - test('nested paths example renders the nested value', () async { - final List output = await _capturePrints( - readme_excerpts.nestedPathsExample, - ); - - expect(output, equals(['Greg Lowe'])); + test('nested paths example renders the nested value', () { + expect(readme_excerpts.nestedPathsExample(), equals('Greg Lowe')); }); - test('partials example renders the partial output', () async { - final List output = await _capturePrints( - readme_excerpts.partialsExample, - ); - - expect(output, equals(['bar'])); + test('partials example renders the partial output', () { + expect(readme_excerpts.partialsExample(), equals('bar')); }); - test('simple lambda example renders the replacement text', () async { - final List output = await _capturePrints( - readme_excerpts.lambdaSimpleExample, - ); - - expect(output, equals(['bar'])); + test('simple lambda example renders the replacement text', () { + expect(readme_excerpts.lambdaSimpleExample(), equals('bar')); }); - test('lambda block example renders the alternate text', () async { - final List output = await _capturePrints( - readme_excerpts.lambdaShownExample, - ); - - expect(output, equals(['shown'])); + test('lambda block example renders the alternate text', () { + expect(readme_excerpts.lambdaShownExample(), equals('shown')); }); - test('lambda render example uppercases the section body', () async { - final List output = await _capturePrints( - readme_excerpts.lambdaRenderExample, - ); - - expect(output, equals(['OI'])); + test('lambda render example uppercases the section body', () { + expect(readme_excerpts.lambdaRenderExample(), equals('OI')); }); - test('lambda render with context data includes the variable value', () async { - final List output = await _capturePrints( - readme_excerpts.lambdaRenderBarExample, - ); - - expect(output, equals(['PUB'])); + test('lambda render with context data includes the variable value', () { + expect(readme_excerpts.lambdaRenderBarExample(), equals('PUB')); }); - test('lambda renderSource example reparses in the current context', () async { - final List output = await _capturePrints( - readme_excerpts.lambdaRenderSourceExample, - ); - - expect(output, equals(['pub build'])); + test('lambda renderSource example reparses in the current context', () { + expect(readme_excerpts.lambdaRenderSourceExample(), equals('pub build')); }); }); }