Skip to content

Commit

Permalink
test: add tests for providers package
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmad committed Nov 13, 2023
1 parent cdd597b commit 178c7ef
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 28 deletions.
19 changes: 19 additions & 0 deletions packages/providers/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
preset: "../../jest-preset.js",
displayName: "@cryptkeeperzk/providers",
setupFilesAfterEnv: ["<rootDir>/src/setupTests.ts"],
moduleNameMapper: {
"@src/(.*)$": "<rootDir>/src/$1",
},
moduleFileExtensions: ["ts", "js"],
collectCoverageFrom: ["src/**/*.{ts,js}"],
coveragePathIgnorePatterns: ["/node_modules/", "/test/", "/__tests__/", "./src/index.ts"],
coverageThreshold: {
global: {
statements: 95,
branches: 95,
functions: 95,
lines: 95,
},
},
};
5 changes: 4 additions & 1 deletion packages/providers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@
"publish:package": "pnpm publish --access=public --no-git-checks",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "pnpm run lint --fix",
"test": "jest",
"test:coverage": "pnpm run test --coverage",
"prettier": "prettier -c . --ignore-path ../../.prettierignore",
"prettier:fix": "prettier -w . --ignore-path ../../.prettierignore",
"types": "tsc -p tsconfig.json --noEmit",
"githook:precommit": "lint-staged && pnpm run types"
"githook:precommit": "lint-staged && pnpm run types",
"githook:prepush": "pnpm run test:coverage"
},
"dependencies": {
"@cryptkeeperzk/types": "workspace:^",
Expand Down
4 changes: 2 additions & 2 deletions packages/providers/src/sdk/CryptKeeperInjectedProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ICryptKeeperInjectedProvider } from "./interface";
import type { IInjectedMessageData, IInjectedProviderRequest } from "@cryptkeeperzk/types";

import { RPCExternalAction } from "../constants";
import { type EventHandler, type EventName, Handler } from "../services";
import { type EventHandler, type EventName, type IHandler, Handler } from "../services";

/**
* Represents the CryptKeeper provider that is injected into the application.
Expand All @@ -14,7 +14,7 @@ export class CryptKeeperInjectedProvider implements ICryptKeeperInjectedProvider
/**
* Handler service
*/
private readonly handler: Handler;
private readonly handler: IHandler;

/**
* Indicates whether the provider is CryptKeeper.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* @jest-environment jsdom
*/
import { RPCExternalAction } from "@src/constants";

import type { IInjectedMessageData } from "@cryptkeeperzk/types";

import { CryptKeeperInjectedProvider } from "..";
import { EventName, Handler } from "../../services";

jest.mock("nanoevents", (): unknown => ({
createNanoEvents: jest.fn(),
}));

jest.mock("../../services", (): unknown => ({
...jest.requireActual("../../services"),
Handler: jest.fn(),
}));

