Skip to content

Commit

Permalink
Merge pull request viction-developers#5 from viction-developers/workf…
Browse files Browse the repository at this point in the history
…lows

@endadinh
add workflows, ci/cd, fix some bugs, enhance ux/ui
  • Loading branch information
endadinh authored Jul 30, 2024
2 parents 1f3f9e5 + c76ba8c commit 6a33a80
Show file tree
Hide file tree
Showing 15 changed files with 2,480 additions and 204 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: CI/CD Pipeline

on:
push:
branches:
- main
- 'release/*'
pull_request:
branches:
- main

jobs:
build:c
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 21.x]

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: yarn install

- name: Run tests
run: npm test

- name: Build project
run: yarn run build

publish:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/')
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 21.x

- name: Install dependencies
run: npm install

- name: Build project
run: npm run build

- name: Publish to NPM
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/node_modules
/node_modules

/dist
200 changes: 200 additions & 0 deletions __tests__/ConnectButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// __tests__/ConnectButton.test.tsx

import React from "react";
import { render, screen, act } from "@testing-library/react";
import "@testing-library/jest-dom";
import userEvent from "@testing-library/user-event";
import ConnectButton from "../src/components/ConnectButton";
import {
WalletProvider,
useWalletProviders,
} from "../src/connectors/WalletProviders";
import WalletConnector from "../src/connectors/WalletConnector";
import { NETWORK, supportNetworks } from "../src/chains";
import { EIP6963ProviderDetail } from "../src/utils/types";

jest.mock("../src/connectors/WalletConnector");
jest.mock("../src/connectors/WalletProviders", () => ({
useWalletProviders: jest.fn(),
WalletProvider: ({ children }: { children: React.ReactNode }) => (
<div>{children}</div>
),
}));

jest.useFakeTimers();

const mockChainInfo = supportNetworks[NETWORK.MAINNET];

// Mock provider with necessary methods
const mockProvider = {
request: jest.fn(),
on: jest.fn(),
removeListener: jest.fn(),
};

const mockProviderDetails: EIP6963ProviderDetail[] = [
{
info: { uuid: "mock-uuid", name: "Mock Wallet", icon: "" },
provider: mockProvider,
accounts: [],
},
];

(mockProvider.request as jest.Mock).mockResolvedValueOnce(
"0x" + mockChainInfo.id.toString(16)
); // Mock chain ID response

(useWalletProviders as jest.Mock).mockReturnValue({
providerDetails: mockProviderDetails,
sponsorWallets: [],
detectProviders: jest.fn(),
});

