зеркало из https://github.com/microsoft/etcd3.git
Flesh out the rest of the CRUD tests, update types to string responses
This commit is contained in:
Родитель
e814557902
Коммит
756d2ac3cd
|
@ -26,27 +26,29 @@ const indentation = ' ';
|
|||
|
||||
const enums = [];
|
||||
const services = {};
|
||||
const pbTypes = {
|
||||
// Built-in types:
|
||||
double: 'number',
|
||||
float: 'number',
|
||||
int32: 'number',
|
||||
int64: 'number',
|
||||
uint32: 'number',
|
||||
uint64: 'number',
|
||||
sint32: 'number',
|
||||
sint64: 'number',
|
||||
fixed32: 'number',
|
||||
fixed64: 'number',
|
||||
sfixed32: 'number',
|
||||
sfixed64: 'number',
|
||||
|
||||
const pbTypeAliases = {
|
||||
bool: 'boolean',
|
||||
string: 'string',
|
||||
bytes: 'Buffer',
|
||||
// Aliases:
|
||||
Type: 'PermissionType',
|
||||
};
|
||||
|
||||
const numericTypes = [
|
||||
'double',
|
||||
'float',
|
||||
'int32',
|
||||
'int64',
|
||||
'uint32',
|
||||
'uint64',
|
||||
'sint32',
|
||||
'sint64',
|
||||
'fixed32',
|
||||
'fixed64',
|
||||
'sfixed32',
|
||||
'sfixed64',
|
||||
];
|
||||
|
||||
class MessageCollection {
|
||||
constructor() {
|
||||
this._messages = {};
|
||||
|
@ -83,13 +85,17 @@ function stripPackageNameFrom(name) {
|
|||
return name;
|
||||
}
|
||||
|
||||
function formatType(type) {
|
||||
if (type in pbTypes) {
|
||||
return pbTypes[type];
|
||||
function formatType(type, isInResponse = false) {
|
||||
if (type in pbTypeAliases) {
|
||||
return pbTypeAliases[type];
|
||||
}
|
||||
|
||||
// grpc unmarshals number as strings, but we want to let people provide them as Numbers.
|
||||
if (numericTypes.includes(type)) {
|
||||
return isInResponse ? 'string' : 'string | number';
|
||||
}
|
||||
|
||||
type = stripPackageNameFrom(type);
|
||||
|
||||
if (enums.includes(type)) {
|
||||
return type;
|
||||
}
|
||||
|
@ -170,14 +176,14 @@ function generateInterface(node, name) {
|
|||
fname = formatFieldName(fname);
|
||||
emit(getCommentPrefixing(fname, getLineContaining(`message ${name}`)));
|
||||
emit(`${indent(1)}${fname}${message.response ? '' : '?'}: `
|
||||
+ `${formatType(field.type)}${field.rule === 'repeated' ? '[]' : '' };`);
|
||||
+ `${formatType(field.type, message.response)}${field.rule === 'repeated' ? '[]' : '' };`);
|
||||
});
|
||||
emit('}\n');
|
||||
}
|
||||
|
||||
function generateEnum(node, name) {
|
||||
enums.push(name);
|
||||
emit(`export enum ${name in pbTypes ? pbTypes[name] : name} {`);
|
||||
emit(`export enum ${name in pbTypeAliases ? pbTypeAliases[name] : name} {`);
|
||||
_.forOwn(node.values, (count, fname) => {
|
||||
emit(getCommentPrefixing(fname, getLineContaining(`enum ${fname}`)));
|
||||
emit(`${indent(1)}${fname} = ${count},`);
|
||||
|
|
|
@ -65,7 +65,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
|
|||
/**
|
||||
* revision is the point-in-time of the key-value store to use for the range.
|
||||
*/
|
||||
public revision(rev: number): this {
|
||||
public revision(rev: number | string): this {
|
||||
this.request.revision = rev;
|
||||
return this;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
|
|||
/**
|
||||
* minModRevision sets the minimum modified revision of keys to return.
|
||||
*/
|
||||
public minModRevision(minModRevision: number): this {
|
||||
public minModRevision(minModRevision: number | string): this {
|
||||
this.request.min_mod_revision = minModRevision;
|
||||
return this;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
|
|||
/**
|
||||
* maxModRevision sets the maximum modified revision of keys to return.
|
||||
*/
|
||||
public maxModRevision(maxModRevision: number): this {
|
||||
public maxModRevision(maxModRevision: number | string): this {
|
||||
this.request.max_mod_revision = maxModRevision;
|
||||
return this;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
|
|||
/**
|
||||
* minCreateRevision sets the minimum create revision of keys to return.
|
||||
*/
|
||||
public minCreateRevision(minCreateRevision: number): this {
|
||||
public minCreateRevision(minCreateRevision: number | string): this {
|
||||
this.request.min_create_revision = minCreateRevision;
|
||||
return this;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
|
|||
/**
|
||||
* maxCreateRevision sets the maximum create revision of keys to return.
|
||||
*/
|
||||
public maxCreateRevision(maxCreateRevision: number): this {
|
||||
public maxCreateRevision(maxCreateRevision: number | string): this {
|
||||
this.request.max_create_revision = maxCreateRevision;
|
||||
return this;
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ export class MultiRangeBuilder extends RangeBuilder {
|
|||
*/
|
||||
public count(): Promise<number> {
|
||||
this.request.count_only = true;
|
||||
return this.exec().then(res => res.count);
|
||||
return this.exec().then(res => Number(res.count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,9 +300,9 @@ export class DeleteBuilder extends PromiseWrap<RPC.IDeleteRangeResponse> {
|
|||
* key before setting it. One may not always be available if a compaction
|
||||
* takes place.
|
||||
*/
|
||||
public getPrevious(): this {
|
||||
public getPrevious(): Promise<RPC.IKeyValue[]> {
|
||||
this.request.prev_kv = true;
|
||||
return this;
|
||||
return this.exec().then(res => res.prev_kvs);
|
||||
}
|
||||
/**
|
||||
* exec runs the delete put request.
|
||||
|
@ -335,21 +335,11 @@ export class PutBuilder extends PromiseWrap<RPC.IPutResponse> {
|
|||
* Sets the lease value to use for storing the key. You usually don't
|
||||
* need to use this directly, use `client.lease()` instead!
|
||||
*/
|
||||
public lease(lease: number): this {
|
||||
public lease(lease: number | string): this {
|
||||
this.request.lease = lease;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPrevious instructs etcd to *try* to get the previous value of the
|
||||
* key before setting it. One may not always be available if a compaction
|
||||
* takes place.
|
||||
*/
|
||||
public getPrevious(): this {
|
||||
this.request.prev_kv = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the key on its current lease, regardless of what that lease is.
|
||||
*/
|
||||
|
@ -358,6 +348,16 @@ export class PutBuilder extends PromiseWrap<RPC.IPutResponse> {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPrevious instructs etcd to *try* to get the previous value of the
|
||||
* key before setting it. One may not always be available if a compaction
|
||||
* takes place.
|
||||
*/
|
||||
public getPrevious(): Promise<RPC.IKeyValue & { header: RPC.IResponseHeader }> {
|
||||
this.request.prev_kv = true;
|
||||
return this.exec().then(res => ({ ...res.prev_kv, header: res.header }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch updates the key's revision without changing its value. This is
|
||||
* equivalent to the etcd 'ignore value' flag.
|
||||
|
|
96
src/rpc.ts
96
src/rpc.ts
|
@ -307,19 +307,19 @@ export interface IResponseHeader {
|
|||
/**
|
||||
* cluster_id is the ID of the cluster which sent the response.
|
||||
*/
|
||||
cluster_id: number;
|
||||
cluster_id: string;
|
||||
/**
|
||||
* member_id is the ID of the member which sent the response.
|
||||
*/
|
||||
member_id: number;
|
||||
member_id: string;
|
||||
/**
|
||||
* revision is the key-value store revision when the request was applied.
|
||||
*/
|
||||
revision: number;
|
||||
revision: string;
|
||||
/**
|
||||
* raft_term is the raft term when the request was applied.
|
||||
*/
|
||||
raft_term: number;
|
||||
raft_term: string;
|
||||
}
|
||||
|
||||
export enum SortOrder {
|
||||
|
@ -357,11 +357,11 @@ export interface IRangeRequest {
|
|||
/**
|
||||
* limit is a limit on the number of keys returned for the request. When limit is set to 0,
|
||||
*/
|
||||
limit?: number;
|
||||
limit?: string | number;
|
||||
/**
|
||||
* revision is the point-in-time of the key-value store to use for the range.
|
||||
*/
|
||||
revision?: number;
|
||||
revision?: string | number;
|
||||
/**
|
||||
* sort_order is the order for returned sorted results.
|
||||
*/
|
||||
|
@ -385,19 +385,19 @@ export interface IRangeRequest {
|
|||
/**
|
||||
* min_mod_revision is the lower bound for returned key mod revisions; all keys with
|
||||
*/
|
||||
min_mod_revision?: number;
|
||||
min_mod_revision?: string | number;
|
||||
/**
|
||||
* max_mod_revision is the upper bound for returned key mod revisions; all keys with
|
||||
*/
|
||||
max_mod_revision?: number;
|
||||
max_mod_revision?: string | number;
|
||||
/**
|
||||
* min_create_revision is the lower bound for returned key create revisions; all keys with
|
||||
*/
|
||||
min_create_revision?: number;
|
||||
min_create_revision?: string | number;
|
||||
/**
|
||||
* max_create_revision is the upper bound for returned key create revisions; all keys with
|
||||
*/
|
||||
max_create_revision?: number;
|
||||
max_create_revision?: string | number;
|
||||
}
|
||||
|
||||
export interface IRangeResponse {
|
||||
|
@ -413,7 +413,7 @@ export interface IRangeResponse {
|
|||
/**
|
||||
* kvs is empty when count is requested.
|
||||
*/
|
||||
count: number;
|
||||
count: string;
|
||||
}
|
||||
|
||||
export interface IPutRequest {
|
||||
|
@ -428,7 +428,7 @@ export interface IPutRequest {
|
|||
/**
|
||||
* lease is the lease ID to associate with the key in the key-value store. A lease
|
||||
*/
|
||||
lease?: number;
|
||||
lease?: string | number;
|
||||
/**
|
||||
* If prev_kv is set, etcd gets the previous key-value pair before changing it.
|
||||
*/
|
||||
|
@ -471,7 +471,7 @@ export interface IDeleteRangeResponse {
|
|||
/**
|
||||
* deleted is the number of keys deleted by the delete range request.
|
||||
*/
|
||||
deleted: number;
|
||||
deleted: string;
|
||||
/**
|
||||
* if prev_kv is set in the request, the previous key-value pairs will be returned.
|
||||
*/
|
||||
|
@ -520,15 +520,15 @@ export interface ICompare {
|
|||
/**
|
||||
* version is the version of the given key
|
||||
*/
|
||||
version?: number;
|
||||
version?: string | number;
|
||||
/**
|
||||
* create_revision is the creation revision of the given key
|
||||
*/
|
||||
create_revision?: number;
|
||||
create_revision?: string | number;
|
||||
/**
|
||||
* mod_revision is the last modified revision of the given key.
|
||||
*/
|
||||
mod_revision?: number;
|
||||
mod_revision?: string | number;
|
||||
/**
|
||||
* target is the key-value field to inspect for the comparison.
|
||||
*/
|
||||
|
@ -566,7 +566,7 @@ export interface ICompactionRequest {
|
|||
/**
|
||||
* revision is the key-value store revision for the compaction operation.
|
||||
*/
|
||||
revision?: number;
|
||||
revision?: string | number;
|
||||
/**
|
||||
* physical is set so the RPC will wait until the compaction is physically
|
||||
*/
|
||||
|
@ -582,7 +582,7 @@ export interface IHashResponse {
|
|||
/**
|
||||
* hash is the hash value computed from the responding member's key-value store.
|
||||
*/
|
||||
hash: number;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
export interface ISnapshotResponse {
|
||||
|
@ -593,7 +593,7 @@ export interface ISnapshotResponse {
|
|||
/**
|
||||
* remaining_bytes is the number of blob bytes to be sent after this message
|
||||
*/
|
||||
remaining_bytes: number;
|
||||
remaining_bytes: string;
|
||||
/**
|
||||
* remaining_bytes is the number of blob bytes to be sent after this message
|
||||
*/
|
||||
|
@ -628,7 +628,7 @@ export interface IWatchCreateRequest {
|
|||
/**
|
||||
* start_revision is an optional revision to watch from (inclusive). No start_revision is "now".
|
||||
*/
|
||||
start_revision?: number;
|
||||
start_revision?: string | number;
|
||||
/**
|
||||
* progress_notify is set so that the etcd server will periodically send a WatchResponse with
|
||||
*/
|
||||
|
@ -647,7 +647,7 @@ export interface IWatchCancelRequest {
|
|||
/**
|
||||
* watch_id is the watcher id to cancel so that no more events are transmitted.
|
||||
*/
|
||||
watch_id?: number;
|
||||
watch_id?: string | number;
|
||||
}
|
||||
|
||||
export interface IWatchResponse {
|
||||
|
@ -655,7 +655,7 @@ export interface IWatchResponse {
|
|||
/**
|
||||
* watch_id is the ID of the watcher that corresponds to the response.
|
||||
*/
|
||||
watch_id: number;
|
||||
watch_id: string;
|
||||
/**
|
||||
* created is set to true if the response is for a create watch request.
|
||||
*/
|
||||
|
@ -667,7 +667,7 @@ export interface IWatchResponse {
|
|||
/**
|
||||
* compact_revision is set to the minimum index if a watcher tries to watch
|
||||
*/
|
||||
compact_revision: number;
|
||||
compact_revision: string;
|
||||
/**
|
||||
* The client should record the watch_id and expect to receive events for
|
||||
*/
|
||||
|
@ -675,11 +675,11 @@ export interface IWatchResponse {
|
|||
}
|
||||
|
||||
export interface ILeaseGrantRequest {
|
||||
ttl?: number;
|
||||
ttl?: string | number;
|
||||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface ILeaseGrantResponse {
|
||||
|
@ -687,8 +687,8 @@ export interface ILeaseGrantResponse {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id: number;
|
||||
ttl: number;
|
||||
id: string;
|
||||
ttl: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
|
@ -696,7 +696,7 @@ export interface ILeaseRevokeRequest {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface ILeaseRevokeResponse {
|
||||
|
@ -707,7 +707,7 @@ export interface ILeaseKeepAliveRequest {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface ILeaseKeepAliveResponse {
|
||||
|
@ -715,15 +715,15 @@ export interface ILeaseKeepAliveResponse {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id: number;
|
||||
ttl: number;
|
||||
id: string;
|
||||
ttl: string;
|
||||
}
|
||||
|
||||
export interface ILeaseTimeToLiveRequest {
|
||||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
/**
|
||||
* keys is true to query all the keys attached to this lease.
|
||||
*/
|
||||
|
@ -735,9 +735,9 @@ export interface ILeaseTimeToLiveResponse {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id: number;
|
||||
ttl: number;
|
||||
granted_ttl: number;
|
||||
id: string;
|
||||
ttl: string;
|
||||
granted_ttl: string;
|
||||
/**
|
||||
* Keys is the list of keys attached to this lease.
|
||||
*/
|
||||
|
@ -748,7 +748,7 @@ export interface IMember {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id: number;
|
||||
id: string;
|
||||
/**
|
||||
* name is the human-readable name of the member. If the member is not started, the name will be an empty string.
|
||||
*/
|
||||
|
@ -773,7 +773,7 @@ export interface IMemberRemoveRequest {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface IMemberRemoveResponse {
|
||||
|
@ -784,7 +784,7 @@ export interface IMemberUpdateRequest {
|
|||
/**
|
||||
* alarm is the type of alarm to consider for this request.
|
||||
*/
|
||||
id?: number;
|
||||
id?: string | number;
|
||||
peer_ur_ls?: string[];
|
||||
}
|
||||
|
||||
|
@ -826,7 +826,7 @@ export interface IAlarmRequest {
|
|||
* action is the kind of alarm request to issue. The action
|
||||
*/
|
||||
action?: AlarmAction;
|
||||
member_id?: number;
|
||||
member_id?: string | number;
|
||||
/**
|
||||
* action is the kind of alarm request to issue. The action
|
||||
*/
|
||||
|
@ -834,7 +834,7 @@ export interface IAlarmRequest {
|
|||
}
|
||||
|
||||
export interface IAlarmMember {
|
||||
member_id: number;
|
||||
member_id: string;
|
||||
/**
|
||||
* memberID is the ID of the member associated with the raised alarm.
|
||||
*/
|
||||
|
@ -855,13 +855,13 @@ export interface IStatusResponse {
|
|||
* version is the cluster protocol version used by the responding member.
|
||||
*/
|
||||
version: string;
|
||||
db_size: number;
|
||||
db_size: string;
|
||||
/**
|
||||
* leader is the member ID which the responding member believes is the current leader.
|
||||
*/
|
||||
leader: number;
|
||||
raft_index: number;
|
||||
raft_term: number;
|
||||
leader: string;
|
||||
raft_index: string;
|
||||
raft_term: string;
|
||||
}
|
||||
|
||||
export interface IAuthenticateRequest {
|
||||
|
@ -1065,15 +1065,15 @@ export interface IKeyValue {
|
|||
/**
|
||||
* min_create_revision is the lower bound for returned key create revisions; all keys with
|
||||
*/
|
||||
create_revision: number;
|
||||
create_revision: string;
|
||||
/**
|
||||
* min_mod_revision is the lower bound for returned key mod revisions; all keys with
|
||||
*/
|
||||
mod_revision: number;
|
||||
mod_revision: string;
|
||||
/**
|
||||
* version is the version of the given key
|
||||
*/
|
||||
version: number;
|
||||
version: string;
|
||||
/**
|
||||
* Range gets the keys in the range from the key-value store.
|
||||
*/
|
||||
|
@ -1081,7 +1081,7 @@ export interface IKeyValue {
|
|||
/**
|
||||
* LeaseGrant creates a lease which expires if the server does not receive a keepAlive
|
||||
*/
|
||||
lease: number;
|
||||
lease: string;
|
||||
}
|
||||
|
||||
export enum EventType {
|
||||
|
|
|
@ -18,23 +18,87 @@ describe('connection pool', () => {
|
|||
|
||||
afterEach(() => client.delete().all());
|
||||
|
||||
it('lists all values', async () => {
|
||||
expect(await client.getAll().strings()).to.containSubset(['bar1', 'bar2', 'bar5']);
|
||||
describe('get() / getAll()', () => {
|
||||
it('lists all values', async () => {
|
||||
expect(await client.getAll().strings()).to.containSubset(['bar1', 'bar2', 'bar5']);
|
||||
});
|
||||
|
||||
it('gets single keys with various encoding', async () => {
|
||||
expect(await client.get('foo1').string()).to.equal('bar1');
|
||||
expect(await client.get('foo2').buffer()).to.deep.equal(Buffer.from('bar2'));
|
||||
expect(await client.get('foo3').json()).to.deep.equal({ value: 'bar3' });
|
||||
expect(await client.get('wut').string()).to.be.null;
|
||||
});
|
||||
|
||||
it('queries prefixes', async () => {
|
||||
expect(await client.getAll().prefix('foo').strings())
|
||||
.to.have.members(['bar1', 'bar2', '{"value":"bar3"}']);
|
||||
});
|
||||
|
||||
it('gets keys', async () => {
|
||||
expect(await client.getAll().keys()).to.have.members(['foo1', 'foo2', 'foo3', 'baz']);
|
||||
});
|
||||
|
||||
it('counts', async () => {
|
||||
expect(await client.getAll().count()).to.equal(4);
|
||||
});
|
||||
|
||||
it('sorts', async () => {
|
||||
expect(await client.getAll()
|
||||
.prefix('foo')
|
||||
.sort('key', 'asc')
|
||||
.limit(2)
|
||||
.keys(),
|
||||
).to.deep.equal(['foo1', 'foo2']);
|
||||
|
||||
expect(await client.getAll()
|
||||
.prefix('foo')
|
||||
.sort('key', 'desc')
|
||||
.limit(2)
|
||||
.keys(),
|
||||
).to.deep.equal(['foo3', 'foo2']);
|
||||
});
|
||||
});
|
||||
|
||||
it('gets single keys with various encoding', async () => {
|
||||
expect(await client.get('foo1').string()).to.equal('bar1');
|
||||
expect(await client.get('foo2').buffer()).to.deep.equal(Buffer.from('bar2'));
|
||||
expect(await client.get('foo3').json()).to.deep.equal({ value: 'bar3' });
|
||||
expect(await client.get('wut').string()).to.be.null;
|
||||
});
|
||||
describe('delete()', () => {
|
||||
it('deletes all', async () => {
|
||||
await client.delete().all();
|
||||
expect(await client.getAll().count()).to.equal(0);
|
||||
});
|
||||
|
||||
it('queries prefixes', async () => {
|
||||
expect(await client.getAll().prefix('foo').strings())
|
||||
.to.have.members(['bar1', 'bar2', '{"value":"bar3"}']);
|
||||
});
|
||||
it('deletes prefix', async () => {
|
||||
await client.delete().prefix('foo');
|
||||
expect(await client.getAll().keys()).to.deep.equal(['baz']);
|
||||
});
|
||||
|
||||
it('gets keys', async () => {
|
||||
expect(await client.getAll().keys()).to.have.members(['foo1', 'foo2', 'foo3', 'baz']);
|
||||
it('gets previous', async () => {
|
||||
expect(await client.delete().key('foo1').getPrevious()).to.containSubset([
|
||||
{
|
||||
key: new Buffer('foo1'),
|
||||
value: new Buffer('bar1'),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('put()', () => {
|
||||
it('allows touching key revisions', async () => {
|
||||
const original = (await client.get('foo1').exec()).kvs[0].mod_revision;
|
||||
await client.put('foo1').touch();
|
||||
const updated = (await client.get('foo1').exec()).kvs[0].mod_revision;
|
||||
expect(Number(updated)).to.be.greaterThan(Number(original));
|
||||
});
|
||||
|
||||
it('updates key values', async () => {
|
||||
await client.put('foo1').value('updated');
|
||||
expect(await client.get('foo1').string()).to.equal('updated');
|
||||
});
|
||||
|
||||
it('includes previous values', async () => {
|
||||
expect(await client.put('foo1').value('updated').getPrevious()).to.containSubset({
|
||||
key: new Buffer('foo1'),
|
||||
value: new Buffer('bar1'),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче