add tests for translation jsons

This commit is contained in:
galister 2026-08-09 18:34:27 +09:00
parent 1a44b54d98
commit 77b5004541
5 changed files with 223 additions and 7 deletions

View File

@ -1,6 +1,7 @@
mod assets;
pub mod frontend;
mod tab;
mod test;
mod util;
mod various;
mod views;

View File

@ -58,13 +58,14 @@ impl SettingsTab for State {
match task {
Task::WhisperDownloadClosed => {
if let Some(model) = self.pending_download.take()
&& !whisper_model_path(model.file_name).exists() {
// download failed, set to selection to none
par.general_config.whisper_model = "".into();
par.config_change_kind.replace(ConfigChangeKind::Other);
// reload the tab
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
}
&& !whisper_model_path(model.file_name).exists()
{
// download failed, set to selection to none
par.general_config.whisper_model = "".into();
par.config_change_kind.replace(ConfigChangeKind::Other);
// reload the tab
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
}
}
Task::WhisperRemoveUnused => {
let _ = whisper_delete_all_models().log_err("could not remove whisper models");

104
dash-frontend/src/test.rs Normal file
View File

@ -0,0 +1,104 @@
#[cfg(test)]
mod tests {
use crate::assets::Asset;
#[test]
fn lang_json_files_are_valid() {
for file in Asset::iter() {
if file.ends_with(".json") {
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
let text =
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
serde_json::from_str::<serde_json::Value>(&text)
.unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
}
}
}
fn parse_csv_keys(data: &[u8]) -> Vec<String> {
let text = std::str::from_utf8(data).expect("en.csv is not valid UTF-8");
let mut keys = Vec::new();
let mut chars = text.chars().peekable();
while chars.peek().is_some() {
let key = read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip value field
read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip description field (may contain newlines via quotes)
read_csv_field(&mut chars);
// skip newline
if chars.peek() == Some(&'\n') {
chars.next();
}
keys.push(key);
}
keys
}
fn read_csv_field(chars: &mut std::iter::Peekable<std::str::Chars>) -> String {
let mut field = String::new();
if chars.peek() == Some(&'"') {
// quoted field
chars.next(); // consume opening quote
loop {
match chars.next() {
Some('"') => {
if chars.peek() == Some(&'"') {
field.push('"'); // escaped quote
chars.next();
} else {
break; // closing quote
}
}
Some(c) => field.push(c),
None => break,
}
}
} else {
// unquoted field
for c in chars.by_ref() {
if c == ',' || c == '\n' {
break;
}
field.push(c);
}
}
field
}
fn get_nested<'a>(value: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> {
let mut current = value;
for segment in key.split('.') {
current = current.get(segment)?;
}
Some(current)
}
#[test]
fn lang_json_files_contain_all_keys() {
let en_data = Asset::get("lang/en.csv").expect("en.csv not found");
let expected_keys = parse_csv_keys(&en_data.data);
for file in Asset::iter() {
if !file.ends_with(".json") {
continue;
}
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
let text =
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
let json: serde_json::Value =
serde_json::from_str(&text).unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
for key in &expected_keys {
assert!(get_nested(&json, key).is_some(), "missing key {key} in {file}");
}
}
}
}

View File

@ -28,6 +28,7 @@ mod overlays;
mod shaders;
mod state;
mod subsystem;
mod test;
mod windowing;
use std::{

109
wayvr/src/test.rs Normal file
View File

@ -0,0 +1,109 @@
#[cfg(test)]
mod tests {
use crate::gui::asset::GuiAsset;
#[test]
fn lang_json_files_are_valid() {
for file in GuiAsset::iter() {
if file.ends_with(".json") {
let data = GuiAsset::get(&file)
.unwrap_or_else(|| panic!("embedded file {file} not found"));
let text = String::from_utf8(data.data.to_vec())
.unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
serde_json::from_str::<serde_json::Value>(&text)
.unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
}
}
}
fn parse_csv_keys(data: &[u8]) -> Vec<String> {
let text = std::str::from_utf8(data).expect("en.csv is not valid UTF-8");
let mut keys = Vec::new();
let mut chars = text.chars().peekable();
while let Some(_) = chars.peek() {
let key = read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip value field
read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip description field (may contain newlines via quotes)
read_csv_field(&mut chars);
// skip newline
if chars.peek() == Some(&'\n') {
chars.next();
}
keys.push(key);
}
keys
}
fn read_csv_field(chars: &mut std::iter::Peekable<std::str::Chars>) -> String {
let mut field = String::new();
if chars.peek() == Some(&'"') {
// quoted field
chars.next(); // consume opening quote
loop {
match chars.next() {
Some('"') => {
if chars.peek() == Some(&'"') {
field.push('"'); // escaped quote
chars.next();
} else {
break; // closing quote
}
}
Some(c) => field.push(c),
None => break,
}
}
} else {
// unquoted field
for c in chars.by_ref() {
if c == ',' || c == '\n' {
break;
}
field.push(c);
}
}
field
}
fn get_nested<'a>(value: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> {
let mut current = value;
for segment in key.split('.') {
current = current.get(segment)?;
}
Some(current)
}
#[test]
fn lang_json_files_contain_all_keys() {
let en_data = GuiAsset::get("lang/en.csv").expect("en.csv not found");
let expected_keys = parse_csv_keys(&en_data.data);
for file in GuiAsset::iter() {
if !file.ends_with(".json") {
continue;
}
let data =
GuiAsset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
let text = String::from_utf8(data.data.to_vec())
.unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
let json: serde_json::Value = serde_json::from_str(&text)
.unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
for key in &expected_keys {
assert!(
get_nested(&json, key).is_some(),
"missing key {key} in {file}"
);
}
}
}
}