<commit_before>import { assert, spy } from 'sinon';
import { expect } from 'chai';
import * as dispatcher from 'source/browser/events';

describe('browser/events', () => {
	beforeEach(() => {
		this.listener = spy();
		this.element = document.createElement('div');
		document.body.appendChild(this.element);
	});

	afterEach(() => {
		dispatcher.off();
		this.element.parentElement.removeChild(this.element);
		delete this.listener;
		delete this.element;
	});

	describe('#on', () => {
		it('should invoke the listener with a Event argument multiple times', () => {
			dispatcher.on(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate popstate popstate');
			expect(this.listener.called).to.be.true;
			expect(this.listener.calledOnce).to.be.false;
			expect(this.listener.callCount).to.be.equal(3);
			for (let ix = 0; ix < this.listener.callCount; ix += 1) {
				const args = this.listener.getCall(ix).args;
				expect(args.length).to.be.at.least(1);
				expect(args[0]).to.be.instanceOf(Event);
				expect(Object.prototype.hasOwnProperty.call(args[0], 'detail')).to.be.true;
			}
		});
	});

	describe('#one', () => {
		it('should invoke the listener with a Event argument one', () => {
			expect(this.listener).to.be.spy;
			dispatcher.one(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate popstate popstate');
			expect(this.listener.called).to.be.true;
			expect(this.listener.calledOnce).to.be.true;
			const args = this.listener.getCall(0).args;
			expect(args.length).to.be.at.least(1);
			expect(args[0]).to.be.instanceOf(Event);
			expect(Object.prototype.hasOwnProperty.call(args[0], 'detail')).to.be.true;
		});
	});

	describe('#off', () => {
		it('should remove an specific event handler from a specific element', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'popstate changestate pushstate', this.listener);
			dispatcher.off(this.element, 'pushstate', this.listener); // <= specific listener
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(2);
		});

		it('should remove all event handlers from a specific element', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'pushstate popstate changestate', this.listener);
			dispatcher.off(this.element); // <= all types
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers from a specific element by type', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'pushstate popstate changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.off(this.element, 'pushstate'); // <= all pushstate listeners from this.element
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(2);
			expect(anotherListener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(document, 'DOMContentLoaded', this.listener);
			dispatcher.on(window, 'changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.on(this.element, 'pushstate', this.listener);
			dispatcher.off(); // <= all types and elements
			dispatcher.emit(document, 'DOMContentLoaded');
			dispatcher.emit(window, 'changestate');
			dispatcher.emit(this.element, 'pushstate');
			expect(this.listener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers by type', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(document, 'DOMContentLoaded', this.listener);
			dispatcher.on(window, 'changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.on(this.element, 'pushstate', this.listener);
			dispatcher.off('pushstate'); // <= all listeners from 'pushstates' type from all elements
			dispatcher.emit(document, 'DOMContentLoaded');
			dispatcher.emit(window, 'changestate');
			dispatcher.emit(this.element, 'pushstate');
			expect(anotherListener.callCount).to.be.equal(0);
			expect(this.listener.callCount).to.be.equal(2);
		});
	});

	describe('#emit', () => {
		it('should invoke the listener', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate');
			expect(this.listener.called).to.be.true;
		});

		it('should pass arguments to the listeners', () => {
			const type = 'popstate';
			const state = { foo: 'foo', bar: 1, baz: {} };
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, type, this.listener);
			dispatcher.emit(this.element, type, { detail: { state } });
			assert.calledOnce(this.listener);
			const args = this.listener.getCall(0).args;
			expect(args.length).to.be.at.least(1);
			expect(args[0]).to.be.instanceOf(Event);
			expect(args[0].detail).to.be.a('object');
			expect(args[0].detail.state).to.equal(state);
			expect(args[0].type).to.equal(type); // <= crossbrowser
		});

		it('should emit all events', () => {
			['popstate', 'changestate', 'hashchange'].map((eventType) => {
				const listener = spy();
				dispatcher.on(this.element, eventType, listener);
				dispatcher.emit();
				return listener;
			}).forEach((listener, index, spies) => {
				expect(listener.callCount).to.be.equal(spies.length - index);
			});
		});
	});

	describe('#willEmit', () => {
		it([
			'should check whether an event listener is registered with this `dom-event-dispatcher`',
			'object or any of its ancestors for the specified event type',
		].join(' '), () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(window, 'changestate', this.listener);
			expect(dispatcher.willEmit('changestate popstate')).to.be.true;
			expect(dispatcher.willEmit('foo bar baz')).to.be.false;
			expect(dispatcher.willEmit('changestate')).to.be.true;
			expect(dispatcher.willEmit('popstate')).to.be.false;
		});
	});

	describe('#hasEvent', () => {
		it([
			'should check whether the `dom-event-dispatcher` object has any listeners',
			'registered for a specific type of event',
		].join(' '), () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(window, 'changestate', this.listener);
			expect(dispatcher.hasEvent(window, 'changestate popstate')).to.be.true;
			expect(dispatcher.hasEvent(window, 'foo bar baz')).to.be.false;
			expect(dispatcher.hasEvent(window, 'changestate')).to.be.true;
			expect(dispatcher.hasEvent(window, 'popstate')).to.be.false;
		});
	});
});<commit_msg>test: cover<commit_after>import { assert, spy } from 'sinon';
import { expect } from 'chai';
import * as dispatcher from 'source/browser/events';

