updating code using knex.
This commit is contained in:
@ -1,240 +1,136 @@
|
||||
// Import necessary packages
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { View, Text, TextInput, StyleSheet, Pressable } from "react-native"; // Add Picker import
|
||||
import { getDb } from "@/app/lib/db";
|
||||
import { View, Text, TextInput, Pressable, StyleSheet } from "react-native";
|
||||
import { WhisperFile } from "@/app/lib/whisper";
|
||||
import { Settings } from "@/app/lib/settings";
|
||||
import { LanguageServer, fetchWithTimeout } from "@/app/i18n/api";
|
||||
import { Picker } from "@react-native-picker/picker";
|
||||
import { longLang } from "@/app/i18n/lang";
|
||||
import FileSystem, { DownloadResumable } from "expo-file-system";
|
||||
import { LIBRETRANSLATE_BASE_URL } from "@/constants/api";
|
||||
import {
|
||||
WHISPER_MODELS,
|
||||
WHISPER_MODEL_DIR,
|
||||
initiateWhisperDownload,
|
||||
download_status,
|
||||
getWhisperDownloadStatus,
|
||||
getWhisperTarget,
|
||||
whisper_model_tag_t,
|
||||
} from "@/app/lib/whisper";
|
||||
import { File, Paths } from "expo-file-system/next";
|
||||
|
||||
type Language = {
|
||||
code: string;
|
||||
name: string;
|
||||
import { LanguageServer, language_matrix, language_matrix_entry } from "@/app/i18n/api";
|
||||
const WHISPER_MODELS = {
|
||||
small: new WhisperFile("small"),
|
||||
medium: new WhisperFile("medium"),
|
||||
large: new WhisperFile("large"),
|
||||
};
|
||||
|
||||
type LanguageMatrix = {
|
||||
[key: string]: Language;
|
||||
};
|
||||
const LIBRETRANSLATE_BASE_URL = "https://translate.argosopentech.com/translate";
|
||||
|
||||
type connection_test_t =
|
||||
| {
|
||||
success: true;
|
||||
}
|
||||
| {
|
||||
success: false;
|
||||
error: string;
|
||||
};
|
||||
|
||||
const SettingsComponent: React.FC = () => {
|
||||
const SettingsComponent = () => {
|
||||
const [hostLanguage, setHostLanguage] = useState<string | null>(null);
|
||||
const [libretranslateBaseUrl, setLibretranslateBaseUrl] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [languages, setLanguages] = useState<undefined | LanguageMatrix>();
|
||||
const [isLoaded, setIsLoaded] = useState<boolean>(false);
|
||||
const [whisperModel, setWhisperModel] = useState<
|
||||
undefined | whisper_model_tag_t
|
||||
>();
|
||||
const [downloadStatus, setDownloadStatus] = useState<
|
||||
undefined | download_status
|
||||
>();
|
||||
|
||||
const [langServerConn, setLangServerConn] = useState<
|
||||
undefined | connection_test_t
|
||||
>();
|
||||
const [languageOptions, setLanguageOptions] = useState<language_matrix | undefined>();
|
||||
const [langServerConn, setLangServerConn] = useState<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
} | null>(null);
|
||||
const [whisperModel, setWhisperModel] =
|
||||
useState<keyof typeof WHISPER_MODELS>("small");
|
||||
const [downloader, setDownloader] = useState<any>(null);
|
||||
const [whisperDownloadProgress, setWhisperDownloadProgress] = useState<
|
||||
FileSystem.DownloadProgressData | undefined
|
||||
>();
|
||||
const [downloader, setDownloader] = useState<DownloadResumable | undefined>();
|
||||
const [whisperModelTarget, setWhisperModelTarget] = useState<File | undefined>()
|
||||
any | null
|
||||
>(null);
|
||||
|
||||
const fillHostLanguageOptions = async () => {
|
||||
useEffect(() => {
|
||||
loadSettings();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
checkDownloadStatus(whisperModel);
|
||||
}, [whisperModel]);
|
||||
|
||||
const getLanguageOptions = async () => {
|
||||
const languageServer = await LanguageServer.getDefault();
|
||||
setLanguageOptions(await languageServer.fetchLanguages());
|
||||
}
|
||||
|
||||
const loadSettings = async () => {
|
||||
const settings = await Settings.getDefault();
|
||||
const hostLang = await settings.getHostLanguage();
|
||||
setHostLanguage(hostLang || "en");
|
||||
const langServer = new LanguageServer(
|
||||
libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL
|
||||
);
|
||||
// Fetch languages from API
|
||||
const hostLanguage = await settings.getHostLanguage();
|
||||
setHostLanguage(hostLanguage);
|
||||
const libretranslateBaseUrl = await settings.getLibretranslateBaseUrl();
|
||||
setLibretranslateBaseUrl(libretranslateBaseUrl);
|
||||
const whisperModel = await settings.getWhisperModel();
|
||||
setWhisperModel(whisperModel as keyof typeof WHISPER_MODELS);
|
||||
};
|
||||
|
||||
const handleHostLanguageChange = async (lang: string) => {
|
||||
const settings = await Settings.getDefault();
|
||||
setHostLanguage(lang);
|
||||
await settings.setHostLanguage(lang);
|
||||
};
|
||||
|
||||
const handleLibretranslateBaseUrlChange = async (url: string) => {
|
||||
const settings = await Settings.getDefault();
|
||||
setLibretranslateBaseUrl(url);
|
||||
await settings.setLibretranslateBaseUrl(url);
|
||||
checkLangServerConnection(url);
|
||||
};
|
||||
|
||||
const checkLangServerConnection = async (baseUrl: string) => {
|
||||
try {
|
||||
const langData = await langServer.fetchLanguages();
|
||||
setLanguages(langData);
|
||||
// Replace with actual connection check logic
|
||||
setLangServerConn({ success: true });
|
||||
} catch (err) {
|
||||
console.warn("Got an error fetching: %s", err);
|
||||
setLangServerConn({
|
||||
success: false,
|
||||
error: `Could not connect to ${libretranslateBaseUrl}: ${err}`,
|
||||
});
|
||||
} catch (error) {
|
||||
setLangServerConn({ success: false, error: `${error}` });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
// Fetch the database connection
|
||||
// const db = await getDb("down");
|
||||
const settings = await Settings.getDefault();
|
||||
|
||||
await fillHostLanguageOptions();
|
||||
|
||||
console.log("Fetched settings");
|
||||
|
||||
// Get the current settings values
|
||||
const libretranslateUrl =
|
||||
(await settings.getLibretranslateBaseUrl()) || LIBRETRANSLATE_BASE_URL;
|
||||
setLibretranslateBaseUrl(libretranslateUrl);
|
||||
console.log("libretranslate url = %s", libretranslateUrl);
|
||||
try {
|
||||
const wModel = await settings.getWhisperModel() || "small";
|
||||
setWhisperModel(wModel);
|
||||
setWhisperModelTarget(new File(WHISPER_MODELS[wModel].target))
|
||||
} catch (err) {
|
||||
console.warn("Could not set whisper model: %s", err);
|
||||
}
|
||||
|
||||
// setWhisperModel(wModel);
|
||||
setIsLoaded(true);
|
||||
// console.log("Set is loaded: %s", isLoaded);
|
||||
})();
|
||||
|
||||
// Check for whether a model is currently downloading and set the status.
|
||||
setInterval(async () => {
|
||||
if (!whisperModel) return null;
|
||||
const dlStatus = await getWhisperDownloadStatus(whisperModel);
|
||||
setDownloadStatus(dlStatus);
|
||||
setWhisperModelTarget(new File(WHISPER_MODELS[whisperModel].target))
|
||||
console.log("Setting whisper model target to %s", whisperModelTarget);
|
||||
}, 1000);
|
||||
|
||||
setInterval(async () => {
|
||||
if (!libretranslateBaseUrl) return;
|
||||
try {
|
||||
const resp = await fetchWithTimeout(
|
||||
libretranslateBaseUrl + "/languages",
|
||||
{
|
||||
method: "HEAD",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
5000
|
||||
);
|
||||
if (resp.status !== 200) {
|
||||
throw new Error(resp.statusText);
|
||||
}
|
||||
setLangServerConn({ success: true });
|
||||
} catch (err) {
|
||||
setLangServerConn({
|
||||
success: false,
|
||||
error: `Could not connect to ${libretranslateBaseUrl}: ${err}`,
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
setInterval(async () => {
|
||||
const settings = await Settings.getDefault();
|
||||
await settings.setHostLanguage(hostLanguage || "en");
|
||||
await settings.setLibretranslateBaseUrl(
|
||||
libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL
|
||||
);
|
||||
await settings.setWhisperModel(whisperModel || "small");
|
||||
}, 1000);
|
||||
}, []);
|
||||
|
||||
const fileExists = async (file: File) => {
|
||||
const info = await FileSystem.getInfoAsync(file.uri);
|
||||
return info.exists;
|
||||
}
|
||||
|
||||
const doDelete = async () => {
|
||||
if (!whisperModelTarget) return;
|
||||
whisperModelTarget.delete();
|
||||
}
|
||||
|
||||
const doReadownload = async () => {
|
||||
if (!whisperModel) return;
|
||||
await initiateWhisperDownload(whisperModel, {
|
||||
force_redownload: true,
|
||||
onDownload: setWhisperDownloadProgress,
|
||||
});
|
||||
const handleWhisperModelChange = async (
|
||||
model: keyof typeof WHISPER_MODELS
|
||||
) => {
|
||||
const settings = await Settings.getDefault();
|
||||
setWhisperModel(model);
|
||||
await settings.setWhisperModel(model);
|
||||
checkDownloadStatus(model);
|
||||
};
|
||||
|
||||
const doDownload = async () => {
|
||||
if (!whisperModel) return;
|
||||
const whisperFile = WHISPER_MODELS[whisperModel];
|
||||
const resumable = await whisperFile.createDownloadResumable({
|
||||
onData: (progress) => setWhisperDownloadProgress(progress),
|
||||
});
|
||||
setDownloader(resumable);
|
||||
try {
|
||||
setDownloader(
|
||||
await initiateWhisperDownload(whisperModel, {
|
||||
onDownload: setWhisperDownloadProgress,
|
||||
force_redownload: true,
|
||||
})
|
||||
);
|
||||
await downloader?.downloadAsync();
|
||||
console.log("completed download");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
await resumable.downloadAsync();
|
||||
checkDownloadStatus(whisperModel);
|
||||
} catch (error) {
|
||||
console.error("Failed to download whisper model:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHostLanguageChange = async (value: string) => {
|
||||
setHostLanguage(value);
|
||||
|
||||
// Fetch the database connection
|
||||
const db = await getDb();
|
||||
const settings = new Settings(db);
|
||||
|
||||
// Save the updated setting value
|
||||
await settings.setHostLanguage(value);
|
||||
};
|
||||
|
||||
const handleLibretranslateBaseUrlChange = async (value: string) => {
|
||||
setLibretranslateBaseUrl(value);
|
||||
|
||||
const settings = await Settings.getDefault();
|
||||
|
||||
// Save the updated setting value
|
||||
await settings.setLibretranslateBaseUrl(value);
|
||||
|
||||
await fillHostLanguageOptions();
|
||||
};
|
||||
|
||||
const handleWhisperModelChange = async (value: string) => {
|
||||
const settings = await Settings.getDefault();
|
||||
setWhisperModel(value);
|
||||
await settings.setWhisperModel(value);
|
||||
setWhisperModelTarget(getWhisperTarget(value));
|
||||
}
|
||||
|
||||
const doStopDownload = async () => {
|
||||
if (!downloader) return;
|
||||
await downloader.pauseAsync()
|
||||
}
|
||||
downloader.cancelAsync();
|
||||
setDownloader(null);
|
||||
};
|
||||
|
||||
return isLoaded ? (
|
||||
const doDelete = async () => {
|
||||
const whisperFile = WHISPER_MODELS[whisperModel];
|
||||
whisperFile.delete();
|
||||
checkDownloadStatus(whisperModel);
|
||||
};
|
||||
|
||||
const checkDownloadStatus = async (model: keyof typeof WHISPER_MODELS) => {
|
||||
const whisperFile = WHISPER_MODELS[model];
|
||||
const status = await whisperFile.getDownloadStatus();
|
||||
if (
|
||||
!status.isDownloadComplete &&
|
||||
(!status.doesTargetExist || !status.hasDownloadStarted)
|
||||
) {
|
||||
setDownloader(null);
|
||||
}
|
||||
};
|
||||
|
||||
return hostLanguage && libretranslateBaseUrl ? (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.label}>Host Language:</Text>
|
||||
<Picker
|
||||
selectedValue={hostLanguage || ""}
|
||||
selectedValue={hostLanguage}
|
||||
style={{ height: 50, width: "100%" }}
|
||||
onValueChange={handleHostLanguageChange}
|
||||
accessibilityHint="hostLanguage"
|
||||
>
|
||||
{languages &&
|
||||
Object.entries(languages).map((lang) => (
|
||||
<Picker.Item key={lang[0]} label={lang[1].name} value={lang[0]} />
|
||||
))}
|
||||
{ languag }
|
||||
<Picker.Item label="English" value="en" />
|
||||
<Picker.Item label="Spanish" value="es" />
|
||||
</Picker>
|
||||
|
||||
<Text style={styles.label}>LibreTranslate Base URL:</Text>
|
||||
@ -253,40 +149,59 @@ const SettingsComponent: React.FC = () => {
|
||||
</Text>
|
||||
))}
|
||||
<Picker
|
||||
selectedValue={whisperModel || "small"}
|
||||
selectedValue={whisperModel}
|
||||
style={{ height: 50, width: "100%" }}
|
||||
onValueChange={handleWhisperModelChange}
|
||||
accessibilityHint="language"
|
||||
>
|
||||
{Object.entries(WHISPER_MODELS).map(([key, { label }]) => (
|
||||
<Picker.Item key={key} label={label} value={key} />
|
||||
{Object.entries(WHISPER_MODELS).map(([key, whisperFile]) => (
|
||||
<Picker.Item
|
||||
key={whisperFile.tag}
|
||||
label={whisperFile.label}
|
||||
value={key}
|
||||
/>
|
||||
))}
|
||||
</Picker>
|
||||
<View>
|
||||
{ /* If there's a downloader, that means we're in the middle of a download */}
|
||||
{downloader && whisperDownloadProgress && (
|
||||
<Text>
|
||||
{whisperDownloadProgress.totalBytesWritten} bytes of {whisperDownloadProgress.totalBytesExpectedToWrite} bytes
|
||||
|
||||
({Math.round((whisperDownloadProgress.totalBytesWritten / whisperDownloadProgress.totalBytesExpectedToWrite) * 100)} %)
|
||||
{whisperDownloadProgress.totalBytesWritten} bytes of{" "}
|
||||
{whisperDownloadProgress.totalBytesExpectedToWrite} bytes (
|
||||
{Math.round(
|
||||
(whisperDownloadProgress.totalBytesWritten /
|
||||
whisperDownloadProgress.totalBytesExpectedToWrite) *
|
||||
100
|
||||
)}
|
||||
%)
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
)}
|
||||
<View style={styles.downloadButtonWrapper}>
|
||||
{downloader && whisperDownloadProgress && (whisperDownloadProgress.totalBytesWritten !== whisperDownloadProgress.totalBytesExpectedToWrite) ? (
|
||||
(<Pressable onPress={doStopDownload} style={styles.pauseDownloadButton}>
|
||||
{downloader &&
|
||||
whisperDownloadProgress &&
|
||||
whisperDownloadProgress.totalBytesWritten !==
|
||||
whisperDownloadProgress.totalBytesExpectedToWrite ? (
|
||||
<Pressable
|
||||
onPress={doStopDownload}
|
||||
style={styles.pauseDownloadButton}
|
||||
>
|
||||
<Text style={styles.buttonText}>Pause Download</Text>
|
||||
</Pressable>)
|
||||
) :
|
||||
(<Pressable onPress={doDownload} style={styles.downloadButton}>
|
||||
<Text style={styles.buttonText}>Download</Text>
|
||||
</Pressable>)
|
||||
}
|
||||
{whisperModelTarget && fileExists(whisperModelTarget) &&
|
||||
(<Pressable onPress={doDelete} style={styles.deleteButton}>
|
||||
<Text style={styles.buttonText}>Delete</Text>
|
||||
</Pressable>)
|
||||
}
|
||||
</Pressable>
|
||||
) : (
|
||||
<Pressable onPress={doDownload} style={styles.downloadButton}>
|
||||
<Text style={styles.buttonText}>DOWNLOAD</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
{whisperModel &&
|
||||
WHISPER_MODELS[whisperModel] &&
|
||||
WHISPER_MODELS[whisperModel].doesTargetExist && (
|
||||
<Pressable
|
||||
onPress={doDelete}
|
||||
style={styles.deleteButton}
|
||||
aria-label="Delete"
|
||||
>
|
||||
<Text style={styles.buttonText}>Delete</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -300,29 +215,36 @@ const SettingsComponent: React.FC = () => {
|
||||
// Create styles for the component
|
||||
const styles = StyleSheet.create({
|
||||
downloadButtonWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
verticalAlign: "middle",
|
||||
},
|
||||
downloadButton: {
|
||||
backgroundColor: "blue",
|
||||
padding: 10,
|
||||
backgroundColor: "darkblue",
|
||||
padding: 20,
|
||||
margin: 10,
|
||||
flex: 3,
|
||||
flexDirection: "column",
|
||||
},
|
||||
deleteButton: {
|
||||
backgroundColor: "darkred",
|
||||
flex: 1,
|
||||
flexDirection: "column",
|
||||
padding: 10,
|
||||
margin: 10,
|
||||
height: 50,
|
||||
},
|
||||
pauseDownloadButton: {
|
||||
backgroundColor: "#444444",
|
||||
padding: 10,
|
||||
margin: 10,
|
||||
height: 50,
|
||||
},
|
||||
buttonText: {
|
||||
color: "white",
|
||||
color: "#fff",
|
||||
flex: 1,
|
||||
fontSize: 16,
|
||||
alignSelf: "center",
|
||||
textAlign: "center",
|
||||
textAlignVertical: "top",
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
|
@ -3,108 +3,115 @@ import { render, screen, fireEvent, act } from "@testing-library/react-native";
|
||||
import SettingsComponent from "@/components/Settings";
|
||||
import { language_matrix } from "@/app/i18n/api";
|
||||
import { Settings } from "@/app/lib/settings";
|
||||
import { getDb, migrateDb } from "@/app/lib/db";
|
||||
import { getDb } from "@/app/lib/db";
|
||||
import { Knex } from "knex";
|
||||
|
||||
const RENDER_TIME = 1000;
|
||||
|
||||
jest.mock("@/app/i18n/api", () => {
|
||||
class LanguageServer {
|
||||
fetchLanguages = () => {
|
||||
return {
|
||||
"en": {
|
||||
code: "en",
|
||||
name: "English",
|
||||
targets: [
|
||||
"fr",
|
||||
"es"
|
||||
]
|
||||
},
|
||||
"fr": {
|
||||
code: "fr",
|
||||
name: "French",
|
||||
targets: [
|
||||
"en",
|
||||
"es"
|
||||
]
|
||||
},
|
||||
"es": {
|
||||
code: "es",
|
||||
name: "Spanish",
|
||||
targets: [
|
||||
"en",
|
||||
"fr"
|
||||
]
|
||||
},
|
||||
} as language_matrix
|
||||
}
|
||||
}
|
||||
class Translator {
|
||||
translate = jest.fn((text : string, target : string) => {
|
||||
return "Hola, como estas?"
|
||||
})
|
||||
}
|
||||
return {
|
||||
LanguageServer,
|
||||
Translator,
|
||||
}
|
||||
})
|
||||
class LanguageServer {
|
||||
fetchLanguages = () => {
|
||||
return {
|
||||
en: {
|
||||
code: "en",
|
||||
name: "English",
|
||||
targets: ["fr", "es"],
|
||||
},
|
||||
fr: {
|
||||
code: "fr",
|
||||
name: "French",
|
||||
targets: ["en", "es"],
|
||||
},
|
||||
es: {
|
||||
code: "es",
|
||||
name: "Spanish",
|
||||
targets: ["en", "fr"],
|
||||
},
|
||||
} as language_matrix;
|
||||
};
|
||||
}
|
||||
class Translator {
|
||||
translate = jest.fn((text: string, target: string) => {
|
||||
return "Hola, como estas?";
|
||||
});
|
||||
}
|
||||
return {
|
||||
LanguageServer,
|
||||
Translator,
|
||||
};
|
||||
});
|
||||
|
||||
describe("SettingsComponent", () => {
|
||||
beforeEach(async() => {
|
||||
await migrateDb();
|
||||
const settings = await Settings.getDefault();
|
||||
await settings.setHostLanguage("en");
|
||||
await settings.setLibretranslateBaseUrl("https://example.com");
|
||||
})
|
||||
let db: Knex;
|
||||
let settings: Settings;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
})
|
||||
beforeEach(async () => {
|
||||
db = await getDb("development");
|
||||
settings = new Settings(db);
|
||||
await settings.setHostLanguage("en");
|
||||
await settings.setLibretranslateBaseUrl("https://example.com");
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers()
|
||||
})
|
||||
afterEach(async () => {
|
||||
await db.migrate.down();
|
||||
await db.destroy();
|
||||
});
|
||||
|
||||
test("renders correctly with initial settings", async () => {
|
||||
render(<SettingsComponent />);
|
||||
jest.advanceTimersByTime(RENDER_TIME);
|
||||
screen.debug();
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
// expect(screen.getByDisplayValue("English")).toBeTruthy();
|
||||
expect(screen.getByAccessibilityHint("libretranslate base url")).toBeTruthy();
|
||||
});
|
||||
test("renders correctly with initial settings", async () => {
|
||||
render(<SettingsComponent />);
|
||||
jest.advanceTimersByTime(RENDER_TIME);
|
||||
screen.debug();
|
||||
|
||||
test("updates host language setting when input changes", async () => {
|
||||
render(<SettingsComponent />);
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
// expect(screen.getByDisplayValue("English")).toBeTruthy();
|
||||
expect(
|
||||
screen.getByAccessibilityHint("libretranslate base url")
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
// Change the host language input value
|
||||
const picker = screen.getByAccessibilityHint("hostLanguage");
|
||||
fireEvent(picker, "onvalueChange", "es");
|
||||
expect(picker.props.selectedIndex).toStrictEqual(0);
|
||||
});
|
||||
test("updates host language setting when input changes", async () => {
|
||||
render(<SettingsComponent />);
|
||||
|
||||
test("updates LibreTranslate base URL setting when input changes", async () => {
|
||||
render(<SettingsComponent />);
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
|
||||
jest.advanceTimersByTime(RENDER_TIME)
|
||||
screen.debug();
|
||||
// Change the host language input value
|
||||
const picker = screen.getByAccessibilityHint("hostLanguage");
|
||||
fireEvent(picker, "onvalueChange", "es");
|
||||
expect(picker.props.selectedIndex).toStrictEqual(0);
|
||||
});
|
||||
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
test("updates LibreTranslate base URL setting when input changes", async () => {
|
||||
render(<SettingsComponent />);
|
||||
|
||||
// Change the LibreTranslate base URL input value
|
||||
fireEvent.changeText(screen.getByAccessibilityHint("libretranslate base url"), "http://new-example.com");
|
||||
jest.advanceTimersByTime(RENDER_TIME);
|
||||
jest.advanceTimersByTime(RENDER_TIME);
|
||||
screen.debug();
|
||||
|
||||
expect(screen.getByAccessibilityHint("libretranslate base url")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
// Wait for the component to fetch and display the initial settings
|
||||
await screen.findByText(/Host Language:/i);
|
||||
await screen.findByText(/LibreTranslate Base URL:/i);
|
||||
|
||||
// Change the LibreTranslate base URL input value
|
||||
fireEvent.changeText(
|
||||
screen.getByAccessibilityHint("libretranslate base url"),
|
||||
"http://new-example.com"
|
||||
);
|
||||
jest.advanceTimersByTime(RENDER_TIME);
|
||||
|
||||
expect(
|
||||
screen.getByAccessibilityHint("libretranslate base url")
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user