describe("sdk/CryptKeeperInjectedProvider", () => {
const defaultHandler = {
request: jest.fn(),
eventResponser: jest.fn(),
on: jest.fn(),
emit: jest.fn(),
cleanListeners: jest.fn(),
getConnectedOrigin: jest.fn(),
};

beforeEach(() => {
(Handler as jest.Mock).mockReturnValue(defaultHandler);
});

afterEach(() => {
jest.clearAllMocks();
});

test("should connect properly", async () => {
const provider = new CryptKeeperInjectedProvider();

await provider.connect();

expect(defaultHandler.request).toHaveBeenCalledTimes(1);
expect(defaultHandler.request).toHaveBeenCalledWith({
method: RPCExternalAction.CONNECT,
payload: {
isChangeIdentity: false,
urlOrigin: undefined,
},
});
});

test("should request rpc properly", async () => {
const provider = new CryptKeeperInjectedProvider();

await provider.request({ method: RPCExternalAction.GET_CONNECTED_IDENTITY_DATA });

expect(defaultHandler.request).toHaveBeenCalledTimes(1);
expect(defaultHandler.request).toHaveBeenCalledWith({
method: RPCExternalAction.GET_CONNECTED_IDENTITY_DATA,
});
});

test("should handle events properly", () => {
const provider = new CryptKeeperInjectedProvider();

provider.eventResponser({} as MessageEvent<IInjectedMessageData>);
provider.on(EventName.CONNECT, jest.fn());
provider.emit(EventName.CONNECT, { data: true });
provider.cleanListeners();

expect(defaultHandler.eventResponser).toHaveBeenCalledTimes(1);
expect(defaultHandler.on).toHaveBeenCalledTimes(1);
expect(defaultHandler.emit).toHaveBeenCalledTimes(1);
expect(defaultHandler.emit).toHaveBeenCalledWith(EventName.CONNECT, { data: true });
expect(defaultHandler.cleanListeners).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @jest-environment jsdom
*/

import { CryptKeeperInjectedProvider, initializeCryptKeeper, initializeCryptKeeperProvider } from "..";

jest.mock("nanoevents", (): unknown => ({
createNanoEvents: jest.fn(),
}));

jest.mock("../CryptKeeperInjectedProvider", (): unknown => ({
...jest.requireActual("../CryptKeeperInjectedProvider"),
CryptKeeperInjectedProvider: jest.fn(),
}));

describe("sdk/initializeInjectedProvider", () => {
const defaultProvider = {
request: jest.fn(),
eventResponser: jest.fn(),
on: jest.fn(),
emit: jest.fn(),
cleanListeners: jest.fn(),
getConnectedOrigin: jest.fn(),
};

beforeEach(() => {
(CryptKeeperInjectedProvider as jest.Mock).mockReturnValue(defaultProvider);
});

afterEach(() => {
jest.clearAllMocks();
window.isCryptkeeperInjected = true;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
window.cryptkeeper = undefined;
});

test("should initialize cryptkeeper properly", () => {
const provider = initializeCryptKeeper();

expect(provider).toStrictEqual(defaultProvider);
expect(window.cryptkeeper).toStrictEqual(provider);
expect(window.dispatchEvent).toHaveBeenCalledTimes(1);
expect(window.addEventListener).toHaveBeenCalledTimes(1);
});

test("should initialize cryptkeeper for extension properly", () => {
const provider = initializeCryptKeeperProvider();

expect(provider).toStrictEqual(defaultProvider);
expect(window.cryptkeeper).toStrictEqual(provider);
expect(window.dispatchEvent).toHaveBeenCalledTimes(1);
expect(window.addEventListener).toHaveBeenCalledTimes(1);
});

test("should not initialize if cryptkeeper is not injected", () => {
window.isCryptkeeperInjected = false;
const provider = initializeCryptKeeper();

expect(provider).toBeUndefined();
expect(window.cryptkeeper).toBeUndefined();
expect(window.dispatchEvent).toHaveBeenCalledTimes(0);
expect(window.addEventListener).toHaveBeenCalledTimes(0);
});
});
12 changes: 6 additions & 6 deletions packages/providers/src/services/event/EventEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Emitter, createNanoEvents } from "nanoevents";
import { type Emitter, createNanoEvents } from "nanoevents";

import { Events, EventHandler, EventName } from "./types";
import type { Events, EventHandler, EventName } from "./types";

/**
* Event emitter class that allows subscribing to and emitting events.
Expand Down Expand Up @@ -29,9 +29,9 @@ export class EventEmitter {
* @param {EventHandler} cb - The event handler callback function.
* @returns {void}
*/
on(eventName: EventName, cb: EventHandler): void {
on = (eventName: EventName, cb: EventHandler): void => {
this.emitter.on(eventName, cb);
}
};

/**
* Emits an event.
Expand All @@ -49,7 +49,7 @@ export class EventEmitter {
*
* @returns {void}
*/
cleanListeners(): void {
cleanListeners = (): void => {
this.emitter.events = {};
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @jest-environment jsdom
*/

/* eslint-disable @typescript-eslint/unbound-method */
import { type Emitter, createNanoEvents } from "nanoevents";

import { EventEmitter, EventName } from "..";

jest.mock("nanoevents", (): unknown => ({
createNanoEvents: jest.fn(),
}));

describe("services/event", () => {
const defaultEventEmitter: Emitter = {
events: {},
on: jest.fn(),
emit: jest.fn(),
};

const defaultHandler = jest.fn();

beforeEach(() => {
(createNanoEvents as jest.Mock).mockReturnValue(defaultEventEmitter);
});

afterEach(() => {
jest.clearAllMocks();
});

test("should handle events properly", () => {
const eventEmitter = new EventEmitter();

eventEmitter.on(EventName.CONNECT, defaultHandler);
eventEmitter.emit(EventName.CONNECT, { data: true });
eventEmitter.cleanListeners();

expect(defaultEventEmitter.on).toHaveBeenCalledTimes(1);
expect(defaultEventEmitter.emit).toHaveBeenCalledTimes(1);
});
});
Loading

0 comments on commit 178c7ef

Please sign in to comment.