Integration tests
Tests to demonstrate each use-case based on the use-case descriptions and the sequence diagrams. External input should be provided via mock objects and results verified via mock objects. Integration tests should not require manual entry of data nor require manual interpretation of results.
Integration Test Documentation
Integration tests verify that the hooks and modules work correctly together as a system. Each test maps directly to a use-case. Only external dependencies (device sensors, network APIs, native TTS, platform APIs) are replaced with mock objects. All assertions are automated.
Use Case 3 — Connecting to a Beacon
Scenario: The application detects a nearby beacon and loads the vocabulary associated with that room.
Modules involved: useLocationDetection, useInteractionLogger
Sequence:
- The app renders with no room selected (
currentRoomisnull). - The beacon is detected and
setRoomManuallyis called with the beacon's room ID (simulating the BLE detection path currently implemented as manual selection). currentRoomupdates to the matching room object.useInteractionLoggeris re-initialised with the newcurrentRoom.- Any subsequent log entries reflect the connected room.
Mocks:
../data/roomContexts→getAllRoomsreturns[{ id: 'kitchen', label: 'Kitchen' }, { id: 'bedroom', label: 'Bedroom' }];getRoomByBeaconIdis ajest.fn().
Automated assertions:
- Before connection:
currentRoomisnullanddetectionModeis'manual'. - After
setRoomManually('kitchen'):currentRoomequals{ id: 'kitchen', label: 'Kitchen' }. allRoomsalways equals the full mocked room array.- Log entries recorded after connection have
location.id === 'kitchen'. - Log entries recorded before connection have
location: { id: 'general', label: 'General' }.
Use Case 4 — Using Vocabulary for Communication
Scenario: A user selects words from the room vocabulary to build and speak a sentence.
Modules involved: useSentenceBuilder, useSpeech, useInteractionLogger
Sequence:
useInteractionLoggeris rendered with an activecurrentRoom;logButtonPressis passed touseSentenceBuilderasonLogPress.- The user taps word tiles one by one;
addWordis called for each. - Each word is spoken immediately via the TTS service.
- Each word tap is logged with event name
'word_tile'and the word as payload. - The user taps "Speak";
speakSentenceis called. - The full joined sentence is passed to the TTS service.
- A visual confirmation alert is shown.
- The speak event is logged with event name
'speak_sentence'and the sentence length.
Mocks:
../services/tts→speakandstoparejest.fn().react-native→Alert.alertis spied upon.
Automated assertions:
speakis called once peraddWord, each time with the correct individual word.sentencestate reflects all added words in order.- After
speakSentence:speakis called with the full space-joined sentence string. Alert.alertis called with('Speaking', <joined sentence>).onLogPressis called with('word_tile', { word: <w> })for every word added.onLogPressis called with('speak_sentence', { sentenceLength: <n> })on speak.interactionLogscontains one entry per user action in call order.
Use Case 4 (extended) — Removing and Clearing Words During Communication
Scenario: A user corrects a mistake by removing the last word, then later clears the whole sentence.
Modules involved: useSentenceBuilder, useSpeech, useInteractionLogger
Sequence:
- The user builds a partial sentence via several
addWordcalls. - The user taps "Backspace";
removeLastWordis called. - Only the last word is removed; the rest of the sentence is preserved.
- The event is logged with
'remove_last_word'. - The user taps "Clear";
clearSentenceis called. - The sentence is reset to
[]and TTS is stopped. - The event is logged with
'clear_sentence'.
Mocks:
../services/tts→speakandstoparejest.fn().
Automated assertions:
- After
removeLastWord:sentencehas one fewer element and all prior words remain. removeLastWordon an empty sentence does not throw andsentenceremains[].- After
clearSentence:sentenceis[]. stopis called exactly once onclearSentence.onLogPressis called with'remove_last_word'(no payload) on each backspace.onLogPressis called with'clear_sentence'(no payload) on clear.
Use Case 3 + 4 (combined) — Beacon Connection Followed by Word Selection
Scenario: Room detection and sentence building work together so that log entries are correctly associated with the detected room.
Modules involved: useLocationDetection, useInteractionLogger, useSentenceBuilder
Sequence:
- App starts;
currentRoomisnull. - Beacon detected →
setRoomManually('living_room')called. useInteractionLoggerreceives the newcurrentRoom.- User taps three word tiles.
- User taps "Speak".
Mocks:
../data/roomContexts→getAllRoomsreturns[{ id: 'living_room', label: 'Living Room' }].../services/tts→speakandstoparejest.fn().react-native→Alert.alertis spied upon.
Automated assertions:
- All log entries (word tiles + speak) have
location: { id: 'living_room', label: 'Living Room' }. currentRoom.labelis'Living Room'throughout the word selection phase.speakis called for each individual word and once for the full sentence.interactionLogs.lengthequals 4 (3 words + 1 speak).
Use Case 6 — Beacon Connection Failure: Fallback Vocabulary
Scenario: The beacon cannot be detected; the app falls back to a default (no-room) vocabulary and continues to function normally without interruption.
Modules involved: useLocationDetection, useInteractionLogger, useSentenceBuilder
Sequence:
- Beacon detection is attempted but fails;
setRoomManuallyis never called. currentRoomremainsnull.- The app loads the default vocabulary (not room-specific).
- The user selects words and speaks a sentence as normal.
- All log entries fall back to
location: { id: 'general', label: 'General' }.
Mocks:
../data/roomContexts→getAllRoomsreturns the full room list (beacon detection path never invoked).../services/tts→speakandstoparejest.fn().react-native→Alert.alertis spied upon.
Automated assertions:
currentRoomisnullthroughout the session.addWord,removeLastWord,clearSentence, andspeakSentenceall operate correctly with no room set.- All
interactionLogsentries havelocation: { id: 'general', label: 'General' }. - No exceptions are thrown at any point.
Use Case 3 (BLE trigger) — Movement Sensor Arms Before Beacon Scan
Scenario: The movement sensor detects the user has walked far enough to warrant a new BLE beacon scan, which would then trigger room detection (Use Case 3).
Modules involved: movementSensor, useLocationDetection
Sequence:
movementSensoris imported; it registers an Accelerometer listener.- The user walks; high-magnitude accelerometer samples are fed to the listener.
- Once 5 m of estimated travel is accumulated, scanning is armed.
- The device becomes still; the 800 ms stillness timer starts.
- After the timer elapses, a BLE scan fires (logged as
[BLE] Scanning for nearby devices...). - The scan result would be passed to
getRoomByBeaconIdthensetRoomManually(simulated as a direct call). currentRoomupdates to the room associated with the discovered beacon.
Mocks:
expo-sensors→Accelerometer.addListenercaptures the listener;Accelerometer.setUpdateIntervalis ajest.fn().jest.useFakeTimers()andDate.nowmock for deterministic timing.console.logspied upon to capture scan and arming messages.../data/roomContexts→getAllRoomsreturns a controlled room list.
Automated assertions:
- Arming log appears after sufficient movement:
'[Tracker] 5m reached — will scan when device stops.' - Scan log appears after stillness timeout:
'[BLE] Scanning for nearby devices...' - No scan occurs if movement resumes before the timeout expires.
- No scan occurs if the device was never armed (distance threshold not reached).
- After simulated scan result:
setRoomManuallyresolvescurrentRoomcorrectly.