UNPKG

@e22m4u/js-repository

Version:

Реализация репозитория для работы с базами данных в Node.js

513 lines (481 loc) 22.7 kB
import {expect} from 'chai'; import {format} from '@e22m4u/js-format'; import {DatabaseSchema} from '../database-schema.js'; import {FieldsClauseTool} from './fields-clause-tool.js'; import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../definition/index.js'; const dbs = new DatabaseSchema(); const MODEL_NAME = 'model'; dbs.defineModel({name: MODEL_NAME}); const T = dbs.getService(FieldsClauseTool); describe('FieldsClauseTool', function () { describe('filter', function () { describe('object', function () { describe('single field', function () { it('does not throw an error if the given field is not exist', function () { const object = {foo: 'a1', bar: 'a2', baz: 'a3'}; const res = T.filter(object, MODEL_NAME, 'qux'); expect(res).to.be.eql({}); }); it('requires the first argument to be an object', function () { const throwable = v => () => T.filter(v, MODEL_NAME, 'bar'); const error = v => format( 'The first argument of FieldsClauseTool.filter should be an Object or ' + 'an Array of Object, but %s was given.', v, ); expect(throwable('str')).to.throw(error('"str"')); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable({foo: 'a1', bar: 'a2'})()).to.be.eql({bar: 'a2'}); expect(throwable({})()).to.be.eql({}); }); it('requires the second argument to be a non-empty string', function () { const entity = {foo: 'a1', bar: 'a2', baz: 'a3'}; const throwable = v => () => T.filter(entity, v, 'bar'); const error = v => format( 'The second argument of FieldsClauseTool.filter should be ' + 'a non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable('model')()).to.be.eql({bar: 'a2'}); }); it('requires the third argument to be a non-empty string', function () { const entity = {foo: 'a1', bar: 'a2', baz: 'a3'}; const throwable = v => () => T.filter(entity, MODEL_NAME, v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable({})).to.throw(error('Object')); expect(throwable('bar')()).to.be.eql({bar: 'a2'}); expect(throwable(undefined)()).to.be.eq(entity); expect(throwable(null)()).to.be.eq(entity); }); it('picks field of the given object', function () { const value = {foo: 'a1', bar: 'a2', baz: 'a3'}; const result = T.filter(value, MODEL_NAME, 'bar'); expect(result).to.be.eql({bar: 'a2'}); }); it('includes the primary key of the given object', function () { const value = {[DEF_PK]: 10, foo: 'a1', bar: 'a2', baz: 'a3'}; const result = T.filter(value, MODEL_NAME, 'bar'); expect(result).to.be.eql({[DEF_PK]: 10, bar: 'a2'}); }); }); describe('multiple fields', function () { it('does not throw an error if multiple fields is not exist', function () { const object = {foo: 'a1', bar: 'a2', baz: 'a3'}; const res = T.filter(object, MODEL_NAME, ['bar', 'qux']); expect(res).to.be.eql({bar: 'a2'}); }); it('requires the first argument to be an object', function () { const throwable = v => () => T.filter(v, MODEL_NAME, ['bar', 'baz']); const error = v => format( 'The first argument of FieldsClauseTool.filter should be an Object or ' + 'an Array of Object, but %s was given.', v, ); expect(throwable('str')).to.throw(error('"str"')); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable({foo: 'a1', bar: 'a2'})()).to.be.eql({bar: 'a2'}); expect(throwable({})()).to.be.eql({}); }); it('requires the second argument to be a non-empty string', function () { const entity = {foo: 'a1', bar: 'a2', baz: 'a3'}; const throwable = v => () => T.filter(entity, v, ['bar', 'baz']); const error = v => format( 'The second argument of FieldsClauseTool.filter should be ' + 'a non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable('model')()).to.be.eql({bar: 'a2', baz: 'a3'}); }); it('requires the third argument to be an array of non-empty strings', function () { const entity = {foo: 'a1', bar: 'a2', baz: 'a3'}; const throwable = v => () => T.filter(entity, MODEL_NAME, v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([{}])).to.throw(error('Object')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); expect(throwable(['bar', 'baz'])()).to.be.eql({bar: 'a2', baz: 'a3'}); expect(throwable([])()).to.be.eq(entity); }); it('picks fields of the given object', function () { const value = {foo: 'a1', bar: 'a2', baz: 'a3'}; const result = T.filter(value, MODEL_NAME, ['bar', 'baz']); expect(result).to.be.eql({bar: 'a2', baz: 'a3'}); }); it('includes the primary key of the given object', function () { const value = {[DEF_PK]: 10, foo: 'a1', bar: 'a2', baz: 'a3'}; const result = T.filter(value, MODEL_NAME, ['bar', 'baz']); expect(result).to.be.eql({[DEF_PK]: 10, bar: 'a2', baz: 'a3'}); }); }); }); describe('array', function () { describe('single field', function () { it('does not throw an error if the given field is not exist', function () { const objects = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const res = T.filter(objects, MODEL_NAME, 'qux'); expect(res).to.be.eql([{}, {}, {}]); }); it('requires the first argument to be an array of objects', function () { const throwable = v => () => T.filter(v, MODEL_NAME, 'bar'); const error = v => format( 'The first argument of FieldsClauseTool.filter should be an Object or ' + 'an Array of Object, but %s was given.', v, ); expect(throwable(['str'])).to.throw(error('"str"')); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); expect(throwable([{foo: 'a1', bar: 'a2'}])()).to.be.eql([ {bar: 'a2'}, ]); expect(throwable([{}])()).to.be.eql([{}]); }); it('requires the second argument to be a non-empty string', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const throwable = v => () => T.filter(entities, v, 'bar'); const error = v => format( 'The second argument of FieldsClauseTool.filter should be ' + 'a non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable('model')()).to.be.eql([ {bar: 'a2'}, {bar: 'b2'}, {bar: 'c2'}, ]); }); it('requires the third argument to be a non-empty string', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const throwable = v => () => T.filter(entities, MODEL_NAME, v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable({})).to.throw(error('Object')); expect(throwable('bar')()).to.be.eql([ {bar: 'a2'}, {bar: 'b2'}, {bar: 'c2'}, ]); expect(throwable(undefined)()).to.be.eq(entities); expect(throwable(null)()).to.be.eq(entities); }); it('picks field of the given object', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const result = T.filter(entities, MODEL_NAME, 'bar'); expect(result).to.have.lengthOf(3); expect(result[0]).to.be.eql({bar: 'a2'}); expect(result[1]).to.be.eql({bar: 'b2'}); expect(result[2]).to.be.eql({bar: 'c2'}); }); it('includes the primary key of the given object', function () { const entities = [ {[DEF_PK]: 1, foo: 'a1', bar: 'a2', baz: 'a3'}, {[DEF_PK]: 2, foo: 'b1', bar: 'b2', baz: 'b3'}, {[DEF_PK]: 3, foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const result = T.filter(entities, MODEL_NAME, 'bar'); expect(result).to.have.lengthOf(3); expect(result[0]).to.be.eql({[DEF_PK]: 1, bar: 'a2'}); expect(result[1]).to.be.eql({[DEF_PK]: 2, bar: 'b2'}); expect(result[2]).to.be.eql({[DEF_PK]: 3, bar: 'c2'}); }); }); describe('multiple fields', function () { it('does not throw an error if multiple fields is not exist', function () { const object = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const res = T.filter(object, MODEL_NAME, ['bar', 'qux']); expect(res[0]).to.be.eql({bar: 'a2'}); expect(res[1]).to.be.eql({bar: 'b2'}); expect(res[2]).to.be.eql({bar: 'c2'}); }); it('requires the first argument to be an array of objects', function () { const throwable = v => () => T.filter(v, MODEL_NAME, ['bar', 'baz']); const error = v => format( 'The first argument of FieldsClauseTool.filter should be an Object or ' + 'an Array of Object, but %s was given.', v, ); expect(throwable(['str'])).to.throw(error('"str"')); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); expect(throwable([{foo: 'a1', bar: 'a2'}])()).to.be.eql([ {bar: 'a2'}, ]); expect(throwable([{}])()).to.be.eql([{}]); }); it('requires the second argument to be a non-empty string', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const throwable = v => () => T.filter(entities, v, ['bar', 'baz']); const error = v => format( 'The second argument of FieldsClauseTool.filter should be ' + 'a non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable(undefined)).to.throw(error('undefined')); expect(throwable(null)).to.throw(error('null')); expect(throwable('model')()).to.be.eql([ {bar: 'a2', baz: 'a3'}, {bar: 'b2', baz: 'b3'}, {bar: 'c2', baz: 'c3'}, ]); }); it('requires the third argument to be a non-empty string', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const throwable = v => () => T.filter(entities, MODEL_NAME, v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([{}])).to.throw(error('Object')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); expect(throwable(['bar', 'baz'])()).to.be.eql([ {bar: 'a2', baz: 'a3'}, {bar: 'b2', baz: 'b3'}, {bar: 'c2', baz: 'c3'}, ]); }); it('picks field of the given object', function () { const entities = [ {foo: 'a1', bar: 'a2', baz: 'a3'}, {foo: 'b1', bar: 'b2', baz: 'b3'}, {foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const result = T.filter(entities, MODEL_NAME, ['bar', 'baz']); expect(result).to.have.lengthOf(3); expect(result[0]).to.be.eql({bar: 'a2', baz: 'a3'}); expect(result[1]).to.be.eql({bar: 'b2', baz: 'b3'}); expect(result[2]).to.be.eql({bar: 'c2', baz: 'c3'}); }); it('includes the primary key of the given object', function () { const entities = [ {[DEF_PK]: 1, foo: 'a1', bar: 'a2', baz: 'a3'}, {[DEF_PK]: 2, foo: 'b1', bar: 'b2', baz: 'b3'}, {[DEF_PK]: 3, foo: 'c1', bar: 'c2', baz: 'c3'}, ]; const result = T.filter(entities, MODEL_NAME, ['bar', 'baz']); expect(result).to.have.lengthOf(3); expect(result[0]).to.be.eql({[DEF_PK]: 1, bar: 'a2', baz: 'a3'}); expect(result[1]).to.be.eql({[DEF_PK]: 2, bar: 'b2', baz: 'b3'}); expect(result[2]).to.be.eql({[DEF_PK]: 3, bar: 'c2', baz: 'c3'}); }); }); }); }); describe('validateFieldsClause', function () { describe('single field', function () { it('requires the first argument to be a non-empty string', function () { const throwable = v => () => FieldsClauseTool.validateFieldsClause(v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable({})).to.throw(error('Object')); throwable('field')(); throwable(undefined)(); throwable(null)(); }); }); describe('multiple fields', function () { it('requires the first argument to be an array of non-empty strings', function () { const throwable = v => () => FieldsClauseTool.validateFieldsClause(v); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([{}])).to.throw(error('Object')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); throwable(['field'])(); throwable([])(); }); }); }); describe('normalizeFieldsClause', function () { describe('single field', function () { it('requires the first argument to be a non-empty string', function () { const throwable = clause => () => FieldsClauseTool.normalizeFieldsClause(clause); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable('')).to.throw(error('""')); expect(throwable(10)).to.throw(error('10')); expect(throwable(0)).to.throw(error('0')); expect(throwable(true)).to.throw(error('true')); expect(throwable(false)).to.throw(error('false')); expect(throwable({})).to.throw(error('Object')); expect(throwable('field')()).to.be.eql(['field']); expect(throwable(undefined)()).to.be.undefined; expect(throwable(null)()).to.be.undefined; }); it('returns an array of strings', function () { const fn = FieldsClauseTool.normalizeFieldsClause; expect(fn('foo')).to.be.eql(['foo']); }); }); describe('multiple fields', function () { it('requires the first argument to be an array of non-empty strings', function () { const throwable = clause => () => FieldsClauseTool.normalizeFieldsClause(clause); const error = v => format( 'The provided option "fields" should be a non-empty String ' + 'or an Array of non-empty String, but %s was given.', v, ); expect(throwable([''])).to.throw(error('""')); expect(throwable([10])).to.throw(error('10')); expect(throwable([0])).to.throw(error('0')); expect(throwable([true])).to.throw(error('true')); expect(throwable([false])).to.throw(error('false')); expect(throwable([{}])).to.throw(error('Object')); expect(throwable([undefined])).to.throw(error('undefined')); expect(throwable([null])).to.throw(error('null')); expect(throwable(['field'])()).to.be.eql(['field']); expect(throwable([])()).to.be.undefined; }); it('returns an array of strings', function () { const fn = FieldsClauseTool.normalizeFieldsClause; expect(fn(['foo'])).to.be.eql(['foo']); expect(fn(['foo', 'bar'])).to.be.eql(['foo', 'bar']); }); }); }); });