added tests
This commit is contained in:
183
frontend/src/store/licenseStore.test.ts
Normal file
183
frontend/src/store/licenseStore.test.ts
Normal file
@ -0,0 +1,183 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { useLicenseStore } from './licenseStore';
|
||||
|
||||
|
||||
function mockElectronAPI(overrides: Record<string, any> = {}) {
|
||||
(window as any).electronAPI = {
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Expired' }),
|
||||
activateLicense: vi.fn().mockResolvedValue(null),
|
||||
deactivateLicense: vi.fn().mockResolvedValue(undefined),
|
||||
hasLicenseFeature: vi.fn().mockResolvedValue(false),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('licenseStore', () => {
|
||||
beforeEach(() => {
|
||||
mockElectronAPI();
|
||||
useLicenseStore.setState({ status: null, isLoaded: false, canEdit: true, showDialog: false });
|
||||
});
|
||||
|
||||
describe('canEdit', () => {
|
||||
test('is true for Licensed status', async () => {
|
||||
mockElectronAPI({
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Licensed', license: { license_id: 'x', tier: 'pro' } }),
|
||||
});
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().canEdit).toBe(true);
|
||||
});
|
||||
|
||||
test('is true for Trial status', async () => {
|
||||
mockElectronAPI({
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Trial', days_remaining: 20, started_at: Date.now() }),
|
||||
});
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().canEdit).toBe(true);
|
||||
});
|
||||
|
||||
test('is false for Expired status', async () => {
|
||||
mockElectronAPI({
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Expired' }),
|
||||
});
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
|
||||
test('is false when status is null', () => {
|
||||
useLicenseStore.setState({ status: null, canEdit: true });
|
||||
useLicenseStore.getState().setStatus(null);
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkStatus', () => {
|
||||
test('sets status to Licensed when backend returns Licensed', async () => {
|
||||
const license = { license_id: 'l1', tier: 'pro', customer_email: 'a@b.com', expires_at: 9999999999, features: [], issued_at: 1, max_activations: 1 };
|
||||
mockElectronAPI({ getAppStatus: vi.fn().mockResolvedValue({ tag: 'Licensed', license }) });
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Licensed');
|
||||
});
|
||||
|
||||
test('sets status to Trial when backend returns Trial', async () => {
|
||||
mockElectronAPI({ getAppStatus: vi.fn().mockResolvedValue({ tag: 'Trial', days_remaining: 15, started_at: Date.now() }) });
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Trial');
|
||||
});
|
||||
|
||||
test('sets status to Expired when backend returns Expired', async () => {
|
||||
mockElectronAPI({ getAppStatus: vi.fn().mockResolvedValue({ tag: 'Expired' }) });
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Expired');
|
||||
});
|
||||
|
||||
test('handles API error gracefully', async () => {
|
||||
mockElectronAPI({ getAppStatus: vi.fn().mockRejectedValue(new Error('network error')) });
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Expired');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
|
||||
test('handles missing electronAPI', async () => {
|
||||
delete (window as any).electronAPI;
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Expired');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
|
||||
test('sets isLoaded to true after check', async () => {
|
||||
await useLicenseStore.getState().checkStatus();
|
||||
expect(useLicenseStore.getState().isLoaded).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activateLicense', () => {
|
||||
test('sets Licensed on valid key', async () => {
|
||||
const license = { license_id: 'l2', tier: 'pro', customer_email: 'x@y.com', expires_at: 9999999999, features: ['bg_removal'], issued_at: 1, max_activations: 1 };
|
||||
mockElectronAPI({ activateLicense: vi.fn().mockResolvedValue(license) });
|
||||
const result = await useLicenseStore.getState().activateLicense('talkedit_v1_validKey');
|
||||
expect(result).toBe(true);
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Licensed');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(true);
|
||||
});
|
||||
|
||||
test('returns false on invalid key', async () => {
|
||||
mockElectronAPI({ activateLicense: vi.fn().mockResolvedValue(null) });
|
||||
const result = await useLicenseStore.getState().activateLicense('invalid-key');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test('returns false on API error', async () => {
|
||||
mockElectronAPI({ activateLicense: vi.fn().mockRejectedValue(new Error('bad key')) });
|
||||
const result = await useLicenseStore.getState().activateLicense('bad-key');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test('closes dialog on success', async () => {
|
||||
useLicenseStore.setState({ showDialog: true });
|
||||
const license = { license_id: 'l3', tier: 'business', customer_email: 'z@z.com', expires_at: 9999999999, features: [], issued_at: 1, max_activations: 5 };
|
||||
mockElectronAPI({ activateLicense: vi.fn().mockResolvedValue(license) });
|
||||
await useLicenseStore.getState().activateLicense('talkedit_v1_key');
|
||||
expect(useLicenseStore.getState().showDialog).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deactivateLicense', () => {
|
||||
test('sets Expired when trial is over', async () => {
|
||||
mockElectronAPI({
|
||||
deactivateLicense: vi.fn().mockResolvedValue(undefined),
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Expired' }),
|
||||
});
|
||||
await useLicenseStore.getState().deactivateLicense();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Expired');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
|
||||
test('restores Trial when trial is still valid', async () => {
|
||||
mockElectronAPI({
|
||||
deactivateLicense: vi.fn().mockResolvedValue(undefined),
|
||||
getAppStatus: vi.fn().mockResolvedValue({ tag: 'Trial', days_remaining: 5, started_at: Date.now() }),
|
||||
});
|
||||
await useLicenseStore.getState().deactivateLicense();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Trial');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(true);
|
||||
});
|
||||
|
||||
test('handles API error', async () => {
|
||||
mockElectronAPI({ deactivateLicense: vi.fn().mockRejectedValue(new Error('fail')) });
|
||||
useLicenseStore.setState({ status: { tag: 'Licensed', license: {} as any }, canEdit: true });
|
||||
await useLicenseStore.getState().deactivateLicense();
|
||||
expect(useLicenseStore.getState().status?.tag).toBe('Expired');
|
||||
expect(useLicenseStore.getState().canEdit).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasFeature', () => {
|
||||
test('returns true when feature exists', async () => {
|
||||
mockElectronAPI({ hasLicenseFeature: vi.fn().mockResolvedValue(true) });
|
||||
const result = await useLicenseStore.getState().hasFeature('bg_removal');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test('returns false when feature missing', async () => {
|
||||
mockElectronAPI({ hasLicenseFeature: vi.fn().mockResolvedValue(false) });
|
||||
const result = await useLicenseStore.getState().hasFeature('nonexistent');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test('returns false on API error', async () => {
|
||||
mockElectronAPI({ hasLicenseFeature: vi.fn().mockRejectedValue(new Error('fail')) });
|
||||
const result = await useLicenseStore.getState().hasFeature('bg_removal');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setShowDialog', () => {
|
||||
test('toggles dialog', () => {
|
||||
useLicenseStore.getState().setShowDialog(true);
|
||||
expect(useLicenseStore.getState().showDialog).toBe(true);
|
||||
useLicenseStore.getState().setShowDialog(false);
|
||||
expect(useLicenseStore.getState().showDialog).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user