Skip to content

Commit

Permalink
feat: let's get to 100% unit-test coverage (coinbase#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zizzamia authored Mar 17, 2024
1 parent 3203aaf commit d8c3349
Show file tree
Hide file tree
Showing 44 changed files with 483 additions and 269 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-fishes-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@coinbase/onchainkit': minor
---

- **feat**: 100% unit-test coverage. By @zizzamia #256
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<p align="center">
<a href="https://onchainkit.xyz">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./site/docs/public/logo/v0-10.png">
<img alt="OnchainKit logo vibes" src="./site/docs/public/logo/v0-10.png" width="auto">
<source media="(prefers-color-scheme: dark)" srcset="./site/docs/public/logo/v0-11.png">
<img alt="OnchainKit logo vibes" src="./site/docs/public/logo/v0-11.png" width="auto">
</picture>
</a>
</p>
Expand Down
8 changes: 4 additions & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module.exports = {
coverageThreshold: {
global: {
branches: 94.8,
functions: 93,
lines: 95.5,
statements: 95.3,
branches: 100,
functions: 100,
lines: 100,
statements: 100,
},
},
modulePathIgnorePatterns: ['<rootDir>/framegear/'],
Expand Down
Binary file added site/docs/public/logo/v0-11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 28 additions & 5 deletions src/frame/getFrameMessage.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
import { mockNeynarResponse } from './mock';
import { getFrameMessage } from './getFrameMessage';
import { getMockFrameRequest } from './getMockFrameRequest';
import { neynarBulkUserLookup } from '../utils/neynar/user/neynarUserFunctions';
import { neynarBulkUserLookup } from '../utils/neynar/user/neynarBulkUserLookup';
import { FrameRequest } from './types';
import { neynarFrameValidation } from '../utils/neynar/frame/neynarFrameFunctions';
import { neynarFrameValidation } from '../utils/neynar/frame/neynarFrameValidation';

jest.mock('../utils/neynar/user/neynarUserFunctions', () => {
jest.mock('../utils/neynar/user/neynarBulkUserLookup', () => {
return {
neynarBulkUserLookup: jest.fn(),
};
});

jest.mock('../utils/neynar/frame/neynarFrameFunctions', () => {
jest.mock('../utils/neynar/frame/neynarFrameValidation', () => {
return {
neynarFrameValidation: jest.fn(),
};
});

function mockNeynarResponse(
fid: number,
addresses: string[] | undefined,
lookupMock: jest.Mock,
frameValidationMock: jest.Mock = jest.fn(),
) {
const neynarResponse = {
users: [
{
verifications: addresses,
},
],
};
lookupMock.mockResolvedValue(neynarResponse);

frameValidationMock.mockResolvedValue({
valid: true,
interactor: {
fid,
verified_accounts: addresses,
},
});
}

describe('getFrameValidatedMessage', () => {
it('should return undefined if the message is invalid', async () => {
const result = await getFrameMessage({
Expand Down
2 changes: 1 addition & 1 deletion src/frame/getFrameMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FrameRequest, FrameValidationResponse, MockFrameRequest } from './types
import {
NEYNAR_DEFAULT_API_KEY,
neynarFrameValidation,
} from '../utils/neynar/frame/neynarFrameFunctions';
} from '../utils/neynar/frame/neynarFrameValidation';

type FrameMessageOptions =
| {
Expand Down
17 changes: 0 additions & 17 deletions src/frame/mock.test.ts

This file was deleted.

39 changes: 0 additions & 39 deletions src/frame/mock.ts

This file was deleted.

26 changes: 26 additions & 0 deletions src/identity/easSupportedChains.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { base, baseSepolia, optimism, zora } from 'viem/chains';
import { getChainEASGraphQLAPI } from './easSupportedChains';

describe('easSupportedChains', () => {
describe('getChainEASGraphQLAPI', () => {
it('should return Base Chain EAS GraphQL API', async () => {
const chainEASGraphQLAPI = getChainEASGraphQLAPI(base);
expect(chainEASGraphQLAPI).toEqual('https://base.easscan.org/graphql');
});

it('should return Base Sepolia Chain EAS GraphQL API', async () => {
const chainEASGraphQLAPI = getChainEASGraphQLAPI(baseSepolia);
expect(chainEASGraphQLAPI).toEqual('https://base-sepolia.easscan.org/graphql');
});

it('should return Optimism Chain EAS GraphQL API', async () => {
const chainEASGraphQLAPI = getChainEASGraphQLAPI(optimism);
expect(chainEASGraphQLAPI).toEqual('https://optimism.easscan.org/graphql');
});

it('should return empty string when Chain EAS GraphQL API is not present', async () => {
const chainEASGraphQLAPI = getChainEASGraphQLAPI(zora);
expect(chainEASGraphQLAPI).toEqual('');
});
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Chain } from 'viem';
import { EASChainDefinition } from '../identity/types';
import { EASChainDefinition } from './types';
import { easChainBase } from '../definitions/base';
import { easChainOptimism } from '../definitions/optimism';
import { easChainBaseSepolia } from '../definitions/baseSepolia';
Expand Down
2 changes: 1 addition & 1 deletion src/identity/getEASAttestations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { getEASAttestationsByFilter } from '../queries/easAttestations';
import { getEASAttestations } from './getEASAttestations';
import { easSupportedChains } from '../utils/easAttestation';
import { easSupportedChains } from '../identity/easSupportedChains';
import { base, opBNBTestnet } from 'viem/chains';
import { GetEASAttestationsOptions } from './types';

Expand Down
2 changes: 1 addition & 1 deletion src/identity/getEASAttestations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getEASAttestationsByFilter } from '../queries/easAttestations';
import { isChainSupported, easSupportedChains } from '../utils/easAttestation';
import { isChainSupported, easSupportedChains } from './easSupportedChains';
import { EASAttestation, GetEASAttestationsOptions } from './types';
import type { Address, Chain } from 'viem';

Expand Down
7 changes: 2 additions & 5 deletions src/identity/getSlicedAddress.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
/**
* getSlicedAddress returns the first 5 and last 4 characters of an address.
* Returns the first 5 and last 4 characters of an address.
*/
export const getSlicedAddress = (address: `0x${string}` | undefined) => {
if (!address) {
return '';
}
export const getSlicedAddress = (address: `0x${string}`) => {
return `${address.slice(0, 5)}...${address.slice(-4)}`;
};
5 changes: 4 additions & 1 deletion src/identity/hooks/useAvatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ type UseNameQueryOptions = {
cacheTime?: number;
};

/**
* Gets an ensName and resolves the Avatar
*/
export const useAvatar = ({ ensName }: UseNameOptions, queryOptions?: UseNameQueryOptions) => {
const { enabled = true, cacheTime } = queryOptions ?? {};
const ensActionKey = `ens-avatar-${ensName}` ?? '';
const ensActionKey = `ens-avatar-${ensName}`;
return useQuery<GetEnsAvatarReturnType>({
queryKey: ['useAvatar', ensActionKey],
queryFn: async () => {
Expand Down
9 changes: 9 additions & 0 deletions src/network/createEasGraphQLClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { base } from 'viem/chains';
import { createEasGraphQLClient } from './createEasGraphQLClient';

describe('createEasGraphQLClient', () => {
it('should return a easGraphqlClient', () => {
const easGraphqlClient = createEasGraphQLClient(base);
expect(easGraphqlClient.requestConfig).toEqual({});
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLClient } from 'graphql-request';
import type { Chain } from 'viem';
import { getChainEASGraphQLAPI } from '../utils/easAttestation'; // Adjust the import path as needed
import { getChainEASGraphQLAPI } from '../identity/easSupportedChains';

export function createEasGraphQLClient(chain: Chain): GraphQLClient {
const endpoint = getChainEASGraphQLAPI(chain);
Expand Down
4 changes: 2 additions & 2 deletions src/queries/easAttestations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
getEASAttestationsByFilter,
easAttestationQuery,
} from './easAttestations';
import { createEasGraphQLClient } from '../network/easGraphQL';
import { createEasGraphQLClient } from '../network/createEasGraphQLClient';
import { base } from 'viem/chains';

jest.mock('../network/easGraphQL');
jest.mock('../network/createEasGraphQLClient');

describe('EAS Attestation Service', () => {
const mockAddress = '0xdbf03b407c01e7cd3cbea99509d93f8dddc8c6fb';
Expand Down
2 changes: 1 addition & 1 deletion src/queries/easAttestations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { gql } from 'graphql-request';
import type { Address, Chain } from 'viem';
import { getAddress } from 'viem';
import { EASSchemaUid, EASAttestation } from '../identity/types';
import { createEasGraphQLClient } from '../network/easGraphQL';
import { createEasGraphQLClient } from '../network/createEasGraphQLClient';

/**
* Type representing the filter options used for querying EAS Attestations.
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FetchError } from '../exceptions/FetchError';
import { neynarFrameValidation } from './neynarFrameFunctions';
import { neynarFrameValidation } from './neynarFrameValidation';

describe('neynar frame functions', () => {
let fetchMock = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FrameValidationData } from '../../../frame/types';
import { convertToNeynarResponseModel } from './neynarFrameModels';
import { convertToNeynarResponseModel } from './convertToNeynarResponseModel';
import { postDataToNeynar } from '../postDataToNeynar';

export const NEYNAR_DEFAULT_API_KEY = 'NEYNAR_ONCHAIN_KIT';
Expand Down
33 changes: 33 additions & 0 deletions src/utils/neynar/getDataFromNeynar.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { version } from '../../version';
import { NEYNAR_DEFAULT_API_KEY } from './frame/neynarFrameValidation';
import { getDataFromNeynar } from './getDataFromNeynar';

describe('getDataFromNeynar', () => {
let fetchMock = jest.fn();
let status = 200;

beforeEach(() => {
status = 200;
global.fetch = jest.fn(() =>
Promise.resolve({
status,
json: fetchMock,
}),
) as jest.Mock;
});

it('should call fetch correctly', async () => {
const apiURLMock = 'https://api.neynar.com/v2/amazing-api';
await getDataFromNeynar(apiURLMock);
expect(global.fetch).toHaveBeenCalledWith(apiURLMock, {
method: 'GET',
url: apiURLMock,
headers: {
accept: 'application/json',
api_key: NEYNAR_DEFAULT_API_KEY,
'content-type': 'application/json',
onchainkit_version: version,
},
});
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { version } from '../../version';
import { FetchError } from './exceptions/FetchError';
import { NEYNAR_DEFAULT_API_KEY } from './frame/neynarFrameFunctions';
import { NEYNAR_DEFAULT_API_KEY } from './frame/neynarFrameValidation';

export async function getDataFromNeynar(url: string, apiKey: string = NEYNAR_DEFAULT_API_KEY) {
const options = {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/neynar/neynar.integ.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { neynarBulkUserLookup } from './user/neynarUserFunctions';
import { neynarFrameValidation } from './frame/neynarFrameFunctions';
import { neynarBulkUserLookup } from './user/neynarBulkUserLookup';
import { neynarFrameValidation } from './frame/neynarFrameValidation';
import { getCustodyAddressForFidNeynar } from './user/getCustodyAddressForFidNeynar';
import { getVerifiedAddressesForFidNeynar } from './user/getVerifiedAddressesForFidNeynar';

Expand Down
35 changes: 35 additions & 0 deletions src/utils/neynar/postDataToNeynar.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { version } from '../../version';
import { NEYNAR_DEFAULT_API_KEY } from './frame/neynarFrameValidation';
import { postDataToNeynar } from './postDataToNeynar';

describe('postDataToNeynar', () => {
let fetchMock = jest.fn();
let status = 200;

beforeEach(() => {
status = 200;
global.fetch = jest.fn(() =>
Promise.resolve({
status,
json: fetchMock,
}),
) as jest.Mock;
});

it('should call fetch correctly', async () => {
const mockURL = 'https://api.neynar.com/v2/amazing-api';
const mockData = {};
await postDataToNeynar(mockURL, NEYNAR_DEFAULT_API_KEY, mockData);
expect(global.fetch).toHaveBeenCalledWith(mockURL, {
method: 'POST',
url: mockURL,
headers: {
accept: 'application/json',
api_key: NEYNAR_DEFAULT_API_KEY,
'content-type': 'application/json',
onchainkit_version: version,
},
body: JSON.stringify(mockData),
});
});
});
7 changes: 1 addition & 6 deletions src/utils/neynar/postDataToNeynar.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { version } from '../../version';
import { FetchError } from './exceptions/FetchError';
import { NEYNAR_DEFAULT_API_KEY } from './frame/neynarFrameFunctions';

export async function postDataToNeynar(
url: string,
apiKey: string = NEYNAR_DEFAULT_API_KEY,
data: any,
) {
export async function postDataToNeynar(url: string, apiKey: string, data: any) {
const options = {
method: 'POST',
url: url,
Expand Down
Loading

0 comments on commit d8c3349

Please sign in to comment.