Skip to content

Commit

Permalink
utility.tsよりexportされている関数やクラスのユニットテストを追加 (VOICEVOX#1701)
Browse files Browse the repository at this point in the history
* utility.tsよりexportされている関数やクラスのユニットテストを追加

* テスト用に付けていたexportを削除

* リファクタリング

* Apply suggestions from code review

* いろいろ微調整

---------

Co-authored-by: Hiroshiba <[email protected]>
  • Loading branch information
weweweok and Hiroshiba authored Jan 12, 2024
1 parent f8ffb90 commit 97ebf38
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 109 deletions.
15 changes: 1 addition & 14 deletions src/store/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,9 @@ export function buildAudioFileNameFromRawData(
}

const characterName = sanitizeFileName(vars.characterName);

const index = (vars.index + 1).toString().padStart(3, "0");

const styleName = sanitizeFileName(vars.styleName);

const date = currentDateString();

const date = vars.date;
return replaceTag(pattern, {
text,
characterName,
Expand Down Expand Up @@ -447,12 +443,3 @@ export const isOnCommandOrCtrlKeyDown = (event: {
metaKey: boolean;
ctrlKey: boolean;
}) => (isMac && event.metaKey) || (!isMac && event.ctrlKey);

/**
* AccentPhraseのtextを結合して返します。
*/
export const joinTextsInAccentPhrases = (
accentPhrase: AccentPhrase
): string => {
return accentPhrase.moras.map((mora) => mora.text).join("");
};
95 changes: 0 additions & 95 deletions tests/unit/lib/tuningTranscription.spec.ts

This file was deleted.

255 changes: 255 additions & 0 deletions tests/unit/store/utility.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import { AccentPhrase, Mora } from "@/openapi";
import { ToolbarButtonTagType, isMac } from "@/type/preload";
import {
formatCharacterStyleName,
sanitizeFileName,
currentDateString,
DEFAULT_STYLE_NAME,
extractExportText,
extractYomiText,
TuningTranscription,
isAccentPhrasesTextDifferent,
buildAudioFileNameFromRawData,
getToolbarButtonName,
createKanaRegex,
convertHiraToKana,
convertLongVowel,
getBaseName,
isOnCommandOrCtrlKeyDown,
} from "@/store/utility";

function createDummyMora(text: string): Mora {
return {
text,
vowel: "dummy",
vowelLength: Math.random(),
pitch: Math.random(),
};
}

function createDummyAccentPhrase(moraTexts: string[]): AccentPhrase {
return {
moras: moraTexts.map(createDummyMora),
accent: Math.random(),
};
}

// AccentPhrasesから特定のmora textを持つものMoraを返す
function findMora(
accentPhrases: AccentPhrase[],
text: string
): Mora | undefined {
let candidate: Mora | undefined;
for (let i = 0; i < accentPhrases.length; i++) {
for (let j = 0; j < accentPhrases[i].moras.length; j++) {
if (accentPhrases[i].moras[j].text === text) {
if (candidate != undefined) {
throw new Error(`AccentPhraseに${text}が複数見つかりました`);
}
candidate = accentPhrases[i].moras[j];
}
}
}
return candidate;
}

test("formatCharacterStyleName", () => {
expect(formatCharacterStyleName("四国めたん", DEFAULT_STYLE_NAME)).toEqual(
"四国めたん(ノーマル)"
);
});

test("sanitizeFileName", () => {
expect(sanitizeFileName("テスト\x00ファイル\x1f名.txt")).toBe(
"テストファイル名.txt"
);
expect(sanitizeFileName('テスト"*/:<>?\\|ファイル名.txt')).toBe(
"テストファイル名.txt"
);
});

test("currentDateString", () => {
expect(currentDateString()).toMatch(/\d{4}\d{2}\d{2}/);
});

test("extractExportText", () => {
const input = "{漢字|かんじ}[半角記号メモ]";
const expected = "漢字";
const result = extractExportText(input);
expect(result).toEqual(expected);
});

test("extractYomiText", () => {
const input = "{漢字|かんじ}[メモ]";
const expected = "かんじ";
const result = extractYomiText(input);
expect(result).toEqual(expected);
});

describe("TuningTranscription", () => {
it("2つ以上のアクセント句でも正しくデータを転写できる", async () => {
const before: AccentPhrase[] = [
createDummyAccentPhrase(["い", "え"]),
createDummyAccentPhrase(["か", "き", "く", "け", "こ"]),
createDummyAccentPhrase(["さ", "し", "す", "せ", "そ"]),
];
const after: AccentPhrase[] = [
createDummyAccentPhrase(["あ", "い", "う", "え", "お"]), // 最初・真ん中・最後に追加
createDummyAccentPhrase(["き", "け"]), // 最初・真ん中・最後を消去
createDummyAccentPhrase(["た", "ち", "つ", "て", "と"]), // すべて置き換え
];
const tuningTransctiption = new TuningTranscription(before, after);
const result = tuningTransctiption.transcribe();

// モーラ数などは変わっていない
expect(result.length).toEqual(after.length);
for (let i = 0; i < result.length; i++) {
expect(result[i].moras.length).toEqual(after[i].moras.length);
}

// 転写されている
["い", "え", "き", "け"].forEach((moraText) => {
expect(findMora(result, moraText)).toEqual(findMora(before, moraText));
});

// 転写されていない
["あ", "う", "お", "た", "ち", "つ", "て", "と"].forEach((moraText) => {
expect(findMora(result, moraText)).not.toEqual(
findMora(before, moraText)
);
});
});

it("拗音のあるモーラも正しくデータを転写できる", async () => {
const before = [
createDummyAccentPhrase(["い", "しぃ", "う", "しゅ", "お", "しょ"]),
];
const after = [
createDummyAccentPhrase(["あ", "しゃ", "き", "きゅ", "お", "しょ"]),
];
const tuningTransctiption = new TuningTranscription(before, after);
const result = tuningTransctiption.transcribe();

// モーラ数などは変わっていない
expect(result.length).toEqual(after.length);
for (let i = 0; i < result.length; i++) {
expect(result[i].moras.length).toEqual(after[i].moras.length);
}

// 転写されている
["お", "しょ"].forEach((moraText) => {
expect(findMora(result, moraText)).toEqual(findMora(before, moraText));
});

// 転写されていない
["あ", "しゃ", "き", "きゅ"].forEach((moraText) => {
expect(findMora(result, moraText)).not.toEqual(
findMora(before, moraText)
);
});
});
});

describe("isAccentPhrasesTextDifferent", () => {
it("アクセントフレーズのテキストが異なる場合、trueを返す", () => {
const accentPhrases1 = [
createDummyAccentPhrase(["あ", "い", "う"]),
createDummyAccentPhrase(["え", "お"]),
];
const accentPhrases2 = [
createDummyAccentPhrase(["か", "き", "く"]),
createDummyAccentPhrase(["け", "こ"]),
];
const result = isAccentPhrasesTextDifferent(accentPhrases1, accentPhrases2);
expect(result).toBe(true);
});

it("アクセントフレーズのテキストが同じ場合、falseを返す", () => {
const accentPhrases1 = [
createDummyAccentPhrase(["あ", "い", "う"]),
createDummyAccentPhrase(["え", "お"]),
];
const accentPhrases2 = [
createDummyAccentPhrase(["あ", "い", "う"]),
createDummyAccentPhrase(["え", "お"]),
];
const result = isAccentPhrasesTextDifferent(accentPhrases1, accentPhrases2);
expect(result).toBe(false);
});
});

test("buildAudioFileNameFromRawData", () => {
const fileNamePattern =
"index=$連番$ characterName=$キャラ$ text=$テキスト$ styleName=$スタイル$ date=$日付$";
const vars = {
index: 10,
characterName: "キャラ1",
text: "テストテキスト",
styleName: "スタイル1",
date: "20210801",
};
const result = buildAudioFileNameFromRawData(fileNamePattern, vars);
expect(result).toBe(
"index=011 characterName=キャラ1 text=テストテキスト styleName=スタイル1 date=20210801"
);
});

test("getToolbarButtonName", () => {
expect(getToolbarButtonName("PLAY_CONTINUOUSLY")).toBe("連続再生");
expect(getToolbarButtonName("STOP")).toBe("停止");
expect(getToolbarButtonName("EXPORT_AUDIO_SELECTED")).toBe(
"選択音声を書き出し"
);
expect(getToolbarButtonName("EXPORT_AUDIO_ALL")).toBe("全部書き出し");
expect(getToolbarButtonName("EXPORT_AUDIO_CONNECT_ALL")).toBe(
"音声を繋げて書き出し"
);
expect(getToolbarButtonName("存在しないタグ" as ToolbarButtonTagType)).toBe(
undefined
);
});

describe("createKanaRegex", () => {
it("includeSeparationがtrueの場合、読点とクエスチョンも含む", () => {
const regex = createKanaRegex(true);
expect(regex.test("あいうえお、")).toBe(true);
expect(regex.test("かきくけこ?")).toBe(true);
});

it("includeSeparationがfalseの場合、読点とクエスチョンを含まない", () => {
const regex = createKanaRegex(false);
expect(regex.test("あいうえお、")).toBe(false);
expect(regex.test("かきくけこ?")).toBe(false);
});
});

test("convertHiraToKana", () => {
expect(convertHiraToKana("あいうえお")).toBe("アイウエオ");
expect(convertHiraToKana("がぱをんー")).toBe("ガパヲンー");
});

test("convertLongVowel", () => {
expect(convertLongVowel("アー")).toBe("アア");
expect(convertLongVowel("ガー")).toBe("ガア");
expect(convertLongVowel("ンー")).toBe("ンン");
});

test("getBaseName", () => {
expect(getBaseName("/path/to/file.txt")).toBe("file.txt");
expect(getBaseName("/path/to/file")).toBe("file");
expect(getBaseName("file.txt")).toBe("file.txt");
expect(getBaseName("file")).toBe("file");
});

test("isOnCommandOrCtrlKeyDown", () => {
expect(isOnCommandOrCtrlKeyDown({ metaKey: true, ctrlKey: false })).toBe(
isMac
);
expect(isOnCommandOrCtrlKeyDown({ metaKey: false, ctrlKey: true })).toBe(
!isMac
);
expect(isOnCommandOrCtrlKeyDown({ metaKey: true, ctrlKey: true })).toBe(true);
expect(isOnCommandOrCtrlKeyDown({ metaKey: false, ctrlKey: false })).toBe(
false
);
});

0 comments on commit 97ebf38

Please sign in to comment.