Skip to content

Commit

Permalink
feat: add unit test (#29)
Browse files Browse the repository at this point in the history
* feat: add unit test

* feat: add more test

* feat: add more tests

* fix: git conflicts

* fix: conflicts between unit test  and stellar sdk version

* feat: keep imports as default
  • Loading branch information
jimenezz22 authored Nov 5, 2024
1 parent 2086cc3 commit 1528826
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 7 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
"format": "prettier --plugin-search-dir . --write .",
"test": "vitest"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
Expand Down Expand Up @@ -48,4 +49,4 @@
"vite": "^5.4.8"
},
"type": "module"
}
}
11 changes: 6 additions & 5 deletions src/lib/stellar/horizonQueries.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// @ts-nocheck
import { error } from '@sveltejs/kit'
import { TransactionBuilder, Networks, StrKey, Asset, Horizon } from '@stellar/stellar-sdk'
import { Server, TransactionBuilder, Networks, StrKey, Asset, Horizon } from '@stellar/stellar-sdk'

const horizonUrl = 'https://horizon-testnet.stellar.org';
export const server = new Horizon.Server(horizonUrl);

const horizonUrl = 'https://horizon-testnet.stellar.org'
const server = new Horizon.Server(horizonUrl)

/**
* @module $lib/stellar/horizonQueries
Expand Down Expand Up @@ -40,7 +42,6 @@ export async function fetchAccount(publicKey) {
if (err.response?.status === 404) {
try {
await fundWithFriendbot(publicKey)

let account = await server.accounts().accountId(publicKey).call()
return account
} catch (err) {
Expand Down Expand Up @@ -227,4 +228,4 @@ export async function findStrictReceivePaths({
} else {
throw error(400, { message: 'no strict receive paths available' })
}
}
}
77 changes: 77 additions & 0 deletions src/lib/test/fetchAccount.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { fetchAccount } from '../stellar/horizonQueries';

vi.mock('@sveltejs/kit', () => {
return {
// @ts-ignore
error: (status, { message }) => {
const err = new Error(message);
// @ts-ignore
err.status = status;
// @ts-ignore
err.body = { message };
return err;
},
};
});

vi.mock('@stellar/stellar-sdk', () => {
const mockServerInstance = {
accounts: () => ({
accountId: () => ({
call: vi.fn().mockResolvedValue({
id: 'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB',
balances: [],
}),
}),
}),
};

const Horizon = {
Server: vi.fn(() => mockServerInstance),
};

return {
Horizon,
StrKey: {
isValidEd25519PublicKey: vi.fn().mockReturnValue(true),
},
};
});

describe('fetchAccount', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('should return account info for a valid public key', async () => {
const publicKey = 'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB';
const mockServerResponse = {
id: publicKey,
balances: [],
};

const { Horizon } = await import('@stellar/stellar-sdk');
// @ts-ignore
Horizon.Server.mockImplementation(() => ({
accounts: () => ({
accountId: () => ({
call: vi.fn().mockResolvedValue(mockServerResponse),
}),
}),
}));

const accountInfo = await fetchAccount(publicKey);
expect(accountInfo).toEqual(mockServerResponse);
});

it('should throw an error for an invalid public key', async () => {
const invalidPublicKey = 'INVALID_KEY';

const { StrKey } = await import('@stellar/stellar-sdk');
// @ts-ignore
StrKey.isValidEd25519PublicKey.mockReturnValue(false);

await expect(fetchAccount(invalidPublicKey)).rejects.toThrow('invalid public key');
});
});
46 changes: 46 additions & 0 deletions src/lib/test/fetchRecentPayments.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, it, expect, vi } from 'vitest';
import { fetchRecentPayments } from '../stellar/horizonQueries';

const callMock = vi.fn().mockResolvedValue({
records: [
{ id: '1', type: 'payment', amount: '100' },
{ id: '2', type: 'payment', amount: '200' },
],
});

vi.mock('@stellar/stellar-sdk', () => {
const Server = vi.fn().mockImplementation(() => ({
payments: () => ({
forAccount: () => ({
limit: () => ({
order: () => ({
call: callMock,
}),
}),
}),
}),
}));

return {
Horizon: { Server },
StrKey: {
isValidEd25519PublicKey: vi.fn().mockReturnValue(true),
},
};
});

describe('fetchRecentPayments', () => {
it('should return an array of recent payments for a valid public key', async () => {
const publicKey = 'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB';
const limit = 5;

const payments = await fetchRecentPayments(publicKey, limit);

expect(payments).toEqual([
{ id: '1', type: 'payment', amount: '100' },
{ id: '2', type: 'payment', amount: '200' },
]);

expect(callMock).toHaveBeenCalled();
});
});
70 changes: 70 additions & 0 deletions src/lib/test/findStrictReceivePaths.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { describe, it, expect, vi } from 'vitest';
import { findStrictReceivePaths, server } from '../stellar/horizonQueries';

vi.restoreAllMocks();

vi.mock('@sveltejs/kit', () => {
return {
// @ts-ignore
error: (status, { message }) => {
const err = new Error(message);
// @ts-ignore
err.status = status;
// @ts-ignore
err.body = { message };
return err;
},
};
});

vi.mock('@stellar/stellar-sdk', async () => {
const actual = await vi.importActual('@stellar/stellar-sdk');

return {
...actual,
};
});


const mockStrictReceivePaths = vi.fn();
server.strictReceivePaths = mockStrictReceivePaths;

describe('findStrictReceivePaths', () => {
it('should return valid payment paths if available', async () => {
const mockResponse = {
records: [
{
source_amount: '100',
destination_amount: '10',
destination_asset: 'native',
},
],
};

mockStrictReceivePaths.mockReturnValue({
call: vi.fn().mockResolvedValue(mockResponse),
});

const result = await findStrictReceivePaths({
sourcePublicKey: 'GXXXXXXXXXXXXX',
destinationAsset: 'native',
destinationAmount: 10,
});

expect(result).toEqual(mockResponse.records);
});

it('should throw an error if no payment paths are available', async () => {
mockStrictReceivePaths.mockReturnValue({
call: vi.fn().mockResolvedValue({ records: [] }),
});

await expect(
findStrictReceivePaths({
sourcePublicKey: 'GXXXXXXXXXXXXX',
destinationAsset: 'native',
destinationAmount: 10,
})
).rejects.toThrow('no strict receive paths available');
});
});
41 changes: 41 additions & 0 deletions src/lib/test/findStrictSendPaths.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, it, expect, vi } from 'vitest';
import { findStrictSendPaths, server } from '../stellar/horizonQueries';
import { Asset } from 'stellar-sdk';

const mockServer = {
strictSendPaths: vi.fn().mockReturnThis(),
call: vi.fn(),
};

mockServer.strictSendPaths.mockImplementation(() => ({
call: mockServer.call
}));

server.strictSendPaths = mockServer.strictSendPaths;

describe('findStrictSendPaths', () => {
it('should return valid payment paths when available', async () => {
const mockResponse = {
records: [
{ id: 1, path: 'path1' },
{ id: 2, path: 'path2' }
]
};

mockServer.call.mockResolvedValue(mockResponse);

const sourceAsset = 'native';
const sourceAmount = 100;
const destinationPublicKey = 'GD6OW23WYT...';

const result = await findStrictSendPaths({
sourceAsset,
sourceAmount,
destinationPublicKey
});

expect(result).toEqual(mockResponse.records);
expect(mockServer.strictSendPaths).toHaveBeenCalledWith(Asset.native(), sourceAmount.toString(), destinationPublicKey);
expect(mockServer.call).toHaveBeenCalled();
});
});
55 changes: 55 additions & 0 deletions src/lib/test/fundWithFriendbot.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, it, expect, vi } from 'vitest';
import { fundWithFriendbot, server } from '../stellar/horizonQueries';

describe('fundWithFriendbot', () => {
it('should call friendbot to fund the account with the given public key', async () => {
const publicKey = 'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB';

const callMock = vi.fn().mockResolvedValue(true);

const friendbotMock = vi
.spyOn(server, 'friendbot')
.mockReturnValue({
call: callMock,
// @ts-ignore
url: undefined,
filter: [],
originalSegments: [],
neighborRoot: '',
stream: function (options) {
throw new Error('Function not implemented.');
},
cursor: function (cursor) {
throw new Error('Function not implemented.');
},
limit: function (recordsNumber) {
throw new Error('Function not implemented.');
},
order: function (direction) {
throw new Error('Function not implemented.');
},
join: function (include) {
throw new Error('Function not implemented.');
},
forEndpoint: function (endpoint, param) {
throw new Error('Function not implemented.');
},
checkFilter: undefined,
_requestFnForLink: undefined,
_parseRecord: undefined,
_sendNormalRequest: undefined,
_parseResponse: undefined,
_toCollectionPage: undefined,
_handleNetworkError: undefined
});

await fundWithFriendbot(publicKey);

expect(friendbotMock).toHaveBeenCalledWith(publicKey);

expect(callMock).toHaveBeenCalled();

friendbotMock.mockRestore();
});
});

56 changes: 56 additions & 0 deletions src/lib/test/startTransaction.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { describe, it, expect, vi } from 'vitest';

const addOperationMock = vi.fn().mockReturnThis();
const addMemoMock = vi.fn().mockReturnThis();
const setTimeoutMock = vi.fn().mockReturnThis();
const buildMock = vi.fn().mockReturnThis();
const loadAccountMock = vi.fn().mockResolvedValue({
accountId: 'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB',
sequence: '1',
});

vi.mock('@stellar/stellar-sdk', () => {
return {
TransactionBuilder: vi.fn().mockImplementation(() => ({
addOperation: addOperationMock,
addMemo: addMemoMock,
setTimeout: setTimeoutMock,
build: buildMock,
})),
Horizon: {
Server: vi.fn().mockImplementation(() => ({
loadAccount: loadAccountMock,
})),
},
Networks: {
TESTNET: 'Test SDF Network ; September 2015',
},
};
});

describe('startTransaction', () => {
it('should initialize a transaction with the correct settings', async () => {
const { startTransaction } = await import('../stellar/horizonQueries');

const sourcePublicKey =
'GA3D5NJZSHR2F7MFXO2QZ4QNNIWMY6KLY2MNZVEWEBCMBQ4Y2JRGK2JB';

const transaction = await startTransaction(sourcePublicKey);

expect(loadAccountMock).toHaveBeenCalledWith(sourcePublicKey);

const { TransactionBuilder } = await import('@stellar/stellar-sdk');
expect(TransactionBuilder).toHaveBeenCalledWith(
{ accountId: sourcePublicKey, sequence: '1' },
{
networkPassphrase: 'Test SDF Network ; September 2015',
fee: '100000',
}
);

expect(transaction.addOperation).not.toHaveBeenCalled();
expect(transaction.addMemo).not.toHaveBeenCalled();
expect(transaction.setTimeout).not.toHaveBeenCalled();
expect(transaction.build).not.toHaveBeenCalled();
});
});
Loading

0 comments on commit 1528826

Please sign in to comment.