Skip to content

Commit

Permalink
Merge pull request #103 from Dprof-in-tech/feat-write-tests
Browse files Browse the repository at this point in the history
Added frontend testing using Jest
  • Loading branch information
djeck1432 authored Oct 26, 2024
2 parents 6f013c6 + be4898d commit 2a58305
Show file tree
Hide file tree
Showing 15 changed files with 686 additions and 71 deletions.
3 changes: 1 addition & 2 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ You may also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
This launches the tests using the node environment provisioned by jest. After running the initial setup and the app is runnign , open another terminal shell, cd into the frontend directory and then run npm test.

### `npm run build`

Expand Down
4 changes: 4 additions & 0 deletions frontend/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-react'],
};

14 changes: 14 additions & 0 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
setupFiles: ['./jest.setup.js'],
transform: {
'^.+\\.[tj]sx?$': 'babel-jest', // Using Babel for transforming JS, JSX, TS, and TSX
},
moduleNameMapper: {
'\\.svg$': '<rootDir>/test/__mocks__/svgMock.js',
},
transformIgnorePatterns: [
'node_modules/(?!(axios|get-starknet)/)' // Ignore transforming node_modules
],

testEnvironment: 'jsdom', // Use node as the test environment
};
4 changes: 4 additions & 0 deletions frontend/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { TextEncoder, TextDecoder } from 'util';

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
18 changes: 12 additions & 6 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.7",
Expand All @@ -13,21 +12,20 @@
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.2",
"react-scripts": "^5.0.1",
"starknet": "^6.11.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "jest",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:8000",
"eslintConfig": {
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"ecmaVersion": 2020,
"sourceType": "module"
},
"extends": [
"react-app",
"react-app/jest"
Expand All @@ -44,5 +42,13 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/preset-env": "^7.25.9",
"@testing-library/jest-dom": "^6.6.2",
"@types/jest": "^29.5.14",
"babel-jest": "^29.7.0",
"jest": "^27.5.1",
"starknet": "^6.11.0"
}
}
136 changes: 73 additions & 63 deletions frontend/src/utils/wallet.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import {connect} from 'get-starknet';
import {ETH_ADDRESS, STRK_ADDRESS, USDC_ADDRESS } from "./constants";
import { ReactComponent as ETH } from '../assets/icons/ethereum.svg';
import { ReactComponent as USDC } from '../assets/icons/borrow_usdc.svg';
import { ReactComponent as STRK } from '../assets/icons/strk.svg';
import { ReactComponent as DAI } from '../assets/icons/dai.svg';

import { connect } from "get-starknet";
import { ETH_ADDRESS, STRK_ADDRESS, USDC_ADDRESS } from "./constants";
import { ReactComponent as ETH } from "../assets/icons/ethereum.svg";
import { ReactComponent as USDC } from "../assets/icons/borrow_usdc.svg";
import { ReactComponent as STRK } from "../assets/icons/strk.svg";
import { ReactComponent as DAI } from "../assets/icons/dai.svg";

