@dossierhq/integration-test
Version:
Integration test to ensure that different Dossier database adapters work as expected.
171 lines • 10.1 kB
JavaScript
/// <reference types="./AdminEntityDeleteEntitiesSubSuite.d.ts" />
import { assertOkResult, copyEntity, ErrorType, EventType, getAllNodesForConnection, } from '@dossierhq/core';
import { assertEquals, assertErrorResult, assertResultValue } from '../Asserts.js';
import { REFERENCES_CREATE, STRINGS_CREATE, SUBJECT_ONLY_CREATE, TITLE_ONLY_CREATE, } from '../shared-entity/Fixtures.js';
export const DeleteEntitiesSubSuite = [
deleteEntities_minimal,
deleteEntities_twoIndependentEntities,
deleteEntities_twoEntitiesWithReferenceToEachOther,
deleteEntities_releasesId,
deleteEntities_releasesName,
deleteEntities_releasesUniqueIndexValue,
deleteEntities_ignoredInSearch,
deleteEntities_deleteEntityEvent,
deleteEntities_errorInvalidReference,
deleteEntities_errorDuplicateReference,
deleteEntities_errorNoReferences,
deleteEntities_errorWrongAuthKey,
deleteEntities_errorDraftEntity,
deleteEntities_errorReferencedByOtherEntity,
deleteEntities_errorReadonlySession,
];
async function deleteEntities_minimal({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id }));
const result = await client.deleteEntities([{ id }]);
const { deletedAt } = result.valueOrThrow();
assertResultValue(result, { effect: 'deleted', deletedAt });
}
async function deleteEntities_twoIndependentEntities({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id: id1 }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
const { entity: { id: id2 }, } = (await client.createEntity(SUBJECT_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id: id1 }));
assertOkResult(await client.archiveEntity({ id: id2 }));
const result = await client.deleteEntities([{ id: id1 }, { id: id2 }]);
const { deletedAt } = result.valueOrThrow();
assertResultValue(result, { effect: 'deleted', deletedAt });
}
async function deleteEntities_twoEntitiesWithReferenceToEachOther({ clientProvider, }) {
const client = clientProvider.dossierClient();
const { entity: { id: id1 }, } = (await client.createEntity(REFERENCES_CREATE)).valueOrThrow();
const { entity: { id: id2 }, } = (await client.createEntity(copyEntity(REFERENCES_CREATE, { fields: { any: { id: id1 } } }))).valueOrThrow();
assertOkResult(await client.updateEntity({ id: id1, fields: { any: { id: id2 } } }));
assertOkResult(await client.archiveEntity({ id: id1 }));
assertOkResult(await client.archiveEntity({ id: id2 }));
const result = await client.deleteEntities([{ id: id1 }, { id: id2 }]);
const { deletedAt } = result.valueOrThrow();
assertResultValue(result, { effect: 'deleted', deletedAt });
}
async function deleteEntities_releasesId({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id }));
assertOkResult(await client.deleteEntities([{ id }]));
assertErrorResult(await client.getEntity({ id }), ErrorType.NotFound, 'No such entity');
assertOkResult(await client.createEntity(copyEntity(STRINGS_CREATE, { id })));
}
async function deleteEntities_releasesName({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id, info: { name }, }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id }));
assertOkResult(await client.deleteEntities([{ id }]));
// If delete didn't release the name we would get another unique name here
const createResult = await client.createEntity(copyEntity(STRINGS_CREATE, { info: { name } }));
assertEquals(name, createResult.valueOrThrow().entity.info.name);
}
async function deleteEntities_releasesUniqueIndexValue({ clientProvider }) {
const client = clientProvider.dossierClient();
const uniqueValue = crypto.randomUUID();
const { entity: { id }, } = (await client.createEntity(copyEntity(STRINGS_CREATE, { fields: { unique: uniqueValue } }))).valueOrThrow();
assertOkResult(await client.archiveEntity({ id }));
assertOkResult(await client.deleteEntities([{ id }]));
// Since delete entity releases the unique value we can create a new entity with the same unique value
const { entity: secondEntity } = (await client.createEntity(copyEntity(STRINGS_CREATE, { fields: { unique: uniqueValue } }))).valueOrThrow();
const getResult = await client.getEntity({ index: 'stringsUnique', value: uniqueValue });
assertResultValue(getResult, secondEntity);
}
async function deleteEntities_ignoredInSearch({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id }));
assertOkResult(await client.deleteEntities([{ id }]));
// Can't guarantee that the deleted entity will be in this page (race condition) but should be good
const page = (await client.getEntities({ order: 'createdAt', reverse: true }, { first: 100 })).valueOrThrow();
const entityWithId = page?.edges.find((edge) => edge.node.isOk() && edge.node.value.id === id);
assertEquals(entityWithId, undefined);
}
async function deleteEntities_deleteEntityEvent({ clientProvider }) {
const client = clientProvider.dossierClient();
const { entity: { id: id1, info: { name: name1 }, }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
const { entity: { id: id2, info: { name: name2 }, }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
assertOkResult(await client.archiveEntity({ id: id1 }));
assertOkResult(await client.archiveEntity({ id: id2 }));
const result = await client.deleteEntities([{ id: id1 }, { id: id2 }]);
const { deletedAt } = result.valueOrThrow();
// Can't use the entity filter since it's deleted, but we can still find it by searching
let matchEvent = null;
for await (const node of getAllNodesForConnection({}, (paging) => client.getChangelogEvents({ types: ['deleteEntities'], reverse: true }, paging))) {
if (node.isError()) {
continue;
}
const event = node.value;
if (event.type === EventType.deleteEntities &&
event.entities.some((it) => [id1, id2].includes(it.id))) {
matchEvent = event;
break;
}
}
const entity1First = matchEvent.entities[0].id === id1;
assertEquals(matchEvent, {
id: matchEvent.id,
createdAt: deletedAt,
createdBy: matchEvent.createdBy,
type: EventType.deleteEntities,
unauthorizedEntityCount: 0,
entities: entity1First
? [
{ id: id1, name: name1, type: 'TitleOnly', version: 1 },
{ id: id2, name: name2, type: 'TitleOnly', version: 1 },
]
: [
{ id: id2, name: name2, type: 'TitleOnly', version: 1 },
{ id: id1, name: name1, type: 'TitleOnly', version: 1 },
],
});
}
async function deleteEntities_errorInvalidReference({ clientProvider }) {
const result = await clientProvider
.dossierClient()
.deleteEntities([{ id: '5b14e69f-6612-4ddb-bb42-7be273104486' }]);
assertErrorResult(result, ErrorType.NotFound, 'No such entities: 5b14e69f-6612-4ddb-bb42-7be273104486');
}
async function deleteEntities_errorDuplicateReference({ clientProvider }) {
const id = '5b14e69f-6612-4ddb-bb42-7be273104486';
const result = await clientProvider.dossierClient().deleteEntities([{ id }, { id }]);
assertErrorResult(result, ErrorType.BadRequest, 'Duplicate ids: 5b14e69f-6612-4ddb-bb42-7be273104486');
}
async function deleteEntities_errorNoReferences({ clientProvider }) {
const result = await clientProvider.dossierClient().deleteEntities([]);
assertErrorResult(result, ErrorType.BadRequest, 'No references provided');
}
async function deleteEntities_errorWrongAuthKey({ clientProvider }) {
const createResult = await clientProvider.dossierClient().createEntity(SUBJECT_ONLY_CREATE);
const { entity: { id }, } = createResult.valueOrThrow();
const deleteResult = await clientProvider.dossierClient('secondary').deleteEntities([{ id }]);
assertErrorResult(deleteResult, ErrorType.NotAuthorized, 'Wrong authKey provided');
}
async function deleteEntities_errorDraftEntity({ clientProvider }) {
const client = clientProvider.dossierClient();
const createResult = await client.createEntity(TITLE_ONLY_CREATE);
const { entity: { id }, } = createResult.valueOrThrow();
const deleteResult = await client.deleteEntities([{ id }]);
assertErrorResult(deleteResult, ErrorType.BadRequest, `Entity is not archived (id: ${id}, status: draft)`);
}
async function deleteEntities_errorReferencedByOtherEntity({ clientProvider, }) {
const client = clientProvider.dossierClient();
const { entity: { id: id1 }, } = (await client.createEntity(TITLE_ONLY_CREATE)).valueOrThrow();
const { entity: { id: id2 }, } = (await client.createEntity(copyEntity(REFERENCES_CREATE, { fields: { any: { id: id1 } } }))).valueOrThrow();
assertOkResult(await client.archiveEntity({ id: id1 }));
const deleteResult = await client.deleteEntities([{ id: id1 }]);
assertErrorResult(deleteResult, ErrorType.BadRequest, `Entity (${id1}) is referenced by other entities (${id2})`);
}
async function deleteEntities_errorReadonlySession({ clientProvider }) {
const client = clientProvider.dossierClient('main', 'readonly');
const createResult = await client.deleteEntities([
{ id: '5b14e69f-6612-4ddb-bb42-7be273104486' },
]);
assertErrorResult(createResult, ErrorType.BadRequest, 'Readonly session used to delete entity');
}
//# sourceMappingURL=AdminEntityDeleteEntitiesSubSuite.js.map