<|start_filename|>src/core/symbol/spec.js<|end_filename|>
/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

import symbolGenerator from 'core/symbol';

describe('core/symbol', () => {
	it('simple case', () => {
		const g = symbolGenerator();
		expect(typeof g.foo).toBe('symbol');
		expect(g.foo).toBe(g.foo);
		expect(symbolGenerator().foo).not.toBe(g.foo);
	});
});


<|start_filename|>src/core/prelude/object/clone/spec.js<|end_filename|>
/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

describe('core/prelude/object/clone/fastClone', () => {
	it('simple object cloning', () => {
		const
			obj1 = {};

		expect(Object.fastClone(obj1)).not.toBe(obj1);
		expect(Object.fastClone(obj1)).toEqual(obj1);

		const
			obj2 = {a: 1, b: {c: [1, 2, 3], d: new Date(), d2: '2017-02-03'}};

		expect(Object.fastClone(obj2)).not.toBe(obj2);
		expect(Object.fastClone(obj2)).toEqual(obj2);
	});

	it('simple array cloning', () => {
		const
			obj1 = [];

		expect(Object.fastClone(obj1)).not.toBe(obj1);
		expect(Object.fastClone(obj1)).toEqual(obj1);

		const
			obj2 = [1, 2, 3, new Date(), '2017-02-03'];

		expect(Object.fastClone(obj2)).not.toBe(obj2);
		expect(Object.fastClone(obj2)).toEqual(obj2);

		const
			obj3 = [{a: 1}, {b: 2}];

		expect(Object.fastClone(obj3)).not.toBe(obj3);
		expect(Object.fastClone(obj3)).toEqual(obj3);
	});

	it('cloning of objects with functions', () => {
		const obj = {a: 1, bla: () => 1};
		expect(Object.fastClone(obj)).not.toBe(obj);
		expect(Object.fastClone(obj)).toEqual(obj);
	});

	it('cloning of objects with cycle links', () => {
		const obj = {a: 1};
		obj.obj = obj;

		expect(Object.fastClone(obj)).not.toBe(obj);
		expect(Object.fastClone(obj)).toEqual(obj);
	});

	it('cloning of non extendable objects', () => {
		const
			obj = Object.preventExtensions({a: 1, b: 2}),
			clone = Object.fastClone(obj, {freezable: true});

		expect(clone).not.toBe(obj);
		expect(clone).toEqual(obj);
		expect(!Object.isExtensible(clone)).toBeTrue();
	});

	it('cloning of sealed objects', () => {
		const
			obj = Object.seal({a: 1, b: 2}),
			clone = Object.fastClone(obj, {freezable: true});

		expect(clone).not.toBe(obj);
		expect(clone).toEqual(obj);
		expect(Object.isSealed(clone)).toBeTrue();
	});

	it('cloning of frozen objects', () => {
		const
			obj = Object.freeze({a: 1, b: 2}),
			clone = Object.fastClone(obj, {freezable: true});

		expect(clone).not.toBe(obj);
		expect(clone).toEqual(obj);
		expect(Object.isFrozen(clone)).toBeTrue();
	});

	it('cloning of date objects', () => {
		const obj = new Date();
		expect(Object.fastClone(obj)).not.toBe(obj);
		expect(Object.fastClone(obj)).toEqual(obj);
	});

	it('cloning of functions', () => {
		const obj = () => 1;
		expect(Object.fastClone(obj)).toBe(obj);
	});

	it('cloning of map objects', () => {
		const obj = new Map([[1, 2], [2, {a: 1}]]);
		expect(Object.fastClone(obj)).not.toBe(obj);
		expect(Object.fastClone(obj)).toEqual(obj);
	});

	it('cloning of set objects', () => {
		const obj = new Set([{a: 1}]);
		expect(Object.fastClone(obj)).not.toBe(obj);
		expect(Object.fastClone(obj)).toEqual(obj);
	});

	it('custom revivers/replacers', () => {
		const
			obj = {a: new Set([1])};

		const clone = Object.fastClone(obj, {
			replacer: (key, obj) => Object.isSet(obj) ? [...obj] : obj,
			reviver: (key, obj) => Object.isArray(obj) ? new Set(obj) : obj
		});

		expect(clone).not.toBe(obj);
		expect(clone).toEqual(obj);
	});

	it('functional overload', () => {
		const
			obj = {a: new Set([1])};

		const clone = Object.fastClone(undefined, {
			replacer: (key, obj) => Object.isSet(obj) ? [...obj] : obj,
			reviver: (key, obj) => Object.isArray(obj) ? new Set(obj) : obj
		})(obj);

		expect(clone).not.toBe(obj);
		expect(clone).toEqual(obj);
	});
});


