from pathlib import Path MP3_SOURCE = Path(__file__).parents[1] / "Apps" / "Mp3Player" / "main" / "Source" / "main.c" def test_mp3_player_uses_the_firmware_audio_stream_device_name(): source = MP3_SOURCE.read_text(encoding="utf-8") assert 'device_find_by_name("audio-stream0")' in source assert 'device_find_by_name("audio-stream")' not in source assert "device_get_first_by_type" not in source assert "device_find_first_by_type" not in source def test_mp3_player_restores_a_visible_persisted_volume_control_above_the_six_button_row(): source = MP3_SOURCE.read_text(encoding="utf-8") assert "lv_obj_t* card = lv_obj_create(parent);" not in source assert "lv_label_set_text(icon, LV_SYMBOL_AUDIO);" not in source assert "lv_obj_t* vol_box = lv_obj_create(parent);" in source assert "g_ctx.slider_volume = lv_slider_create(vol_box);" in source assert "lv_slider_set_value(g_ctx.slider_volume, g_ctx.volume, LV_ANIM_OFF);" in source assert "on_volume_slider_changed" in source assert "save_volume(ctx);" in source assert "lv_obj_set_size(bottom_box, lv_pct(100), 52);" in source assert "lv_obj_t* btn_close = lv_btn_create(ctrl_box);" in source assert "lv_obj_t* btn_hist = lv_btn_create(ctrl_box);" in source assert "lv_label_set_text(lbl_close, LV_SYMBOL_CLOSE);" in source assert "lv_label_set_text(lbl_hist_btn, LV_SYMBOL_DIRECTORY);" in source assert "lv_label_set_text(lbl_back, \"-15s\");" in source assert "lv_label_set_text(lbl_fwd, \"+15s\");" in source def test_mp3_player_folder_button_returns_to_the_files_list(): source = MP3_SOURCE.read_text(encoding="utf-8") library_callback = source.split("static void on_library_click", 1)[1].split("/* ─── App Lifecycle", 1)[0] assert "tt_app_stop();" not in library_callback assert "show_history_screen(&g_ctx);" in library_callback assert "load_first_sd_mp3" not in library_callback def test_mp3_player_history_view_and_fifteen_second_seek_are_present(): source = MP3_SOURCE.read_text(encoding="utf-8") assert "#define SEEK_SECONDS 15" in source assert 'tt_app_get_user_data_child_path(app, "play_history.txt"' in source assert "static void show_history_screen" in source assert "static void on_history_selected" in source assert "char label[640];" in source assert "request_seek(ctx, -SEEK_SECONDS);" in source assert "request_seek(ctx, SEEK_SECONDS);" in source def test_mp3_player_persists_and_resumes_short_tracks_too(): source = MP3_SOURCE.read_text(encoding="utf-8") history_selector = source.split("static void on_history_selected", 1)[1].split("static void refresh_history_list", 1)[0] assert "Skip history: audio too short" not in source assert "Resuming last 10min+ play" not in source assert "Resuming last play %s at %d sec from history" in source assert "if (he->total_sec >= 600)" not in history_selector assert "resume_pos = he->pos_sec;" in history_selector def test_mp3_player_close_waits_for_playback_before_stopping_the_app(): source = MP3_SOURCE.read_text(encoding="utf-8") close_callback = source.split("static void on_close_click", 1)[1].split("static void on_library_click", 1)[0] assert "wait_for_playback_task_to_exit(&g_ctx);" in close_callback assert close_callback.index("wait_for_playback_task_to_exit(&g_ctx);") < close_callback.index("tt_app_stop();") assert "tt_lvgl_unlock();" in source assert "tt_lvgl_lock(portMAX_DELAY);" in source def test_mp3_player_has_a_consumed_dev_autoclose_hook_for_device_tests(): source = MP3_SOURCE.read_text(encoding="utf-8") assert '"mp3player_dev_autoclose_ms"' in source assert "on_close_click(NULL);" in source assert "unlink(marker_path);" in source