Files
NeoTachyon/fe-app-tachyon/src/tachyon/services/tests/uiState.service.test.ts
T

430 lines
11 KiB
TypeScript

import { beforeEach, describe, expect, it } from 'vitest';
import { applyUiStateToStore } from '../uiState.service';
import { store } from '../store.service';
import { Tachyon } from '../../types';
import {
clearLocalActionOverlay,
setLocalComponentAction,
setLocalLatencyAction,
setLocalServiceAction,
setLocalSubscriptionAction,
} from '../localActionOverlay.service';
function createUiState(
actions: Partial<Tachyon.UiState['actions']> = {},
capabilities: Partial<Tachyon.UiState['capabilities']> = {},
): Tachyon.UiState {
return {
service: {
tachyon: {
running: 0,
enabled: 1,
status: 'starting',
dns_configured: 0,
},
sing_box: {
running: 0,
enabled: 1,
status: 'stopped but enabled',
},
},
capabilities: {
sing_box_extended: 1,
sing_box_tiny: 0,
sing_box_compressed: 0,
sing_box_tailscale: 1,
zapret_installed: 1,
zapret2_installed: 0,
byedpi_installed: 1,
server_inbounds_enabled_count: 0,
...capabilities,
},
actions: {
service: [],
latency: [],
component: [],
subscription: [],
...actions,
},
};
}
describe('applyUiStateToStore', () => {
beforeEach(() => {
clearLocalActionOverlay();
store.reset();
});
it('applies service, capability, and running action state before first render', () => {
applyUiStateToStore(
createUiState({
service: [
{
success: true,
running: true,
kind: 'service',
action: 'start',
job_id: 'service-1',
},
],
subscription: [
{
success: true,
running: true,
job_id: 'subscription-1',
section: 'main',
message: 'Subscription update is running',
},
],
latency: [
{
success: true,
running: true,
kind: 'latency',
latency_type: 'group',
section: 'main',
tag: 'AUTO',
job_id: 'latency-1',
progress: {
completed: 2,
total: 5,
failed: 1,
},
},
],
component: [
{
success: true,
running: true,
job_id: 'component-1',
component: 'zapret',
action: 'install',
message: 'Install is running',
current_version: '',
latest_version: '',
changed: false,
},
],
}),
);
const state = store.get();
expect(state.servicesInfoWidget).toMatchObject({
loading: false,
failed: false,
data: {
tachyonEnabled: 1,
tachyonRunning: 0,
tachyonStatus: 'starting',
},
});
expect(state.diagnosticsSystemInfo).toMatchObject({
providerInfoLoaded: true,
sing_box_extended: 1,
zapret_installed: 1,
zapret2_installed: 0,
byedpi_installed: 1,
server_inbounds_enabled_count: 0,
});
expect(state.diagnosticsActions.start.loading).toBe(true);
expect(state.sectionsWidget.subscriptionUpdatingSections).toEqual({
main: true,
});
expect(state.sectionsWidget.latencyFetchingSections).toEqual({
main: true,
});
expect(state.sectionsWidget.latencyProgressSections).toEqual({
main: {
completed: 2,
total: 5,
failed: 1,
},
});
expect(state.updatesActions.zapretInstall.loading).toBe(true);
});
it('clears finished persisted action flags while preserving local enable actions', () => {
store.set({
diagnosticsActions: {
...store.get().diagnosticsActions,
start: { loading: true },
enable: { loading: true },
},
sectionsWidget: {
...store.get().sectionsWidget,
subscriptionUpdatingSections: { main: true },
latencyFetchingSections: { main: true },
latencyProgressSections: {
main: {
completed: 1,
total: 2,
failed: 0,
},
},
},
updatesActions: {
...store.get().updatesActions,
zapretInstall: { loading: true },
},
});
applyUiStateToStore(createUiState());
const state = store.get();
expect(state.diagnosticsActions.start.loading).toBe(false);
expect(state.diagnosticsActions.enable.loading).toBe(true);
expect(state.sectionsWidget.subscriptionUpdatingSections).toEqual({});
expect(state.sectionsWidget.latencyFetchingSections).toEqual({});
expect(state.sectionsWidget.latencyProgressSections).toEqual({});
expect(state.updatesActions.zapretInstall.loading).toBe(false);
});
it('keeps locally started actions loading until their owner clears them', () => {
setLocalComponentAction('zapretInstall', true);
setLocalSubscriptionAction('proxy', true);
setLocalLatencyAction('gemini', true);
setLocalServiceAction('restart', true);
applyUiStateToStore(createUiState());
expect(store.get().updatesActions.zapretInstall.loading).toBe(true);
expect(store.get().sectionsWidget.subscriptionUpdatingSections).toEqual({
proxy: true,
});
expect(store.get().sectionsWidget.latencyFetchingSections).toEqual({
gemini: true,
});
expect(store.get().diagnosticsActions.restart.loading).toBe(true);
clearLocalActionOverlay();
applyUiStateToStore(createUiState());
expect(store.get().updatesActions.zapretInstall.loading).toBe(false);
expect(store.get().sectionsWidget.subscriptionUpdatingSections).toEqual({});
expect(store.get().sectionsWidget.latencyFetchingSections).toEqual({});
expect(store.get().diagnosticsActions.restart.loading).toBe(false);
});
it('preserves local latency progress while waiting for runtime progress', () => {
setLocalLatencyAction('gemini', true);
store.set({
sectionsWidget: {
...store.get().sectionsWidget,
latencyFetchingSections: { gemini: true },
latencyProgressSections: {
gemini: {
completed: 0,
total: 3,
failed: 0,
},
},
},
});
applyUiStateToStore(createUiState());
expect(store.get().sectionsWidget.latencyFetchingSections).toEqual({
gemini: true,
});
expect(store.get().sectionsWidget.latencyProgressSections).toEqual({
gemini: {
completed: 0,
total: 3,
failed: 0,
},
});
});
it('preserves latency progress for running runtime actions without progress', () => {
store.set({
sectionsWidget: {
...store.get().sectionsWidget,
latencyFetchingSections: { main: true },
latencyProgressSections: {
main: {
completed: 2,
total: 5,
failed: 0,
},
},
},
});
applyUiStateToStore(
createUiState({
latency: [
{
success: true,
running: true,
kind: 'latency',
latency_type: 'proxy_list',
section: 'main',
tag: '["one","two"]',
job_id: 'latency-1',
},
],
}),
);
expect(store.get().sectionsWidget.latencyFetchingSections).toEqual({
main: true,
});
expect(store.get().sectionsWidget.latencyProgressSections).toEqual({
main: {
completed: 2,
total: 5,
failed: 0,
},
});
});
it('maps a running reload action to the restart control', () => {
applyUiStateToStore(
createUiState({
service: [
{
success: true,
running: true,
kind: 'service',
action: 'reload',
job_id: 'service-reload',
},
],
}),
);
expect(store.get().diagnosticsActions.restart.loading).toBe(true);
});
it('does not combine a stale extended version with tiny capabilities', () => {
store.set({
diagnosticsSystemInfo: {
...store.get().diagnosticsSystemInfo,
sing_box_version: '1.13.12-extended-2.3.2',
sing_box_extended: 1,
sing_box_tiny: 0,
},
});
applyUiStateToStore(
createUiState(undefined, {
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 0,
}),
);
expect(store.get().diagnosticsSystemInfo).toMatchObject({
sing_box_version: '1.13.12-extended-2.3.2',
sing_box_extended: 1,
sing_box_tiny: 0,
sing_box_tailscale: 1,
});
});
it('keeps current sing-box variant while a different sing-box install action is running', () => {
store.set({
diagnosticsSystemInfo: {
...store.get().diagnosticsSystemInfo,
providerInfoLoaded: true,
sing_box_version: '1.12.25',
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 1,
zapret_installed: 0,
zapret2_installed: 0,
byedpi_installed: 1,
server_inbounds_enabled_count: 0,
},
});
applyUiStateToStore(
createUiState(
{
component: [
{
success: true,
running: true,
job_id: 'sing-box-install',
component: 'sing_box',
action: 'install_extended_compressed',
message: 'Install is running',
current_version: '',
latest_version: '',
changed: false,
},
],
},
{
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 0,
zapret_installed: 1,
zapret2_installed: 1,
byedpi_installed: 0,
server_inbounds_enabled_count: 2,
},
),
);
expect(store.get().diagnosticsSystemInfo).toMatchObject({
providerInfoLoaded: true,
sing_box_version: '1.12.25',
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 0,
zapret_installed: 1,
zapret2_installed: 1,
byedpi_installed: 0,
server_inbounds_enabled_count: 2,
});
expect(
store.get().updatesActions.singBoxInstallExtendedCompressed.loading,
).toBe(true);
});
it('marks the running sing-box install action without pretending it is installed', () => {
applyUiStateToStore(
createUiState(
{
component: [
{
success: true,
running: true,
job_id: 'sing-box-install',
component: 'sing_box',
action: 'install_extended',
message: 'Install is running',
current_version: '',
latest_version: '',
changed: false,
},
],
},
{
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 0,
},
),
);
expect(store.get().diagnosticsSystemInfo).toMatchObject({
sing_box_extended: 0,
sing_box_tiny: 1,
sing_box_compressed: 0,
sing_box_tailscale: 0,
});
expect(store.get().updatesActions.singBoxInstallExtended.loading).toBe(
true,
);
});
});