<|start_filename|>src/core/queue/worker/merge/spec.js<|end_filename|>
/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

import MergeQueue from 'core/queue/worker/merge';

describe('core/queue/worker/merge', () => {
	it('simple usage', async () => {
		const
			res = [];

		const queue = new MergeQueue((task) => {
			res.push(task.a);
			return Promise.resolve();

		}, {
			concurrency: 2,
			refreshInterval: 50,
			hashFn: (task) => JSON.stringify(task)
		});

		expect(queue.push({a: 1}))
			.toBeInstanceOf(Promise);

		queue.push({a: 1});
		queue.push({a: 2});
		queue.push({a: 3});

		expect(queue.length).toBe(1);
		expect(queue.head).toEqual({a: 3});
		expect(queue.pop()).toEqual({a: 3});

		queue.push({a: 4});
		await queue.push({a: 4}).then(() => {
			expect(queue.length).toBe(0);
			expect(res).toEqual([1, 2, 4]);
		});
	});

	it('alternative API', async () => {
		const
			res = [];

		const queue = new MergeQueue((task) => {
			res.push(task.a);
			return Promise.resolve();

		}, {
			concurrency: 2,
			refreshInterval: 50,
			hashFn: (task) => JSON.stringify(task)
		});

		expect(queue.unshift({a: 1}))
			.toBeInstanceOf(Promise);

		queue.unshift({a: 1});
		queue.unshift({a: 2});
		queue.unshift({a: 3});

		expect(queue.length).toBe(1);
		expect(queue.head).toEqual({a: 3});
		expect(queue.shift()).toEqual({a: 3});

		queue.unshift({a: 4});
		await queue.unshift({a: 4}).then(() => {
			expect(queue.length).toBe(0);
			expect(res).toEqual([1, 2, 4]);
		});
	});

	it('clearing of a queue', () => {
		const
			res = [];

		const queue = new MergeQueue((task) => {
			res.push(task.a);
			return Promise.resolve();

		}, {concurrency: 1});

		queue.unshift({a: 1});
		queue.unshift({a: 2});
		queue.unshift({a: 3});

		expect(queue.length).toBe(2);

		queue.clear();

		expect(queue.length).toBe(0);
		expect(res).toEqual([1]);
	});
});


<|start_filename|>docs/media/js/config.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

