blob: 4e804a10ef26cf8cdfc836a2d4319bb38c868b8a [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is hand-formatted.
// This file contains and briefly tests the snippets used in the README.md file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rfw/formats.dart';
import 'package:rfw/rfw.dart';
const Map<String, String> rawRemoteWidgetSnippets = <String, String>{
'root': '''
// #docregion root
import local;
widget root = GreenBox(
child: Hello(name: "World"),
);
// #enddocregion root
''',
'fruit': '''
import local;
// #docregion fruit
widget fruit = Foo(
bar: { quux: [ 'apple', 'banana', 'cherry' ] },
);
// #enddocregion fruit
''',
'example1': '''
import local;
// #docregion example1
widget example1 = GreenBox(
child: Foo(
bar: 'Jean',
),
);
// #enddocregion example1
''',
'example2': '''
import local;
// #docregion example2
widget example2 = GreenBox(
child: Foo(
bar: { name: 'Jean' },
),
);
// #enddocregion example2
''',
'example3': '''
import local;
// #docregion example3
widget example3 = GreenBox(
child: Foo(
text: ['apple', 'banana']
),
);
// #enddocregion example3
''',
'tap': '''
import local;
import core;
widget tap = GestureDetector(
onTap: event 'test' { },
child: SizedBox(),
);
''',
'tapDown': '''
import local;
import core;
widget tapDown = GestureDetector(
onTapDown: event 'test' { },
child: SizedBox(),
);
''',
'Shop': '''
// #docregion Shop
import core;
widget Shop = ListView(
children: [
Text(text: "Products:"),
...for product in data.server.games:
Product(product: product)
],
);
widget Product = Text(text: args.product.name, softWrap: false, overflow: "fade");
// #enddocregion Shop
''',
'MaterialShop': '''
// #docregion MaterialShop
import core;
import material;
widget MaterialShop = Scaffold(
appBar: AppBar(
title: Text(text: ['Products']),
),
body: ListView(
children: [
...for product in data.server.games:
Product(product: product)
],
),
);
widget Product = ListTile(
title: Text(text: args.product.name),
onTap: event 'shop.productSelect' { name: args.product.name, path: args.product.link },
);
// #enddocregion MaterialShop
''',
};
// The empty docregion at the end of the following causes the snippet to end with "// ...".
const String gameData =
'''
// #docregion game-data
{ "games": [
{"rating": 8.219, "users-rated": 16860, "name": "Twilight Struggle", "rank": 1, "link": "/boardgame/12333/twilight-struggle", "id": 12333},
{"rating": 8.093, "users-rated": 11750, "name": "Through the Ages: A Story of Civilization", "rank": 2, "link": "/boardgame/25613/through-ages-story-civilization", "id": 25613},
{"rating": 8.088, "users-rated": 34745, "name": "Agricola", "rank": 3, "link": "/boardgame/31260/agricola", "id": 31260},
{"rating": 8.082, "users-rated": 8913, "name": "Terra Mystica", "rank": 4, "link": "/boardgame/120677/terra-mystica", "id": 120677},
// #enddocregion game-data
// #docregion game-data
// #enddocregion game-data
] }
''';
List<WidgetLibrary> _createLocalWidgets(String region) {
switch (region) {
case 'root':
return <WidgetLibrary>[LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// #docregion defaultLocalWidgets
'GreenBox': (BuildContext context, DataSource source) {
return Container(color: const Color(0xFF002211), child: source.child(<Object>['child']));
},
'Hello': (BuildContext context, DataSource source) {
return Center(child: Text('Hello, ${source.v<String>(<Object>["name"])}!', textDirection: TextDirection.ltr));
},
// #enddocregion defaultLocalWidgets
})];
case 'fruit':
return <WidgetLibrary>[
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// #docregion v
'Foo': (BuildContext context, DataSource source) {
return Text(source.v<String>(<Object>['bar', 'quux', 2])!);
},
// #enddocregion v
}),
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// #docregion isList
'Foo': (BuildContext context, DataSource source) {
if (source.isList(<Object>['bar', 'quux'])) {
return Text('${source.v<String>(<Object>['bar', 'quux', 2])}', textDirection: TextDirection.ltr);
}
return Text('${source.v<String>(<Object>['baz'])}', textDirection: TextDirection.ltr);
},
// #enddocregion isList
}),
];
case 'example1':
case 'example2':
return <WidgetLibrary>[LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// #docregion child
'GreenBox': (BuildContext context, DataSource source) {
return Container(color: const Color(0xFF002211), child: source.child(<Object>['child']));
},
// #enddocregion child
// #docregion isMap
'Foo': (BuildContext context, DataSource source) {
if (source.isMap(<Object>['bar'])) {
return Text('${source.v<String>(<Object>['bar', 'name'])}', textDirection: TextDirection.ltr);
}
return Text('${source.v<String>(<Object>['bar'])}', textDirection: TextDirection.ltr);
},
// #enddocregion isMap
})];
case 'example3':
return <WidgetLibrary>[LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// #docregion optionalChild
'GreenBox': (BuildContext context, DataSource source) {
return Container(color: const Color(0xFF002211), child: source.optionalChild(<Object>['child']));
},
// #enddocregion optionalChild
// #docregion length
'Foo': (BuildContext context, DataSource source) {
final int length = source.length(<Object>['text']);
if (length > 0) {
final StringBuffer text = StringBuffer();
for (int index = 0; index < length; index += 1) {
text.write(source.v<String>(<Object>['text', index]));
}
return Text(text.toString(), textDirection: TextDirection.ltr);
}
return const Text('<empty>', textDirection: TextDirection.ltr);
},
// #enddocregion length
})];
case 'tap':
// #docregion onTap
return <WidgetLibrary>[
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
// The local widget is called `GestureDetector`...
'GestureDetector': (BuildContext context, DataSource source) {
// The local widget is implemented using the `GestureDetector`
// widget from the Flutter framework.
return GestureDetector(
onTap: source.voidHandler(<Object>['onTap']),
// A full implementation of a `GestureDetector` local widget
// would have more arguments here, like `onTapDown`, etc.
child: source.optionalChild(<Object>['child']),
);
},
}),
];
// #enddocregion onTap
case 'tapDown':
return <WidgetLibrary>[
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
'GestureDetector': (BuildContext context, DataSource source) {
// #docregion onTapDown
return GestureDetector(
onTapDown: source.handler(<Object>['onTapDown'], (HandlerTrigger trigger) => (TapDownDetails details) => trigger()),
child: source.optionalChild(<Object>['child']),
);
// #enddocregion onTapDown
},
}),
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
'GestureDetector': (BuildContext context, DataSource source) {
// #docregion onTapDown-long
return GestureDetector(
// onTapDown expects a function that takes a TapDownDetails
onTapDown: source.handler<GestureTapDownCallback>( // this returns a function that takes a TapDownDetails
<Object>['onTapDown'],
(HandlerTrigger trigger) { // "trigger" is the function that will send the event to RemoteWidget.onEvent
return (TapDownDetails details) { // this is the function that is returned by handler() above
trigger(); // the function calls "trigger"
};
},
),
child: source.optionalChild(<Object>['child']),
);
// #enddocregion onTapDown-long
},
}),
LocalWidgetLibrary(<String, LocalWidgetBuilder>{
'GestureDetector': (BuildContext context, DataSource source) {
// #docregion onTapDown-position
return GestureDetector(
onTapDown: source.handler(<Object>['onTapDown'], (HandlerTrigger trigger) {
return (TapDownDetails details) => trigger(<String, Object>{
'x': details.globalPosition.dx,
'y': details.globalPosition.dy,
});
}),
child: source.optionalChild(<Object>['child']),
);
// #enddocregion onTapDown-position
},
}),
];
case 'Shop':
case 'MaterialShop':
return <WidgetLibrary>[];
default:
fail('test has no defined local widgets for root widget "$region"');
}
}
void main() {
testWidgets('readme snippets', (WidgetTester tester) async {
final Runtime runtime = Runtime()
..update(const LibraryName(<String>['core']), createCoreWidgets())
..update(const LibraryName(<String>['material']), createMaterialWidgets());
final DynamicContent data = DynamicContent(parseDataFile(gameData));
for (final String region in rawRemoteWidgetSnippets.keys) {
final String body = rawRemoteWidgetSnippets[region]!;
runtime.update(LibraryName(<String>[region]), parseLibraryFile(body));
}
for (final String region in rawRemoteWidgetSnippets.keys) {
for (final WidgetLibrary localWidgets in _createLocalWidgets(region)) {
await tester.pumpWidget(
MaterialApp(
home: RemoteWidget(
runtime: runtime
..update(const LibraryName(<String>['local']), localWidgets),
data: data,
widget: FullyQualifiedWidgetName(LibraryName(<String>[region]), region),
),
),
);
}
}
});
}