184 lines
5.6 KiB
TypeScript
184 lines
5.6 KiB
TypeScript
/** @vitest-environment jsdom */
|
|
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
import { promptForAudienceProfileFields } from "../src/content/market/audience-profile-field-dialog";
|
|
|
|
describe("audience-profile-field-dialog", () => {
|
|
test("keeps an explicitly empty field selection empty", async () => {
|
|
const result = promptForAudienceProfileFields(
|
|
document,
|
|
[
|
|
{
|
|
headers: ["粉丝数", "观众画像-男性占比"],
|
|
label: "测试字段"
|
|
}
|
|
],
|
|
[]
|
|
);
|
|
|
|
const fields = Array.from(
|
|
document.querySelectorAll(
|
|
'[data-audience-profile-field-dialog-field="checkbox"]'
|
|
)
|
|
) as HTMLInputElement[];
|
|
expect(fields).toHaveLength(2);
|
|
expect(fields.every((field) => !field.checked)).toBe(true);
|
|
expect(
|
|
document.querySelectorAll(
|
|
"[data-audience-profile-field-dialog-selected-field]"
|
|
)
|
|
).toHaveLength(0);
|
|
expect(
|
|
document.querySelector(
|
|
'[data-audience-profile-field-dialog-selected-empty="text"]'
|
|
)?.hidden
|
|
).toBe(false);
|
|
|
|
clickSave();
|
|
await expect(result).resolves.toEqual([]);
|
|
});
|
|
|
|
test("keeps selected fields visible while searching and synchronizes both panes", async () => {
|
|
const result = promptForAudienceProfileFields(
|
|
document,
|
|
[
|
|
{
|
|
headers: ["粉丝数"],
|
|
label: "列表字段"
|
|
},
|
|
{
|
|
headers: ["内容数据-近30天-完播率", "内容数据-近30天-播放量"],
|
|
label: "内容数据"
|
|
}
|
|
],
|
|
["粉丝数", "内容数据-近30天-播放量"]
|
|
);
|
|
|
|
expect(readSelectedFieldNames()).toEqual([
|
|
"粉丝数",
|
|
"内容数据-近30天-播放量"
|
|
]);
|
|
expect(
|
|
document.querySelector(
|
|
'[data-audience-profile-field-dialog-selected-count="text"]'
|
|
)?.textContent
|
|
).toBe("2 个");
|
|
|
|
const search = document.querySelector(
|
|
'[data-audience-profile-field-dialog-search="input"]'
|
|
) as HTMLInputElement;
|
|
search.value = "完播率";
|
|
search.dispatchEvent(new Event("input"));
|
|
|
|
expect(readResultItem("内容数据-近30天-完播率")?.hidden).toBe(false);
|
|
expect(readResultItem("粉丝数")?.hidden).toBe(true);
|
|
expect(readSelectedFieldNames()).toEqual([
|
|
"粉丝数",
|
|
"内容数据-近30天-播放量"
|
|
]);
|
|
expect(
|
|
document.querySelector(
|
|
'[data-audience-profile-field-dialog-result-count="text"]'
|
|
)?.textContent
|
|
).toBe("找到 1 个");
|
|
|
|
const finishRateInput = readResultInput("内容数据-近30天-完播率");
|
|
finishRateInput.checked = true;
|
|
finishRateInput.dispatchEvent(new Event("change"));
|
|
expect(readSelectedFieldNames()).toEqual([
|
|
"粉丝数",
|
|
"内容数据-近30天-完播率",
|
|
"内容数据-近30天-播放量"
|
|
]);
|
|
|
|
const selectedFansInput = readSelectedInput("粉丝数");
|
|
selectedFansInput.checked = false;
|
|
selectedFansInput.dispatchEvent(new Event("change"));
|
|
expect(readResultInput("粉丝数").checked).toBe(false);
|
|
expect(readSelectedFieldNames()).toEqual([
|
|
"内容数据-近30天-完播率",
|
|
"内容数据-近30天-播放量"
|
|
]);
|
|
|
|
clickSave();
|
|
await expect(result).resolves.toEqual([
|
|
"内容数据-近30天-完播率",
|
|
"内容数据-近30天-播放量"
|
|
]);
|
|
});
|
|
|
|
test("shows a dedicated empty state when no field matches the keyword", async () => {
|
|
const result = promptForAudienceProfileFields(
|
|
document,
|
|
[{ headers: ["粉丝数"], label: "列表字段" }],
|
|
undefined
|
|
);
|
|
const search = document.querySelector(
|
|
'[data-audience-profile-field-dialog-search="input"]'
|
|
) as HTMLInputElement;
|
|
search.value = "不存在的字段";
|
|
search.dispatchEvent(new Event("input"));
|
|
|
|
expect(
|
|
document.querySelector(
|
|
'[data-audience-profile-field-dialog-result-empty="text"]'
|
|
)?.hidden
|
|
).toBe(false);
|
|
expect(
|
|
document.querySelector(
|
|
'[data-audience-profile-field-dialog-result-count="text"]'
|
|
)?.textContent
|
|
).toBe("找到 0 个");
|
|
expect(readSelectedFieldNames()).toEqual(["粉丝数"]);
|
|
|
|
clickSave();
|
|
await expect(result).resolves.toEqual(["粉丝数"]);
|
|
});
|
|
});
|
|
|
|
function clickSave(): void {
|
|
const saveButton = document.querySelector(
|
|
'[data-audience-profile-field-dialog-save="button"]'
|
|
) as HTMLButtonElement;
|
|
saveButton.click();
|
|
}
|
|
|
|
function readResultItem(field: string): HTMLElement | undefined {
|
|
return Array.from(
|
|
document.querySelectorAll<HTMLElement>(
|
|
"[data-audience-profile-field-dialog-result]"
|
|
)
|
|
).find(
|
|
(element) => element.dataset.audienceProfileFieldDialogResult === field
|
|
);
|
|
}
|
|
|
|
function readResultInput(field: string): HTMLInputElement {
|
|
const input = Array.from(
|
|
document.querySelectorAll<HTMLInputElement>(
|
|
'[data-audience-profile-field-dialog-field="checkbox"]'
|
|
)
|
|
).find((element) => element.value === field);
|
|
if (!input) throw new Error(`Missing result field input: ${field}`);
|
|
return input;
|
|
}
|
|
|
|
function readSelectedInput(field: string): HTMLInputElement {
|
|
const input = Array.from(
|
|
document.querySelectorAll<HTMLInputElement>(
|
|
'[data-audience-profile-field-dialog-selected-checkbox="checkbox"]'
|
|
)
|
|
).find((element) => element.value === field);
|
|
if (!input) throw new Error(`Missing selected field input: ${field}`);
|
|
return input;
|
|
}
|
|
|
|
function readSelectedFieldNames(): string[] {
|
|
return Array.from(
|
|
document.querySelectorAll<HTMLElement>(
|
|
"[data-audience-profile-field-dialog-selected-field]"
|
|
)
|
|
).map((element) => element.dataset.audienceProfileFieldDialogSelectedField ?? "");
|
|
}
|