const handleConnectWallet = async (setWalletId, setError) => {
try {
setError(null);
const address = await connectWallet();
if (address) {
setWalletId(address);
}
} catch (err) {
console.error("Failed to connect wallet:", err);
setError(err.message);
try {
setError(null);
const address = await connectWallet();
if (address) {
setWalletId(address);
}
} catch (err) {
console.error("Failed to connect wallet:", err);
setError(err.message);
}
};

export const connectWallet = async () => {
try {
console.log("Attempting to connect to wallet...");

const starknet = await connect({
modalMode: 'alwaysAsk',
modalTheme: 'light',
modalMode: "alwaysAsk",
modalTheme: "light",
});

if (!starknet) {
Expand All @@ -48,54 +47,53 @@ export const connectWallet = async () => {
}
};


export function logout() {
// Clear local storage
localStorage.removeItem('wallet_id');
// Clear local storage
localStorage.removeItem("wallet_id");
}

export async function getTokenBalances(walletAddress) {
try {
const starknet = await connect();
if (!starknet.isConnected) {
throw new Error("Wallet not connected");
}

const tokenBalances = {
ETH: await getTokenBalance(starknet, walletAddress, ETH_ADDRESS),
USDC: await getTokenBalance(starknet, walletAddress, USDC_ADDRESS),
STRK: await getTokenBalance(starknet, walletAddress, STRK_ADDRESS)
};

return tokenBalances;
} catch (error) {
console.error("Error fetching token balances:", error);
throw error;
try {
const starknet = await connect();
if (!starknet.isConnected) {
throw new Error("Wallet not connected");
}

const tokenBalances = {
ETH: await getTokenBalance(starknet, walletAddress, ETH_ADDRESS),
USDC: await getTokenBalance(starknet, walletAddress, USDC_ADDRESS),
STRK: await getTokenBalance(starknet, walletAddress, STRK_ADDRESS),
};

return tokenBalances;
} catch (error) {
console.error("Error fetching token balances:", error);
throw error;
}
}

async function getTokenBalance(starknet, walletAddress, tokenAddress) {
try {
const response = await starknet.provider.callContract({
contractAddress: tokenAddress,
entrypoint: 'balanceOf',
calldata: [walletAddress]
});

// Convert the balance to a human-readable format
// Note: This assumes the balance is returned as a single uint256
// You may need to adjust this based on the actual return value of your contract
const balance = BigInt(response.result[0]).toString();

// Convert to a more readable format (e.g., whole tokens instead of wei)
// This example assumes 18 decimal places, adjust as needed for each token
const readableBalance = (Number(balance) / 1e18).toFixed(4);

return readableBalance;
} catch (error) {
console.error(`Error fetching balance for token ${tokenAddress}:`, error);
return '0'; // Return '0' in case of error
}
try {
const response = await starknet.provider.callContract({
contractAddress: tokenAddress,
entrypoint: "balanceOf",
calldata: [walletAddress],
});

// Convert the balance to a human-readable format
// Note: This assumes the balance is returned as a single uint256
// You may need to adjust this based on the actual return value of your contract
const balance = BigInt(response.result[0]).toString();

// Convert to a more readable format (e.g., whole tokens instead of wei)
// This example assumes 18 decimal places, adjust as needed for each token
const readableBalance = (Number(balance) / 1e18).toFixed(4);

return readableBalance;
} catch (error) {
console.error(`Error fetching balance for token ${tokenAddress}:`, error);
return "0"; // Return '0' in case of error
}
}

export const getBalances = async (walletId, setBalances) => {
Expand All @@ -104,15 +102,27 @@ export const getBalances = async (walletId, setBalances) => {
const data = await getTokenBalances(walletId);

const updatedBalances = [
{ icon: <ETH />, title: 'ETH', balance: data.ETH !== undefined ? data.ETH.toString() : '0.00' },
{ icon: <USDC />, title: 'USDC', balance: data.USDC !== undefined ? data.USDC.toString() : '0.00' },
{ icon: <STRK />, title: 'STRK', balance: data.STRK !== undefined ? data.STRK.toString() : '0.00' },
{ icon: <DAI />, title: 'DAI', balance: data.DAI !== undefined ? data.DAI.toString() : '0.00' },
{
icon: <ETH />,
title: "ETH",
balance: data.ETH !== undefined ? data.ETH.toString() : "0.00",
},
{
icon: <USDC />,
title: "USDC",
balance: data.USDC !== undefined ? data.USDC.toString() : "0.00",
},
{
icon: <STRK />,
title: "STRK",
balance: data.STRK !== undefined ? data.STRK.toString() : "0.00",
},
// { icon: <DAI />, title: 'DAI', balance: data.DAI !== undefined ? data.DAI.toString() : '0.00' }, dont have DAI in the constants file
];

setBalances(updatedBalances);
} catch (error) {
console.error('Error fetching user balances:', error);
console.error("Error fetching user balances:", error);
}
};

Expand Down
13 changes: 13 additions & 0 deletions frontend/test/__mocks__/get-starknet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const mockStarknet = {
isConnected: true,
account: {
deployContract: jest.fn().mockResolvedValue({
transaction_hash: '0xabc...',
contract_address: '0xdef...'
}),
waitForTransaction: jest.fn().mockResolvedValue(true),
},
};

export const connect = jest.fn().mockResolvedValue(mockStarknet);

6 changes: 6 additions & 0 deletions frontend/test/__mocks__/svgMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';

const SvgMock = React.forwardRef((props, ref) => <span ref={ref} {...props} />);

export const ReactComponent = SvgMock;
export default SvgMock;
1 change: 1 addition & 0 deletions frontend/test/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const mockBackendUrl = "http://127.0.0.1:8000";
Empty file.
Empty file.
Empty file.
Loading

0 comments on commit 2a58305

Please sign in to comment.