cloudx-react-native 3.6.1 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +92 -2
- package/android/src/main/java/com/cloudxreactnative/CloudXAdViewEvent.kt +2 -2
- package/android/src/main/java/com/cloudxreactnative/CloudXAdViewManagerImpl.kt +6 -6
- package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +208 -102
- package/android/src/test/java/com/cloudxreactnative/CloudXModuleImplArbiterBidsTest.kt +254 -0
- package/android/src/test/java/com/cloudxreactnative/CloudXModuleImplThreadingTest.kt +170 -0
- package/android/src/test/java/com/cloudxreactnative/FakeReadable.kt +101 -0
- package/cloudx-react-native.podspec +1 -1
- package/ios/CloudX.mm +62 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/Arbiter.js +27 -0
- package/lib/commonjs/types/Arbiter.js.map +1 -1
- package/lib/commonjs/types/RevenueData.js +1 -0
- package/lib/commonjs/types/RevenueData.js.map +1 -1
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/Arbiter.js +27 -0
- package/lib/module/types/Arbiter.js.map +1 -1
- package/lib/module/types/RevenueData.js +1 -0
- package/lib/module/types/RevenueData.js.map +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/Arbiter.d.ts +45 -2
- package/lib/typescript/src/types/Arbiter.d.ts.map +1 -1
- package/lib/typescript/src/types/RevenueData.d.ts +1 -0
- package/lib/typescript/src/types/RevenueData.d.ts.map +1 -1
- package/lib/typescript/src/types/index.d.ts +1 -1
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/types/Arbiter.ts +61 -2
- package/src/types/RevenueData.ts +1 -0
- package/src/types/index.ts +2 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
package com.cloudxreactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import io.cloudx.sdk.CloudXArbiterBid
|
|
5
|
+
import io.cloudx.sdk.CloudXArbiterPlatform
|
|
6
|
+
import io.mockk.every
|
|
7
|
+
import io.mockk.mockk
|
|
8
|
+
import org.junit.Assert.assertEquals
|
|
9
|
+
import org.junit.Assert.assertNull
|
|
10
|
+
import org.junit.Assert.assertTrue
|
|
11
|
+
import org.junit.Test
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Covers ADMOB bid parsing in [CloudXModuleImpl.arbiterBids], including coexistence with the
|
|
15
|
+
* pre-existing bid platforms.
|
|
16
|
+
*
|
|
17
|
+
* The SDK's AdMobBid class is internal to io.cloudx.sdk, so its adUnitId / networkName /
|
|
18
|
+
* manualRevenuePerImpressionUSD are not visible from this module. Assertions read them back by
|
|
19
|
+
* reflection; platform and extras come off the public CloudXArbiterBid surface.
|
|
20
|
+
*/
|
|
21
|
+
class CloudXModuleImplArbiterBidsTest {
|
|
22
|
+
|
|
23
|
+
// arbiterBids never touches the context, but the constructor registers a lifecycle listener.
|
|
24
|
+
private fun module(): CloudXModuleImpl {
|
|
25
|
+
val context = mockk<ReactApplicationContext>(relaxed = true)
|
|
26
|
+
every { context.addLifecycleEventListener(any()) } returns Unit
|
|
27
|
+
return CloudXModuleImpl(context)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private fun bidsFrom(vararg bids: Map<String, Any?>): List<CloudXArbiterBid> {
|
|
31
|
+
val configuration = FakeReadableMap(
|
|
32
|
+
mapOf("bids" to FakeReadableArray(bids.map { FakeReadableMap(it) }))
|
|
33
|
+
)
|
|
34
|
+
return module().arbiterBids(configuration)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private fun CloudXArbiterBid.field(name: String): Any? {
|
|
38
|
+
val field = javaClass.getDeclaredField(name)
|
|
39
|
+
field.isAccessible = true
|
|
40
|
+
return field.get(this)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Test
|
|
44
|
+
fun `routes ADMOB platform to an AdMob bid`() {
|
|
45
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB", "adUnitId" to "unit-1"))
|
|
46
|
+
|
|
47
|
+
assertEquals(1, bids.size)
|
|
48
|
+
assertEquals(CloudXArbiterPlatform.ADMOB, bids[0].platform)
|
|
49
|
+
assertEquals("unit-1", bids[0].field("adUnitId"))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Test
|
|
53
|
+
fun `accepts a lowercase platform token`() {
|
|
54
|
+
val bids = bidsFrom(mapOf("platform" to "admob", "adUnitId" to "unit-1"))
|
|
55
|
+
|
|
56
|
+
assertEquals(1, bids.size)
|
|
57
|
+
assertEquals(CloudXArbiterPlatform.ADMOB, bids[0].platform)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Test
|
|
61
|
+
fun `defaults networkName to admob when absent`() {
|
|
62
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB", "adUnitId" to "unit-1"))
|
|
63
|
+
|
|
64
|
+
assertEquals("admob", bids[0].field("networkName"))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Test
|
|
68
|
+
fun `defaults networkName to admob when blank`() {
|
|
69
|
+
val bids = bidsFrom(
|
|
70
|
+
mapOf("platform" to "ADMOB", "adUnitId" to "unit-1", "networkName" to " ")
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
assertEquals("admob", bids[0].field("networkName"))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Test
|
|
77
|
+
fun `passes an explicit networkName through`() {
|
|
78
|
+
val bids = bidsFrom(
|
|
79
|
+
mapOf("platform" to "ADMOB", "adUnitId" to "unit-1", "networkName" to "applovin")
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
assertEquals("applovin", bids[0].field("networkName"))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@Test
|
|
86
|
+
fun `drops a bid with a missing adUnitId`() {
|
|
87
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB"))
|
|
88
|
+
|
|
89
|
+
assertTrue(bids.isEmpty())
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Test
|
|
93
|
+
fun `drops a bid with a blank adUnitId`() {
|
|
94
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB", "adUnitId" to " "))
|
|
95
|
+
|
|
96
|
+
assertTrue(bids.isEmpty())
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Test
|
|
100
|
+
fun `keeps surrounding bids when one ADMOB bid is dropped`() {
|
|
101
|
+
val bids = bidsFrom(
|
|
102
|
+
mapOf("platform" to "ADMOB", "adUnitId" to ""),
|
|
103
|
+
mapOf("platform" to "ADMOB", "adUnitId" to "unit-2"),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
assertEquals(1, bids.size)
|
|
107
|
+
assertEquals("unit-2", bids[0].field("adUnitId"))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@Test
|
|
111
|
+
fun `carries a manual price when present`() {
|
|
112
|
+
val bids = bidsFrom(
|
|
113
|
+
mapOf(
|
|
114
|
+
"platform" to "ADMOB",
|
|
115
|
+
"adUnitId" to "unit-1",
|
|
116
|
+
"manualRevenuePerImpressionUSD" to 0.004,
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
assertEquals(0.004, bids[0].field("manualRevenuePerImpressionUSD") as Double, 1e-9)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Test
|
|
124
|
+
fun `leaves the manual price null when absent`() {
|
|
125
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB", "adUnitId" to "unit-1"))
|
|
126
|
+
|
|
127
|
+
assertNull(bids[0].field("manualRevenuePerImpressionUSD"))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Test
|
|
131
|
+
fun `keeps a zero manual price distinct from absent`() {
|
|
132
|
+
val bids = bidsFrom(
|
|
133
|
+
mapOf(
|
|
134
|
+
"platform" to "ADMOB",
|
|
135
|
+
"adUnitId" to "unit-1",
|
|
136
|
+
"manualRevenuePerImpressionUSD" to 0.0,
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
assertEquals(0.0, bids[0].field("manualRevenuePerImpressionUSD") as Double, 1e-9)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Test
|
|
144
|
+
fun `forwards a negative manual price unchanged`() {
|
|
145
|
+
val bids = bidsFrom(
|
|
146
|
+
mapOf(
|
|
147
|
+
"platform" to "ADMOB",
|
|
148
|
+
"adUnitId" to "unit-1",
|
|
149
|
+
"manualRevenuePerImpressionUSD" to -1.5,
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
// The wrapper is transparent about the value it was handed; the native SDK decides to drop it.
|
|
154
|
+
assertEquals(-1.5, bids[0].field("manualRevenuePerImpressionUSD") as Double, 1e-9)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@Test
|
|
158
|
+
fun `maps a CUSTOM bid alongside an ADMOB bid in order`() {
|
|
159
|
+
val bids = bidsFrom(
|
|
160
|
+
mapOf(
|
|
161
|
+
"platform" to "CUSTOM",
|
|
162
|
+
"platformName" to "CUSTOM_MEDIATOR",
|
|
163
|
+
"revenuePerImpressionUSD" to 0.002,
|
|
164
|
+
"precision" to "exact",
|
|
165
|
+
),
|
|
166
|
+
mapOf("platform" to "ADMOB", "adUnitId" to "unit-2"),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
assertEquals(2, bids.size)
|
|
170
|
+
assertEquals(CloudXArbiterPlatform.CUSTOM, bids[0].platform)
|
|
171
|
+
assertEquals("CUSTOM_MEDIATOR", bids[0].platformName)
|
|
172
|
+
assertEquals(CloudXArbiterPlatform.ADMOB, bids[1].platform)
|
|
173
|
+
assertEquals("unit-2", bids[1].field("adUnitId"))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Test
|
|
177
|
+
fun `maps string extras and skips non-string entries`() {
|
|
178
|
+
val bids = bidsFrom(
|
|
179
|
+
mapOf(
|
|
180
|
+
"platform" to "ADMOB",
|
|
181
|
+
"adUnitId" to "unit-1",
|
|
182
|
+
"extras" to FakeReadableMap(mapOf("k" to "v", "n" to 1.0)),
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
assertEquals(mapOf("k" to "v"), bids[0].extras)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Test
|
|
190
|
+
fun `defaults extras to empty when absent`() {
|
|
191
|
+
val bids = bidsFrom(mapOf("platform" to "ADMOB", "adUnitId" to "unit-1"))
|
|
192
|
+
|
|
193
|
+
assertEquals(emptyMap<String, String>(), bids[0].extras)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@Test
|
|
197
|
+
fun `routes GAM platform to a Gam bid with default networkName`() {
|
|
198
|
+
val bids = bidsFrom(mapOf("platform" to "GAM", "adUnitId" to "/21775744923/example/banner"))
|
|
199
|
+
|
|
200
|
+
assertEquals(1, bids.size)
|
|
201
|
+
assertEquals(CloudXArbiterPlatform.GAM, bids[0].platform)
|
|
202
|
+
assertEquals("/21775744923/example/banner", bids[0].field("adUnitId"))
|
|
203
|
+
assertEquals("gam", bids[0].field("networkName"))
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@Test
|
|
207
|
+
fun `carries GAM manual price and extras through`() {
|
|
208
|
+
val bids = bidsFrom(
|
|
209
|
+
mapOf(
|
|
210
|
+
"platform" to "GAM",
|
|
211
|
+
"adUnitId" to "/21775744923/example/banner",
|
|
212
|
+
"networkName" to "reservation",
|
|
213
|
+
"manualRevenuePerImpressionUSD" to 0.0025,
|
|
214
|
+
"extras" to FakeReadableMap(mapOf("k" to "v")),
|
|
215
|
+
)
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
assertEquals("reservation", bids[0].field("networkName"))
|
|
219
|
+
assertEquals(0.0025, bids[0].field("manualRevenuePerImpressionUSD") as Double, 1e-9)
|
|
220
|
+
assertEquals(mapOf("k" to "v"), bids[0].extras)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@Test
|
|
224
|
+
fun `keeps a zero GAM manual price distinct from absent`() {
|
|
225
|
+
val bids = bidsFrom(
|
|
226
|
+
mapOf(
|
|
227
|
+
"platform" to "GAM",
|
|
228
|
+
"adUnitId" to "/21775744923/example/banner",
|
|
229
|
+
"manualRevenuePerImpressionUSD" to 0.0,
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
assertEquals(0.0, bids[0].field("manualRevenuePerImpressionUSD") as Double, 1e-9)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@Test
|
|
237
|
+
fun `drops a GAM bid with a blank adUnitId`() {
|
|
238
|
+
val bids = bidsFrom(mapOf("platform" to "GAM", "adUnitId" to " "))
|
|
239
|
+
|
|
240
|
+
assertTrue(bids.isEmpty())
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@Test
|
|
244
|
+
fun `maps an ADMOB bid alongside a GAM bid in order`() {
|
|
245
|
+
val bids = bidsFrom(
|
|
246
|
+
mapOf("platform" to "ADMOB", "adUnitId" to "ca-app-pub-1/2"),
|
|
247
|
+
mapOf("platform" to "GAM", "adUnitId" to "/21775744923/example/banner"),
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
assertEquals(2, bids.size)
|
|
251
|
+
assertEquals(CloudXArbiterPlatform.ADMOB, bids[0].platform)
|
|
252
|
+
assertEquals(CloudXArbiterPlatform.GAM, bids[1].platform)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
package com.cloudxreactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import io.cloudx.sdk.CloudX
|
|
5
|
+
import io.cloudx.sdk.CloudXAppOpenAd
|
|
6
|
+
import io.cloudx.sdk.CloudXInterstitialAd
|
|
7
|
+
import io.cloudx.sdk.CloudXRewardedAd
|
|
8
|
+
import io.cloudx.sdk.CloudXAdView
|
|
9
|
+
import io.mockk.every
|
|
10
|
+
import io.mockk.mockk
|
|
11
|
+
import io.mockk.mockkStatic
|
|
12
|
+
import io.mockk.unmockkAll
|
|
13
|
+
import io.mockk.verify
|
|
14
|
+
import kotlinx.coroutines.Dispatchers
|
|
15
|
+
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
16
|
+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
|
17
|
+
import kotlinx.coroutines.test.resetMain
|
|
18
|
+
import kotlinx.coroutines.test.setMain
|
|
19
|
+
import org.junit.After
|
|
20
|
+
import org.junit.Assert.assertEquals
|
|
21
|
+
import org.junit.Before
|
|
22
|
+
import org.junit.Test
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Covers the module's UI-thread invariant: every public method posts its body via
|
|
26
|
+
* [ReactApplicationContext.runOnUiQueueThread], so JS call order is preserved and a destroy
|
|
27
|
+
* followed by a load always operates on a fresh native ad instance.
|
|
28
|
+
*/
|
|
29
|
+
@OptIn(ExperimentalCoroutinesApi::class)
|
|
30
|
+
class CloudXModuleImplThreadingTest {
|
|
31
|
+
|
|
32
|
+
private val adUnitId = "unit-1"
|
|
33
|
+
private val queuedRunnables = mutableListOf<Runnable>()
|
|
34
|
+
|
|
35
|
+
@Before
|
|
36
|
+
fun setUp() {
|
|
37
|
+
// CloudX's static initializer resolves Dispatchers.Main, which needs a main looper on the JVM.
|
|
38
|
+
Dispatchers.setMain(UnconfinedTestDispatcher())
|
|
39
|
+
mockkStatic(CloudX::class)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@After
|
|
43
|
+
fun tearDown() {
|
|
44
|
+
unmockkAll()
|
|
45
|
+
Dispatchers.resetMain()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Simulates the UI thread's FIFO queue by running every posted runnable immediately.
|
|
49
|
+
private fun moduleWithInlineUiThread(): CloudXModuleImpl {
|
|
50
|
+
val context = mockk<ReactApplicationContext>(relaxed = true)
|
|
51
|
+
every { context.runOnUiQueueThread(any()) } answers { firstArg<Runnable>().run() }
|
|
52
|
+
return CloudXModuleImpl(context)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Swallows every posted runnable, so anything that runs is running off the UI thread.
|
|
56
|
+
private fun moduleWithStalledUiThread(): CloudXModuleImpl {
|
|
57
|
+
val context = mockk<ReactApplicationContext>(relaxed = true)
|
|
58
|
+
every { context.runOnUiQueueThread(any()) } returns Unit
|
|
59
|
+
return CloudXModuleImpl(context)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Queues posted runnables into [queuedRunnables]; call [drainUiThread] to run them in FIFO order.
|
|
63
|
+
private fun moduleWithQueuedUiThread(): CloudXModuleImpl {
|
|
64
|
+
val context = mockk<ReactApplicationContext>(relaxed = true)
|
|
65
|
+
every { context.runOnUiQueueThread(any()) } answers { queuedRunnables.add(firstArg()) }
|
|
66
|
+
return CloudXModuleImpl(context)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private fun drainUiThread() {
|
|
70
|
+
while (queuedRunnables.isNotEmpty()) queuedRunnables.removeAt(0).run()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Test
|
|
74
|
+
fun `destroy then load on same ad unit loads a fresh interstitial`() {
|
|
75
|
+
// Arrange
|
|
76
|
+
val first = mockk<CloudXInterstitialAd>(relaxed = true)
|
|
77
|
+
val second = mockk<CloudXInterstitialAd>(relaxed = true)
|
|
78
|
+
every { CloudX.createInterstitial(any(), any()) } returnsMany listOf(first, second)
|
|
79
|
+
val subject = moduleWithInlineUiThread()
|
|
80
|
+
subject.loadInterstitial(adUnitId)
|
|
81
|
+
|
|
82
|
+
// Act
|
|
83
|
+
subject.destroyInterstitial(adUnitId)
|
|
84
|
+
subject.loadInterstitial(adUnitId)
|
|
85
|
+
|
|
86
|
+
// Assert
|
|
87
|
+
verify(exactly = 1) { first.load() }
|
|
88
|
+
verify(exactly = 1) { first.destroy() }
|
|
89
|
+
verify(exactly = 1) { second.load() }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Test
|
|
93
|
+
fun `destroy then load on same ad unit loads a fresh app open ad`() {
|
|
94
|
+
// Arrange
|
|
95
|
+
val first = mockk<CloudXAppOpenAd>(relaxed = true)
|
|
96
|
+
val second = mockk<CloudXAppOpenAd>(relaxed = true)
|
|
97
|
+
every { CloudX.createAppOpen(any(), any()) } returnsMany listOf(first, second)
|
|
98
|
+
val subject = moduleWithInlineUiThread()
|
|
99
|
+
subject.loadAppOpen(adUnitId)
|
|
100
|
+
|
|
101
|
+
// Act
|
|
102
|
+
subject.destroyAppOpen(adUnitId)
|
|
103
|
+
subject.loadAppOpen(adUnitId)
|
|
104
|
+
|
|
105
|
+
// Assert
|
|
106
|
+
verify(exactly = 1) { first.load() }
|
|
107
|
+
verify(exactly = 1) { first.destroy() }
|
|
108
|
+
verify(exactly = 1) { second.load() }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Test
|
|
112
|
+
fun `destroy then load on same ad unit loads a fresh rewarded ad`() {
|
|
113
|
+
// Arrange
|
|
114
|
+
val first = mockk<CloudXRewardedAd>(relaxed = true)
|
|
115
|
+
val second = mockk<CloudXRewardedAd>(relaxed = true)
|
|
116
|
+
every { CloudX.createRewarded(any(), any()) } returnsMany listOf(first, second)
|
|
117
|
+
val subject = moduleWithInlineUiThread()
|
|
118
|
+
subject.loadRewarded(adUnitId)
|
|
119
|
+
|
|
120
|
+
// Act
|
|
121
|
+
subject.destroyRewarded(adUnitId)
|
|
122
|
+
subject.loadRewarded(adUnitId)
|
|
123
|
+
|
|
124
|
+
// Assert
|
|
125
|
+
verify(exactly = 1) { first.load() }
|
|
126
|
+
verify(exactly = 1) { first.destroy() }
|
|
127
|
+
verify(exactly = 1) { second.load() }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Test
|
|
131
|
+
fun `load does not touch the SDK before the UI runnable runs`() {
|
|
132
|
+
// Arrange
|
|
133
|
+
val subject = moduleWithStalledUiThread()
|
|
134
|
+
|
|
135
|
+
// Act
|
|
136
|
+
subject.loadInterstitial(adUnitId)
|
|
137
|
+
|
|
138
|
+
// Assert
|
|
139
|
+
verify(exactly = 0) { CloudX.createInterstitial(any(), any()) }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@Test
|
|
143
|
+
fun `position update followed by offsets update keeps the new position`() {
|
|
144
|
+
// Arrange
|
|
145
|
+
every { CloudX.createBanner(any(), any()) } returns mockk<CloudXAdView>(relaxed = true)
|
|
146
|
+
val subject = moduleWithQueuedUiThread()
|
|
147
|
+
subject.createBanner(adUnitId, "top")
|
|
148
|
+
drainUiThread()
|
|
149
|
+
|
|
150
|
+
// Act
|
|
151
|
+
subject.updateBannerPosition(adUnitId, "bottom")
|
|
152
|
+
subject.updateBannerOffsets(adUnitId, 1.0, 2.0)
|
|
153
|
+
drainUiThread()
|
|
154
|
+
|
|
155
|
+
// Assert
|
|
156
|
+
assertEquals("bottom", subject.adViewPositionForTesting(adUnitId))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@Test
|
|
160
|
+
fun `config setter does not touch the SDK before the UI runnable runs`() {
|
|
161
|
+
// Arrange
|
|
162
|
+
val subject = moduleWithStalledUiThread()
|
|
163
|
+
|
|
164
|
+
// Act
|
|
165
|
+
subject.setHashedUserID("hashed")
|
|
166
|
+
|
|
167
|
+
// Assert
|
|
168
|
+
verify(exactly = 0) { CloudX.setHashedUserId(any()) }
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.cloudxreactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.bridge.ReadableMapKeySetIterator
|
|
7
|
+
import com.facebook.react.bridge.ReadableType
|
|
8
|
+
import java.util.ArrayList
|
|
9
|
+
import java.util.HashMap
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Minimal in-memory [ReadableMap] backed by a plain Kotlin map.
|
|
13
|
+
*
|
|
14
|
+
* The bridge only ever reads values through hasKey/getType/getString/getDouble/getMap, so the
|
|
15
|
+
* remaining members throw rather than pretend to work.
|
|
16
|
+
*/
|
|
17
|
+
internal class FakeReadableMap(private val values: Map<String, Any?>) : ReadableMap {
|
|
18
|
+
|
|
19
|
+
override val entryIterator: Iterator<Map.Entry<String, Any>>
|
|
20
|
+
get() = throw UnsupportedOperationException("not used by the bridge")
|
|
21
|
+
|
|
22
|
+
override fun hasKey(name: String): Boolean = values.containsKey(name)
|
|
23
|
+
|
|
24
|
+
override fun isNull(name: String): Boolean = values[name] == null
|
|
25
|
+
|
|
26
|
+
override fun getType(name: String): ReadableType = when (values[name]) {
|
|
27
|
+
null -> ReadableType.Null
|
|
28
|
+
is Boolean -> ReadableType.Boolean
|
|
29
|
+
is Number -> ReadableType.Number
|
|
30
|
+
is String -> ReadableType.String
|
|
31
|
+
is ReadableMap -> ReadableType.Map
|
|
32
|
+
is ReadableArray -> ReadableType.Array
|
|
33
|
+
else -> throw IllegalArgumentException("unsupported value for key=$name")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override fun getString(name: String): String? = values[name] as String?
|
|
37
|
+
|
|
38
|
+
override fun getDouble(name: String): Double = (values[name] as Number).toDouble()
|
|
39
|
+
|
|
40
|
+
override fun getInt(name: String): Int = (values[name] as Number).toInt()
|
|
41
|
+
|
|
42
|
+
override fun getLong(name: String): Long = (values[name] as Number).toLong()
|
|
43
|
+
|
|
44
|
+
override fun getBoolean(name: String): Boolean = values[name] as Boolean
|
|
45
|
+
|
|
46
|
+
override fun getMap(name: String): ReadableMap? = values[name] as ReadableMap?
|
|
47
|
+
|
|
48
|
+
override fun getArray(name: String): ReadableArray? = values[name] as ReadableArray?
|
|
49
|
+
|
|
50
|
+
override fun keySetIterator(): ReadableMapKeySetIterator {
|
|
51
|
+
val keys = values.keys.toList().iterator()
|
|
52
|
+
return object : ReadableMapKeySetIterator {
|
|
53
|
+
override fun hasNextKey(): Boolean = keys.hasNext()
|
|
54
|
+
override fun nextKey(): String = keys.next()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override fun getDynamic(name: String): Dynamic =
|
|
59
|
+
throw UnsupportedOperationException("not used by the bridge")
|
|
60
|
+
|
|
61
|
+
override fun toHashMap(): HashMap<String, Any> =
|
|
62
|
+
throw UnsupportedOperationException("not used by the bridge")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Minimal in-memory [ReadableArray] holding the bid maps handed to the bridge. */
|
|
66
|
+
internal class FakeReadableArray(private val values: List<Any?>) : ReadableArray {
|
|
67
|
+
|
|
68
|
+
override fun size(): Int = values.size
|
|
69
|
+
|
|
70
|
+
override fun isNull(index: Int): Boolean = values[index] == null
|
|
71
|
+
|
|
72
|
+
override fun getType(index: Int): ReadableType = when (values[index]) {
|
|
73
|
+
null -> ReadableType.Null
|
|
74
|
+
is Boolean -> ReadableType.Boolean
|
|
75
|
+
is Number -> ReadableType.Number
|
|
76
|
+
is String -> ReadableType.String
|
|
77
|
+
is ReadableMap -> ReadableType.Map
|
|
78
|
+
is ReadableArray -> ReadableType.Array
|
|
79
|
+
else -> throw IllegalArgumentException("unsupported value at index=$index")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
override fun getMap(index: Int): ReadableMap = values[index] as ReadableMap
|
|
83
|
+
|
|
84
|
+
override fun getString(index: Int): String = values[index] as String
|
|
85
|
+
|
|
86
|
+
override fun getDouble(index: Int): Double = (values[index] as Number).toDouble()
|
|
87
|
+
|
|
88
|
+
override fun getInt(index: Int): Int = (values[index] as Number).toInt()
|
|
89
|
+
|
|
90
|
+
override fun getLong(index: Int): Long = (values[index] as Number).toLong()
|
|
91
|
+
|
|
92
|
+
override fun getBoolean(index: Int): Boolean = values[index] as Boolean
|
|
93
|
+
|
|
94
|
+
override fun getArray(index: Int): ReadableArray = values[index] as ReadableArray
|
|
95
|
+
|
|
96
|
+
override fun getDynamic(index: Int): Dynamic =
|
|
97
|
+
throw UnsupportedOperationException("not used by the bridge")
|
|
98
|
+
|
|
99
|
+
override fun toArrayList(): ArrayList<Any> =
|
|
100
|
+
throw UnsupportedOperationException("not used by the bridge")
|
|
101
|
+
}
|
package/ios/CloudX.mm
CHANGED
|
@@ -141,6 +141,11 @@ static NSString *const ARBITER_PLATFORM_CLOUDX = @"CLOUDX";
|
|
|
141
141
|
static NSString *const ARBITER_PLATFORM_LEVELPLAY = @"LEVELPLAY";
|
|
142
142
|
static NSString *const ARBITER_PLATFORM_PUBMATIC = @"PUBMATIC";
|
|
143
143
|
static NSString *const ARBITER_PLATFORM_CUSTOM = @"CUSTOM";
|
|
144
|
+
static NSString *const ARBITER_PLATFORM_ADMOB = @"ADMOB";
|
|
145
|
+
static NSString *const ARBITER_PLATFORM_GAM = @"GAM";
|
|
146
|
+
|
|
147
|
+
static NSString *const ADMOB_DEFAULT_NETWORK_NAME = @"admob";
|
|
148
|
+
static NSString *const GAM_DEFAULT_NETWORK_NAME = @"gam";
|
|
144
149
|
|
|
145
150
|
static CloudX *CloudXShared;
|
|
146
151
|
|
|
@@ -1644,6 +1649,11 @@ RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
|
1644
1649
|
return CLXRevenuePlatformAdMob;
|
|
1645
1650
|
}
|
|
1646
1651
|
|
|
1652
|
+
if ( [trimmedPlatform caseInsensitiveCompare: CLXRevenuePlatformGAM] == NSOrderedSame )
|
|
1653
|
+
{
|
|
1654
|
+
return CLXRevenuePlatformGAM;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1647
1657
|
if ( [trimmedPlatform caseInsensitiveCompare: CLXRevenuePlatformInMobi] == NSOrderedSame )
|
|
1648
1658
|
{
|
|
1649
1659
|
return CLXRevenuePlatformInMobi;
|
|
@@ -1792,6 +1802,14 @@ RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
|
1792
1802
|
{
|
|
1793
1803
|
return [self customArbiterBidFromDictionary: dictionary];
|
|
1794
1804
|
}
|
|
1805
|
+
if ( [platform isEqualToString: ARBITER_PLATFORM_ADMOB] )
|
|
1806
|
+
{
|
|
1807
|
+
return [self adMobArbiterBidFromDictionary: dictionary];
|
|
1808
|
+
}
|
|
1809
|
+
if ( [platform isEqualToString: ARBITER_PLATFORM_GAM] )
|
|
1810
|
+
{
|
|
1811
|
+
return [self gamArbiterBidFromDictionary: dictionary];
|
|
1812
|
+
}
|
|
1795
1813
|
return nil;
|
|
1796
1814
|
}
|
|
1797
1815
|
|
|
@@ -1874,6 +1892,50 @@ RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
|
1874
1892
|
extras: [self stringMapFromDictionaryValue: dictionary[@"extras"]]];
|
|
1875
1893
|
}
|
|
1876
1894
|
|
|
1895
|
+
- (nullable CLXArbiterBid *)adMobArbiterBidFromDictionary:(NSDictionary<NSString *, id> *)dictionary
|
|
1896
|
+
{
|
|
1897
|
+
// Values are passed untrimmed once valid; blankness only decides accept vs default.
|
|
1898
|
+
NSString *adUnitId = [self stringValueFromDictionary: dictionary key: @"adUnitId"];
|
|
1899
|
+
if ( [self isBlankString: adUnitId] )
|
|
1900
|
+
{
|
|
1901
|
+
[self log: @"arbiter: ignoring ADMOB bid with missing adUnitId"];
|
|
1902
|
+
return nil;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
NSString *networkName = [self stringValueFromDictionary: dictionary key: @"networkName"];
|
|
1906
|
+
if ( [self isBlankString: networkName] )
|
|
1907
|
+
{
|
|
1908
|
+
networkName = ADMOB_DEFAULT_NETWORK_NAME;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
return [CLXArbiterBid adMobBidWithAdUnitId: adUnitId
|
|
1912
|
+
networkName: networkName
|
|
1913
|
+
manualRevenuePerImpressionUSD: [self revenueNumberValueFromDictionary: dictionary key: @"manualRevenuePerImpressionUSD"]
|
|
1914
|
+
extras: [self stringMapFromDictionaryValue: dictionary[@"extras"]]];
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
- (nullable CLXArbiterBid *)gamArbiterBidFromDictionary:(NSDictionary<NSString *, id> *)dictionary
|
|
1918
|
+
{
|
|
1919
|
+
// Same blank-check rationale as the ADMOB parser above.
|
|
1920
|
+
NSString *adUnitId = [self stringValueFromDictionary: dictionary key: @"adUnitId"];
|
|
1921
|
+
if ( [self isBlankString: adUnitId] )
|
|
1922
|
+
{
|
|
1923
|
+
[self log: @"arbiter: ignoring GAM bid with missing adUnitId"];
|
|
1924
|
+
return nil;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
NSString *networkName = [self stringValueFromDictionary: dictionary key: @"networkName"];
|
|
1928
|
+
if ( [self isBlankString: networkName] )
|
|
1929
|
+
{
|
|
1930
|
+
networkName = GAM_DEFAULT_NETWORK_NAME;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
return [CLXArbiterBid gamBidWithAdUnitId: adUnitId
|
|
1934
|
+
networkName: networkName
|
|
1935
|
+
manualRevenuePerImpressionUSD: [self revenueNumberValueFromDictionary: dictionary key: @"manualRevenuePerImpressionUSD"]
|
|
1936
|
+
extras: [self stringMapFromDictionaryValue: dictionary[@"extras"]]];
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1877
1939
|
- (NSDictionary<NSString *, id> *)arbiterResultInfoForResult:(CLXArbiterResult *)result
|
|
1878
1940
|
{
|
|
1879
1941
|
return @{@"id": result.identifier ?: @"",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_CloudX","_interopRequireWildcard","require","_NativeCloudX","_interopRequireDefault","_EventEmitter","_Arbiter","_RevenueData","_CloudXInterstitialAd","_CloudXAppOpenAd","_CloudXRewardedAd","_CloudXBannerAd","_CloudXMRECAd","_CloudXAdPosition","_CloudXBannerView","_CloudXMRECView","_CloudXErrorCode","_AppTrackingTransparency","_hooks","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","CloudXLogLevel","exports","VERBOSE","DEBUG","INFO","WARN","ERROR","NONE"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAAA,OAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,aAAA,GAAAC,sBAAA,CAAAF,OAAA;AAIA,IAAAG,aAAA,GAAAH,OAAA;AACA,IAAAI,QAAA,GAAAJ,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AAGA,IAAAM,qBAAA,GAAAN,OAAA;AACA,IAAAO,gBAAA,GAAAP,OAAA;AACA,IAAAQ,iBAAA,GAAAR,OAAA;AACA,IAAAS,eAAA,GAAAT,OAAA;AACA,IAAAU,aAAA,GAAAV,OAAA;AACA,IAAAW,iBAAA,GAAAX,OAAA;AAGA,IAAAY,iBAAA,GAAAZ,OAAA;AACA,IAAAa,eAAA,GAAAb,OAAA;AAIA,IAAAc,gBAAA,GAAAd,OAAA;AAGA,IAAAe,wBAAA,GAAAf,OAAA;AAGA,IAAAgB,MAAA,GAAAhB,OAAA;AAAsG,SAAAE,uBAAAe,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAlB,wBAAAkB,CAAA,EAAAG,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAtB,uBAAA,YAAAA,CAAAkB,CAAA,EAAAG,CAAA,SAAAA,CAAA,IAAAH,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAO,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAR,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAS,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAX,CAAA,UAAAO,CAAA,CAAAK,GAAA,CAAAZ,CAAA,GAAAO,CAAA,CAAAM,GAAA,CAAAb,CAAA,EAAAS,CAAA,gBAAAN,CAAA,IAAAH,CAAA,gBAAAG,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAG,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAG,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAH,CAAA,CAAAG,CAAA,WAAAM,CAAA,KAAAT,CAAA,EAAAG,CAAA;AA9BtG;;AAGA;AACA;AACA;;AAKA;;AAQA;;AAKA;;AAGA;;AAGA;;AASA;;
|
|
1
|
+
{"version":3,"names":["_CloudX","_interopRequireWildcard","require","_NativeCloudX","_interopRequireDefault","_EventEmitter","_Arbiter","_RevenueData","_CloudXInterstitialAd","_CloudXAppOpenAd","_CloudXRewardedAd","_CloudXBannerAd","_CloudXMRECAd","_CloudXAdPosition","_CloudXBannerView","_CloudXMRECView","_CloudXErrorCode","_AppTrackingTransparency","_hooks","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","CloudXLogLevel","exports","VERBOSE","DEBUG","INFO","WARN","ERROR","NONE"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAAA,OAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,aAAA,GAAAC,sBAAA,CAAAF,OAAA;AAIA,IAAAG,aAAA,GAAAH,OAAA;AACA,IAAAI,QAAA,GAAAJ,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AAGA,IAAAM,qBAAA,GAAAN,OAAA;AACA,IAAAO,gBAAA,GAAAP,OAAA;AACA,IAAAQ,iBAAA,GAAAR,OAAA;AACA,IAAAS,eAAA,GAAAT,OAAA;AACA,IAAAU,aAAA,GAAAV,OAAA;AACA,IAAAW,iBAAA,GAAAX,OAAA;AAGA,IAAAY,iBAAA,GAAAZ,OAAA;AACA,IAAAa,eAAA,GAAAb,OAAA;AAIA,IAAAc,gBAAA,GAAAd,OAAA;AAGA,IAAAe,wBAAA,GAAAf,OAAA;AAGA,IAAAgB,MAAA,GAAAhB,OAAA;AAAsG,SAAAE,uBAAAe,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAlB,wBAAAkB,CAAA,EAAAG,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAtB,uBAAA,YAAAA,CAAAkB,CAAA,EAAAG,CAAA,SAAAA,CAAA,IAAAH,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAO,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAR,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAS,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAX,CAAA,UAAAO,CAAA,CAAAK,GAAA,CAAAZ,CAAA,GAAAO,CAAA,CAAAM,GAAA,CAAAb,CAAA,EAAAS,CAAA,gBAAAN,CAAA,IAAAH,CAAA,gBAAAG,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAG,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAG,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAH,CAAA,CAAAG,CAAA,WAAAM,CAAA,KAAAT,CAAA,EAAAG,CAAA;AA9BtG;;AAGA;AACA;AACA;;AAKA;;AAQA;;AAKA;;AAGA;;AAGA;;AASA;;AAoCA;AACO,MAAMgB,cAAc,GAAAC,OAAA,CAAAD,cAAA,GAAG;EAC1BE,OAAO,EAAE,SAAS;EAClBC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE,MAAM;EACZC,IAAI,EAAE,MAAM;EACZC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE;AACV,CAAU","ignoreList":[]}
|
|
@@ -28,6 +28,33 @@ const CloudXArbiterBid = exports.CloudXArbiterBid = {
|
|
|
28
28
|
platform: 'CUSTOM',
|
|
29
29
|
...params
|
|
30
30
|
};
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* Creates an AdMob bid candidate.
|
|
34
|
+
*
|
|
35
|
+
* `manualRevenuePerImpressionUSD` of `0.0` is a real price, not an absent one; negative and
|
|
36
|
+
* non-finite values are dropped natively with a warning. Omitting it leaves pricing to the
|
|
37
|
+
* realized price recorded for `adUnitId`.
|
|
38
|
+
*/
|
|
39
|
+
adMob(params) {
|
|
40
|
+
return {
|
|
41
|
+
platform: 'ADMOB',
|
|
42
|
+
...params
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Creates a Google Ad Manager bid candidate. Priced exactly like {@link adMob}; Ad Manager
|
|
47
|
+
* is a separate demand source, so both may bid in the same arbitration.
|
|
48
|
+
*
|
|
49
|
+
* `manualRevenuePerImpressionUSD` of `0.0` is a real price, not an absent one; negative and
|
|
50
|
+
* non-finite values are dropped natively with a warning. Omitting it leaves pricing to the
|
|
51
|
+
* realized price recorded for `adUnitId`.
|
|
52
|
+
*/
|
|
53
|
+
gam(params) {
|
|
54
|
+
return {
|
|
55
|
+
platform: 'GAM',
|
|
56
|
+
...params
|
|
57
|
+
};
|
|
31
58
|
}
|
|
32
59
|
};
|
|
33
60
|
//# sourceMappingURL=Arbiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CloudXArbiterBid","exports","cloudX","ad","platform","levelPlay","params","pubMatic","custom"],"sourceRoot":"../../../src","sources":["types/Arbiter.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"names":["CloudXArbiterBid","exports","cloudX","ad","platform","levelPlay","params","pubMatic","custom","adMob","gam"],"sourceRoot":"../../../src","sources":["types/Arbiter.ts"],"mappings":";;;;;;AAqEO,MAAMA,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG;EAC5BE,MAAMA,CAACC,EAAgB,EAAuB;IAC1C,OAAO;MACHC,QAAQ,EAAE,QAAQ;MAClBD;IACJ,CAAC;EACL,CAAC;EAEDE,SAASA,CAACC,MAAmD,EAA6B;IACtF,OAAO;MACHF,QAAQ,EAAE,WAAW;MACrB,GAAGE;IACP,CAAC;EACL,CAAC;EAEDC,QAAQA,CAACD,MAAkD,EAA4B;IACnF,OAAO;MACHF,QAAQ,EAAE,UAAU;MACpB,GAAGE;IACP,CAAC;EACL,CAAC;EAEDE,MAAMA,CAACF,MAAgD,EAA0B;IAC7E,OAAO;MACHF,QAAQ,EAAE,QAAQ;MAClB,GAAGE;IACP,CAAC;EACL,CAAC;EAED;AACJ;AACA;AACA;AACA;AACA;AACA;EACIG,KAAKA,CAACH,MAA+C,EAAyB;IAC1E,OAAO;MACHF,QAAQ,EAAE,OAAO;MACjB,GAAGE;IACP,CAAC;EACL,CAAC;EAED;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACII,GAAGA,CAACJ,MAA6C,EAAuB;IACpE,OAAO;MACHF,QAAQ,EAAE,KAAK;MACf,GAAGE;IACP,CAAC;EACL;AACJ,CAAU","ignoreList":[]}
|