(function () {
	if (localStorage.getItem('visibility') == null) {
		localStorage.setItem('visibility', 'public');
	}

	document.title = document.title.replace(/['"]+|src\//g, '');
	document.body.style.display = 'none';
})();


<|start_filename|>src/core/prelude/object/metrics/spec.js<|end_filename|>
/* eslint-disable @typescript-eslint/typedef, @typescript-eslint/restrict-plus-operands */

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

describe('core/prelude/object/metrics/size', () => {
	it('array', () => {
		expect(Object.size([1, 2, 3])).toBe(3);
	});

	it('object', () => {
		expect(Object.size({a: 1})).toBe(1);
	});

	it('map', () => {
		expect(Object.size(new Map([[0, 1]]))).toBe(1);
	});

	it('set', () => {
		expect(Object.size(new Set([1, 2]))).toBe(2);
	});

	it('function', () => {
		expect(Object.size(foo)).toBe(2);

		function foo(a, b) {
			return a + b;
		}
	});

	it('string', () => {
		expect(Object.size('123')).toBe(3);
	});

	it('number', () => {
		expect(Object.size(2)).toBe(2);
		expect(Object.size(NaN)).toBe(0);
		expect(Object.size(Infinity)).toBe(Infinity);
	});

	it('iterable', () => {
		expect(Object.size([1, 2].values())).toBe(2);
	});

	it('null', () => {
		expect(Object.size(null)).toBe(0);
		expect(Object.size(undefined)).toBe(0);
	});
});


<|start_filename|>build/doc.gulp.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

/**
 * Registers gulp tasks to generate HTML documentation based on the project
 *
 * @example
 * ```bash
 * npx gulp build:docs
 * ```
 */
module.exports = function init(gulp) {
	const
		$ = require('gulp-load-plugins')({scope: ['optionalDependencies']});

	/**
	 * Builds an HTML files by using typedoc
	 */
	gulp.task('build:doc:typedoc', () => $.run('typedoc')
		.exec()
		.on('error', console.error));

	/**
	 * Normalizes generated HTML files: attaches extra styles and js, removes some trash
	 */
	gulp.task('build:doc:normalize', gulp.series([
		() => gulp.src('./docs/**/*.+(html|js|json)')
			.pipe($.replace(/(['"/\\])_+(.+?)_+(\.(?:[^\s'"/\\<>#.]+\.)?html\b)/g, (...str) => str.slice(1, 4).join('')))
			.pipe(gulp.dest('./docs')),

		() => gulp.src('./docs/**/*.html')
			.pipe($.replace(/<\/head>/, [
				`<style>${include('assets/css/docs.css', {source: true})}</style>`,
				'</head>'
			].join('\n')))

			.pipe($.replace(/<body>/, [
				'<body>',
				`<script>${include('assets/js/config.js', {source: true})}</script>`
			].join('\n')))

			.pipe($.replace(/<\/body>/, [
				`<script>${include('assets/js/docs.js', {source: true})}</script>`,
				'</body>'
			].join('\n')))

			.pipe(gulp.dest('./docs')),

		() => gulp.src('./docs/**/_*.html')
			.pipe($.rename((path) => {
				path.basename = path.basename.replace(/^_+|_+(?=\.)|_+$/g, '');
			}))

			.pipe(gulp.dest('./docs')),

		() => require('del')('./docs/**/_*.html')
	]));

	/**
	 * The main task to generate documentation
	 */
	gulp.task('build:doc', gulp.series(['build:tsconfig', 'build:doc:typedoc', 'build:doc:normalize']));
};


<|start_filename|>build/other.gulp.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

/**
 * Registers some helper gulp tasks
 *
 * @example
 * ```bash
 * # The task sets NODE_ENV environment variable to "production"
 * npx gulp setProd
 *
 * # Updates or adds head disclaimers to all files from the project
 * npx gulp head
 * ```
 */
module.exports = function init(gulp) {
	/**
	 * Sets NODE_ENV to production
	 */
	gulp.task('setProd', (cb) => {
		process.env.NODE_ENV = 'production';
		globalThis.isProd = true;
		cb();
	});

	/**
	 * Updates or adds head disclaimers to all files from the project
	 */
	gulp.task('head', () => {
		const
			through = require('through2'),
			{getHead} = include('build/helpers');

		const
			fullHead = `${getHead()}\n`,
			headRgxp = /(\/\*![\s\S]*?\*\/\n{2})/;

		const src = [
			'./@(src|config|build|ts-definitions)/**/*.@(js|ts|styl|ss)',
			'./@(index|gulpfile|webpack.config).js',
			'./index.d.ts'
		];

		return gulp.src(src, {base: './', since: gulp.lastRun('head')})
			.pipe(through.obj(function thread(file, enc, cb) {
				const
					contents = file.contents.toString(),
					header = headRgxp.exec(contents);

				if (header) {
					if (header[0] !== fullHead) {
						file.contents = new Buffer(contents.replace(headRgxp, fullHead));
						this.push(file);
					}

				} else {
					const
						useStrict = /^(['"])use strict\1;\n+/;

					if (useStrict.test(contents)) {
						file.contents = new Buffer(contents.replace(useStrict, (str) => str + fullHead));

					} else {
						file.contents = new Buffer(fullHead + contents);
					}

					this.push(file);
				}

				return cb();
			}))

			.pipe(gulp.dest('./'));
	});
};


<|start_filename|>config/global.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

const
	path = require('path');

globalThis.isProd = false;
globalThis.include = require;

Object.defineProperties(globalThis, {
	include: {
		get() {
			return require(path.join(process.cwd(), 'config/default')).src.include();
		}
	},

	API_URL: {
		get() {
			return require('config').apiURL();
		}
	},

	isProd: {
		get() {
			return require('config').environment === 'production';
		}
	},

	IS_PROD: {
		get() {
			return isProd;
		}
	}
});


<|start_filename|>docs/media/js/docs.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

(function () {
	document.body.style.display = 'block';

	var
		isDTS = /^index$|\.d$/,
		needHide = /\/(?:prelude|interface|const|modules|helpers|engines)\b/,
		isNode = /(?:^|\/)node_modules(?:\/|$)/;

	var
		trimRgxp = /^\s+|[\n\v"']+|\s+$/g,
		normalizeRgxp = /(?:^|\b)src\/|\/index$/g;

	var
		breadcrumbs = Array.from(document.querySelectorAll('.tsd-breadcrumb a')),
		headers = Array.from(document.querySelectorAll('h1'));

	breadcrumbs.forEach(function (el) {
		el.textContent = el.textContent.replace(trimRgxp, '').replace(normalizeRgxp, '');
	});

	headers.forEach(function (el) {
		el.textContent = el.textContent.replace(trimRgxp, '').replace(normalizeRgxp, '');
	});

	var
		navigation = Array.from(document.querySelectorAll('.tsd-navigation.primary .tsd-kind-module a')),
		globalIndex = Array.from(document.querySelectorAll('.tsd-kind-module a'));

	[].concat(breadcrumbs.length <= 1 ? globalIndex : navigation).forEach(function (el) {
		var
			wrapper = el.parentNode,
			linkText = el.textContent.replace(trimRgxp, '');

		if (isDTS.test(linkText)) {
			var
				nm = RegExp.$1;

			if (linkText === 'index') {
				el.innerHTML = '<b>prelude</b>';

			} else if (isNode.test(linkText)) {
				el.textContent = nm;

			} else {
				wrapper.parentNode.removeChild(wrapper);
			}

		} else if (needHide.test(linkText)) {
			wrapper.parentNode.removeChild(wrapper);

		} else {
			el.textContent = linkText.replace(normalizeRgxp, '');
		}
	});
})();


<|start_filename|>build/const.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

const
	{config: {projectName, dependencies}} = require('@pzlr/build-core');

/**
 * String with project dependencies to use with regular expressions
 */
exports.depsRgxpStr = [projectName]
	.concat(dependencies)

	.map((el) => {
		const src = Object.isString(el) ? el : el.src;
		return src.split(/[\\/]/).map(RegExp.escape).join('[\\\\/]');
	})

	.join('|');

/**
 * RegExp to detect file paths that are registered as dependencies within ".pzlrrc"
 * @type {RegExp}
 *
 * @example
 * **.pzlrrc**
 * ```json
 * {
 *   dependencies: ['@v4fire/client', '@v4fire/core']
 * }
 * ```
 *
 * ```js
 * isLayerDep.test('./node_modules/@v4fire/client/bla')              // true
 * isLayerDep.test('./node_modules/@v4fire/client/node_modules/bla') // false
 * isLayerDep.test('./node_modules/bla')                             // false
 * ```
 */
exports.isLayerDep = new RegExp(
	'' +

	// Layer imports
	`(?:^|[\\\\/])node_modules[\\\\/](?:${exports.depsRgxpStr})(?:[\\\\/]|$)` +

	'|' +

	// Simple imports
	'^(?:(?!(?:^|[\\\\/])node_modules[\\\\/]).)*$'
);

/**
 * RegExp to detect file paths that aren't registered as dependencies within ".pzlrrc"
 * @type {RegExp}
 *
 * @example
 * **.pzlrrc**
 * ```json
 * {
 *   dependencies: ['@v4fire/client', '@v4fire/core']
 * }
 * ```
 *
 * ```js
 * isExternalDep.test('./node_modules/@v4fire/client/bla')              // false
 * isExternalDep.test('./node_modules/@v4fire/client/node_modules/bla') // true
 * isExternalDep.test('./node_modules/bla')                             // true
 * ```
 */
exports.isExternalDep = new RegExp(
	'' +

	'^(?:(?!(?:^|[\\\\/])node_modules[\\\\/]).)*' +

	`[\\\\/]?node_modules[\\\\/](?:(?!${exports.depsRgxpStr}).)*$`
);


<|start_filename|>gulpfile.js<|end_filename|>
'use strict';

/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

require('config');

/**
 * Initializes the specified gulp instance.
 * This helper brings a feature to extends one gulp config from another.
 *
 * @param gulp - link to the gulp module
 *
 * @example
 * ```js
 * require('config');
 *
 * module.exports = function (gulp = require('gulp')) {
 *   // Include the parent config
 *   include('@super/gulpfile', __dirname)(gulp);
 *
 *   // Register own tasks
 *   include('build/my-extra-gulp-tasks')(gulp);
 *
 *   // Call the special method to initialize registered tasks
 *   global.callGulp(module);
 * };
 *
 * module.exports();
 * ```
 */
module.exports = function initGulp(gulp = require('gulp')) {
	/**
	 * The global helper to initialize gulp tasks
	 */
	globalThis.callGulp = (module) => {
		if (/gulp-cli/.test(module.parent.id)) {
			gulp.init();
		}
	};

	const {wrapGulp} = include('build/wrap.gulp');
	wrapGulp(gulp);

	include('build/tsconfig.gulp')(gulp);
	include('build/build.gulp')(gulp);
	include('build/doc.gulp')(gulp);
	include('build/other.gulp')(gulp);

	globalThis.callGulp(module);
};

module.exports();


<|start_filename|>docs/media/css/docs.css<|end_filename|>
/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

body {
	font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
}

code, pre, tt {
	font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
}

.tsd-typography h1,
.tsd-typography h2,
.tsd-typography h3,
.tsd-typography h4,
.tsd-typography h5,
.tsd-typography h6 {
	margin: 1em 0;
	font-family: -apple-system, BlinkMacSystemFont, UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
}

.tsd-panel {
	padding: 20px 40px;
	border: 1px solid #DDD;
	border-radius: 10px;
	box-shadow: none;
}

.tsd-page-title {
	color: #EEE;

	background: #232526; /* fallback for old browsers */
	background: -webkit-linear-gradient(to right, #414345, #232526); /* Chrome 10-25, Safari 5.1-6 */
	background: linear-gradient(to right, #414345, #232526); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}

.tsd-page-toolbar {
	height: 43px;
}

.title {
	display: inline-flex;
	align-items: center;
}

.title::before {
	content: "";

	display: inline-block;
	width: 20px;
	height: 20px;
	margin-right: 10px;

	border-radius: 5px;
	background-image: url("https://avatars0.githubusercontent.com/u/29952525?s=200&v=4");
	background-size: contain;
}

#tsd-search .tsd-widget.search.no-caption {
	bottom: 0;
}

#tsd-search .field {
	height: 100%;
}

pre {
	background-color: rgba(7, 7, 7, 0.01);
}

/**
 * GitHub Gist Theme
 * Author : <NAME> - https://github.com/AnthonyAttard
 * Author : <NAME> - https://github.com/LouisBarranqueiro
 */

.hljs {
	display: block;
	background: white;
	padding: 0.5em;
	color: #333333;
	overflow-x: auto;
}

.hljs-comment,
.hljs-meta {
	color: #969896;
}

.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
	color: #df5000;
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
	color: #d73a49;
}

.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
	color: #0086b3;
}

.hljs-section,
.hljs-name {
	color: #63a35c;
}

.hljs-tag {
	color: #333333;
}

.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
	color: #6f42c1;
}

.hljs-addition {
	color: #55a532;
	background-color: #eaffea;
}

.hljs-deletion {
	color: #bd2c00;
	background-color: #ffecec;
}

.hljs-link {
	text-decoration: underline;
}

.hljs-number {
	color: #005cc5;
}

.hljs-string {
	color: #032f62;
}


<|start_filename|>src/core/semver/spec.js<|end_filename|>
/*!
 * V4Fire Core
 * https://github.com/V4Fire/Core
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Core/blob/master/LICENSE
 */

import check, { operandLengthErrorText } from 'core/semver';

describe('core/semver', () => {
	it('greater than (>)', () => {
		expect(check('1.1.1', '2.1.1', '>')).toBeFalse();
		expect(check('1.1.1', '1.2.1', '>')).toBeFalse();
		expect(check('1.1.1', '1.1.2', '>')).toBeFalse();
		expect(check('1.1.2', '2.1.1', '>')).toBeFalse();
		expect(check('1.1.2', '1.2.1', '>')).toBeFalse();
		expect(check('1.1.3', '2.1.1', '>')).toBeFalse();
		expect(check('1.1.3', '1.2.1', '>')).toBeFalse();
		expect(check('1.2.1', '2.1.1', '>')).toBeFalse();
		expect(check('1.3.1', '2.1.1', '>')).toBeFalse();

		expect(check('2.1.1', '1.1.1', '>')).toBeTrue();
		expect(check('1.2.1', '1.1.1', '>')).toBeTrue();
		expect(check('1.1.2', '1.1.1', '>')).toBeTrue();
		expect(check('2.1.1', '1.1.2', '>')).toBeTrue();
		expect(check('1.2.1', '1.1.2', '>')).toBeTrue();
		expect(check('2.1.1', '1.1.3', '>')).toBeTrue();
		expect(check('1.2.1', '1.1.3', '>')).toBeTrue();
		expect(check('2.1.1', '1.2.1', '>')).toBeTrue();
		expect(check('2.1.1', '1.3.1', '>')).toBeTrue();

		expect(check('1.1.2', '1.1.2', '>')).toBeFalse();

		expect(check('1.0.0', '1.2.7', '>')).toBeFalse();

		expect(check('1.*', '1.2.7', '>')).toBeFalse();

		expect(check('1.3.0', '1.2.*', '>')).toBeTrue();
		expect(check('1.2.*', '1.3.0', '>')).toBeFalse();

		expect(check('1.2.7', '1.*', '>')).toBeFalse();
		expect(check('1.2.4', '1.2.*', '>')).toBeFalse();
	});

	it('greater than or equal (>=)', () => {
		expect(check('1.1.1', '2.1.1', '>=')).toBeFalse();
		expect(check('1.1.1', '1.2.1', '>=')).toBeFalse();
		expect(check('1.1.1', '1.1.2', '>=')).toBeFalse();
		expect(check('1.1.2', '2.1.1', '>=')).toBeFalse();
		expect(check('1.1.2', '1.2.1', '>=')).toBeFalse();
		expect(check('1.1.3', '2.1.1', '>=')).toBeFalse();
		expect(check('1.1.3', '1.2.1', '>=')).toBeFalse();
		expect(check('1.2.1', '2.1.1', '>=')).toBeFalse();
		expect(check('1.3.1', '2.1.1', '>=')).toBeFalse();

		expect(check('2.1.1', '1.1.1', '>=')).toBeTrue();
		expect(check('1.2.1', '1.1.1', '>=')).toBeTrue();
		expect(check('1.1.2', '1.1.1', '>=')).toBeTrue();
		expect(check('2.1.1', '1.1.2', '>=')).toBeTrue();
		expect(check('1.2.1', '1.1.2', '>=')).toBeTrue();
		expect(check('2.1.1', '1.1.3', '>=')).toBeTrue();
		expect(check('1.2.1', '1.1.3', '>=')).toBeTrue();
		expect(check('2.1.1', '1.2.1', '>=')).toBeTrue();
		expect(check('2.1.1', '1.3.1', '>=')).toBeTrue();

		expect(check('1.1.2', '1.1.2', '>=')).toBeTrue();

		expect(check('1.*', '1.2.7', '>=')).toBeTrue();

		expect(check('1.3.0', '1.2.*', '>=')).toBeTrue();
		expect(check('1.2.*', '1.3.0', '>=')).toBeFalse();

		expect(check('1.2.7', '1.*', '>=')).toBeTrue();
		expect(check('1.2.4', '1.2.*', '>=')).toBeTrue();
	});

	it('less than (<)', () => {
		expect(check('1.1.1', '2.1.1', '<')).toBeTrue();
		expect(check('1.1.1', '1.2.1', '<')).toBeTrue();
		expect(check('1.1.1', '1.1.2', '<')).toBeTrue();
		expect(check('1.1.2', '2.1.1', '<')).toBeTrue();
		expect(check('1.1.2', '1.2.1', '<')).toBeTrue();
		expect(check('1.1.3', '2.1.1', '<')).toBeTrue();
		expect(check('1.1.3', '1.2.1', '<')).toBeTrue();
		expect(check('1.2.1', '2.1.1', '<')).toBeTrue();
		expect(check('1.3.1', '2.1.1', '<')).toBeTrue();

		expect(check('2.1.1', '1.1.1', '<')).toBeFalse();
		expect(check('1.2.1', '1.1.1', '<')).toBeFalse();
		expect(check('1.1.2', '1.1.1', '<')).toBeFalse();
		expect(check('2.1.1', '1.1.2', '<')).toBeFalse();
		expect(check('1.2.1', '1.1.2', '<')).toBeFalse();
		expect(check('2.1.1', '1.1.3', '<')).toBeFalse();
		expect(check('1.2.1', '1.1.3', '<')).toBeFalse();
		expect(check('2.1.1', '1.2.1', '<')).toBeFalse();
		expect(check('2.1.1', '1.3.1', '<')).toBeFalse();

		expect(check('1.1.2', '1.1.2', '<')).toBeFalse();

		expect(check('1.0.0', '1.2.7', '<')).toBeTrue();

		expect(check('1.*', '1.2.7', '<')).toBeFalse();
		expect(check('1.3.0', '1.2.*', '<')).toBeFalse();
		expect(check('1.2.7', '1.*', '<')).toBeFalse();
		expect(check('1.2.4', '1.2.*', '<')).toBeFalse();
	});

	it('less than or equal (<=)', () => {
		expect(check('1.1.1', '2.1.1', '<=')).toBeTrue();
		expect(check('1.1.1', '1.2.1', '<=')).toBeTrue();
		expect(check('1.1.1', '1.1.2', '<=')).toBeTrue();
		expect(check('1.1.2', '2.1.1', '<=')).toBeTrue();
		expect(check('1.1.2', '1.2.1', '<=')).toBeTrue();
		expect(check('1.1.3', '2.1.1', '<=')).toBeTrue();
		expect(check('1.1.3', '1.2.1', '<=')).toBeTrue();
		expect(check('1.2.1', '2.1.1', '<=')).toBeTrue();
		expect(check('1.3.1', '2.1.1', '<=')).toBeTrue();

		expect(check('2.1.1', '1.1.1', '<=')).toBeFalse();
		expect(check('1.2.1', '1.1.1', '<=')).toBeFalse();
		expect(check('1.1.2', '1.1.1', '<=')).toBeFalse();
		expect(check('2.1.1', '1.1.2', '<=')).toBeFalse();
		expect(check('1.2.1', '1.1.2', '<=')).toBeFalse();
		expect(check('2.1.1', '1.1.3', '<=')).toBeFalse();
		expect(check('1.2.1', '1.1.3', '<=')).toBeFalse();
		expect(check('2.1.1', '1.2.1', '<=')).toBeFalse();
		expect(check('2.1.1', '1.3.1', '<=')).toBeFalse();

		expect(check('1.1.2', '1.1.2', '<=')).toBeTrue();

		expect(check('1.3.0', '1.2.*', '<=')).toBeFalse();
		expect(check('1.0.0', '1.2.7', '<=')).toBeTrue();

		expect(check('1.*', '1.2.7', '<=')).toBeTrue();
		expect(check('1.3.*', '1.2.*', '<=')).toBeFalse();
		expect(check('1.2.7', '1.*', '<=')).toBeTrue();
		expect(check('1.2.4', '1.2.*', '<=')).toBeTrue();
	});

	it('equal (==)', () => {
		expect(check('1.3.0', '1.2.*', '==')).toBeFalse();
		expect(check('1.2.9', '1.2.7', '==')).toBeFalse();
		expect(check('1.2.9', '1.2.9', '==')).toBeTrue();
		expect(check('1.0.0', '1.2.7', '==')).toBeFalse();

		expect(check('1', '1.2.7', '==')).toBeTrue();
		expect(check('1.*', '1.2.7', '==')).toBeTrue();
		expect(check('1.2.7', '1.*', '==')).toBeTrue();
		expect(check('1.2.4', '1.2.*', '==')).toBeTrue();
	});

	it('caret range', () => {
		expect(check('0.8.3', '0.9.0', '^=')).toBeFalse();
		expect(check('0.0.1', '0.0.2', '^=')).toBeFalse();
		expect(check('2.1.0', '1.2.3', '^=')).toBeFalse();

		expect(check('1.2', '2.0', '^=')).toBeFalse();

		expect(check('1', '1.0.0', '^=')).toBeTrue();
		expect(check('2', '2.2.10', '^=')).toBeTrue();
		expect(check('3', '2.0.0', '^=')).toBeFalse();
		expect(check('5', '6', '^=')).toBeFalse();
	});

	it('tilda range', () => {
		expect(check('0.8.3', '0.9.0', '~=')).toBeFalse();
		expect(check('0.0.1', '0.0.2', '~=')).toBeFalse();
		expect(check('2.0.2', '1.0.1', '~=')).toBeFalse();

		expect(check('0.0.2', '0.0.1', '~=')).toBeTrue();
		expect(check('1.2.4', '1.2.3', '~=')).toBeTrue();
		expect(check('1.5.2', '1', '~=')).toBeTrue();
	});

	it('caret range with x-range', () => {
		expect(check('*', '0.0.2', '^=')).toBeTrue();
		expect(check('1.*', '0.0.5', '^=')).toBeFalse();
		expect(check('1.*', '1.0.2', '^=')).toBeTrue();
		expect(check('1.*', '1.2.3', '^=')).toBeTrue();
		expect(check('1.2.*', '2.0.0', '^=')).toBeFalse();

		expect(check('1.2.*', '2.0.0', '^=')).toBeFalse();
		expect(check('1.2.3', '2.*', '^=')).toBeFalse();
		expect(check('1.2.3', '1.*', '^=')).toBeTrue();
		expect(check('2', '1.*', '^=')).toBeFalse();
	});

	it('expect error', () => {
		expect(() => check(' ', '0.0.2', '^=')).toThrowError(operandLengthErrorText);
		expect(() => check('', '2.0.0', '^=')).toThrowError(operandLengthErrorText);
		expect(() => check('2.0.0', '', '^=')).toThrowError(operandLengthErrorText);
		expect(() => check('', '', '^=')).toThrowError(operandLengthErrorText);
	});
});