describe("ConnectButton", () => {
let mockConnector: WalletConnector;

beforeEach(() => {
mockConnector = new WalletConnector(NETWORK.MAINNET);
jest
.spyOn(mockConnector, "connect")
.mockImplementation(() => Promise.resolve());
jest
.spyOn(mockConnector, "disconnect")
.mockImplementation(() => Promise.resolve());
jest
.spyOn(mockConnector, "getChainInfo")
.mockImplementation(() => mockChainInfo);
jest
.spyOn(mockConnector, "switchChain")
.mockImplementation(() => Promise.resolve());

// Mock the provider request method
mockProvider.request.mockImplementation((req: any) => {
if (req.method === "eth_chainId") {
return Promise.resolve("0x58"); // Return chain ID as a hex string
}
return Promise.reject(new Error("Method not supported"));
});
});

test("renders Connect Wallet button", async () => {
await act(async () => {
render(
<WalletProvider>
<ConnectButton
connector={mockConnector}
onConnect={jest.fn()}
onDisconnect={jest.fn()}
/>
</WalletProvider>
);
});

const buttonElement = screen.getByText(/Connect Wallet/i);
expect(buttonElement).toBeInTheDocument();
});

test("renders Disconnect button when connected", async () => {
await act(async () => {
render(
<WalletProvider>
<ConnectButton
connector={mockConnector}
connectedAccount="0x123"
onConnect={jest.fn()}
onDisconnect={jest.fn()}
/>
</WalletProvider>
);
});

const buttonElement = screen.getByText(/Disconnect/i);
expect(buttonElement).toBeInTheDocument();
});

test("calls onConnect when a wallet is connected", async () => {
const mockOnConnect = jest.fn();

await act(async () => {
render(
<WalletProvider>
<ConnectButton
connector={mockConnector}
onConnect={mockOnConnect}
onDisconnect={jest.fn()}
/>
</WalletProvider>
);
});

// Click the "Connect Wallet" button to open the modal
const modalConnectButton = screen.getByText(/Connect Wallet/i);

await act(async () => {
modalConnectButton.dispatchEvent(
new MouseEvent("click", { bubbles: true })
);
});

// Simulate waiting for wallet data to load
await act(async () => {
jest.advanceTimersByTime(2000);
});

// Check if the modal is open by looking for a wallet option
const walletButton = await screen.findByText(/Mock Wallet/i);
expect(walletButton).toBeInTheDocument();

// Click the mock wallet button to simulate connection
await act(() => {
walletButton.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});

// Ensure the mockOnConnect callback was called
expect(mockOnConnect).toHaveBeenCalledTimes(1);
expect(mockOnConnect).toHaveBeenCalledWith(mockProviderDetails[0]);
});

test("calls onDisconnect when the Disconnect button is clicked", async () => {
const mockOnDisconnect = jest.fn();

await act(async () => {
render(
<WalletProvider>
<ConnectButton
connector={mockConnector}
connectedAccount="0x123"
onConnect={jest.fn()}
onDisconnect={mockOnDisconnect}
/>
</WalletProvider>
);
});

const buttonElement = screen.getByText(/Disconnect/i);
await act(async () => {
buttonElement.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(mockOnDisconnect).toHaveBeenCalled();
});

test("applies custom styles correctly", async () => {
const customStyle = { background: "blue", color: "white" };

await act(async () => {
render(
<WalletProvider>
<ConnectButton
connector={mockConnector}
style={customStyle}
onConnect={jest.fn()}
onDisconnect={jest.fn()}
/>
</WalletProvider>
);
});

const buttonElement = screen.getByText(/Connect Wallet/i);
expect(buttonElement).toHaveStyle(customStyle);
});
});
9 changes: 9 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
setupFiles: ['./setupTests.ts'],
preset: 'ts-jest',
testEnvironment: 'jest-environment-jsdom',
setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
},
};
20 changes: 15 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
{
"name": "wallet-kit",
"version": "1.0.0",
"name": "@viction-kit/wallet-kit",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest",
"start": "webpack serve --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@abstraction-hq/wallet-sdk": "^1.0.7",
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@types/react": "^18.3.3",
Expand All @@ -20,15 +22,23 @@
"react-dom": "^18.3.1",
"react-modal": "^3.16.1",
"typescript": "^5.5.3",
"viem": "^2.17.9",
"@abstraction-hq/wallet-sdk": "^1.0.7"
"util": "^0.12.5",
"viem": "^2.17.9"
},
"devDependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/react-modal": "^3.16.3",
"html-webpack-plugin": "^5.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"ts-jest": "^29.2.3",
"ts-loader": "^9.2.3",
"webpack": "^5.51.1",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.0.0"
}
}
}
7 changes: 7 additions & 0 deletions setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// setupTests.ts
import { TextEncoder, TextDecoder } from "util";

// @ts-ignore
global.TextEncoder = TextEncoder;
// @ts-ignore
global.TextDecoder = TextDecoder;
8 changes: 3 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const App: React.FC = () => {
}
};
loadData();
}, [chain, wallet]);
}, [chain, wallet, account, balance]);

const handleConnect = async (wallet: EIP6963ProviderDetail | undefined) => {
try {
Expand Down Expand Up @@ -188,10 +188,8 @@ const App: React.FC = () => {
};

const buttonStyle = {
backgroundColor: "green",
background: "linear-gradient(135deg, #36d1dc, #5b86e5)",
color: "white",
padding: "15px 30px",
fontSize: "18px",
};

return (
Expand Down Expand Up @@ -228,7 +226,7 @@ const App: React.FC = () => {
onAccountChanged={handleAccountChanged}
onChainChanged={handleChainChanged}
onError={handleError}
style={buttonStyle}
// style={buttonStyle} // Active if modifier button style.
/>
</WalletProvider>
</Container>
Expand Down
Loading

0 comments on commit 6a33a80

Please sign in to comment.