Files
3x-ui/frontend/src/test/sub-app-icons.test.ts
T
Sanaei e26cf1d3ed feat(sub): redesign the subscription page around usage, tabs and app imports
The info page was a long key/value table followed by every link and two
app dropdowns, and it rendered left-to-right even for Persian and Arabic.
It now leads with a usage ring, the remaining quota and a stats grid, and
splits the rest into Subscription / Apps / Configs tabs.

- Status tells expired, data-used-up and disabled apart instead of one
  "Inactive", replacing the hard-coded English expiry chip.
- The Apps tab keeps every Android and iOS app with its existing deep
  link, preselects the visitor's platform and adds Windows: Hiddify and
  Clash Verge Rev import directly, v2rayN copies the link.
- fa-IR and ar-EG render right-to-left; URLs, IDs and sizes stay LTR.
- The footer shows the support link and the client refresh interval, so
  subPageContext now carries subUpdates (also in ?format=info).
- Status, days-left and app deep-link logic lives in subPageModel.ts,
  with unit tests pinning the deep links the page already shipped.
2026-09-16 01:55:56 +02:00

29 lines
970 B
TypeScript

import { describe, expect, it } from 'vitest';
import { APP_ICONS } from '@/pages/sub/appIcons';
import { buildSubApps } from '@/pages/sub/subPageModel';
describe('APP_ICONS', () => {
it('has an icon for every app the subscription page offers on every platform', () => {
const apps = buildSubApps({
subUrl: 'https://sub.example.com/sub/abc',
sId: 'abc',
subTitle: '',
});
const names = [...new Set(Object.values(apps).flatMap((list) => list.map((app) => app.name)))];
expect(names.filter((name) => !APP_ICONS[name]?.src)).toEqual([]);
});
it('carries no icon for an app the page no longer offers', () => {
const apps = buildSubApps({
subUrl: 'https://sub.example.com/sub/abc',
sId: 'abc',
subTitle: '',
});
const offered = new Set(Object.values(apps).flatMap((list) => list.map((app) => app.name)));
expect(Object.keys(APP_ICONS).filter((name) => !offered.has(name))).toEqual([]);
});
});