mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
feat(subscription): API и утилиты СБП-автопродления Platega
This commit is contained in:
109
src/utils/sbpRecurring.test.ts
Normal file
109
src/utils/sbpRecurring.test.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { SbpRecurringInfo } from '../types';
|
||||
import { isSbpFeatureDisabledError, sbpIntervalLabelKey, sbpUiState } from './sbpRecurring';
|
||||
|
||||
/**
|
||||
* Утилиты для СБП-автопродления (Platega recurrent). Бэк отдаёт GET-статусы
|
||||
* только 'none' | 'PENDING' | 'ACTIVE' | 'PAST_DUE' (CANCELLED/FAILED — это
|
||||
* терминальные состояния, до которых GET не доживает: запись либо удаляется,
|
||||
* либо переоткрывается новым PENDING). UI на неизвестный статус должен
|
||||
* деградировать в 'off', а не падать.
|
||||
*/
|
||||
|
||||
describe('sbpIntervalLabelKey', () => {
|
||||
it.each([
|
||||
[1, 'subscription.sbpRecurring.interval.day'],
|
||||
[2, 'subscription.sbpRecurring.interval.week'],
|
||||
[3, 'subscription.sbpRecurring.interval.month'],
|
||||
[4, 'subscription.sbpRecurring.interval.year'],
|
||||
[undefined, 'subscription.sbpRecurring.interval.month'],
|
||||
[99, 'subscription.sbpRecurring.interval.month'],
|
||||
])('interval=%s -> %s', (interval, expected) => {
|
||||
expect(sbpIntervalLabelKey(interval as number | undefined)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSbpFeatureDisabledError', () => {
|
||||
it('403 + detail ровно "Platega recurrent disabled" -> true', () => {
|
||||
const error = {
|
||||
response: { status: 403, data: { detail: 'Platega recurrent disabled' } },
|
||||
};
|
||||
expect(isSbpFeatureDisabledError(error)).toBe(true);
|
||||
});
|
||||
|
||||
it('неверный статус (404) -> false', () => {
|
||||
const error = {
|
||||
response: { status: 404, data: { detail: 'Platega recurrent disabled' } },
|
||||
};
|
||||
expect(isSbpFeatureDisabledError(error)).toBe(false);
|
||||
});
|
||||
|
||||
it('неверный текст detail -> false', () => {
|
||||
const error = {
|
||||
response: { status: 403, data: { detail: 'Something else' } },
|
||||
};
|
||||
expect(isSbpFeatureDisabledError(error)).toBe(false);
|
||||
});
|
||||
|
||||
it('detail — объект (другая форма 403), не должно падать -> false', () => {
|
||||
const error = {
|
||||
response: { status: 403, data: { detail: { code: 'blacklisted', message: 'x' } } },
|
||||
};
|
||||
expect(isSbpFeatureDisabledError(error)).toBe(false);
|
||||
});
|
||||
|
||||
it('null error -> false, без исключений', () => {
|
||||
expect(isSbpFeatureDisabledError(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('произвольный не-axios объект -> false, без исключений', () => {
|
||||
expect(isSbpFeatureDisabledError({ foo: 'bar' })).toBe(false);
|
||||
});
|
||||
|
||||
it('undefined -> false', () => {
|
||||
expect(isSbpFeatureDisabledError(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
it('строка вместо объекта ошибки -> false', () => {
|
||||
expect(isSbpFeatureDisabledError('plain string error')).toBe(false);
|
||||
});
|
||||
|
||||
it('response без data -> false, без исключений', () => {
|
||||
expect(isSbpFeatureDisabledError({ response: { status: 403 } })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sbpUiState', () => {
|
||||
const info = (overrides: Partial<SbpRecurringInfo>): SbpRecurringInfo => ({
|
||||
status: 'none',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('фича отключена -> "hidden", даже если данные есть', () => {
|
||||
expect(sbpUiState(info({ status: 'ACTIVE' }), true)).toBe('hidden');
|
||||
});
|
||||
|
||||
it('info === undefined -> "off"', () => {
|
||||
expect(sbpUiState(undefined, false)).toBe('off');
|
||||
});
|
||||
|
||||
it('status \'none\' -> "off"', () => {
|
||||
expect(sbpUiState(info({ status: 'none' }), false)).toBe('off');
|
||||
});
|
||||
|
||||
it('status \'PENDING\' -> "pending"', () => {
|
||||
expect(sbpUiState(info({ status: 'PENDING' }), false)).toBe('pending');
|
||||
});
|
||||
|
||||
it('status \'ACTIVE\' -> "active"', () => {
|
||||
expect(sbpUiState(info({ status: 'ACTIVE' }), false)).toBe('active');
|
||||
});
|
||||
|
||||
it('status \'PAST_DUE\' -> "past_due"', () => {
|
||||
expect(sbpUiState(info({ status: 'PAST_DUE' }), false)).toBe('past_due');
|
||||
});
|
||||
|
||||
it('неизвестный статус \'CANCELLED\' -> "off"', () => {
|
||||
expect(sbpUiState(info({ status: 'CANCELLED' }), false)).toBe('off');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user