328 lines
11 KiB
TypeScript
328 lines
11 KiB
TypeScript
jest.mock('../storage', () => ({
|
|
setItem: jest.fn(() => Promise.resolve(true)),
|
|
getItem: jest.fn(() => Promise.resolve(false)),
|
|
removeItem: jest.fn(() => Promise.resolve(true))
|
|
}));
|
|
|
|
import {
|
|
handleEnableGraphSync,
|
|
handleIgnoreOnce,
|
|
handleNeverAskAgain,
|
|
checkGraphSyncBeforePayment,
|
|
savePendingPaymentData,
|
|
loadPendingPaymentData,
|
|
clearPendingPaymentData
|
|
} from './GraphSyncUtils';
|
|
|
|
import { settingsStore, transactionsStore } from '../stores/Stores';
|
|
|
|
import { restartNeeded } from './RestartUtils';
|
|
import storage from '../storage';
|
|
|
|
jest.mock('../stores/Stores', () => ({
|
|
settingsStore: {
|
|
updateSettings: jest.fn(),
|
|
embeddedLndNetwork: 'Mainnet'
|
|
},
|
|
transactionsStore: {
|
|
proceedWithPayment: jest.fn(),
|
|
pendingPaymentData: null,
|
|
showGraphSyncPrompt: false
|
|
}
|
|
}));
|
|
|
|
jest.mock('./RestartUtils', () => ({
|
|
restartNeeded: jest.fn()
|
|
}));
|
|
|
|
const mockSettingsStore = settingsStore as jest.Mocked<typeof settingsStore>;
|
|
const mockTransactionsStore = transactionsStore as jest.Mocked<
|
|
typeof transactionsStore
|
|
>;
|
|
const mockRestartNeeded = restartNeeded as jest.MockedFunction<
|
|
typeof restartNeeded
|
|
>;
|
|
const mockStorage = storage as jest.Mocked<typeof storage>;
|
|
|
|
describe('GraphSyncUtils', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
mockTransactionsStore.pendingPaymentData = null;
|
|
mockTransactionsStore.showGraphSyncPrompt = false;
|
|
});
|
|
|
|
describe('handleEnableGraphSync', () => {
|
|
it('should enable graph sync and trigger restart without pending data', async () => {
|
|
mockTransactionsStore.pendingPaymentData = null;
|
|
|
|
await handleEnableGraphSync();
|
|
|
|
expect(mockStorage.setItem).not.toHaveBeenCalled();
|
|
expect(mockSettingsStore.updateSettings).toHaveBeenCalledWith({
|
|
expressGraphSync: true,
|
|
graphSyncPromptIgnoreOnce: false
|
|
});
|
|
expect(mockRestartNeeded).toHaveBeenCalledWith(true);
|
|
});
|
|
|
|
it('should save pending payment data before restart', async () => {
|
|
const paymentData = { payment_request: 'lnbc123...' };
|
|
mockTransactionsStore.pendingPaymentData = paymentData;
|
|
|
|
await handleEnableGraphSync();
|
|
|
|
expect(mockStorage.setItem).toHaveBeenCalledWith(
|
|
'zeus-pending-payment-after-graph-sync',
|
|
JSON.stringify(paymentData)
|
|
);
|
|
expect(mockSettingsStore.updateSettings).toHaveBeenCalledWith({
|
|
expressGraphSync: true,
|
|
graphSyncPromptIgnoreOnce: false
|
|
});
|
|
expect(mockRestartNeeded).toHaveBeenCalledWith(true);
|
|
});
|
|
});
|
|
|
|
describe('handleIgnoreOnce', () => {
|
|
it('should set ignore once flag and proceed with payment', async () => {
|
|
await handleIgnoreOnce();
|
|
|
|
expect(mockSettingsStore.updateSettings).toHaveBeenCalledWith({
|
|
graphSyncPromptIgnoreOnce: true
|
|
});
|
|
expect(mockTransactionsStore.proceedWithPayment).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('handleNeverAskAgain', () => {
|
|
it('should set never ask flag and reset ignore once', async () => {
|
|
await handleNeverAskAgain();
|
|
|
|
expect(mockSettingsStore.updateSettings).toHaveBeenCalledWith({
|
|
graphSyncPromptNeverAsk: true,
|
|
graphSyncPromptIgnoreOnce: false
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('checkGraphSyncBeforePayment', () => {
|
|
const mockSettings = {
|
|
expressGraphSync: false,
|
|
graphSyncPromptNeverAsk: false,
|
|
graphSyncPromptIgnoreOnce: false
|
|
};
|
|
|
|
it('should return true for non-embedded nodes', () => {
|
|
const result = checkGraphSyncBeforePayment(
|
|
mockSettings,
|
|
'lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should return true and not show prompt on testnet', () => {
|
|
// Temporarily set to testnet
|
|
(mockSettingsStore as any).embeddedLndNetwork = 'Testnet';
|
|
|
|
const result = checkGraphSyncBeforePayment(
|
|
mockSettings,
|
|
'embedded-lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(result).toBe(true);
|
|
expect(mockTransactionsStore.showGraphSyncPrompt).toBe(false);
|
|
expect(mockTransactionsStore.pendingPaymentData).toBeNull();
|
|
|
|
// Restore to mainnet for other tests
|
|
(mockSettingsStore as any).embeddedLndNetwork = 'Mainnet';
|
|
});
|
|
|
|
it('should return true when graph sync is enabled', () => {
|
|
const settingsWithGraphSync = {
|
|
...mockSettings,
|
|
expressGraphSync: true
|
|
};
|
|
|
|
const result = checkGraphSyncBeforePayment(
|
|
settingsWithGraphSync,
|
|
'embedded-lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should return true when never ask is set', () => {
|
|
const settingsNeverAsk = {
|
|
...mockSettings,
|
|
graphSyncPromptNeverAsk: true
|
|
};
|
|
|
|
const result = checkGraphSyncBeforePayment(
|
|
settingsNeverAsk,
|
|
'embedded-lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should reset ignore once flag and show prompt when ignore once is set', () => {
|
|
const settingsIgnoreOnce = {
|
|
...mockSettings,
|
|
graphSyncPromptIgnoreOnce: true
|
|
};
|
|
|
|
const result = checkGraphSyncBeforePayment(
|
|
settingsIgnoreOnce,
|
|
'embedded-lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(mockSettingsStore.updateSettings).toHaveBeenCalledWith({
|
|
graphSyncPromptIgnoreOnce: false
|
|
});
|
|
expect(mockTransactionsStore.pendingPaymentData).toEqual({
|
|
payment_request: 'test'
|
|
});
|
|
expect(mockTransactionsStore.showGraphSyncPrompt).toBe(true);
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('should show prompt and return false when graph sync is disabled', () => {
|
|
const result = checkGraphSyncBeforePayment(
|
|
mockSettings,
|
|
'embedded-lnd',
|
|
{ payment_request: 'test' },
|
|
mockTransactionsStore
|
|
);
|
|
|
|
expect(mockTransactionsStore.pendingPaymentData).toEqual({
|
|
payment_request: 'test'
|
|
});
|
|
expect(mockTransactionsStore.showGraphSyncPrompt).toBe(true);
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('savePendingPaymentData', () => {
|
|
it('should save payment data to storage', async () => {
|
|
const paymentData = {
|
|
payment_request: 'lnbc123...',
|
|
amount: '1000'
|
|
};
|
|
|
|
await savePendingPaymentData(paymentData);
|
|
|
|
expect(mockStorage.setItem).toHaveBeenCalledWith(
|
|
'zeus-pending-payment-after-graph-sync',
|
|
JSON.stringify(paymentData)
|
|
);
|
|
});
|
|
|
|
it('should re-throw storage errors', async () => {
|
|
const consoleErrorSpy = jest
|
|
.spyOn(console, 'error')
|
|
.mockImplementation();
|
|
const storageError = new Error('Storage full');
|
|
mockStorage.setItem.mockRejectedValueOnce(storageError);
|
|
|
|
const paymentData = { payment_request: 'lnbc123...' };
|
|
|
|
await expect(savePendingPaymentData(paymentData)).rejects.toThrow(
|
|
'Storage full'
|
|
);
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
'Error saving pending payment data:',
|
|
storageError
|
|
);
|
|
|
|
consoleErrorSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('loadPendingPaymentData', () => {
|
|
it('should load and parse payment data from storage', async () => {
|
|
const paymentData = {
|
|
payment_request: 'lnbc123...',
|
|
amount: '1000'
|
|
};
|
|
mockStorage.getItem.mockResolvedValueOnce(
|
|
JSON.stringify(paymentData)
|
|
);
|
|
|
|
const result = await loadPendingPaymentData();
|
|
|
|
expect(mockStorage.getItem).toHaveBeenCalledWith(
|
|
'zeus-pending-payment-after-graph-sync'
|
|
);
|
|
expect(result).toEqual(paymentData);
|
|
});
|
|
|
|
it('should return null when no data is stored', async () => {
|
|
mockStorage.getItem.mockResolvedValueOnce(false);
|
|
|
|
const result = await loadPendingPaymentData();
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should handle storage errors gracefully', async () => {
|
|
const consoleErrorSpy = jest
|
|
.spyOn(console, 'error')
|
|
.mockImplementation();
|
|
mockStorage.getItem.mockRejectedValueOnce(
|
|
new Error('Storage error')
|
|
);
|
|
|
|
const result = await loadPendingPaymentData();
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
'Error loading pending payment data:',
|
|
expect.any(Error)
|
|
);
|
|
expect(result).toBeNull();
|
|
|
|
consoleErrorSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('clearPendingPaymentData', () => {
|
|
it('should remove payment data from storage', async () => {
|
|
await clearPendingPaymentData();
|
|
|
|
expect(mockStorage.removeItem).toHaveBeenCalledWith(
|
|
'zeus-pending-payment-after-graph-sync'
|
|
);
|
|
});
|
|
|
|
it('should re-throw removal errors', async () => {
|
|
const consoleErrorSpy = jest
|
|
.spyOn(console, 'error')
|
|
.mockImplementation();
|
|
const removalError = new Error('Removal failed');
|
|
mockStorage.removeItem.mockRejectedValueOnce(removalError);
|
|
|
|
await expect(clearPendingPaymentData()).rejects.toThrow(
|
|
'Removal failed'
|
|
);
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
'Error clearing pending payment data:',
|
|
removalError
|
|
);
|
|
|
|
consoleErrorSpy.mockRestore();
|
|
});
|
|
});
|
|
});
|