The service provides the ability to test custom protocol handlers and deeplinks in your Tauri application using the browser.tauri.triggerDeeplink() method.
Deeplink testing allows you to verify that your Tauri application correctly handles custom protocol URLs (e.g., myapp://action?param=value). This is essential when your app registers as a protocol handler and needs to respond to URLs opened from external sources.
Use browser.tauri.triggerDeeplink() when you need to:
- Test that your app correctly handles custom protocol URLs
- Verify deeplink parameter parsing and routing logic
- Test protocol handler registration and activation
- Validate deeplink-driven workflows in your application
Your Tauri app must have the @tauri-apps/plugin-deep-link plugin installed and configured. See the official Tauri deep linking documentation for setup instructions.
Your app must register its custom protocol scheme in tauri.conf.json under the deep-link plugin configuration:
{
"plugins": {
"deep-link": {
"desktop": {
"schemes": ["myapp"]
}
}
}
}describe('Protocol Handler Tests', () => {
it('should handle custom protocol deeplinks', async () => {
await browser.tauri.triggerDeeplink('myapp://open?file=test.txt');
await browser.waitUntil(async () => {
const openedFile = await browser.tauri.execute(() => {
return globalThis.lastOpenedFile;
});
return openedFile === 'test.txt';
}, {
timeout: 5000,
timeoutMsg: 'App did not handle the deeplink'
});
});
});it('should preserve query parameters', async () => {
await browser.tauri.triggerDeeplink(
'myapp://action?param1=value1¶m2=value2&array[]=a&array[]=b'
);
const receivedParams = await browser.tauri.execute(() => {
return globalThis.lastDeeplinkParams;
});
expect(receivedParams.param1).toBe('value1');
expect(receivedParams.param2).toBe('value2');
expect(receivedParams.array).toEqual(['a', 'b']);
});it('should reject invalid protocols', async () => {
await expect(
browser.tauri.triggerDeeplink('https://example.com')
).rejects.toThrow('Invalid deeplink protocol');
});
it('should reject malformed URLs', async () => {
await expect(
browser.tauri.triggerDeeplink('not a url')
).rejects.toThrow('Invalid deeplink URL');
});The service handles platform-specific differences automatically:
- Uses
cmd /c startcommand to trigger the deeplink - No URL modification needed
- Uses
opencommand to trigger the deeplink - No URL modification needed
- Uses
xdg-opencommand to trigger the deeplink - No URL modification needed
Your app needs to listen for deep links in the frontend:
import { listen } from '@tauri-apps/plugin-deep-link';
listen('myapp://', (url) => {
console.log('Received deeplink:', url);
const parsed = new URL(url);
globalThis.lastDeeplinkUrl = url.toString();
const action = parsed.hostname;
const params = Object.fromEntries(parsed.searchParams);
switch (action) {
case 'open':
if (params.file) {
globalThis.lastOpenedFile = params.file;
}
break;
case 'action':
globalThis.lastDeeplinkParams = params;
break;
}
});For more complex scenarios, you can also handle deep links in the Rust backend:
use tauri_plugin_deep_link::DeepLinkExt;
#[tauri::main]
async fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_deep_link::init())
.setup(|app| {
app.handle().register_uri_scheme_protocol("myapp", |request| {
let url = request.url();
println!("Received deep link: {}", url);
});
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}Symptom: The deeplink is triggered but your app doesn't receive it.
Possible Causes and Solutions:
-
Protocol not registered:
- Verify
protocol.registeris set intauri.conf.json - Check your app is properly registered as the handler
- Verify
-
Deep link listener not set up:
- Ensure
listen()from@tauri-apps/plugin-deep-linkis called - Verify the listener is set up before triggering the deeplink
- Ensure
-
Deep link parsed incorrectly:
- Check console logs to see if the URL is being received
- Verify URL parsing logic handles your URL format
Symptom: Error: "Invalid deeplink protocol: https. Expected a custom protocol."
Cause: You're trying to use triggerDeeplink() with http/https/file protocols.
Solution: Only use custom protocol schemes:
// Correct - custom protocol
await browser.tauri.triggerDeeplink('myapp://action');
// Incorrect - web protocol
await browser.tauri.triggerDeeplink('https://example.com'); // Throws error
// Incorrect - file protocol
await browser.tauri.triggerDeeplink('file:///path/to/file'); // Throws errorSymptom: Tests fail intermittently because the app hasn't processed the deeplink yet.
Solution: Always use waitUntil to wait for the app to process the deeplink:
await browser.tauri.triggerDeeplink('myapp://action');
await browser.waitUntil(async () => {
const processed = await browser.tauri.execute(() => {
return globalThis.deeplinkProcessed;
});
return processed === true;
}, {
timeout: 5000,
timeoutMsg: 'App did not process the deeplink within 5 seconds'
});- Tauri Deep Linking Documentation
- API Reference for complete method documentation
- Usage Examples for additional patterns