Skip to content

Commit

Permalink
make attachRootComponent synchronous
Browse files Browse the repository at this point in the history
  • Loading branch information
Kilian Schulte committed Oct 3, 2024
1 parent 8acda68 commit b3248c9
Show file tree
Hide file tree
Showing 44 changed files with 95 additions and 88 deletions.
2 changes: 1 addition & 1 deletion docs/concepts/testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void main() {
testComponents('renders my component', (tester) async {
// We want to test the MyComponent component.
// Assume this shows a count and a button to increase it.
await tester.pumpComponent(MyComponent());
tester.pumpComponent(MyComponent());
// Should render a [Text] component with content 'Count: 0'.
expect(find.text('Count: 0'), findsOneComponent);
Expand Down
1 change: 0 additions & 1 deletion examples/flutter_multi_view/lib/widgets/counter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class CounterWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
var theme = ThemeData.light();
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Card(
Expand Down
4 changes: 2 additions & 2 deletions experiments/mobx_hooks/test/hooks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ void main() {

group('jaspr context', () {
// test('App', () async {
// await tester.pumpComponent(MobXHooksObserverComponent(child: App()));
// tester.pumpComponent(MobXHooksObserverComponent(child: App()));
// });

testComponents('custom flow', (tester) async {
await tester.pumpComponent(
tester.pumpComponent(
MobXHooksObserverComponent(
child: Builder(
builder: (context) sync* {
Expand Down
1 change: 1 addition & 0 deletions packages/jaspr/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased breaking

- **BREAKING** Migrate all packages to `package:web`, replacing `dart:html`.
- **BREAKING** Make `ComponentsBinding.attachRootComponent()` and `ComponentTester.pumpComponent()` synchronous.

- Add `InheritedModel<T>` similar to Flutters [InheritedModel](https://api.flutter.dev/flutter/widgets/InheritedModel-class.html)
- Improved html formatting on the server to not introduce unwanted whitespaces.
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void main() {
testComponents('renders my component', (tester) async {
// We want to test the MyComponent component.
// Assume this shows a count and a button to increase it.
await tester.pumpComponent(MyComponent());
tester.pumpComponent(MyComponent());
// Should render a [Text] component with content 'Count: 0'.
expect(find.text('Count: 0'), findsOneComponent);
Expand Down
4 changes: 2 additions & 2 deletions packages/jaspr/lib/src/browser/browser_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class BrowserAppBinding extends AppBinding with ComponentsBinding {
late (Node, Node)? attachBetween;

@override
Future<void> attachRootComponent(Component app, {String attachTo = 'body', (Node, Node)? attachBetween}) {
void attachRootComponent(Component app, {String attachTo = 'body', (Node, Node)? attachBetween}) {
attachTarget = attachTo;
this.attachBetween = attachBetween;
return super.attachRootComponent(app);
super.attachRootComponent(app);
}

@override
Expand Down
24 changes: 15 additions & 9 deletions packages/jaspr/lib/src/framework/build_owner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class BuildOwner {
assert(_debugStateLockLevel >= 0);
}

Future<void> performInitialBuild(Element element, Future<void> Function() completeBuild) async {
Future<void> performInitialBuild(Element element, void Function() completeBuild) async {
assert(_debugStateLockLevel >= 0);
assert(!_debugBuilding);

Expand All @@ -87,16 +87,22 @@ class BuildOwner {
element.mount(null, null);
element.didMount();

_isFirstBuild = false;
completeInitialBuild(element, () {
_isFirstBuild = false;

assert(_debugBuilding);
assert(() {
_debugBuilding = false;
_debugStateLockLevel -= 1;
return true;
}());
assert(_debugBuilding);
assert(() {
_debugBuilding = false;
_debugStateLockLevel -= 1;
return true;
}());

completeBuild();
});
}

return completeBuild();
void completeInitialBuild(Element element, void Function() buildCallback) {
buildCallback();
}

/// Rebuilds [child] and correctly accounts for any asynchronous operations that can
Expand Down
6 changes: 2 additions & 4 deletions packages/jaspr/lib/src/framework/components_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ part of 'framework.dart';
/// Main app binding, controls the root component and global state
mixin ComponentsBinding on AppBinding {
/// Sets [app] as the new root of the component tree and performs an initial build
Future<void> attachRootComponent(Component app) async {
void attachRootComponent(Component app) async {
var buildOwner = _rootElement?._owner ?? createRootBuildOwner();

var element = _Root(child: app).createElement();
Expand All @@ -13,9 +13,7 @@ mixin ComponentsBinding on AppBinding {

_rootElement = element;

return buildOwner.performInitialBuild(element, () async {
completeInitialFrame();
});
buildOwner.performInitialBuild(element, completeInitialFrame);
}

RenderObject createRootRenderObject();
Expand Down
8 changes: 3 additions & 5 deletions packages/jaspr/lib/src/server/async_build_owner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ extension AsyncElement on Element {

class AsyncBuildOwner extends BuildOwner {
@override
Future<void> performInitialBuild(Element element, Future<void> Function() completeBuild) {
return super.performInitialBuild(element, () async {
await element._asyncBuildLock?.asFuture;
return completeBuild();
});
void completeInitialBuild(Element element, void Function() buildCallback) async {
await element._asyncBuildLock?.asFuture;
super.completeInitialBuild(element, buildCallback);
}

@override
Expand Down
15 changes: 9 additions & 6 deletions packages/jaspr/lib/src/server/server_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ class ServerAppBinding extends AppBinding with ComponentsBinding {
@override
bool get isClient => false;

final rootCompleter = Completer.sync();

@override
Future<void> attachRootComponent(Component app) async {
await super.attachRootComponent(ClientComponentRegistry(child: app));
rootCompleter.complete();
void attachRootComponent(Component app) async {
super.attachRootComponent(ClientComponentRegistry(child: app));
}

Future<String> render() async {
await rootCompleter.future;
if (rootElement == null) return '';

if (rootElement!.owner.isFirstBuild) {
final completer = Completer.sync();
rootElement!.binding.addPostFrameCallback(completer.complete);
await completer.future;
}

var root = rootElement!.renderObject as MarkupRenderObject;
var adapters = [
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/browser/basic/basic_browser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'basic_app.dart';
void main() {
group('basic browser test', () {
testBrowser('should render component', (tester) async {
await tester.pumpComponent(App());
tester.pumpComponent(App());

expect(find.text('Count: 0'), findsOneComponent);

Expand Down
10 changes: 5 additions & 5 deletions packages/jaspr/test/browser/events_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ void main() {
testBrowser('handle click events', (tester) async {
int clicked = 0;

await tester.pumpComponent(button(onClick: () {
tester.pumpComponent(button(onClick: () {
clicked++;
}, []));

Expand All @@ -20,7 +20,7 @@ void main() {
bool checkedInput = false;
bool checkedChange = false;

await tester.pumpComponent(input(
tester.pumpComponent(input(
type: InputType.checkbox,
onInput: (value) => checkedInput = value,
onChange: (value) => checkedChange = value,
Expand All @@ -38,7 +38,7 @@ void main() {
double numberInput = 0;
double numberChange = 0;

await tester.pumpComponent(input(
tester.pumpComponent(input(
type: InputType.number,
onInput: (value) => numberInput = value,
onChange: (value) => numberChange = value,
Expand All @@ -56,7 +56,7 @@ void main() {
String textInput = "";
String textChange = "";

await tester.pumpComponent(input(
tester.pumpComponent(input(
type: InputType.text,
onInput: (value) => textInput = value,
onChange: (value) => textChange = value,
Expand All @@ -74,7 +74,7 @@ void main() {
String textInput = "";
String textChange = "";

await tester.pumpComponent(textarea(
tester.pumpComponent(textarea(
onInput: (value) => textInput = value,
onChange: (value) => textChange = value,
[],
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/browser/head/head_browser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'head_app.dart';
void main() {
group('head browser test', () {
testBrowser('should serve component', (tester) async {
await tester.pumpComponent(App());
tester.pumpComponent(App());

var nodes = AttachAdapter.instanceFor(AttachTarget.head).liveNodes.toList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void main() {
expect(pElement.parentNode, equals(divElement));
expect(bElement.parentNode, equals(pElement));

await tester.pumpComponent(div([
tester.pumpComponent(div([
p([
text('Hello '),
b([text('World2')]),
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/components/html/content_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders content', (tester) async {
await tester.pumpComponent(html([
tester.pumpComponent(html([
head([]),
body([
header([
Expand Down
4 changes: 2 additions & 2 deletions packages/jaspr/test/components/html/forms_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders button', (tester) async {
await tester.pumpComponent(button(
tester.pumpComponent(button(
autofocus: false,
disabled: false,
type: ButtonType.button,
Expand All @@ -18,7 +18,7 @@ void main() {
});

testComponents('renders form', (tester) async {
await tester.pumpComponent(form(
tester.pumpComponent(form(
action: "",
method: FormMethod.post,
encType: FormEncType.text,
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/components/html/media_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders media', (tester) async {
await tester.pumpComponent(div([
tester.pumpComponent(div([
audio(
autoplay: false,
controls: false,
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/components/html/other_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders other', (tester) async {
await tester.pumpComponent(div([
tester.pumpComponent(div([
details(open: false, []),
dialog(open: false, []),
summary([]),
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/components/html/svg_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders svg', (tester) async {
await tester.pumpComponent(svg(viewBox: "0 0 100 100", width: 100.px, height: 100.px, [
tester.pumpComponent(svg(viewBox: "0 0 100 100", width: 100.px, height: 100.px, [
rect(
x: "0",
y: "0",
Expand Down
2 changes: 1 addition & 1 deletion packages/jaspr/test/components/html/text_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:jaspr_test/jaspr_test.dart';
void main() {
group('html components', () {
testComponents('renders text', (tester) async {
await tester.pumpComponent(div([
tester.pumpComponent(div([
a(
download: "",
href: "a",
Expand Down
6 changes: 3 additions & 3 deletions packages/jaspr/test/framework/async/async_component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void main() {
testComponents('should render future with data', (tester) async {
var completer = Completer<String>();

await tester.pumpComponent(FutureTester(completer.future));
tester.pumpComponent(FutureTester(completer.future));

expect(find.text('LOADING'), findsOneComponent);

Expand All @@ -24,7 +24,7 @@ void main() {
testComponents('should render future with error', (tester) async {
var completer = Completer<String>();

await tester.pumpComponent(FutureTester(completer.future));
tester.pumpComponent(FutureTester(completer.future));

expect(find.text('LOADING'), findsOneComponent);

Expand All @@ -37,7 +37,7 @@ void main() {
testComponents('should render stream', (tester) async {
var controller = StreamController<String>();

await tester.pumpComponent(StreamTester(controller.stream));
tester.pumpComponent(StreamTester(controller.stream));

expect(find.text('LOADING'), findsOneComponent);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'basic_app.dart';
void main() {
group('basic component test', () {
testComponents('should render component', (tester) async {
await tester.pumpComponent(App());
tester.pumpComponent(App());

expect(find.text('Count: 0'), findsOneComponent);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'global_key_schenanigans_app.dart';
void main() {
group('global key schenanigans test', () {
testComponents('should keep state on reparenting', (tester) async {
var controller = await tester.pumpTestComponent(App());
var controller = tester.pumpTestComponent(App());

// phase 1: component should be mounted directly
expect(find.byType(Child), findsOneComponent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'inherited_component_app.dart';
void main() {
group('inherited component test', () {
testComponents('should inherit component', (tester) async {
var controller = await tester.pumpTestComponent(App());
var controller = tester.pumpTestComponent(App());

// phase 1: inherited component should be mounted
expect(find.text('Inherited value: 0'), findsOneComponent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void testAgainstDto(MyDto src, {required Set<Key> expectedRebuilds}) {
void main() {
group('inherited model test', () {
testComponents('should update dependencies only', (tester) async {
var controller = await tester.pumpTestComponent(App());
var controller = tester.pumpTestComponent(App());
Future<void> rebuildThenTestAgainstDto(
MyDto src, {
required Set<Key> expectedRebuilds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void main() {
testComponents('should track elements', (tester) async {
ObserverParam params = ObserverParam(renderBoth: true, events: []);
final events = params.events;
final controller = await tester.pumpTestComponent(App(params));
final controller = tester.pumpTestComponent(App(params));

// phase 1: observer component should be mounted
expect(find.text('Leaf true false'), findsOneComponent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'reorder_children_app.dart';
void main() {
group('reorder children test', () {
testComponents('should keep child state on reordering', (tester) async {
var controller = await tester.pumpTestComponent(App());
var controller = tester.pumpTestComponent(App());
var app = controller.element;

expect((app.component as App).child2Key.toString(), equals('[<2>]'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'stateful_reparenting_app.dart';
void main() {
group('stateful reparenting test', () {
testComponents('should keep state on reparenting', (tester) async {
var controller = await tester.pumpTestComponent(App());
var controller = tester.pumpTestComponent(App());

// phase 1: component should be mounted directly
expect(find.byType(MyStatefulComponent), findsOneComponent);
Expand Down
4 changes: 2 additions & 2 deletions packages/jaspr/test/utils/test_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:jaspr/jaspr.dart';
import 'package:jaspr_test/jaspr_test.dart';

extension PumpTestComponent on ComponentTester {
Future<TestComponentController<T>> pumpTestComponent<T>(TestComponent<T> component) async {
await pumpComponent(component);
TestComponentController<T> pumpTestComponent<T>(TestComponent<T> component) {
pumpComponent(component);
late Element testElem;
binding.rootElement!.visitChildren((element) {
testElem = element;
Expand Down
Loading

0 comments on commit b3248c9

Please sign in to comment.