UNPKG

botframework-s3storage

Version:

This is a library to store botframework bot state to s3

342 lines (306 loc) 8.45 kB
import S3Storage from '../s3storage'; jest.mock('aws-sdk'); test('read of unknown key', async () => { let AWS = require('aws-sdk'); AWS.S3 = class S3 { getObject() { return { promise: async () => { throw Error('object not found'); }, }; } }; const storage = new S3Storage('bucket'); expect(await storage.read(['unk'])).toEqual({}); }); test('read of known key', async () => { let AWS = require('aws-sdk'); const mockFunc = jest.fn(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ hoge: 'moge1' })), ETag: 'etag1', }; }, }; }); AWS.S3 = class S3 { getObject = mockFunc; }; const storage = new S3Storage('bucket'); expect(await storage.read(['known/key/'])).toEqual({ 'known/key/': { hoge: 'moge1', eTag: 'etag1' }, }); expect({ ...mockFunc.mock.calls[0] }[0]).toHaveProperty('Key', 'known/key'); }); test('key creation', async () => { let AWS = require('aws-sdk'); const mockPutObject = jest.fn(() => { return { promise: async () => {}, }; }); const mockGetObject = jest.fn(() => { return { promise: async () => { throw Error('object not found'); }, }; }); AWS.S3 = class S3 { getObject = mockGetObject; putObject = mockPutObject; }; const storage = new S3Storage('bucket'); expect(await storage.write({ keyCreate: { count: 1 } })).toBeUndefined(); expect(mockGetObject.mock.calls.length).toBe(1); expect(mockPutObject.mock.calls.length).toBe(1); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Key', 'keyCreate' ); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 1 }) ); }); test('key update', async () => { let AWS = require('aws-sdk'); const mockPutObject = jest.fn(() => { return { promise: async () => {}, }; }); const mockGetObject = jest.fn(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 1 })), ETag: 'etag1', }; }, }; }); AWS.S3 = class S3 { getObject = mockGetObject; putObject = mockPutObject; }; const storage = new S3Storage('bucket'); const item = await storage.read(['known/key/']); item['known/key/'].count = 2; expect(await storage.write({ ...item })).toBeUndefined(); expect(mockGetObject.mock.calls.length).toBe(2); expect(mockPutObject.mock.calls.length).toBe(1); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Key', 'known/key' ); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 2, eTag: 'etag1' }) ); }); test('invalid eTag', async () => { let AWS = require('aws-sdk'); const mockPutObject = jest.fn(() => { return { promise: async () => {}, }; }); const mockGetObject = jest.fn(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 1 })), ETag: 'etag1', }; }, }; }); AWS.S3 = class S3 { getObject = mockGetObject; putObject = mockPutObject; }; const storage = new S3Storage('bucket'); const item = await storage.read(['known/key/']); item['known/key/'].count = 2; item['known/key/'].eTag = 'etag2'; await expect(storage.write({ ...item })).rejects.toThrowError(/Storage/); expect(mockGetObject.mock.calls.length).toBe(2); expect(mockPutObject.mock.calls.length).toBe(0); }); test('wildcard eTag', async () => { let AWS = require('aws-sdk'); const mockPutObject = jest.fn(() => { return { promise: async () => {}, }; }); const mockGetObject = jest.fn(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 1 })), ETag: 'etag1', }; }, }; }); AWS.S3 = class S3 { getObject = mockGetObject; putObject = mockPutObject; }; const storage = new S3Storage('bucket'); const item = await storage.read(['known/key/']); item['known/key/'].count = 2; item['known/key/'].eTag = '*'; expect(await storage.write({ ...item })).toBeUndefined(); expect(mockGetObject.mock.calls.length).toBe(2); expect(mockPutObject.mock.calls.length).toBe(1); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 2, eTag: '*' }) ); }); test('delete key', async () => { let AWS = require('aws-sdk'); const mockDeleteObject = jest.fn(() => { return { promise: async () => {}, }; }); AWS.S3 = class S3 { deleteObject = mockDeleteObject; }; const storage = new S3Storage('bucket'); expect(await storage.delete(['delete/key/'])).toBeUndefined(); expect(mockDeleteObject.mock.calls.length).toBe(1); expect({ ...mockDeleteObject.mock.calls[0] }[0]).toHaveProperty( 'Key', 'delete/key' ); }); test('batch put operations', async () => { let AWS = require('aws-sdk'); const mockPutObject = jest.fn(() => { return { promise: async () => {}, }; }); const mockGetObject = jest.fn(() => { return { promise: async () => {}, }; }); AWS.S3 = class S3 { getObject = mockGetObject; putObject = mockPutObject; }; const storage = new S3Storage('bucket'); expect( await storage.write({ batch1: { count: 10 }, batch2: { count: 20 }, batch3: { count: 30 }, }) ).toBeUndefined(); expect(mockPutObject.mock.calls.length).toBe(3); expect(mockGetObject.mock.calls.length).toBe(3); expect({ ...mockGetObject.mock.calls[0] }[0]).toHaveProperty('Key', 'batch1'); expect({ ...mockGetObject.mock.calls[1] }[0]).toHaveProperty('Key', 'batch2'); expect({ ...mockGetObject.mock.calls[2] }[0]).toHaveProperty('Key', 'batch3'); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty('Key', 'batch1'); expect({ ...mockPutObject.mock.calls[1] }[0]).toHaveProperty('Key', 'batch2'); expect({ ...mockPutObject.mock.calls[2] }[0]).toHaveProperty('Key', 'batch3'); expect({ ...mockPutObject.mock.calls[0] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 10, }) ); expect({ ...mockPutObject.mock.calls[1] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 20, }) ); expect({ ...mockPutObject.mock.calls[2] }[0]).toHaveProperty( 'Body', JSON.stringify({ count: 30, }) ); }); test('batch read operations', async () => { let AWS = require('aws-sdk'); const mockGetObject = jest .fn() .mockImplementationOnce(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 10 })), ETag: 'etag1', }; }, }; }) .mockImplementationOnce(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 20 })), ETag: 'etag2', }; }, }; }) .mockImplementationOnce(() => { return { promise: async () => { return { Body: Buffer.from(JSON.stringify({ count: 30 })), ETag: 'etag3', }; }, }; }); AWS.S3 = class S3 { getObject = mockGetObject; }; const storage = new S3Storage('bucket'); expect(await storage.read(['batch1', 'batch2', 'batch3'])).toEqual({ batch1: { count: 10, eTag: 'etag1' }, batch2: { count: 20, eTag: 'etag2' }, batch3: { count: 30, eTag: 'etag3' }, }); expect(mockGetObject.mock.calls.length).toBe(3); }); test('batch delete operations', async () => { let AWS = require('aws-sdk'); const mockDeleteObject = jest.fn(() => { return { promise: async () => {}, }; }); AWS.S3 = class S3 { deleteObject = mockDeleteObject; }; const storage = new S3Storage('bucket'); expect(await storage.delete(['batch1', 'batch2', 'batch3'])).toBeUndefined(); expect(mockDeleteObject.mock.calls.length).toBe(3); expect({ ...mockDeleteObject.mock.calls[0] }[0]).toHaveProperty( 'Key', 'batch1' ); expect({ ...mockDeleteObject.mock.calls[1] }[0]).toHaveProperty( 'Key', 'batch2' ); expect({ ...mockDeleteObject.mock.calls[2] }[0]).toHaveProperty( 'Key', 'batch3' ); });