@getanthill/datastore
Version:
Event-Sourced Datastore
358 lines (322 loc) • 8.06 kB
text/typescript
import type { Services } from '../../typings';
import type { MongoDbConnector } from '@getanthill/mongodb-connector';
import { checkProcessingAuthorization, mapFindQuery, mapQueryValues } from '.';
import setup from '../../../test/setup';
import fixtureUsers from '../../../test/fixtures/users';
describe('utils', () => {
let app;
let services: Services;
let mongodb: MongoDbConnector;
let models;
beforeAll(async () => {
app = await setup.build();
services = app.services;
mongodb = services.mongodb;
models = await setup.initModels(services, [fixtureUsers]);
});
afterAll(async () => {
await setup.teardownDb(mongodb);
});
describe('#mapFindQuery', () => {
it('returns a query and an options objects', () => {
const Model = models.getModel('users');
const mapped = mapFindQuery(Model, {});
expect(mapped).toEqual({
query: {},
options: {
projection: {},
sort: {
created_at: 1,
_id: 1,
},
},
});
});
it('returns _sort options', () => {
const Model = models.getModel('users');
const mapped = mapFindQuery(Model, {
_sort: {
created_at: -1,
},
});
expect(mapped).toMatchObject({
options: {
sort: {
created_at: -1,
},
},
});
});
it('returns _fields options as projections', () => {
const Model = models.getModel('users');
const mapped = mapFindQuery(Model, {
_fields: {
created_at: 1,
},
});
expect(mapped).toMatchObject({
options: {
projection: {
created_at: 1,
},
},
});
});
});
describe('#mapQueryValues', () => {
it('returns values not modified if no formatter defined', () => {
const query = mapQueryValues(
models.getModel('users'),
{},
{
created_at: '2021-01-01T00:00:00.000Z',
},
);
expect(query).toEqual({
created_at: '2021-01-01T00:00:00.000Z',
});
});
it('returns array values mapped to correct query if not defined at array', () => {
const query = mapQueryValues(
models.getModel('users'),
{},
{
firstname: ['Alice'],
},
);
expect(query).toEqual({
firstname: {
$in: ['Alice'],
},
});
});
it('returns array values unchanged if the property is of type `array`', () => {
const query = mapQueryValues(
models.getModel('users'),
{
tags: {
type: 'array',
},
},
{
tags: ['Alice'],
},
);
expect(query).toEqual({
tags: ['Alice'],
});
});
it('returns values formatted with formatter date()', () => {
const query = mapQueryValues(
models.getModel('users'),
{},
{
'date(created_at)': '2021-01-01T00:00:00.000Z',
'date(updated_at)': [
'2021-01-02T00:00:00.000Z',
'2021-01-03T00:00:00.000Z',
],
nested: {
'date($gt)': '2021-01-04T00:00:00.000Z',
},
},
);
expect(query).toEqual({
created_at: new Date('2021-01-01T00:00:00.000Z'),
updated_at: {
$in: [
new Date('2021-01-02T00:00:00.000Z'),
new Date('2021-01-03T00:00:00.000Z'),
],
},
nested: {
$gt: new Date('2021-01-04T00:00:00.000Z'),
},
});
});
it('lets the value unchanged in case of invalid formatter', () => {
const query = mapQueryValues(
models.getModel('users'),
{},
{
'unknown(created_at)': '2021-01-01T00:00:00.000Z',
},
);
expect(query).toEqual({
created_at: '2021-01-01T00:00:00.000Z',
});
});
it('returns nested values formatted', () => {
const query = mapQueryValues(
models.getModel('users'),
{
nested: {
properties: {},
},
},
{
nested: {
'date(created_at)': '2021-01-01T00:00:00.000Z',
},
},
);
expect(query).toEqual({
nested: {
created_at: new Date('2021-01-01T00:00:00.000Z'),
},
});
});
});
describe('#checkProcessingAuthorization', () => {
it('noops if the feature flag is not activated', () => {
expect(checkProcessingAuthorization({}, {}, {})).toBeUndefined();
});
it('noops if no processing is defined', () => {
expect(
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
{}, // <- No processing
{},
),
).toBeUndefined();
});
it('noops if no encrypted field is defined', () => {
expect(
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
'id',
{
processings: [
{
field: 'firstname',
},
],
},
{}, // <- No encrypted field
),
).toBeUndefined();
});
it('noops if no processing is defined but encrypted fields are', () => {
expect(
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
'id',
{
encrypted_fields: ['firstname'],
},
{},
),
).toBeUndefined();
});
it('noops if the data does not contain the encrypted field', () => {
expect(
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
'id',
{
encrypted_fields: ['firstname'],
processings: [
{
field: 'firstname',
},
],
},
{
hello: 1,
},
),
).toBeUndefined();
});
it('noops if no access token is defined', () => {
expect(
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
'id',
{
encrypted_fields: ['firstname'],
processings: [
{
field: 'firstname',
},
],
},
{
firstname: 'John',
},
),
).toBeUndefined();
});
it('throws an error if not authorized', () => {
let error;
try {
checkProcessingAuthorization(
{
config: {
features: {
api: {
checkProcessingAuthorization: true,
},
},
},
},
'id',
{
encrypted_fields: ['firstname'],
processings: [
{
field: 'firstname',
tokens: ['another_one'],
},
],
},
{
firstname: 'John',
},
);
} catch (err) {
error = err;
}
expect(error).toHaveProperty('message', 'Unauthorized field processing');
});
});
});