describe('browser/events', () => {
	beforeEach(() => {
		this.listener = spy();
		this.element = document.createElement('div');
		document.body.appendChild(this.element);
	});

	afterEach(() => {
		dispatcher.off();
		this.element.parentElement.removeChild(this.element);
		delete this.listener;
		delete this.element;
	});

	describe('#on', () => {
		it('should invoke the listener with a Event argument multiple times', () => {
			dispatcher.on(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate popstate popstate');
			expect(this.listener.called).to.be.true;
			expect(this.listener.calledOnce).to.be.false;
			expect(this.listener.callCount).to.be.equal(3);
			for (let ix = 0; ix < this.listener.callCount; ix += 1) {
				const args = this.listener.getCall(ix).args;
				expect(args.length).to.be.at.least(1);
				expect(args[0]).to.be.instanceOf(Event);
				expect(Object.prototype.hasOwnProperty.call(args[0], 'detail')).to.be.true;
			}
		});
	});

	describe('#one', () => {
		it('should invoke the listener with a Event argument one', () => {
			expect(this.listener).to.be.spy;
			dispatcher.one(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate popstate popstate');
			expect(this.listener.called).to.be.true;
			expect(this.listener.calledOnce).to.be.true;
			const args = this.listener.getCall(0).args;
			expect(args.length).to.be.at.least(1);
			expect(args[0]).to.be.instanceOf(Event);
			expect(Object.prototype.hasOwnProperty.call(args[0], 'detail')).to.be.true;
		});
	});

	describe('#off', () => {
		it('should remove an specific event handler from a specific element', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'popstate changestate pushstate', this.listener);
			dispatcher.off(this.element, 'pushstate', this.listener); // <= specific listener
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(2);
		});

		it('should remove all event handlers from a specific element', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'pushstate popstate changestate', this.listener);
			dispatcher.off(this.element); // <= all types
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers from a specific element by type', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'pushstate popstate changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.off(this.element, 'pushstate'); // <= all pushstate listeners from this.element
			dispatcher.emit(this.element, 'popstate changestate pushstate');
			expect(this.listener.callCount).to.be.equal(2);
			expect(anotherListener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(document, 'DOMContentLoaded', this.listener);
			dispatcher.on(window, 'changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.on(this.element, 'pushstate', this.listener);
			dispatcher.off(); // <= all types and elements
			dispatcher.emit(document, 'DOMContentLoaded');
			dispatcher.emit(window, 'changestate');
			dispatcher.emit(this.element, 'pushstate');
			expect(this.listener.callCount).to.be.equal(0);
		});

		it('should remove all event handlers by type', () => {
			const anotherListener = spy();
			expect(this.listener).to.be.spy;
			dispatcher.on(document, 'DOMContentLoaded', this.listener);
			dispatcher.on(window, 'changestate', this.listener);
			dispatcher.on(this.element, 'pushstate', anotherListener);
			dispatcher.on(this.element, 'pushstate', this.listener);
			dispatcher.off('pushstate'); // <= all listeners from 'pushstates' type from all elements
			dispatcher.emit(document, 'DOMContentLoaded');
			dispatcher.emit(window, 'changestate');
			dispatcher.emit(this.element, 'pushstate');
			expect(anotherListener.callCount).to.be.equal(0);
			expect(this.listener.callCount).to.be.equal(2);
		});
	});

	describe('#emit', () => {
		it('should invoke the listener', () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, 'popstate', this.listener);
			dispatcher.emit(this.element, 'popstate');
			expect(this.listener.called).to.be.true;
		});

		it('should pass arguments to the listeners', () => {
			const type = 'popstate';
			const state = { foo: 'foo', bar: 1, baz: {} };
			expect(this.listener).to.be.spy;
			dispatcher.on(this.element, type, this.listener);
			dispatcher.emit(this.element, type, { detail: { state } });
			assert.calledOnce(this.listener);
			const args = this.listener.getCall(0).args;
			expect(args.length).to.be.at.least(1);
			expect(args[0]).to.be.instanceOf(Event);
			expect(args[0].detail).to.be.a('object');
			expect(args[0].detail.state).to.equal(state);
			expect(args[0].type).to.equal(type); // <= crossbrowser
		});

		it('should emit all events', () => {
			['popstate', 'changestate', 'hashchange'].map((eventType) => {
				const listener = spy();
				dispatcher.on(this.element, eventType, listener);
				dispatcher.emit();
				return listener;
			}).forEach((listener, index, spies) => {
				expect(listener.callCount).to.be.equal(spies.length - index);
			});
		});
	});

	describe('#willEmit', () => {
		it([
			'should check whether an event listener is registered with this `dom-event-dispatcher`',
			'object or any of its ancestors for the specified event type',
		].join(' '), () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(window, 'changestate', this.listener);
			expect(dispatcher.willEmit('changestate popstate')).to.be.true;
			expect(dispatcher.willEmit('foo bar baz')).to.be.false;
			expect(dispatcher.willEmit('changestate')).to.be.true;
			expect(dispatcher.willEmit('popstate')).to.be.false;
		});
	});

	describe('#hasEvent', () => {
		it([
			'should check whether the `dom-event-dispatcher` object has any listeners',
			'registered for a specific type of event',
		].join(' '), () => {
			expect(this.listener).to.be.spy;
			dispatcher.on(window, 'changestate', this.listener);
			expect(dispatcher.hasEvent(window, 'changestate popstate')).to.be.true;
			expect(dispatcher.hasEvent(window, 'foo bar baz')).to.be.false;
			expect(dispatcher.hasEvent(window, 'changestate')).to.be.true;
			expect(dispatcher.hasEvent(window, 'popstate')).to.be.false;
			expect(dispatcher.hasEvent(window, 'anon')).to.be.false;
		});
	});
});
{'fraction_non_alphanumeric': 0.17767804590935846, 'fraction_numerical': 0.003531489111241907, 'mean_word_length': 4.452466907340553, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6254820', 'n_tokens_mistral': 4958, 'n_tokens_neox': 4434, 'n_words': 777}