@smileid/usesmileid_testing
v12.4.0
Published
Test doubles for the UseSmileID React Native (Expo) SDK: the native SDKs' in-process test server, for your own E2E tests.
Readme
@smileid/usesmileid_testing
Test doubles for the UseSmileID React Native (Expo) SDK: the Android and iOS SDKs' in-process
test server (com.usesmileid:testing, UseSmileIDTesting), so your E2E tests run a whole flow
with no Smile ID backend.
Installation
pnpm add -D @smileid/usesmileid_testingApply its config plugin only in the app config you test with. On iOS it links the
UseSmileIDTesting product in every build configuration (the server throws outside a Debug
build), so it must not reach the config you ship. For example, in app.config.js:
module.exports = ({ config }) => ({
...config,
plugins: [
...(config.plugins ?? []),
// Your E2E build only.
...(process.env.EXPO_PUBLIC_E2E === "1"
? ["@smileid/usesmileid_testing"]
: []),
],
});The server runs only in a debug build. On Android a release build gets a stub that refuses to
start, so the test doubles never reach a shipped app, and the plugin lets the debug build's native
network client reach the server on loopback: it adds 127.0.0.1 and localhost to your network
security config in the debug source set only, or writes a debug-only config when your app names
none. On iOS, an app built without the plugin gets a module that refuses to start a server.
Use
import {
UseSmileIDTestServer,
UseSmileIDTestResponse,
testToken,
} from "@smileid/usesmileid_testing";
const server = await UseSmileIDTestServer.start();
// In the flow's network block:
// n.config((c) => { c.token = testToken(); ... })
// n.interceptors((i) => i.testRoute(server))
// After the flow:
expect(server.submissions().map((request) => request.path)).toEqual([
"/v3/registration",
]);
server.close();Every request the flow makes goes to the server, whatever host the configuration names, after the
native network client has signed it. respond(path, response)
scripts UseSmileIDTestResponse.status(code, body), tokenExpired (a 401, so your
onTokenExpired runs) or connectionDropped. Once closed, the flow's requests fail rather than
reach Smile ID.
A whole flow, with no one in front of the camera
UseSmileIDTest adds a scripted person to the server: one of the shared scenarios every Smile ID
SDK runs (UseSmileIDTestScenario.selfieHappyPath, enhancedSelfieHeadTurns, selfieTimeout,
skipSubmission and the document ones) or your own, UseSmileIDTestScenario.fromJson(text).
UseSmileIDTestScenario.named("selfie-happy-path") finds one of them by the name its JSON gives it,
or returns null.
const test = await UseSmileIDTest.create(
UseSmileIDTestScenario.selfieHappyPath,
);
// In the flow's blocks:
// n.config((c) => { c.token = test.token; ... })
// n.interceptors((i) => test.install(i))
// m.analyzers((a) => {
// a.forCaptureType(CaptureType.selfie, (face) => face.add(useSmileIDMlkitFace));
// test.install(a);
// })
test.close();The scenario answers in place of your selfie analyzer, inside that analyzer's own native session,
so the capture, the files it writes and the submission are the real ones; any camera frames will
do, an emulator's included. On iOS that means a phone, since a simulator has no camera. A document
scenario's install throws.
