fix(i18n): preserve safe interview and attachment purpose fallbacks
This commit is contained in:
@@ -502,5 +502,5 @@ function interviewCategoryLabel(t: (key: any) => string, category: string) {
|
||||
note: "interviewCategoryNotes",
|
||||
debrief: "interviewCategoryDebrief",
|
||||
};
|
||||
return keys[category] ? t(keys[category]) : category;
|
||||
return Object.hasOwn(keys, category) ? t(keys[category]) : category;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,15 @@ function page(items: ReturnType<typeof item>[] = [item()], currentPage = 1, tota
|
||||
return { items, page: currentPage, pageSize: 25, total, totalPages: Math.ceil(total / 25) };
|
||||
}
|
||||
|
||||
describe.each(['en', 'nb'])('%s unknown attachment purposes', language => {
|
||||
test.each(['constructor', 'toString', '__proto__'])('uses the localized Other label for %s', async purpose => {
|
||||
localStorage.setItem('uiLanguage', language);
|
||||
mockedApi.get.mockResolvedValue({ data: page([item({ type: 'attachment', purpose, visibility: 'private' })]) } as never);
|
||||
renderPage();
|
||||
expect(await screen.findByText(`${copy('attachmentsPurpose')}: ${copy('attachmentsPurposeOther')}`)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
function deferred<T>() {
|
||||
let resolve!: (value: T) => void;
|
||||
let reject!: (reason: unknown) => void;
|
||||
|
||||
@@ -62,6 +62,16 @@ beforeEach(() => {
|
||||
window.localStorage.setItem("uiLanguage", "en");
|
||||
});
|
||||
|
||||
describe.each(['en', 'nb'])('%s unknown interview categories', language => {
|
||||
test.each(['constructor', 'toString', '__proto__'])('preserves %s as a category label', async category => {
|
||||
window.localStorage.setItem('uiLanguage', language);
|
||||
routeGet({ board: { ...board, groups: [{ ...board.groups[0], category }] } });
|
||||
render(<ApplicationInterviewPrep jobId={7} />);
|
||||
expect(await screen.findByText(category)).toBeInTheDocument();
|
||||
expect(screen.getByText('Funding history')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("localizes interview categories while preserving user-authored preparation", async () => {
|
||||
window.localStorage.setItem("uiLanguage", "nb");
|
||||
routeGet();
|
||||
|
||||
@@ -240,7 +240,7 @@ export default function DocumentsPage() {
|
||||
{item.type === "email-draft" ? <Typography variant="caption" color="text.secondary">{t("documentsEmailHelp")}</Typography> : null}
|
||||
{item.type === "attachment" ? <>
|
||||
<Typography variant="caption" color="text.secondary">{[item.fileType, item.fileSize != null ? t("documentsFileSize", { size: new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }).format(item.fileSize / 1024) }) : null].filter(Boolean).join(" · ")}</Typography>
|
||||
{item.purpose ? <Typography variant="caption" color="text.secondary">{t("attachmentsPurpose")}: {t(({ resume: "attachmentsPurposeResume", "cover-letter": "attachmentsPurposeCoverLetter", portfolio: "attachmentsPurposePortfolio", "case-study": "attachmentsPurposeCaseStudy", certificate: "attachmentsPurposeCertificate" } as Record<string, TranslationKey>)[item.purpose.toLowerCase()] ?? "attachmentsPurposeOther")}</Typography> : null}
|
||||
{item.purpose ? <Typography variant="caption" color="text.secondary">{t("attachmentsPurpose")}: {t((Object.assign(Object.create(null), { resume: "attachmentsPurposeResume", "cover-letter": "attachmentsPurposeCoverLetter", portfolio: "attachmentsPurposePortfolio", "case-study": "attachmentsPurposeCaseStudy", certificate: "attachmentsPurposeCertificate" }) as Record<string, TranslationKey>)[item.purpose.toLowerCase()] ?? "attachmentsPurposeOther")}</Typography> : null}
|
||||
{item.purpose?.toLowerCase() === "certificate" ? <Typography variant="caption" color="text.secondary">{t("documentsCertificateHelp")}</Typography> : null}
|
||||
{item.useForAi != null ? <Typography variant="caption" color="text.secondary">{t("attachmentsAiUse")}: {t(item.useForAi ? "attachmentsAiEnabled" : "attachmentsAiDisabled")}</Typography> : null}
|
||||
</> : null}
|
||||
|
||||
Reference in New Issue
Block a user