diff --git a/CODEOWNERS b/CODEOWNERS index 8b9a96d8fd8c..19876d6184bf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -19,6 +19,7 @@ packages/flutter_template_images/** @stuartmorgan packages/go_router/** @chunhtai packages/go_router_builder/** @chunhtai packages/google_adsense/** @sokoloff06 +packages/google_adsense_ad_placement_api_web/** @astivi packages/google_identity_services_web/** @ditman packages/google_maps_flutter/** @stuartmorgan packages/google_sign_in/** @stuartmorgan diff --git a/README.md b/README.md index 64dce4761744..3f708e8147d2 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ These are the packages hosted in this repository: | [go\_router](./packages/go_router/) | [![pub package](https://img.shields.io/pub/v/go_router.svg)](https://pub.dev/packages/go_router) | [![pub points](https://img.shields.io/pub/points/go_router)](https://pub.dev/packages/go_router/score) | [![popularity](https://img.shields.io/pub/popularity/go_router)](https://pub.dev/packages/go_router/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20go_router?label=)](https://github.com/flutter/flutter/labels/p%3A%20go_router) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20go_router?label=)](https://github.com/flutter/packages/labels/p%3A%20go_router) | | [go\_router\_builder](./packages/go_router_builder/) | [![pub package](https://img.shields.io/pub/v/go_router_builder.svg)](https://pub.dev/packages/go_router_builder) | [![pub points](https://img.shields.io/pub/points/go_router_builder)](https://pub.dev/packages/go_router_builder/score) | [![popularity](https://img.shields.io/pub/popularity/go_router_builder)](https://pub.dev/packages/go_router_builder/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20go_router_builder?label=)](https://github.com/flutter/flutter/labels/p%3A%20go_router_builder) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20go_router_builder?label=)](https://github.com/flutter/packages/labels/p%3A%20go_router_builder) | | [google\_adsense](./packages/google_adsense/)| [![pub package](https://img.shields.io/pub/v/google_adsense.svg)](https://pub.dev/packages/google_adsense) | [![pub points](https://img.shields.io/pub/points/google_adsense)](https://pub.dev/packages/google_adsense/score) | [![popularity](https://img.shields.io/pub/popularity/google_adsense)](https://pub.dev/packages/google_adsense/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_adsense?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_adsense) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_adsense?label=)](https://github.com/flutter/packages/labels/p%3A%20google_adsense) | +| [google\_adsense\_ad\_placement\_api\_web](./packages/google_adsense_ad_placement_api_web/)| [![pub package](https://img.shields.io/pub/v/google_adsense_ad_placement_api_web.svg)](https://pub.dev/packages/google_adsense_ad_placement_api_web)| [![pub points](https://img.shields.io/pub/points/google_adsense_ad_placement_api_web)](https://pub.dev/packages/google_adsense_ad_placement_api_web/score)| [![popularity](https://img.shields.io/pub/popularity/google_adsense_ad_placement_api_web)](https://pub.dev/packages/google_adsense_ad_placement_api_web/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_adsense_ad_placement_api_web?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_adsense_ad_placement_api_web) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_adsense_ad_placement_api_web?label=)](https://github.com/flutter/packages/labels/p%3A%20google_adsense_ad_placement_api_web) | | [google\_maps\_flutter](./packages/google_maps_flutter/) | [![pub package](https://img.shields.io/pub/v/google_maps_flutter.svg)](https://pub.dev/packages/google_maps_flutter) | [![pub points](https://img.shields.io/pub/points/google_maps_flutter)](https://pub.dev/packages/google_maps_flutter/score) | [![popularity](https://img.shields.io/pub/popularity/google_maps_flutter)](https://pub.dev/packages/google_maps_flutter/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20maps?label=)](https://github.com/flutter/flutter/labels/p%3A%20maps) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_maps_flutter?label=)](https://github.com/flutter/packages/labels/p%3A%20google_maps_flutter) | | [google\_sign\_in](./packages/google_sign_in/) | [![pub package](https://img.shields.io/pub/v/google_sign_in.svg)](https://pub.dev/packages/google_sign_in) | [![pub points](https://img.shields.io/pub/points/google_sign_in)](https://pub.dev/packages/google_sign_in/score) | [![popularity](https://img.shields.io/pub/popularity/google_sign_in)](https://pub.dev/packages/google_sign_in/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_sign_in?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_sign_in) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_sign_in?label=)](https://github.com/flutter/packages/labels/p%3A%20google_sign_in) | | [image\_picker](./packages/image_picker/) | [![pub package](https://img.shields.io/pub/v/image_picker.svg)](https://pub.dev/packages/image_picker) | [![pub points](https://img.shields.io/pub/points/image_picker)](https://pub.dev/packages/image_picker/score) | [![popularity](https://img.shields.io/pub/popularity/image_picker)](https://pub.dev/packages/image_picker/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20image_picker?label=)](https://github.com/flutter/flutter/labels/p%3A%20image_picker) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20image_picker?label=)](https://github.com/flutter/packages/labels/p%3A%20image_picker) | diff --git a/packages/google_adsense_ad_placement_api_web/AUTHORS b/packages/google_adsense_ad_placement_api_web/AUTHORS new file mode 100644 index 000000000000..ad59f1184179 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Process project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/packages/google_adsense_ad_placement_api_web/CHANGELOG.md b/packages/google_adsense_ad_placement_api_web/CHANGELOG.md new file mode 100644 index 000000000000..31490590d5a4 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +* Initial version diff --git a/packages/google_adsense_ad_placement_api_web/LICENSE b/packages/google_adsense_ad_placement_api_web/LICENSE new file mode 100644 index 000000000000..c6823b81eb84 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/google_adsense_ad_placement_api_web/README.md b/packages/google_adsense_ad_placement_api_web/README.md new file mode 100644 index 000000000000..4838b3aacc4d --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/README.md @@ -0,0 +1,36 @@ +# google_adsense_ad_placement_api_web + +Wrapper of the AdSense Ad Placement API to be used in Dart and Flutter apps. +This Wrapper targets only the WEB platform. + +## Features + +To view the complete API, please check the official [AdSense website](https://developers.google.com/ad-placement/apis) + +## Getting started + +Add this package as a dependency on `pubspec.yaml` and import the library and the `ad_placement_api.dart` file. +This package supports interacting with the Ad Placement API after it's already loaded. Please remember to include the appropriate adsense js files to the page before using this package. + + +## Usage + +When you import the library inside a file, you'll have access to the singleton object `adPlacementApi`, which will have wrappers to both of the global functions that the Ad Placement API exposes: adBreak and adConfig. + +Example: + +```dart +import 'package:google_adsense_ad_placement_api_web/google_adsense_ad_placement_api_web.dart'; + +void main() { + adPlacementApi.adBreak( + name: 'rewarded-example', + type: BreakType.reward, + ); +} +``` + +## Testing + +Use `dart run script/tool/bin/flutter_plugin_tools.dart test --packages google_adsense_ad_placement_api_web --platform chrome` to test. +You need to specify a web platform to be able to test the JS Interop library. diff --git a/packages/google_adsense_ad_placement_api_web/example/lib/main.dart b/packages/google_adsense_ad_placement_api_web/example/lib/main.dart new file mode 100644 index 000000000000..0ebe5e8d4467 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/example/lib/main.dart @@ -0,0 +1,14 @@ +// 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. + +// #docregion main-example +import 'package:google_adsense_ad_placement_api_web/google_adsense_ad_placement_api_web.dart'; + +void main() { + adPlacementApi.adBreak( + name: 'rewarded-example', + type: BreakType.reward, + ); +} +// #enddocregion main-example diff --git a/packages/google_adsense_ad_placement_api_web/example/pubspec.yaml b/packages/google_adsense_ad_placement_api_web/example/pubspec.yaml new file mode 100644 index 000000000000..74b3bb617c21 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/example/pubspec.yaml @@ -0,0 +1,21 @@ +name: google_adsense_ad_placement_api_web_example +description: An example for the google_adsense_ad_placement_api_web_example package. +publish_to: 'none' + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +dependencies: + flutter: + sdk: flutter + google_adsense_ad_placement_api_web: + path: ../ + web: ^1.0.0 + +dev_dependencies: + build_runner: ^2.1.10 + flutter_test: + sdk: flutter + integration_test: + sdk: flutter diff --git a/packages/google_adsense_ad_placement_api_web/lib/google_adsense_ad_placement_api_web.dart b/packages/google_adsense_ad_placement_api_web/lib/google_adsense_ad_placement_api_web.dart new file mode 100644 index 000000000000..d800f5e24c79 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/lib/google_adsense_ad_placement_api_web.dart @@ -0,0 +1,12 @@ +// 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. + +/// AdSense Ad Placement API Library +library; + +export 'src/ad_placement_api_js_interop.dart' + show AdBreakDoneCallbackParamJSObject, AdBreakParamJSObject; +export 'src/enums.dart' + show BreakFormat, BreakStatus, BreakType, PreloadAdBreaks, SoundEnabled; +export 'src/globals.dart' show adPlacementApi; diff --git a/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api.dart b/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api.dart new file mode 100644 index 000000000000..8919d3a69892 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api.dart @@ -0,0 +1,107 @@ +// 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. + +import 'dart:js_interop'; + +import 'ad_placement_api_js_interop.dart'; +import 'enums.dart'; + +/// Main class to interact with the Ad Placement API from Flutter Web/Dart code. +class AdPlacementApi { + /// Wraps JS Ad Placement API in a dart object. + AdPlacementApi(this._adPlacementApiJsObject); + + final String _namePrefix = 'APFlutter-'; + + final AdPlacementApiJSObject? _adPlacementApiJsObject; + + /// Key function for placing ads within your app. It defines an ad placement and takes an object called a placement config that specifies everything required to show an ad. + void adBreak({ + /// The type of this placement + required BreakType type, + + /// A descriptive name for this placement + String? name, + + /// Prepare for the ad. Mute sounds and pause flow. + void Function()? beforeAd, + + /// Resume the app flow and re-enable sound + void Function()? afterAd, + + /// Show reward prompt (call showAdFn() if clicked) + void Function(JSFunction showAdFn)? beforeReward, + + /// User dismissed the ad before completion + void Function()? adDismissed, + + /// Ad was viewed and closed + void Function()? adViewed, + + /// Always called (if provided) even if an ad didn't show + void Function( + BreakType? breakType, + String? breakName, + BreakFormat? breakFormat, + BreakStatus? breakStatus, + )? adBreakDone, + }) { + final AdBreakParamJSObject param = AdBreakParamJSObject(JSObject()); + void empty() {} + void showAdDefault(JSFunction? showAd) { + if (showAd != null) { + showAd.callAsFunction(); + } + } + + void wrappedAdBreakDoneCallback(AdBreakDoneCallbackParamJSObject param) { + final BreakType type = BreakType.values.byName(param.breakType.toDart); + final BreakFormat format = + BreakFormat.values.byName(param.breakFormat.toDart); + final BreakStatus status = + BreakStatus.values.byName(param.breakStatus.toDart); + final String name = param.breakName.toDart; + if (adBreakDone != null) { + adBreakDone(type, name, format, status); + } + } + + String breakName = _namePrefix; + if (name != null) { + breakName = breakName + name; + } + + param.type = type.name.toJS; + param.name = breakName.toJS; + param.beforeAd = beforeAd != null ? beforeAd.toJS : empty.toJS; + if (type != BreakType.preroll) { + param.afterAd = afterAd != null ? afterAd.toJS : empty.toJS; + } + if (type == BreakType.reward) { + param.beforeReward = + beforeReward != null ? beforeReward.toJS : showAdDefault.toJS; + param.adDismissed = adDismissed != null ? adDismissed.toJS : empty.toJS; + param.adViewed = adViewed != null ? adViewed.toJS : empty.toJS; + } + param.adBreakDone = wrappedAdBreakDoneCallback.toJS; + + _adPlacementApiJsObject?.adBreak(param); + } + + /// The adConfig() call communicates the app's current configuration to the Ad Placement API. + /// The Ad Placement API can use this to tune the way it preloads ads and to filter the kinds of ads it requests so they're suitable (eg. video ads that require sound). + void adConfig( + PreloadAdBreaks preloadAdBreaks, + SoundEnabled sound, + void Function()? onReady, + ) { + final AdConfigParamJSObject param = AdConfigParamJSObject(JSObject()); + + param.preloadAdBreaks = preloadAdBreaks.name.toJS; + param.sound = sound.name.toJS; + param.onReady = onReady?.toJS; + + _adPlacementApiJsObject?.adConfig(param); + } +} diff --git a/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api_js_interop.dart b/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api_js_interop.dart new file mode 100644 index 000000000000..4e8e798af3cc --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/lib/src/ad_placement_api_js_interop.dart @@ -0,0 +1,72 @@ +// 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. + +import 'dart:js_interop'; + +/// JSInterop object that wraps the Javascript object for the Ad Placement API. +extension type AdPlacementApiJSObject(JSObject _) implements JSObject { + /// Key function for placing ads within your app. It defines an ad placement and takes an object called a placement config that specifies everything required to show an ad. + @JS() + external void adBreak(AdBreakParamJSObject o); + + /// The adConfig() call communicates the app's current configuration to the Ad Placement API. + /// The Ad Placement API can use this to tune the way it preloads ads and to filter the kinds of ads it requests so they're suitable (eg. video ads that require sound). + @JS() + external void adConfig(AdConfigParamJSObject o); +} + +/// JSInterop object that wraps the parameters for the adBreak call in the Ad Placement API. +extension type AdBreakParamJSObject(JSObject _) implements JSObject { + /// The type of this placement + external JSString type; + + /// A descriptive name for this placement + external JSString? name; + + /// Prepare for the ad. Mute sounds and pause flow. + external JSFunction? beforeAd; + + /// Resume the app flow and re-enable sound + external JSFunction? afterAd; + + /// Show reward prompt (call showAdFn() if clicked) + external JSFunction? beforeReward; + + /// User dismissed the ad before completion + external JSFunction? adDismissed; + + /// Ad was viewed and closed + external JSFunction? adViewed; + + /// Always called (if provided) even if an ad didn't show + external JSFunction? adBreakDone; +} + +/// JSInterop object representing the return object of the AdBreakDone callback +extension type AdBreakDoneCallbackParamJSObject(JSObject _) + implements JSObject { + /// See [BreakType] enum + external JSString breakType; + + /// Name of the ad break + external JSString breakName; + + /// See [BreakFormat] enum + external JSString breakFormat; + + /// See [BreakStatus] enum + external JSString breakStatus; +} + +/// JSInterop object that wraps the parameters for the adConfig call in the Ad Placement API. +extension type AdConfigParamJSObject(JSObject _) implements JSObject { + /// Ad preloading strategy + external JSString preloadAdBreaks; + + /// This app has sound + external JSString? sound; + + /// Called when API has initialised and adBreak() is ready + external JSExportedDartFunction? onReady; +} diff --git a/packages/google_adsense_ad_placement_api_web/lib/src/enums.dart b/packages/google_adsense_ad_placement_api_web/lib/src/enums.dart new file mode 100644 index 000000000000..948925520570 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/lib/src/enums.dart @@ -0,0 +1,84 @@ +// 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. + +/// Available types of Ad Breaks. +enum BreakType { + /// Before the app loads (before UI has rendered) + preroll, + + /// before the app flow starts (after UI has rendered) + start, + + /// the app is paused + pause, + + /// user navigates to the next screen + next, + + /// the user explores options + browse, + + /// a rewarded ad + reward, +} + +/// Available formats of Ad Breaks. +enum BreakFormat { + /// Used in the middle of content + interstitial, + + /// User gets rewarded for watching the entire ad + reward, +} + +/// Response from AdSense, provided as param of the adBreakDone callback +enum BreakStatus { + ///The Ad Placement API had not initialised + notReady, + + ///A placement timed out because the Ad Placement API took too long to respond + timeout, + + ///There was a JavaScript error in a callback + error, + + /// An ad had not been preloaded yet so this placement was skipped + noAdPreloaded, + + ///An ad wasn't shown because the frequency cap was applied to this placement + frequencyCapped, + + ///The user didn't click on a reward prompt before they reached the next placement, that is showAdFn() wasn't called before the next adBreak(). + ignored, + + ///The ad was not shown for another reason. (e.g., The ad was still being fetched, or a previously cached ad was disposed because the screen was resized/rotated.) + other, + + ///The user dismissed a rewarded ad before viewing it to completion + dismissed, + + ///The ad was viewed by the user + viewed, + + ///The placement was invalid and was ignored–for instance there should only be one preroll placement per page load, subsequent prerolls are failed with this status + invalid, +} + +/// Whether ads should always be preloaded before the first call to adBreak(). +enum PreloadAdBreaks { + /// Always preload. + on, + + ///The default value of auto leaves the decision up to the Ad Placement API. + auto, +} + +/// Whether the app is plays sounds during normal operations. +enum SoundEnabled { + /// Sound is played. + on, + + /// Sound is never played. + off, +} diff --git a/packages/google_adsense_ad_placement_api_web/lib/src/globals.dart b/packages/google_adsense_ad_placement_api_web/lib/src/globals.dart new file mode 100644 index 000000000000..4ebc076442c8 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/lib/src/globals.dart @@ -0,0 +1,16 @@ +// 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. + +import 'dart:js_interop'; + +import 'ad_placement_api.dart'; +import 'ad_placement_api_js_interop.dart'; + +/// Wraps the javascript window object to get loaded Ad Sense Ad Placement API. +@JS() +external AdPlacementApiJSObject get window; + +/// Main entrypoint for the library, named this way to mirror the API for the JS sdk +// ignore: non_constant_identifier_names +AdPlacementApi adPlacementApi = AdPlacementApi(window); diff --git a/packages/google_adsense_ad_placement_api_web/pubspec.yaml b/packages/google_adsense_ad_placement_api_web/pubspec.yaml new file mode 100644 index 000000000000..328d9da5138c --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/pubspec.yaml @@ -0,0 +1,24 @@ +name: google_adsense_ad_placement_api_web +description: Dart classes to interact with Google's AdSense Ad Placement API in Flutter Web applications. +version: 1.0.0 +repository: https://github.com/flutter/packages/tree/main/packages/google_adsense_ad_placement_api_web +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_adsense_ad_placement_api_web%22 + +environment: + sdk: ^3.4.4 + +dependencies: + web: "^1.1.0" + +dev_dependencies: + lints: ^5.0.0 + test: ^1.24.0 + +platforms: + web: + +topics: + - google-adsense + - adsense-ad-placement-api + - advertising + - web diff --git a/packages/google_adsense_ad_placement_api_web/test/ad_placement_api_test.dart b/packages/google_adsense_ad_placement_api_web/test/ad_placement_api_test.dart new file mode 100644 index 000000000000..0fe5144110d6 --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/test/ad_placement_api_test.dart @@ -0,0 +1,117 @@ +// 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. + +@TestOn('chrome') +library; + +import 'dart:js_interop'; + +import 'package:google_adsense_ad_placement_api_web/google_adsense_ad_placement_api_web.dart'; +import 'package:google_adsense_ad_placement_api_web/src/ad_placement_api.dart'; +import 'package:google_adsense_ad_placement_api_web/src/ad_placement_api_js_interop.dart'; +import 'package:test/test.dart'; + +@JSExport() +class FakeAdPlacementApiJSObject { + bool adBreakCalled = false; + JSString? nameUsed; + JSString? lastBreakTypeUsed; + JSString? preloadAdBreaks; + JSString? sound; + + @JSExport() + // ignore: unreachable_from_main + void adBreak(AdBreakParamJSObject o) { + adBreakCalled = true; + lastBreakTypeUsed = o.type; + nameUsed = o.name; + if (o.adBreakDone != null) { + final AdBreakDoneCallbackParamJSObject adBreakDoneParam = + AdBreakDoneCallbackParamJSObject(JSObject()); + adBreakDoneParam.breakFormat = 'interstitial'.toJS; + adBreakDoneParam.breakName = 'myBreak'.toJS; + adBreakDoneParam.breakType = 'reward'.toJS; + adBreakDoneParam.breakStatus = 'dismissed'.toJS; + o.adBreakDone!.callAsFunction(null, adBreakDoneParam); + } + } + + @JSExport() + // ignore: unreachable_from_main + void adConfig(AdConfigParamJSObject param) { + preloadAdBreaks = param.preloadAdBreaks; + sound = param.sound; + param.onReady?.callAsFunction(); + } +} + +void main() { + group('AdPlacementApi', () { + AdPlacementApi? adPlacementApi; + FakeAdPlacementApiJSObject? fakeAdPlacementApi; + + setUp(() { + fakeAdPlacementApi = FakeAdPlacementApiJSObject(); + final AdPlacementApiJSObject adPlacementApiJSObject = + createJSInteropWrapper( + fakeAdPlacementApi!) as AdPlacementApiJSObject; + adPlacementApi = AdPlacementApi(adPlacementApiJSObject); + }); + + test('can do ad breaks', () { + adPlacementApi?.adBreak( + type: BreakType.reward, + ); + + expect(fakeAdPlacementApi?.adBreakCalled, isTrue); + expect(fakeAdPlacementApi?.lastBreakTypeUsed?.toDart, + equals(BreakType.reward.name)); + }); + + test('can call the adBreakDone callback', () { + bool called = false; + void adBreakDoneCallback( + BreakType? breakType, + String? breakName, + BreakFormat? breakFormat, + BreakStatus? breakStatus, + ) { + called = true; + } + + adPlacementApi?.adBreak( + type: BreakType.reward, + adBreakDone: adBreakDoneCallback, + ); + + expect(called, isTrue); + }); + + test('can set up configuration', () { + bool called = false; + void onReadyCallback() { + called = true; + } + + adPlacementApi?.adConfig( + PreloadAdBreaks.on, SoundEnabled.off, onReadyCallback); + + expect(fakeAdPlacementApi?.sound?.toDart, equals(SoundEnabled.off.name)); + expect(fakeAdPlacementApi?.preloadAdBreaks?.toDart, + equals(PreloadAdBreaks.on.name)); + expect(called, isTrue); + }); + + test('perfixes adBreak name', () { + adPlacementApi?.adBreak( + type: BreakType.preroll, + name: 'My Break', + ); + + expect(fakeAdPlacementApi?.adBreakCalled, isTrue); + expect( + fakeAdPlacementApi?.nameUsed?.toDart, equals('APFlutter-My Break')); + }); + }); +} diff --git a/packages/google_adsense_ad_placement_api_web/test/only_web_test.dart b/packages/google_adsense_ad_placement_api_web/test/only_web_test.dart new file mode 100644 index 000000000000..844adda7aacf --- /dev/null +++ b/packages/google_adsense_ad_placement_api_web/test/only_web_test.dart @@ -0,0 +1,19 @@ +// 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. + +// ignore_for_file: avoid_print + +@TestOn('vm') +library; + +import 'package:test/test.dart'; + +void main() { + test('Tell the user where to find the real tests', () { + print('---'); + print('This package uses `dart test -p chrome` for its tests.'); + print('See `README.md` for more info.'); + print('---'); + }); +}