import pytest from spectral.database import Database from spectral.main import app, get_db from fastapi.testclient import TestClient from fastapi import HTTPException import json from scipy.io import wavfile as wv import os from unittest.mock import Mock, patch client = TestClient(app) # Load the JSON file data_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data") with open(os.path.join(data_dir, "frames.json"), "r") as file: frame_data = json.load(file) typical_1_fs, typical_1_data = wv.read( os.path.join(data_dir, "torgo-dataset/MC02_control_head_sentence1.wav") ) typical_1_data = typical_1_data.tolist() with open( os.path.join(data_dir, "torgo-dataset/MC02_control_head_sentence1.wav"), mode="rb" ) as f: control_sentence = f.read() @pytest.fixture def file_state(): return { "id": 1, "name": "something", "cycleEnabled": True, "frame": { "startIndex": 1, "endIndex": 200, }, "transcriptions": [[]], } @pytest.fixture def db_mock(): mock = Mock() mock.fetch_file.return_value = { "data": control_sentence, "creationTime": 1, "groundTruth": "hai test", } mock.get_transcriptions.return_value = [[{"value": "hi", "start": 0, "end": 1}]] mock.__class__ = Database yield mock @pytest.fixture(autouse=True) def override_dependency(db_mock): app.dependency_overrides[get_db] = lambda: db_mock yield app.dependency_overrides = {} def test_signal_correct_mode_file_not_found(db_mock, file_state): db_mock.fetch_file.side_effect = HTTPException( status_code=500, detail="database error" ) response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 404 ), "Expected status code 404 when file is not found" assert ( response.json()["detail"] == "File not found" ), "Expected detail message 'File not found'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_correct_simple_info(db_mock, file_state): file_state["frame"] = None response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200, "Expected status code 200 for simple info mode" result = response.json() assert result["fileSize"] == 146158, "Expected file size to be 146158" assert ( result["fileCreationDate"] == "1970-01-01T00:00:01Z" ), "Expected creation date to be '1970-01-01T00:00:01Z'" assert result["frame"] is None, "Expected frame to be None" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_correct_spectrogram(db_mock, file_state): response = client.get( "/signals/modes/spectrogram", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200, "Expected status code 200 for spectrogram mode" assert response.json() is None, "Expected response to be None" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file not to be called" def test_signal_correct_waveform(db_mock, file_state): response = client.get( "/signals/modes/waveform", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200, "Expected status code 200 for waveform mode" result = response.json() assert result is None, "Expected response to be None" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file not to be called" def test_signal_correct_vowel_space(db_mock, file_state): response = client.get( "/signals/modes/vowel-space", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200, "Expected status code 200 for vowel-space mode" assert response.json() == { "f1": 1242.857422568559, "f2": 2503.8350190318893, }, "Expected f1 and f2 values" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_correct_transcription(db_mock, file_state): response = client.get( "/signals/modes/transcription", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 for transcription mode" assert response.json() is None, "Expected response to be None" def test_signal_mode_wrong_mode(db_mock, file_state): response = client.get( "/signals/modes/wrongmode", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 422, "Expected status code 422 for wrong mode" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file not to be called" def test_signal_mode_frame_start_index_missing(db_mock, file_state): file_state["frame"] = {"endIndex": 1} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when startIndex is missing" assert ( response.json()["detail"] == "no startIndex provided" ), "Expected detail message 'no startIndex provided'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_end_index_missing(db_mock, file_state): file_state["frame"] = {"startIndex": 1} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when endIndex is missing" assert ( response.json()["detail"] == "no endIndex provided" ), "Expected detail message 'no endIndex provided'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_start_index_bigger_than_end_index(db_mock, file_state): file_state["frame"] = {"startIndex": 2, "endIndex": 1} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when startIndex is bigger than endIndex" assert ( response.json()["detail"] == "startIndex should be strictly lower than endIndex" ), "Expected detail message 'startIndex should be strictly lower than endIndex'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_start_index_bigger_than_end_index_equal_numbers( db_mock, file_state ): file_state["frame"] = {"startIndex": 2, "endIndex": 2} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when startIndex is equal to endIndex" assert ( response.json()["detail"] == "startIndex should be strictly lower than endIndex" ), "Expected detail message 'startIndex should be strictly lower than endIndex'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_negative_start_index(db_mock, file_state): file_state["frame"] = {"startIndex": -1, "endIndex": 2} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when startIndex is negative" assert ( response.json()["detail"] == "startIndex should be larger or equal to 0" ), "Expected detail message 'startIndex should be larger or equal to 0'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_too_large_end_index(db_mock, file_state): file_state["frame"] = {"startIndex": 0, "endIndex": 73041} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 400 ), "Expected status code 400 when endIndex is too large" assert ( response.json()["detail"] == "endIndex should be lower than the file length" ), "Expected detail message 'endIndex should be lower than the file length'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_frame_too_large_boundary(db_mock, file_state): file_state["frame"] = {"startIndex": 0, "endIndex": 73040} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 when frame boundaries are valid" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_simple_info_with_frame(db_mock, file_state): file_state["frame"] = {"startIndex": 22500, "endIndex": 23250} response = client.get( "/signals/modes/simple-info", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 for simple info mode with frame" result = response.json() assert result["fileSize"] == 146158, "Expected file size to be 146158" assert ( result["fileCreationDate"] == "1970-01-01T00:00:01Z" ), "Expected creation date to be '1970-01-01T00:00:01Z'" assert result["averagePitch"] == pytest.approx( 34.38, 0.1 ), "Expected average pitch to be approximately 34.38" assert result["duration"] == pytest.approx( 4.565, 0.01 ), "Expected duration to be approximately 4.565" assert result["frame"] is not None, "Expected frame to be not None" assert result["frame"]["duration"] == pytest.approx( 0.046875 ), "Expected frame duration to be approximately 0.046875" assert result["frame"]["f1"] == pytest.approx( 623.19, 0.1 ), "Expected frame f1 to be approximately 623.19" assert result["frame"]["f2"] == pytest.approx( 1635.4, 0.1 ), "Expected frame f2 to be approximately 1635.4" assert result["frame"]["pitch"] == pytest.approx( 591.6, 0.1 ), "Expected frame pitch to be approximately 591.6" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_vowel_space_mode_with_frame(db_mock, file_state): file_state["frame"] = {"startIndex": 22500, "endIndex": 23250} response = client.get( "/signals/modes/vowel-space", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 for vowel-space mode with frame" result = response.json() assert result["f1"] == pytest.approx( 623.19, 0.1 ), "Expected frame f1 to be approximately 623.19" assert result["f2"] == pytest.approx( 1635.4, 0.1 ), "Expected frame f2 to be approximately 1635.4" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_signal_mode_transcription_db_problem(db_mock): db_mock.fetch_file.side_effect = HTTPException( status_code=500, detail="database error" ) response = client.get("/transcription/deepgram/1") assert ( response.status_code == 404 ), "Expected status code 404 when there is a database error" assert ( response.json()["detail"] == "File not found" ), "Expected detail message 'File not found'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_transcription_model_found(db_mock): with patch( "spectral.transcription.transcription.deepgram_transcription" ) as mock_deepgram_transcription: mock_deepgram_transcription.return_value = [ {"value": "word1", "start": 0.5, "end": 1.0}, {"value": "word2", "start": 1.5, "end": 2.0}, ] response = client.get("/transcription/deepgram/1") assert ( response.status_code == 200 ), "Expected status code 200 for deepgram transcription" result = response.json() assert result == [ {"value": "", "start": 0, "end": 0.5}, {"value": "word1", "start": 0.5, "end": 1.0}, {"value": "", "start": 1.0, "end": 1.5}, {"value": "word2", "start": 1.5, "end": 2.0}, {"end": 4.565, "start": 2.0, "value": ""}, ], "Expected transcription result to match the mock return value" assert ( db_mock.fetch_file.call_count == 1 ), "Expected fetch_file to be called once" def test_transcription_model_not_found(db_mock): response = client.get("/transcription/non_existant_model/1") assert ( response.status_code == 404 ), "Expected status code 404 when model is not found" assert ( response.json()["detail"] == "Model was not found" ), "Expected detail message 'Model was not found'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_analyze_signal_mode_invalid_id(db_mock, file_state): file_state["id"] = "invalid_id" db_mock.fetch_file.side_effect = Exception("Database error") response = client.get( "/signals/modes/vowel-space", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 404 ), "Expected status code 404 when file ID is invalid" assert ( response.json()["detail"] == "File not found" ), "Expected detail message 'File not found'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" def test_transcribe_file_invalid_model(db_mock): response = client.get("/transcription/invalid_model/1") assert ( response.status_code == 404 ), "Expected status code 404 when transcription model is invalid" assert ( response.json()["detail"] == "Model was not found" ), "Expected detail message 'Model was not found'" assert db_mock.fetch_file.call_count == 1, "Expected fetch_file to be called once" @pytest.mark.skip(reason="Not implemented") def test_transcribe_file_no_api_key(db_mock): with patch("spectral.transcription.models.deepgram.os.getenv") as mock_getenv: mock_getenv.return_value = None response = client.get("/transcription/deepgram/1") assert ( response.status_code == 500 ), "Expected status code 500 when API key is missing" assert ( db_mock.fetch_file.call_count == 1 ), "Expected fetch_file to be called once" @pytest.fixture def mock_db(mocker): mock_db_class = mocker.patch("spectral.database.Database") mock_db_instance = mock_db_class.return_value mock_db_instance.connection = Mock() mock_db_instance.close = Mock() return mock_db_instance def test_error_rate_no_reference(db_mock, file_state): response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 when ground truth is missing" assert response.json() is None, "Expected response to be None" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file to be called never" def test_error_rate_reference_None(file_state): file_state["reference"] = None response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 when ground truth is missing" assert response.json() is None, "Expected response to be None" def test_error_rate_no_reference_caption(db_mock, file_state): file_state["reference"] = {} response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 assert response.json() is None assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_no_hypothesis(db_mock, file_state): file_state["reference"] = {"captions": [{"value": "Hi"}]} file_state["hypothesis"] = None response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 assert response.json() is None assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_hypothesis_None(db_mock, file_state): file_state["reference"] = {"captions": [{"value": "Hi"}]} file_state["hypothesis"] = None response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 assert response.json() is None assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_no_hypothesis_caption(db_mock, file_state): file_state["reference"] = {"captions": [{"value": "Hi"}]} file_state["hypothesis"] = {} response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 assert response.json() is None assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_empty_reference_array(db_mock, file_state): file_state["reference"] = {"captions": []} file_state["hypothesis"] = {"captions": [{"value": "Hi"}]} response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 assert response.json() is None assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_empty_hypothesis_array(db_mock, file_state): file_state["reference"] = {"captions": [{"value": "Hi"}]} file_state["hypothesis"] = {"captions": []} response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert response.status_code == 200 print(response.json()) assert response.json() == { "wordLevel": { "wer": 1.0, "mer": 1.0, "wil": 1.0, "wip": 0.0, "hits": 0, "substitutions": 0, "insertions": 0, "deletions": 1, "reference": ["Hi"], "hypothesis": [], "alignments": [ { "type": "delete", "referenceStartIndex": 0, "referenceEndIndex": 1, "hypothesisStartIndex": 0, "hypothesisEndIndex": 0, } ], }, "characterLevel": { "cer": 1.0, "hits": 0, "substitutions": 0, "insertions": 0, "deletions": 2, "reference": ["H", "i"], "hypothesis": [], "alignments": [ { "type": "delete", "referenceStartIndex": 0, "referenceEndIndex": 2, "hypothesisStartIndex": 0, "hypothesisEndIndex": 0, } ], }, }, "the response was not the same" assert db_mock.get_transcriptions.call_count == 0 def test_error_rate_with_reference_no_hypothesis(db_mock, file_state): file_state["reference"] = {} file_state["reference"]["captions"] = [{"value": "hai test"}] file_state["hypothesis"] = {} file_state["hypothesis"]["captions"] = [] response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) assert ( response.status_code == 200 ), "Expected status code 200 when ground truth is provided" result = response.json() word_level = result["wordLevel"] assert word_level["wer"] == 1.0, "Expected word error rate (WER) to be 1.0" assert word_level["mer"] == 1.0, "Expected match error rate (MER) to be 1.0" assert word_level["wil"] == 1.0, "Expected word information lost (WIL) to be 1.0" assert word_level["wip"] == 0, "Expected word information preserved (WIP) to be 0" assert word_level["hits"] == 0, "Expected hits to be 0" assert word_level["substitutions"] == 0, "Expected substitutions to be 0" assert word_level["insertions"] == 0, "Expected insertions to be 0" assert word_level["deletions"] == 2, "Expected deletions to be 2" assert word_level["reference"] == [ "hai", "test", ], "Expected reference to be ['hai', 'test']" assert word_level["hypothesis"] == [], "Expected hypothesis to be empty" assert len(word_level["alignments"]) == 1, "Expected one alignment" assert word_level["alignments"][0] == { "type": "delete", "referenceStartIndex": 0, "referenceEndIndex": 2, "hypothesisStartIndex": 0, "hypothesisEndIndex": 0, }, "Expected delete alignment" character_level = result["characterLevel"] assert character_level["cer"] == 1, "Expected character error rate (CER) to be 1" assert character_level["hits"] == 0, "Expected hits to be 0" assert character_level["substitutions"] == 0, "Expected substitutions to be 0" assert character_level["insertions"] == 0, "Expected insertions to be 0" assert character_level["deletions"] == 8, "Expected deletions to be 8" assert character_level["reference"] == [ "h", "a", "i", " ", "t", "e", "s", "t", ], "Expected reference to be ['h', 'a', 'i', ' ', 't', 'e', 's', 't']" assert character_level["hypothesis"] == [], "Expected hypothesis to be empty" assert len(character_level["alignments"]) == 1, "Expected one alignment" assert character_level["alignments"][0] == { "type": "delete", "referenceStartIndex": 0, "referenceEndIndex": 8, "hypothesisStartIndex": 0, "hypothesisEndIndex": 0, }, "Expected delete alignment" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file to be called once" def test_error_rate_with_reference_and_hypothesis(db_mock, file_state): file_state["reference"] = {} file_state["reference"]["captions"] = [{"value": "hai test"}] file_state["hypothesis"] = {} file_state["hypothesis"]["captions"] = [{"value": "hi"}] response = client.get( "/signals/modes/error-rate", params={"fileState": json.dumps(file_state)} ) result = response.json() word_level = result["wordLevel"] assert word_level["wer"] == 1.0, "Expected word error rate (WER) to be 1.0" assert word_level["mer"] == 1.0, "Expected match error rate (MER) to be 1.0" assert word_level["wil"] == 1.0, "Expected word information lost (WIL) to be 1.0" assert word_level["wip"] == 0, "Expected word information preserved (WIP) to be 0" assert word_level["hits"] == 0, "Expected hits to be 0" assert word_level["substitutions"] == 1, "Expected substitutions to be 1" assert word_level["insertions"] == 0, "Expected insertions to be 0" assert word_level["deletions"] == 1, "Expected deletions to be 1" assert word_level["reference"] == [ "hai", "test", ], "Expected reference to be ['hai', 'test']" assert word_level["hypothesis"] == ["hi"], "Expected hypothesis to be ['hi']" assert len(word_level["alignments"]) == 2, "Expected two alignments" assert word_level["alignments"][0] == { "type": "substitute", "referenceStartIndex": 0, "referenceEndIndex": 1, "hypothesisStartIndex": 0, "hypothesisEndIndex": 1, }, "Expected substitute alignment" assert word_level["alignments"][1] == { "type": "delete", "referenceStartIndex": 1, "referenceEndIndex": 2, "hypothesisStartIndex": 1, "hypothesisEndIndex": 1, }, "Expected delete alignment" character_level = result["characterLevel"] assert ( character_level["cer"] == 0.75 ), "Expected character error rate (CER) to be 0.75" assert character_level["hits"] == 2, "Expected hits to be 2" assert character_level["substitutions"] == 0, "Expected substitutions to be 0" assert character_level["insertions"] == 0, "Expected insertions to be 0" assert character_level["deletions"] == 6, "Expected deletions to be 6" assert len(character_level["alignments"]) == 4, "Expected four alignments" assert character_level["reference"] == [ "h", "a", "i", " ", "t", "e", "s", "t", ], "Expected reference to be ['h', 'a', 'i', ' ', 't', 'e', 's', 't']" assert character_level["hypothesis"] == [ "h", "i", ], "Expected hypothesis to be ['h', 'i']" assert character_level["alignments"][0] == { "type": "equal", "referenceStartIndex": 0, "referenceEndIndex": 1, "hypothesisStartIndex": 0, "hypothesisEndIndex": 1, }, "Expected equal alignment" assert character_level["alignments"][1] == { "type": "delete", "referenceStartIndex": 1, "referenceEndIndex": 2, "hypothesisStartIndex": 1, "hypothesisEndIndex": 1, }, "Expected delete alignment" assert character_level["alignments"][2] == { "type": "equal", "referenceStartIndex": 2, "referenceEndIndex": 3, "hypothesisStartIndex": 1, "hypothesisEndIndex": 2, }, "Expected equal alignment" assert character_level["alignments"][3] == { "type": "delete", "referenceStartIndex": 3, "referenceEndIndex": 8, "hypothesisStartIndex": 2, "hypothesisEndIndex": 2, }, "Expected delete alignment" assert db_mock.fetch_file.call_count == 0, "Expected fetch_file to be called never" def test_phone_transcription(db_mock, file_state): with patch( "spectral.transcription.models.allosaurus.deepgram_transcription" ) as mock_deepgram_transcription: mock_deepgram_transcription.return_value = [ {"value": "", "start": 0.0, "end": 1.04}, {"value": "the", "start": 1.04, "end": 1.36}, {"value": "quick", "start": 1.36, "end": 1.68}, {"value": "brown", "start": 1.68, "end": 2.0}, {"value": "fox", "start": 2.0, "end": 2.3999999}, {"value": "jumps", "start": 2.3999999, "end": 2.72}, {"value": "over", "start": 2.72, "end": 3.04}, {"value": "the", "start": 3.04, "end": 3.1999998}, {"value": "lazy", "start": 3.1999998, "end": 3.52}, {"value": "dog", "start": 3.52, "end": 4.02}, {"value": "", "start": 4.02, "end": 4.565}, ] response = client.get("/transcription/allosaurus/1") assert ( response.status_code == 200 ), "Expected status code 200 for allosaurus transcription" result = response.json() assert result == [ {"value": "", "start": 0, "end": 1.04}, {"value": "ð", "start": 1.04, "end": 1.275}, {"value": "ə", "start": 1.275, "end": 1.36}, {"value": "k", "start": 1.36, "end": 1.44}, {"value": "uə", "start": 1.44, "end": 1.5}, {"value": "ɪ", "start": 1.5, "end": 1.56}, {"value": "tʰ", "start": 1.56, "end": 1.68}, {"value": "b̥", "start": 1.68, "end": 1.77}, {"value": "a", "start": 1.77, "end": 1.845}, {"value": "l̪", "start": 1.845, "end": 2.0}, {"value": "f", "start": 2.0, "end": 2.085}, {"value": "ɑ", "start": 2.085, "end": 2.19}, {"value": "k", "start": 2.19, "end": 2.31}, {"value": "s", "start": 2.31, "end": 2.3999999}, {"value": "d͡ʒ", "start": 2.3999999, "end": 2.505}, {"value": "ʌ", "start": 2.505, "end": 2.565}, {"value": "m", "start": 2.565, "end": 2.6100000000000003}, {"value": "p", "start": 2.6100000000000003, "end": 2.67}, {"value": "ʂ", "start": 2.67, "end": 2.72}, {"value": "ə", "start": 2.72, "end": 2.76}, {"value": "o", "start": 2.76, "end": 2.8049999999999997}, {"value": "w", "start": 2.8049999999999997, "end": 2.8499999999999996}, {"value": "v", "start": 2.8499999999999996, "end": 2.895}, {"value": "ɾ", "start": 2.895, "end": 2.9400000000000004}, {"value": "u", "start": 2.9400000000000004, "end": 3.04}, {"value": "ð", "start": 3.04, "end": 3.075}, {"value": "ə", "start": 3.075, "end": 3.135}, {"value": "l", "start": 3.135, "end": 3.1999998}, {"value": "i", "start": 3.1999998, "end": 3.3}, {"value": "z", "start": 3.3, "end": 3.3899999999999997}, {"value": "i", "start": 3.3899999999999997, "end": 3.52}, {"value": "d", "start": 3.52, "end": 3.5700000000000003}, {"value": "ʌ", "start": 3.5700000000000003, "end": 3.675}, {"value": "g", "start": 3.675, "end": 4.02}, {"value": "", "start": 4.02, "end": 4.565}, ], "Expected phonetic transcription result to match the mock return value" assert ( db_mock.fetch_file.call_count == 1 ), "Expected fetch_file to be called once" def test_phone_transcription_no_words(db_mock, file_state): with patch( "spectral.transcription.models.deepgram.deepgram_transcription" ) as mock_deepgram_transcription: mock_deepgram_transcription.return_value = [] response = client.get("/transcription/allosaurus/1") assert ( response.status_code == 200 ), "Expected status code 200 for allosaurus transcription with no words" result = response.json() assert ( result == [ {"value": "ð", "start": 0, "end": 1.275}, {"value": "ə", "start": 1.275, "end": 1.35}, {"value": "k", "start": 1.35, "end": 1.44}, {"value": "uə", "start": 1.44, "end": 1.5}, {"value": "ɪ", "start": 1.5, "end": 1.56}, {"value": "tʰ", "start": 1.56, "end": 1.665}, {"value": "b̥", "start": 1.665, "end": 1.77}, {"value": "a", "start": 1.77, "end": 1.845}, {"value": "l̪", "start": 1.845, "end": 1.9649999999999999}, {"value": "f", "start": 1.9649999999999999, "end": 2.085}, {"value": "ɑ", "start": 2.085, "end": 2.19}, {"value": "k", "start": 2.19, "end": 2.31}, {"value": "s", "start": 2.31, "end": 2.415}, {"value": "d͡ʒ", "start": 2.415, "end": 2.505}, {"value": "ʌ", "start": 2.505, "end": 2.565}, {"value": "m", "start": 2.565, "end": 2.6100000000000003}, {"value": "p", "start": 2.6100000000000003, "end": 2.67}, {"value": "ʂ", "start": 2.67, "end": 2.715}, {"value": "ə", "start": 2.715, "end": 2.76}, {"value": "o", "start": 2.76, "end": 2.8049999999999997}, {"value": "w", "start": 2.8049999999999997, "end": 2.8499999999999996}, {"value": "v", "start": 2.8499999999999996, "end": 2.895}, {"value": "ɾ", "start": 2.895, "end": 2.9400000000000004}, {"value": "u", "start": 2.9400000000000004, "end": 3.015}, {"value": "ð", "start": 3.015, "end": 3.075}, {"value": "ə", "start": 3.075, "end": 3.135}, {"value": "l", "start": 3.135, "end": 3.21}, {"value": "i", "start": 3.21, "end": 3.3}, {"value": "z", "start": 3.3, "end": 3.3899999999999997}, {"value": "i", "start": 3.3899999999999997, "end": 3.48}, {"value": "d", "start": 3.48, "end": 3.5700000000000003}, {"value": "ʌ", "start": 3.5700000000000003, "end": 3.675}, {"value": "g", "start": 3.675, "end": 4.565}, ] ), "Expected phonetic transcription result to match the mock return value when no words are provided" assert ( db_mock.fetch_file.call_count == 1 ), "Expected fetch_file to be called once"