Skip to content

Commit

Permalink
feat: add options shorthand (#1127)
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan authored Jan 28, 2022
1 parent 4907dab commit 1fdd8e5
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ In v6 the [internals were rewritten](/~https://github.com/stipsan/ioredis-mock/pul
const Redis = require('ioredis-mock')
const redis1 = new Redis()
const redis2 = new Redis()
const redis3 = new Redis({ port: 6380 }) // 6379 is the default port
const redis3 = new Redis(6380) // 6379 is the default port

await redis1.set('foo', 'bar')
console.log(
Expand Down
57 changes: 54 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable max-classes-per-file */
import { EventEmitter } from 'events'
import { parseURL } from 'ioredis/built/utils/index'
import redisCommands from 'redis-commands'

import createCommand, { Command } from './command'
Expand All @@ -19,7 +20,57 @@ const defaultOptions = {
lazyConnect: false,
notifyKeyspaceEvents: '', // string pattern as specified in https://redis.io/topics/notifications#configuration e.g. 'gxK'
host: 'localhost',
port: '6379',
port: 6379,
}

const pathToHostPort = path => {
const { host, port } = parseURL(path)
return { host, port }
}

const routeOptionsArgs = (...args) => {
switch (args.length) {
case 3:
// port: number, host: string, options: IRedisOptions
return { ...args[2], port: args[0], host: args[1] }

case 2:
// if args[0] is a string, then it's:
// path: string, options: IRedisOptions
// if args[0] is a number and args[1] is a string, then it's:
// port: number, host: string
// if neither we can assume it's:
// port: number, options: IRedisOptions
// eslint-disable-next-line no-nested-ternary
return typeof args[0] === 'string'
? { ...args[1], ...pathToHostPort(args[0]) }
: Number.isInteger(args[0]) && typeof args[1] === 'string'
? { port: args[0], host: args[1] }
: { ...args[1], port: args[0] }
case 1:
// if args[0] is a string, then it's:
// path: string
// if args[0] is a number then it's:
// port: number
// if neither we can assume it's:
// options: IRedisOptions
// eslint-disable-next-line no-nested-ternary
return typeof args[0] === 'string'
? { ...pathToHostPort(args[0]) }
: Number.isInteger(args[0])
? { port: args[0] }
: { ...args[0] }
default:
return {}
}
}

const getOptions = (...args) => {
const parsed = routeOptionsArgs(...args)
const port = parsed.port ? parseInt(parsed.port, 10) : defaultOptions.port
const { host = defaultOptions.host } = parsed

return { ...parsed, port, host }
}

class RedisMock extends EventEmitter {
Expand All @@ -31,7 +82,7 @@ class RedisMock extends EventEmitter {
return promiseContainer.set(lib)
}

constructor(options = {}) {
constructor(...args) {
super()

this.batch = undefined
Expand All @@ -41,7 +92,7 @@ class RedisMock extends EventEmitter {
// a mapping of sha1<string>:script<string>, used by evalsha command
this.shaScripts = {}

const optionsWithDefault = { ...defaultOptions, ...options }
const optionsWithDefault = { ...defaultOptions, ...getOptions(...args) }

this.keyData = `${optionsWithDefault.host}:${optionsWithDefault.port}`

Expand Down
129 changes: 129 additions & 0 deletions test/integration/options-shorthand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import Redis from 'ioredis'

describe('constructor options', () => {
it('new Redis()', async () => {
const client1 = new Redis({ host: 'localhost', port: '6379' })
const client2 = new Redis()
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(port, host, options)', async () => {
const client1 = new Redis({ keyPrefix: 'shared:' })
const client2 = new Redis(6379, 'localhost', { keyPrefix: 'shared:' })
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(url, options)', async () => {
const client1 = new Redis({ keyPrefix: 'shared:' })
const client2 = new Redis('//localhost:6379', { keyPrefix: 'shared:' })
const client3 = new Redis('redis://localhost:6379', {
keyPrefix: 'private:',
})

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(port, options)', async () => {
const client1 = new Redis({ keyPrefix: 'shared:' })
const client2 = new Redis(6379, { keyPrefix: 'shared:' })
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(port, host, options)', async () => {
const client1 = new Redis({ keyPrefix: 'shared:' })
const client2 = new Redis(6379, 'localhost', { keyPrefix: 'shared:' })
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(options)', async () => {
const client1 = new Redis({ keyPrefix: 'shared:' })
const client2 = new Redis({
host: 'localhost',
port: 6379,
keyPrefix: 'shared:',
})
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(port)', async () => {
const client1 = new Redis()
const client2 = new Redis(6379)
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})

it('new Redis(url)', async () => {
const client1 = new Redis()
const client2 = new Redis('redis://localhost:6379/')
const client3 = new Redis({ keyPrefix: 'private:' })

await client1.set('foo', 'bar')

expect(await client1.get('foo')).toBe(await client2.get('foo'))
expect(await client1.get('foo')).not.toBe(await client3.get('foo'))

client1.disconnect()
client2.disconnect()
client3.disconnect()
})
})

0 comments on commit 1fdd8e5

Please sign in to comment.