Ctrl K
ComunidadGuías…

frontend/test/server-text.test.ts

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/* 服务端文字的解析(ADR-0156 第三条):按 message_code 取译文,没有译文回落到原文;
 * 取数入口换好的原因再经过 requestErrorMessage 不会被按状态码换掉。英文界面才看得出这两件事,所以按英文加载。 */
import { afterEach, describe, expect, it, vi } from 'vitest';

import { SETTINGS_KEY } from '../src/settings-key';
import enServer from '../src/locales/en/server.json' with { type: 'json' };
import enShell from '../src/locales/en/shell.json' with { type: 'json' };

async function load(language: 'en' | 'zh-CN') {
  vi.resetModules();
  localStorage.setItem(SETTINGS_KEY, JSON.stringify({ interfaceLanguage: language }));
  vi.doMock('../src/locales/en/server.json', () => ({
    default: { ...enServer, sample: { withParams: 'Peach found {{count}} files in {{folder}}.' } },
  }));
  const [server, request, api, core] = await Promise.all([
    import('../src/core/server-text'), import('../src/core/request-error'), import('../src/api'), import('../src/core'),
  ]);
  return { ...server, ...request, ...api, legacyApi: core.api };
}

const respond = (status: number, body: unknown) => vi.fn(async () => new Response(JSON.stringify(body), {
  status, headers: { 'Content-Type': 'application/json' },
}));

afterEach(() => {
  localStorage.removeItem(SETTINGS_KEY);
  vi.unstubAllGlobals();
  vi.doUnmock('../src/locales/en/server.json');
  vi.resetModules();
});

describe('serverText', () => {
  it('有 code 且有译文时用当前界面语言,参数填进占位', async () => {
    const { serverText } = await load('en');
    expect(serverText({ error: '这个地址下没有页面。', message_code: 'http.notFound', message_params: {} }))
      .toBe(enServer.http.notFound);
    expect(serverText({ message: '在 R:\\media 找到 3 个文件。', message_code: 'sample.withParams', message_params: { count: 3, folder: 'R:\\media' } }))
      .toBe('Peach found 3 files in R:\\media.');
  });

  it('code 没有译文时显示服务端原文,不显示键名', async () => {
    const { serverText, serverLabel } = await load('en');
    expect(serverText({ error: '整理路径不在所选来源内', message_code: 'organize.notYetTranslated' })).toBe('整理路径不在所选来源内');
    expect(serverLabel('release.installation.unknown', '源码运行')).toBe('源码运行');
  });

  it('没带 code 的原文只有中文才显示,英文协议值交给状态码', async () => {
    const { serverText } = await load('en');
    expect(serverText({ error: '媒体盘没有挂载' })).toBe('媒体盘没有挂载');
    expect(serverText({ error: 'not found' })).toBe('');
    expect(serverText(null)).toBe('');
  });
});

describe('取数失败的原因', () => {
  it('apiGet 抛出的译文经过页面再处理一次仍是译文', async () => {
    const { apiGet, ApiError, requestErrorMessage, errorMessage } = await load('en');
    vi.stubGlobal('fetch', respond(404, { error: '这个地址下没有页面。', message_code: 'http.notFound', message_params: {} }));
    const error = await apiGet('/api/missing').catch((cause: unknown) => cause);
    expect(error).toBeInstanceOf(ApiError);
    expect((error as Error).message).toBe(enServer.http.notFound);
    expect(requestErrorMessage(error)).toBe(enServer.http.notFound);
    expect(errorMessage(error)).toBe(enServer.http.notFound);
  });

  it('apiSend 收到英文协议值时按状态码给通用句', async () => {
    const { apiSend } = await load('en');
    vi.stubGlobal('fetch', respond(404, { error: 'no such id' }));
    const error = await apiSend('/api/items/1', {}).catch((cause: unknown) => cause);
    expect((error as Error).message).toBe(enShell.requestError.notFound);
  });

  it('遗留层的 api() 走同一个解析函数,再处理一次也不变', async () => {
    const { legacyApi, requestErrorMessage } = await load('en');
    vi.stubGlobal('fetch', respond(500, { error: '服务处理失败,请导出诊断报告', message_code: 'http.serverError', error_id: 'abc' }));
    const error = await legacyApi('/api/boom').catch((cause: unknown) => cause);
    expect((error as Error).message).toBe(enServer.http.serverError);
    expect(requestErrorMessage(error)).toBe(enServer.http.serverError);
  });

  it('页面自己的英文句子原样显示,运行时异常与 Python 异常行换成通用句', async () => {
    const { requestErrorMessage } = await load('en');
    expect(requestErrorMessage("Couldn't load the list.")).toBe("Couldn't load the list.");
    expect(requestErrorMessage(new TypeError('Failed to fetch'))).toBe(enShell.requestError.unreachable);
    expect(requestErrorMessage(new SyntaxError('Unexpected token < in JSON'))).toBe(enShell.requestError.fallback);
    expect(requestErrorMessage('ConnectionError: HTTPSConnectionPool(host=example.com)')).toBe(enShell.requestError.fallback);
    expect(requestErrorMessage('request failed', 503)).toBe(enShell.requestError.unavailable);
  });
});