Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/google_adsense/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.2

* Added a callback to the widget for testing to make unit tests more deterministic.

## 0.1.1

* Adds `AdSenseCodeParameters` configuration object for `adSense.initialize`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ import 'js_interop_mocks/adsense_test_js_interop.dart';
const String testClient = 'test_client';
const String testSlot = 'test_slot';

class CallbackTracker {
void Function() createCallback() {
final int callbackIndex = _callbackStates.length;
_callbackStates.add(false);
return () => _callbackStates[callbackIndex] = true;
}

bool get allCalled => _callbackStates.every((bool state) => state);
final List<bool> _callbackStates = <bool>[];
}

void main() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

Expand Down Expand Up @@ -47,15 +58,17 @@ void main() async {

await adSense.initialize(testClient);

final CallbackTracker tracker = CallbackTracker();
final Widget adUnitWidget = AdUnitWidget(
configuration: AdUnitConfiguration.displayAdUnit(
adSlot: testSlot,
adFormat: AdFormat.AUTO, // Important!
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
);

await pumpAdWidget(adUnitWidget, tester);
await pumpAdWidget(adUnitWidget, tester, tracker);

// Then
// Widget level
Expand All @@ -81,19 +94,21 @@ void main() async {

await adSense.initialize(testClient);

final CallbackTracker tracker = CallbackTracker();
final Widget adUnitWidget = AdUnitWidget(
configuration: AdUnitConfiguration.displayAdUnit(
adSlot: testSlot,
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
);

final Widget constrainedAd = Container(
constraints: constraints,
child: adUnitWidget,
);

await pumpAdWidget(constrainedAd, tester);
await pumpAdWidget(constrainedAd, tester, tracker);

// Then
// Widget level
Expand All @@ -110,14 +125,17 @@ void main() async {
mockAdsByGoogle(mockAd(adStatus: AdStatus.UNFILLED));

await adSense.initialize(testClient);

final CallbackTracker tracker = CallbackTracker();
final Widget adUnitWidget = AdUnitWidget(
configuration: AdUnitConfiguration.displayAdUnit(
adSlot: testSlot,
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
);

await pumpAdWidget(adUnitWidget, tester);
await pumpAdWidget(adUnitWidget, tester, tracker);

// Then
expect(find.byType(HtmlElementView), findsNothing,
Expand All @@ -142,6 +160,7 @@ void main() async {

await adSense.initialize(testClient);

final CallbackTracker tracker = CallbackTracker();
final Widget bunchOfAds = Column(
children: <Widget>[
AdUnitWidget(
Expand All @@ -150,13 +169,15 @@ void main() async {
adFormat: AdFormat.AUTO,
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
),
AdUnitWidget(
configuration: AdUnitConfiguration.displayAdUnit(
adSlot: testSlot,
adFormat: AdFormat.AUTO,
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
),
Container(
constraints: const BoxConstraints(maxHeight: 100),
Expand All @@ -165,12 +186,13 @@ void main() async {
adSlot: testSlot,
),
adClient: adSense.adClient,
onInjected: tracker.createCallback(),
),
),
],
);

await pumpAdWidget(bunchOfAds, tester);
await pumpAdWidget(bunchOfAds, tester, tracker);

// Then
// Widget level
Expand All @@ -192,7 +214,8 @@ void main() async {
}

// Pumps an AdUnit Widget into a given tester, with some parameters
Future<void> pumpAdWidget(Widget adUnit, WidgetTester tester) async {
Future<void> pumpAdWidget(
Widget adUnit, WidgetTester tester, CallbackTracker tracker) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
Expand All @@ -203,10 +226,14 @@ Future<void> pumpAdWidget(Widget adUnit, WidgetTester tester) async {
),
);

// This extra pump is needed for the platform view to actually render in the DOM.
await tester.pump();
// One more for skwasm.
await tester.pump();
final Stopwatch timer = Stopwatch()..start();
while (!tracker.allCalled) {
if (timer.elapsedMilliseconds > 1000) {
fail('timeout while waiting for ad widget to be injected');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet!

}
// Pump until all the widgets have had their platform views injected into the dom.
await tester.pump();
}
// This extra pump is needed to simulate the async behavior of the adsense JS mock.
await tester.pumpAndSettle();
}
27 changes: 16 additions & 11 deletions packages/google_adsense/lib/src/adsense/ad_unit_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ class AdUnitWidget extends StatefulWidget {
super.key,
required AdUnitConfiguration configuration,
@visibleForTesting String? adClient,
@visibleForTesting void Function()? onInjected,
}) : _adClient = adClient ?? adSense.adClient,
_onInjected = onInjected,
_adUnitConfiguration = configuration {
assert(_adClient != null,
'Attempted to render an AdUnitWidget before calling adSense.initialize');
}

final String? _adClient;
final void Function()? _onInjected;

final AdUnitConfiguration _adUnitConfiguration;

Expand All @@ -58,17 +61,19 @@ class _AdUnitWidgetWebState extends State<AdUnitWidget>
@override
bool get wantKeepAlive => true;

static final web.ResizeObserver _adSenseResizeObserver = web.ResizeObserver(
(JSArray<web.ResizeObserverEntry> entries, web.ResizeObserver observer) {
for (final web.ResizeObserverEntry entry in entries.toDart) {
final web.Element target = entry.target;
if (target.isConnected) {
// First time resized since attached to DOM -> attachment callback from Flutter docs by David
_onElementAttached(target as web.HTMLElement);
observer.disconnect();
}
}
}.toJS);
web.ResizeObserver get _adSenseResizeObserver =>
web.ResizeObserver((JSArray<web.ResizeObserverEntry> entries,
web.ResizeObserver observer) {
for (final web.ResizeObserverEntry entry in entries.toDart) {
final web.Element target = entry.target;
if (target.isConnected) {
// First time resized since attached to DOM -> attachment callback from Flutter docs by David
_onElementAttached(target as web.HTMLElement);
widget._onInjected?.call();
observer.disconnect();
}
}
}.toJS);

@override
Widget build(BuildContext context) {
Expand Down
2 changes: 1 addition & 1 deletion packages/google_adsense/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_adsense
description: A wrapper plugin with convenience APIs allowing easier inserting Google Adsense HTML snippets withing a Flutter UI Web application
repository: https://github.com/flutter/packages/tree/main/packages/google_adsense
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_adsense%22
version: 0.1.1
version: 0.1.2

environment:
sdk: ^3.4.0
Expand Down