dyngoose
Version:
Elegant DynamoDB object modeling for Typescript
278 lines (227 loc) • 7.56 kB
text/typescript
import { expect, should } from 'chai'
import { Table } from '../table'
import { PrimaryKey } from './primary-key'
import {
Attribute as AttributeDecorator,
PrimaryKey as PrimaryKeyDecorator,
Table as TableDecorator,
} from '../decorator'
describe('Query/PrimaryKey', () => {
@TableDecorator({ name: 'QueryPrimaryKeyCardTable', backup: false })
class Card extends Table {
@PrimaryKeyDecorator('id', 'title')
public static readonly primaryKey: PrimaryKey<Card, number, string>
@AttributeDecorator.Number()
public id: number
@AttributeDecorator.String()
public title: string
@AttributeDecorator.Number()
public count: number
}
@TableDecorator({ name: 'QueryPrimaryKeyTableWithDateRange', backup: false })
class TableWithDateRange extends Table {
@PrimaryKeyDecorator('id', 'date')
public static readonly primaryKey: PrimaryKey<TableWithDateRange, number, Date>
@AttributeDecorator.Number()
public id: number
@AttributeDecorator.Date()
public date: Date
}
let primaryKey: PrimaryKey<Card, number, string>
before(async () => {
await TableWithDateRange.createTable()
})
after(async () => {
await TableWithDateRange.deleteTable()
})
beforeEach(async () => {
await Card.createTable()
primaryKey = Card.primaryKey
})
afterEach(async () => {
await Card.deleteTable()
})
describe('#delete', () => {
it('should delete item if exist', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
await primaryKey.delete(10, 'abc')
expect(await primaryKey.get(10, 'abc')).to.eq(undefined)
})
})
describe('#get', () => {
it('should find nothing when nothing exists', async () => {
let item = await primaryKey.get({ id: 10, title: 'abc' })
expect(item).to.eq(undefined)
item = await primaryKey.get(10, 'abc')
expect(item).to.eq(undefined)
})
it('should not find item using a query filter object when aborted', async () => {
const abortController = new AbortController()
await Card.new({ id: 10, title: 'abc' }).save()
abortController.abort()
let exception
try {
await primaryKey.get({ id: 10, title: 'abc' }, { abortSignal: abortController.signal })
} catch (ex) {
exception = ex
}
should().exist(exception)
})
it('should find item using a query filter object', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
const item = await primaryKey.get({ id: 10, title: 'abc' })
expect(item).to.be.instanceof(Card)
if (item != null) {
expect(item.id).to.eq(10)
expect(item.title).to.eq('abc')
}
})
it('should find item using hash and range arguments', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
const item = await primaryKey.get(10, 'abc')
expect(item).to.be.instanceof(Card)
if (item != null) {
expect(item.id).to.eq(10)
expect(item.title).to.eq('abc')
}
})
it('should not find item using hash and range arguments when aborted', async () => {
const abortController = new AbortController()
await Card.new({ id: 10, title: 'abc' }).save()
abortController.abort()
let exception
try {
await primaryKey.get(10, 'abc', { abortSignal: abortController.signal })
} catch (ex) {
exception = ex
}
should().exist(exception)
})
it('should allow date type to be the range', async () => {
const now = new Date()
await TableWithDateRange.new({ id: 1, date: now }).save()
const item = await TableWithDateRange.primaryKey.get(1, now)
expect(item).to.be.instanceof(TableWithDateRange)
if (item != null) {
expect(item.id).to.eq(1)
expect(item.date.toISOString()).to.eq(now.toISOString())
}
})
})
describe('#batchGet', () => {
it('should find items', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
await Card.new({ id: 11, title: 'abc' }).save()
await Card.new({ id: 12, title: 'abc' }).save()
const items1 = await primaryKey.batchGet([
[10, 'abc'],
[11, 'abc'],
])
expect(items1.length).to.eq(2)
expect(items1[0].id).to.eq(10)
expect(items1[1].id).to.eq(11)
const items2 = await primaryKey.batchGet([
[10, 'abc'],
[10000, 'asdgasdgs'],
[11, 'abc'],
])
expect(items2.length).to.eq(2)
expect(items2[0].id).to.eq(10)
expect(items2[0].title).to.eq('abc')
expect(items2[1].id).to.eq(11)
expect(items2[1].title).to.eq('abc')
})
})
describe('#query', () => {
it('should find items', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
await Card.new({ id: 10, title: 'abd' }).save()
await Card.new({ id: 10, title: 'aba' }).save()
let res = await primaryKey.query({
id: 10,
title: ['between', 'abc', 'abf'],
})
expect(res.records.length).to.eq(2)
expect(res.records[0].title).to.eq('abc')
expect(res.records[1].title).to.eq('abd')
res = await primaryKey.query({
id: 10,
title: ['between', 'abc', 'abf'],
}, {
rangeOrder: 'DESC',
})
expect(res.records.length).to.eq(2)
expect(res.records[0].title).to.eq('abd')
expect(res.records[1].title).to.eq('abc')
})
it('should return an empty array when no results match', async () => {
const res = await primaryKey.query({
id: 420,
})
expect(res[0]).to.not.eq(null)
expect(res.length).to.eq(0)
expect(res.count).to.eq(0)
expect(res.records.length).to.eq(0)
expect(res.map(i => i)[0]).to.eq(undefined)
})
})
describe('#scan', () => {
it('should find items', async () => {
await Card.new({ id: 10, title: 'abc' }).save()
await Card.new({ id: 10, title: 'abd' }).save()
await Card.new({ id: 10, title: 'aba' }).save()
const res = await primaryKey.scan(null, {
limit: 2,
})
expect(res.records.length).to.eq(2)
// Ordered by range key since it's "scan"
expect(res.records[0].title).to.eq('aba')
expect(res.records[1].title).to.eq('abc')
})
it('should not find items when aborted', async () => {
const abortController = new AbortController()
await Card.new({ id: 10, title: 'abc' }).save()
await Card.new({ id: 10, title: 'abd' }).save()
await Card.new({ id: 10, title: 'aba' }).save()
abortController.abort()
let exception
try {
await primaryKey.scan(null, {
abortSignal: abortController.signal,
limit: 2,
})
} catch (ex) {
exception = ex
}
should().exist(exception)
})
})
describe('#update', () => {
it('should be able to update items', async () => {
await primaryKey.update({
hash: 10,
range: 'abc',
changes: {
count: 1,
},
})
let card = await primaryKey.get(10, 'abc')
expect(card).to.be.instanceOf(Card)
if (card != null) {
expect(card.count).to.eq(1)
}
await primaryKey.update({
hash: 10,
range: 'abc',
changes: {
count: 2,
},
})
card = await primaryKey.get(10, 'abc')
expect(card).to.be.instanceOf(Card)
if (card != null) {
expect(card.count).to.eq(2)
}
})
})
})