You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-10 11:43:01 +03:00
* init v4 * add .gitignore to benchmark * spawn redis-servers for tests, add some tests, fix client auth on connect * add tests coverage report * add tests workflow, replace nyc text reporter with text-summary * run tests with node 16.x & redis 6.x only (for now) * add socket events on client, stop reconnectiong when manually calling disconnect, remove abort signal listener when a command is written on the socket * add isOpen boolean getter on client, add maxLength option to command queue, add test for client.multi * move to use CommonJS * add MULTI and EXEC commands to when executing multi command, make client.multi return type innerit the module commands, clean some tests, exclute spec files from coverage report * missing file from commit61edd4f1b5
* exclude spec files from coverage report * add support for options in a command function (.get, .set, ...), add support for the SELECT command, implement a couple of commands, fix client socket reconnection strategy, add support for using replicas (RO) in cluster, and more.. * fix client.blPop test * use which to find redis-server path * change command options to work with Symbol rather then WeakSet * implement more commands * Add support for lua scripts in client & muilti, fix client socket initiator, implement simple cluster nodes discovery strategy * replace `callbackify` with `legacyMode` * add the SCAN command and client.scanIterator * rename scanIterator * init benchmark workflow * fix benchmark workflow * fix benchmark workflow * fix benchmark workflow * push coverage report to Coveralls * fix Coveralls * generator lcov (for Coveralls) * fix .nycrc.json * PubSub * add support for all set commands (including sScanIterator) * support pipeline * fix KEEPTTL in SET * remove console.log * add HyperLogLog commands * update README.md (thanks to @guyroyse) * add support for most of the "keys commands" * fix EXPIREAT.spec.ts * add support for date in both EXPIREAT & EXPIRE * add tests * better cluster nodes discorvery strategy after MOVED error, add PubSub test * fix PubSub UNSUBSCRIBE/PUNSUBSCRIBE without channel and/or listener * fix PubSub * add release-it to dev dependencies * Release 4.0.0-next.0 * fix .npmignore * Release 4.0.0-next.1 * fix links in README.md * fix .npmignore * Release 4.0.0-next.2 * add support for all sorted set commands * add support for most stream commands * add missing file from commit53de279afe
* lots of todo commends * make PubSub test more stable * clean ZPOPMAX * add support for lua scripts and modules in cluster, spawn cluster for tests, add some cluster tests, fix pubsub listener arguments * GET.spec.ts * add support for List commands, fix some Sorted Set commands, add some cluster commands, spawn cluster for testing, add support for command options in cluster, and more * add missing file from commitfaab94fab2
* clean ZRANK and ZREVRANK * add XREAD and XREADGROUP commands * remove unused files * implement a couple of more commands, make cluster random iterator be per node (instead of per slot) * Release 4.0.0-next.3 * app spec files to npmignore * fix some code analyzers (LGTM, deepsource, codeclimate) issues * fix CLUSTER_NODES, add some tests * add HSCAN, clean some commands, add tests for generic transformers * add missing files from0feb35a1fb
* update README.md (thanks to @guyroyse) * handle ASK errors, add some commands and tests * Release 4.0.0-next.4 * replace "modern" with "v4" * remove unused imports * add all ACL subcommands, all MODULE subcommands, and some other commands * remove 2 unused imports * fix BITFIELD command * fix XTRIM spec file * clean code * fix package.json types field * better modules support, fix some bugs in legacy mode, add some tests * remove unused function * add test for hScanIterator * change node mimimum version to 12 (latest LTS) * update tsconfig.json to support node 12, run tests on Redis 5 & 6 and on all node live versions * remove future node releases :P * remove "lib" from ts compiler options * Update tsconfig.json * fix build * run some tests only on supported redis versions, use coveralls parallel mode * fix tests * Do not use "timers/promises", fix "isRedisVersionGreaterThan" * skip AbortController tests when not available * use 'fs'.promises instead of 'fs/promises' * add some missing commands * run GETDEL tests only if the redis version is greater than 6.2 * implement some GEO commands, improve scan generic transformer, expose RPUSHX * fix GEOSEARCH & GEOSEARCHSTORE * use socket.setNoDelay and queueMicrotask to improve latency * commands-queue.ts: String length / byte length counting issue (#1630) * Update commands-queue.ts Hopefully fixing #1628 * Reverted 2fa5ea6, and implemented test for byte length check * Changed back to Buffer.byteLength, due to issue author input. Updated test to look for 4 bytes. * Fixed. There were two places that length was calculated. * Removed redundant string assignment * add 2 bytes test as well Co-authored-by: Leibale Eidelman <leibale1998@gmail.com> * fix scripts in multi * do not hide bugs in redis * fix fore7bf09644b
* remove unused import * implement WATCH command, fix ZRANGESTORE & GEOSEARCHSTORE tests * update README.md Co-authored-by: @GuyRoyse * use typedoc to auto generate documentation * run "npm install" before "npm run documentation" * clean documentation workflow * fix WATCH spec file * increase "CLUSTER_NODE_TIMEOUT" to 5000ms to avoid "CLUSTERDOWN" errors in tests * pull cluster state every 100 ms * await meetPromises before pulling the cluster state * enhance the way commanders (client/multi/cluster) get extended with modules and scripts * add test for socket retry strategy * implement more commands * set GETEX minimum version to 6.2 * remove unused imports * add support for multi in cluster * upgrade dependencies * Release 4.0.0-next.5 * remove unused imports * improve benchmarking * use the same Multi with duplicated clients * exclude some files from the documentation, add some exports, clean code * fix #1636 - handle null in multi.exec * remove unused import * add supoprt for tuples in HSET * add FIRST_KEY_INDEX to HSET * add a bunch of missing commands, fix MSET and HELLO, add some tests * add FIRST_KEY_INDEX to MSET and MSETNX * upgrade actions * fix coverallsapp/github-action version * Update documentation.yml * Update documentation.yml * clean code * remove unused imports * use "npm ci" instead of "npm install" * fix `self` binding on client modules, use connection pool for `duplicateConnection` * add client.executeIsolated, rename "duplicateConnection" to "isolated", update README.md (thanks to @GuyRoyse and @SimonPrickett) * update README (thanks to @GuyRoyse), add some tests * try to fix "cluster is down" errors in tests * try to fix "cluster is down" errors in tests * upgrade dependencies * update package-lock * Release 4.0.0-next.6 * fix #1636 - fix WatchError * fix forf1bf0beebf
- remove .only from multi tests * Release 4.0.0-next.7 * update README and other markdown files Co-authored-by: @GuyRoyse & @SimonPrickett * Doc updates. (#1640) * update docs, upgrade dependencies * fix README * Release 4.0.0-rc.0 * Update README.md * update docs, add `connectTimeout` options, fix tls Co-authored-by: Guy Royse <guy@guyroyse.com> * npm update, "fix" some tests, clean code * fix AssertionError import * fix #1642 - fix XREAD, XREADGROUP and XTRIM * fix #1644 - add the QUIT command * add socket.noDelay and socket.keepAlive configurations * Update README.md (#1645) * Update README.md Fixed issue with how connection string was specified. Now you can have user@host without having to specify a password, which just makes more sense * Update client-configuration.md as well Co-authored-by: Leibale Eidelman <leibale1998@gmail.com> * update socket.reconnectStrategy description * fix borken link in v3-to-v4.md * increase test coverage, fix bug in cluster redirection strategy, implement CLIENT_ID, remove unused EXEC command Co-authored-by: Nova <novaw@warrenservices.co.uk> Co-authored-by: Simon Prickett <simon@crudworks.org> Co-authored-by: Guy Royse <guy@guyroyse.com>
624 lines
17 KiB
TypeScript
624 lines
17 KiB
TypeScript
import { strict as assert } from 'assert';
|
|
import { isObject } from 'util';
|
|
import {
|
|
transformReplyBoolean,
|
|
transformReplyBooleanArray,
|
|
pushScanArguments,
|
|
transformReplyNumberInfinity,
|
|
transformReplyNumberInfinityArray,
|
|
transformReplyNumberInfinityNull,
|
|
transformArgumentNumberInfinity,
|
|
transformReplyTuples,
|
|
transformReplyStreamMessages,
|
|
transformReplyStreamsMessages,
|
|
transformReplySortedSetWithScores,
|
|
pushGeoCountArgument,
|
|
pushGeoSearchArguments,
|
|
GeoReplyWith,
|
|
transformGeoMembersWithReply,
|
|
transformEXAT,
|
|
transformPXAT,
|
|
pushEvalArguments,
|
|
pushStringTuplesArguments,
|
|
pushVerdictArguments,
|
|
pushVerdictArgument,
|
|
pushOptionalVerdictArgument
|
|
} from './generic-transformers';
|
|
|
|
describe('Generic Transformers', () => {
|
|
describe('transformReplyBoolean', () => {
|
|
it('0', () => {
|
|
assert.equal(
|
|
transformReplyBoolean(0),
|
|
false
|
|
);
|
|
});
|
|
|
|
it('1', () => {
|
|
assert.equal(
|
|
transformReplyBoolean(1),
|
|
true
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformReplyBooleanArray', () => {
|
|
it('empty array', () => {
|
|
assert.deepEqual(
|
|
transformReplyBooleanArray([]),
|
|
[]
|
|
);
|
|
});
|
|
|
|
it('0, 1', () => {
|
|
assert.deepEqual(
|
|
transformReplyBooleanArray([0, 1]),
|
|
[false, true]
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushScanArguments', () => {
|
|
it('cusror only', () => {
|
|
assert.deepEqual(
|
|
pushScanArguments([], 0),
|
|
['0']
|
|
);
|
|
});
|
|
|
|
it('with MATCH', () => {
|
|
assert.deepEqual(
|
|
pushScanArguments([], 0, {
|
|
MATCH: 'pattern'
|
|
}),
|
|
['0', 'MATCH', 'pattern']
|
|
);
|
|
});
|
|
|
|
it('with COUNT', () => {
|
|
assert.deepEqual(
|
|
pushScanArguments([], 0, {
|
|
COUNT: 1
|
|
}),
|
|
['0', 'COUNT', '1']
|
|
);
|
|
});
|
|
|
|
it('with MATCH & COUNT', () => {
|
|
assert.deepEqual(
|
|
pushScanArguments([], 0, {
|
|
MATCH: 'pattern',
|
|
COUNT: 1
|
|
}),
|
|
['0', 'MATCH', 'pattern', 'COUNT', '1']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformReplyNumberInfinity', () => {
|
|
it('0.5', () => {
|
|
assert.equal(
|
|
transformReplyNumberInfinity('0.5'),
|
|
0.5
|
|
);
|
|
});
|
|
|
|
it('+inf', () => {
|
|
assert.equal(
|
|
transformReplyNumberInfinity('+inf'),
|
|
Infinity
|
|
);
|
|
});
|
|
|
|
it('-inf', () => {
|
|
assert.equal(
|
|
transformReplyNumberInfinity('-inf'),
|
|
-Infinity
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformReplyNumberInfinityArray', () => {
|
|
it('empty array', () => {
|
|
assert.deepEqual(
|
|
transformReplyNumberInfinityArray([]),
|
|
[]
|
|
);
|
|
});
|
|
|
|
it('0.5, +inf, -inf', () => {
|
|
assert.deepEqual(
|
|
transformReplyNumberInfinityArray(['0.5', '+inf', '-inf']),
|
|
[0.5, Infinity, -Infinity]
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformReplyNumberInfinityNull', () => {
|
|
it('null', () => {
|
|
assert.equal(
|
|
transformReplyNumberInfinityNull(null),
|
|
null
|
|
);
|
|
});
|
|
|
|
it('1', () => {
|
|
assert.equal(
|
|
transformReplyNumberInfinityNull('1'),
|
|
1
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformArgumentNumberInfinity', () => {
|
|
it('0.5', () => {
|
|
assert.equal(
|
|
transformArgumentNumberInfinity(0.5),
|
|
'0.5'
|
|
);
|
|
});
|
|
|
|
it('Infinity', () => {
|
|
assert.equal(
|
|
transformArgumentNumberInfinity(Infinity),
|
|
'+inf'
|
|
);
|
|
});
|
|
|
|
it('-Infinity', () => {
|
|
assert.equal(
|
|
transformArgumentNumberInfinity(-Infinity),
|
|
'-inf'
|
|
);
|
|
});
|
|
});
|
|
|
|
it('transformReplyTuples', () => {
|
|
assert.deepEqual(
|
|
transformReplyTuples(['key1', 'value1', 'key2', 'value2']),
|
|
Object.create(null, {
|
|
key1: {
|
|
value: 'value1',
|
|
configurable: true,
|
|
enumerable: true
|
|
},
|
|
key2: {
|
|
value: 'value2',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
);
|
|
});
|
|
|
|
it('transformReplyStreamMessages', () => {
|
|
assert.deepEqual(
|
|
transformReplyStreamMessages([['0-0', ['0key', '0value']], ['1-0', ['1key', '1value']]]),
|
|
[{
|
|
id: '0-0',
|
|
message: Object.create(null, {
|
|
'0key': {
|
|
value: '0value',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
}, {
|
|
id: '1-0',
|
|
message: Object.create(null, {
|
|
'1key': {
|
|
value: '1value',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
}]
|
|
);
|
|
});
|
|
|
|
describe('transformReplyStreamsMessages', () => {
|
|
it('null', () => {
|
|
assert.equal(
|
|
transformReplyStreamsMessages(null),
|
|
null
|
|
);
|
|
});
|
|
|
|
it('with messages', () => {
|
|
assert.deepEqual(
|
|
transformReplyStreamsMessages([['stream1', [['0-1', ['11key', '11value']], ['1-1', ['12key', '12value']]]], ['stream2', [['0-2', ['2key1', '2value1', '2key2', '2value2']]]]]),
|
|
[{
|
|
name: 'stream1',
|
|
messages: [{
|
|
id: '0-1',
|
|
message: Object.create(null, {
|
|
'11key': {
|
|
value: '11value',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
}, {
|
|
id: '1-1',
|
|
message: Object.create(null, {
|
|
'12key': {
|
|
value: '12value',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
}]
|
|
}, {
|
|
name: 'stream2',
|
|
messages: [{
|
|
id: '0-2',
|
|
message: Object.create(null, {
|
|
'2key1': {
|
|
value: '2value1',
|
|
configurable: true,
|
|
enumerable: true
|
|
},
|
|
'2key2': {
|
|
value: '2value2',
|
|
configurable: true,
|
|
enumerable: true
|
|
}
|
|
})
|
|
}]
|
|
}]
|
|
)
|
|
});
|
|
});
|
|
|
|
it('transformReplySortedSetWithScores', () => {
|
|
assert.deepEqual(
|
|
transformReplySortedSetWithScores(['member1', '0.5', 'member2', '+inf', 'member3', '-inf']),
|
|
[{
|
|
value: 'member1',
|
|
score: 0.5
|
|
}, {
|
|
value: 'member2',
|
|
score: Infinity
|
|
}, {
|
|
value: 'member3',
|
|
score: -Infinity
|
|
}]
|
|
);
|
|
});
|
|
|
|
describe('pushGeoCountArgument', () => {
|
|
it('undefined', () => {
|
|
assert.deepEqual(
|
|
pushGeoCountArgument([], undefined),
|
|
[]
|
|
);
|
|
});
|
|
|
|
it('number', () => {
|
|
assert.deepEqual(
|
|
pushGeoCountArgument([], 1),
|
|
['COUNT', '1']
|
|
);
|
|
});
|
|
|
|
it('with ANY', () => {
|
|
assert.deepEqual(
|
|
pushGeoCountArgument([], {
|
|
value: 1,
|
|
ANY: true
|
|
}),
|
|
['COUNT', '1', 'ANY']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushGeoSearchArguments', () => {
|
|
it('FROMMEMBER, BYRADIUS', () => {
|
|
assert.deepEqual(
|
|
pushGeoSearchArguments([], 'key', 'member', {
|
|
radius: 1,
|
|
unit: 'm'
|
|
}),
|
|
['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm']
|
|
);
|
|
});
|
|
|
|
it('FROMLONLAT, BYBOX', () => {
|
|
assert.deepEqual(
|
|
pushGeoSearchArguments([], 'key', {
|
|
longitude: 1,
|
|
latitude: 2
|
|
}, {
|
|
width: 1,
|
|
height: 2,
|
|
unit: 'm'
|
|
}),
|
|
['key', 'FROMLONLAT', '1', '2', 'BYBOX', '1', '2', 'm']
|
|
);
|
|
});
|
|
|
|
it('with SORT', () => {
|
|
assert.deepEqual(
|
|
pushGeoSearchArguments([], 'key', 'member', {
|
|
radius: 1,
|
|
unit: 'm'
|
|
}, {
|
|
SORT: 'ASC'
|
|
}),
|
|
['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformGeoMembersWithReply', () => {
|
|
it('DISTANCE', () => {
|
|
assert.deepEqual(
|
|
transformGeoMembersWithReply([
|
|
[
|
|
'1',
|
|
'2'
|
|
],
|
|
[
|
|
'3',
|
|
'4'
|
|
]
|
|
], [GeoReplyWith.DISTANCE]),
|
|
[{
|
|
member: '1',
|
|
distance: '2'
|
|
}, {
|
|
member: '3',
|
|
distance: '4'
|
|
}]
|
|
);
|
|
});
|
|
|
|
it('HASH', () => {
|
|
assert.deepEqual(
|
|
transformGeoMembersWithReply([
|
|
[
|
|
'1',
|
|
2
|
|
],
|
|
[
|
|
'3',
|
|
4
|
|
]
|
|
], [GeoReplyWith.HASH]),
|
|
[{
|
|
member: '1',
|
|
hash: 2
|
|
}, {
|
|
member: '3',
|
|
hash: 4
|
|
}]
|
|
);
|
|
});
|
|
|
|
it('COORDINATES', () => {
|
|
assert.deepEqual(
|
|
transformGeoMembersWithReply([
|
|
[
|
|
'1',
|
|
[
|
|
'2',
|
|
'3'
|
|
]
|
|
],
|
|
[
|
|
'4',
|
|
[
|
|
'5',
|
|
'6'
|
|
]
|
|
]
|
|
], [GeoReplyWith.COORDINATES]),
|
|
[{
|
|
member: '1',
|
|
coordinates: {
|
|
longitude: '2',
|
|
latitude: '3'
|
|
}
|
|
}, {
|
|
member: '4',
|
|
coordinates: {
|
|
longitude: '5',
|
|
latitude: '6'
|
|
}
|
|
}]
|
|
);
|
|
});
|
|
|
|
it('DISTANCE, HASH, COORDINATES', () => {
|
|
assert.deepEqual(
|
|
transformGeoMembersWithReply([
|
|
[
|
|
'1',
|
|
'2',
|
|
3,
|
|
[
|
|
'4',
|
|
'5'
|
|
]
|
|
],
|
|
[
|
|
'6',
|
|
'7',
|
|
8,
|
|
[
|
|
'9',
|
|
'10'
|
|
]
|
|
]
|
|
], [GeoReplyWith.DISTANCE, GeoReplyWith.HASH, GeoReplyWith.COORDINATES]),
|
|
[{
|
|
member: '1',
|
|
distance: '2',
|
|
hash: 3,
|
|
coordinates: {
|
|
longitude: '4',
|
|
latitude: '5'
|
|
}
|
|
}, {
|
|
member: '6',
|
|
distance: '7',
|
|
hash: 8,
|
|
coordinates: {
|
|
longitude: '9',
|
|
latitude: '10'
|
|
}
|
|
}]
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformEXAT', () => {
|
|
it('number', () => {
|
|
assert.equal(
|
|
transformEXAT(1),
|
|
'1'
|
|
);
|
|
});
|
|
|
|
it('date', () => {
|
|
const d = new Date();
|
|
assert.equal(
|
|
transformEXAT(d),
|
|
Math.floor(d.getTime() / 1000).toString()
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('transformPXAT', () => {
|
|
it('number', () => {
|
|
assert.equal(
|
|
transformPXAT(1),
|
|
'1'
|
|
);
|
|
});
|
|
|
|
it('date', () => {
|
|
const d = new Date();
|
|
assert.equal(
|
|
transformPXAT(d),
|
|
d.getTime().toString()
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushEvalArguments', () => {
|
|
it('empty', () => {
|
|
assert.deepEqual(
|
|
pushEvalArguments([]),
|
|
['0']
|
|
);
|
|
});
|
|
|
|
it('with keys', () => {
|
|
assert.deepEqual(
|
|
pushEvalArguments([], {
|
|
keys: ['key']
|
|
}),
|
|
['1', 'key']
|
|
);
|
|
});
|
|
|
|
it('with arguments', () => {
|
|
assert.deepEqual(
|
|
pushEvalArguments([], {
|
|
arguments: ['argument']
|
|
}),
|
|
['0', 'argument']
|
|
);
|
|
});
|
|
|
|
it('with keys and arguments', () => {
|
|
assert.deepEqual(
|
|
pushEvalArguments([], {
|
|
keys: ['key'],
|
|
arguments: ['argument']
|
|
}),
|
|
['1', 'key', 'argument']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushStringTuplesArguments', () => {
|
|
it("['key1', 'value1', 'key2', 'value2']", () => {
|
|
assert.deepEqual(
|
|
pushStringTuplesArguments([], ['key1', 'value1', 'key2', 'value2']),
|
|
['key1', 'value1', 'key2', 'value2']
|
|
);
|
|
});
|
|
|
|
it("[['key1', 'value1'], ['key2', 'value2']]", () => {
|
|
assert.deepEqual(
|
|
pushStringTuplesArguments([], [['key1', 'value1'], ['key2', 'value2']]),
|
|
['key1', 'value1', 'key2', 'value2']
|
|
);
|
|
});
|
|
|
|
it("{key1: 'value1'. key2: 'value2'}", () => {
|
|
assert.deepEqual(
|
|
pushStringTuplesArguments([], { key1: 'value1', key2: 'value2' }),
|
|
['key1', 'value1', 'key2', 'value2']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushVerdictArguments', () => {
|
|
it('string', () => {
|
|
assert.deepEqual(
|
|
pushVerdictArguments([], 'string'),
|
|
['string']
|
|
);
|
|
});
|
|
|
|
it('array', () => {
|
|
assert.deepEqual(
|
|
pushVerdictArguments([], ['1', '2']),
|
|
['1', '2']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushVerdictArgument', () => {
|
|
it('string', () => {
|
|
assert.deepEqual(
|
|
pushVerdictArgument([], 'string'),
|
|
['1', 'string']
|
|
);
|
|
});
|
|
|
|
it('array', () => {
|
|
assert.deepEqual(
|
|
pushVerdictArgument([], ['1', '2']),
|
|
['2', '1', '2']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('pushOptionalVerdictArgument', () => {
|
|
it('undefined', () => {
|
|
assert.deepEqual(
|
|
pushOptionalVerdictArgument([], 'name', undefined),
|
|
[]
|
|
);
|
|
});
|
|
|
|
it('string', () => {
|
|
assert.deepEqual(
|
|
pushOptionalVerdictArgument([], 'name', 'string'),
|
|
['name', '1', 'string']
|
|
);
|
|
});
|
|
|
|
it('array', () => {
|
|
assert.deepEqual(
|
|
pushOptionalVerdictArgument([], 'name', ['1', '2']),
|
|
['name', '2', '1', '2']
|
|
);
|
|
});
|
|
});
|
|
});
|