also looking at this
fix(android): hand the launch link to the page that subscribes for it
#232
17 files
+776
-136
| @@ -327,6 +327,38 @@ describe('Craft Android builder', () => { | ||
| 327 | 327 | expect(bridge).toContain('craft.ar.onPlaneDetected is unavailable because ARCore requires native Activity integration') |
| 328 | 328 | }) |
| 329 | 329 | |
| 330 | it('queues deep links until the bridge is injected, and marks only the launch link initial', async () => { | |
| 331 | // #215: the launch link used to go only to getInitialURL, and a warm link | |
| 332 | // replaced the launch link as getInitialURL's answer. | |
| 333 | const output = mkdtempSync(join(tmpdir(), 'craft-android-deep-links-')) | |
| 334 | await init({ name: 'WildLoop', packageName: 'org.wildloop.app', output }) | |
| 335 | ||
| 336 | const sourceRoot = join(output, 'app/src/main/java/org/wildloop/app') | |
| 337 | const bridge = readFileSync(join(sourceRoot, 'CraftBridge.kt'), 'utf8') | |
| 338 | const activity = readFileSync(join(sourceRoot, 'MainActivity.kt'), 'utf8') | |
| 339 | const holder = readFileSync(join(output, 'app/src/main/java/com/craft/runtime/CraftNative.kt'), 'utf8') | |
| 340 | ||
| 341 | expect(activity).not.toContain('dispatch = false') | |
| 342 | expect(activity).toContain('craftBridge.receiveDeepLink(launchLink)') | |
| 343 | expect(activity).toContain('Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY') | |
| 344 | expect(activity).toContain('intent.data?.toString()?.let(craftBridge::receiveDeepLink)') | |
| 345 | // A recreated activity restores what the bridge saved, not getIntent(), | |
| 346 | // which onNewIntent may have replaced with a warm link. | |
| 347 | expect(activity).toContain('craftBridge.saveDeepLinks(outState)') | |
| 348 | expect(activity).toContain('craftBridge.restoreDeepLinks(savedInstanceState)') | |
| 349 | ||
| 350 | // Flushed in the injection's completion, after the page's replay exists. | |
| 351 | const injected = bridge.slice(bridge.indexOf('webView.evaluateJavascript(script) {')) | |
| 352 | const flush = injected.slice(0, injected.indexOf('fun markBridgeLoading()')) | |
| 353 | expect(flush.indexOf('bridgeReady = true')).toBeLessThan(flush.indexOf('links.forEach { (url, initial) -> dispatchDeepLink(url, initial) }')) | |
| 354 | ||
| 355 | expect(bridge).toContain('val initial = !hasBeenReady && !initialAssigned') | |
| 356 | expect(bridge).toContain('put("initial", initial)') | |
| 357 | expect(bridge).not.toContain('if (initialURL == null)') | |
| 358 | expect(bridge).toContain('pendingDeepLinks.clear()\n }') | |
| 359 | expect(holder).toContain('private external fun nativeDispatchDeepLink(url: String, initial: Boolean): Boolean') | |
| 360 | }) | |
| 361 | ||
| 330 | 362 | it('routes external Activity results back to every pending media promise', async () => { |
| 331 | 363 | const output = mkdtempSync(join(tmpdir(), 'craft-android-activity-results-')) |
| 332 | 364 | await init({ name: 'WildLoop', packageName: 'org.wildloop.app', output }) |