diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 2dd584bee94..3499c620c2d 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -185,3 +185,8 @@ Documentation: - defaultTransactionType is now type 0x2 instead of 0x0 (#6282) - Allows formatter to parse large base fee (#6456) +- The package now uses `EventEmitter` from `web3-utils` that works in node envrioment as well as in the browser. (#6398) + +### Fixed + +- Fix the issue: "Uncaught TypeError: Class extends value undefined is not a constructor or null #6371". (#6398) diff --git a/packages/web3-utils/.eslintignore b/packages/web3-utils/.eslintignore index e3d7e665285..fea9beae6d6 100644 --- a/packages/web3-utils/.eslintignore +++ b/packages/web3-utils/.eslintignore @@ -2,3 +2,5 @@ dist lib jest.config.js .eslintrc.js +cypress +cypress.config.js diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 4213b98b2d9..5db90f9426b 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -158,4 +158,8 @@ Documentation: - `soliditySha3()` with BigInt support -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- As a replacment of the node EventEmitter, a custom `EventEmitter` has been implemented and exported. (#6398) diff --git a/packages/web3-utils/cypress b/packages/web3-utils/cypress new file mode 120000 index 00000000000..4a671a7beac --- /dev/null +++ b/packages/web3-utils/cypress @@ -0,0 +1 @@ +../../templates/cypress \ No newline at end of file diff --git a/packages/web3-utils/cypress.config.js b/packages/web3-utils/cypress.config.js new file mode 120000 index 00000000000..8cd9ba29af0 --- /dev/null +++ b/packages/web3-utils/cypress.config.js @@ -0,0 +1 @@ +../../templates/cypress.config.js \ No newline at end of file diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index 3958ddabe1c..72a7b760da3 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -40,7 +40,10 @@ "test:ci": "jest --coverage=true --coverage-reporters=json --verbose", "test:watch": "npm test -- --watch", "test:unit": "jest --config=./test/unit/jest.config.js", - "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" + "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests", + "test:e2e:electron": "npx cypress run --headless --browser electron", + "test:e2e:chrome": "npx cypress run --headless --browser chrome", + "test:e2e:firefox": "npx cypress run --headless --browser firefox" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-utils/test/integration/event_emitter.test.ts b/packages/web3-utils/test/integration/event_emitter.test.ts new file mode 100644 index 00000000000..7bf018dd00c --- /dev/null +++ b/packages/web3-utils/test/integration/event_emitter.test.ts @@ -0,0 +1,124 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +// this file contains the unit test for the event emitter in the DOM environment +// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file) + +// ignore the following rule to allow keeping `@jest-environment jsdom` on top: +// eslint-disable-next-line header/header +import { EventEmitter } from '../../src/event_emitter'; + +describe('EventEmitter in the browser with Cypress', () => { + let emitter: EventEmitter; + + beforeEach(() => { + emitter = new EventEmitter(); + }); + + describe('on', () => { + it('should add a listener for the specified event', () => { + const callback = jest.fn(); + emitter.on('test', callback); + emitter.emit('test', 'hello'); + expect(callback).toHaveBeenCalledWith('hello'); + }); + }); + + describe('once', () => { + it('should add a listener for the specified event that is only called once', () => { + const callback = jest.fn(); + emitter.once('test', callback); + emitter.emit('test', 'hello'); + emitter.emit('test', 'world'); + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith('hello'); + }); + }); + + describe('off', () => { + it('should remove a listener for the specified event', () => { + const callback = jest.fn(); + emitter.on('test', callback); + emitter.off('test', callback); + emitter.emit('test', 'hello'); + expect(callback).not.toHaveBeenCalled(); + }); + }); + + describe('emit', () => { + it('should call all listeners for the specified event', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + emitter.on('test', callback1); + emitter.on('test', callback2); + emitter.emit('test', 'hello'); + expect(callback1).toHaveBeenCalledWith('hello'); + expect(callback2).toHaveBeenCalledWith('hello'); + }); + }); + + describe('listenerCount', () => { + it('should return the number of listeners for the specified event', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + emitter.on('test', callback1); + emitter.on('test', callback2); + expect(emitter.listenerCount('test')).toBe(2); + }); + }); + + describe('listeners', () => { + it('should return an array of listeners for the specified event', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + emitter.on('test', callback1); + emitter.on('test', callback2); + expect(emitter.listeners('test')).toEqual([callback1, callback2]); + }); + }); + + describe('eventNames', () => { + it('should return an array of event names that have listeners', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + emitter.on('test1', callback1); + emitter.on('test2', callback2); + expect(emitter.eventNames()).toEqual(['test1', 'test2']); + }); + }); + + describe('removeAllListeners', () => { + it('should remove all listeners for all events', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + emitter.on('test1', callback1); + emitter.on('test2', callback2); + emitter.removeAllListeners(); + emitter.emit('test1', 'hello'); + emitter.emit('test2', 'world'); + expect(callback1).not.toHaveBeenCalled(); + expect(callback2).not.toHaveBeenCalled(); + }); + }); + + describe('setMaxListeners', () => { + it('should set the maximum number of listeners for an event', () => { + emitter.setMaxListeners(2); + expect(emitter.getMaxListeners()).toBe(2); + }); + }); +});