UNPKG

@dossierhq/integration-test

Version:

Integration test to ensure that different Dossier database adapters work as expected.

582 lines 26.6 kB
/// <reference types="./AdminEntityUpdateEntitySubSuite.d.ts" /> import { copyEntity, EntityStatus, ErrorType, EventType, isEntityNameAsRequested, Schema, } from '@dossierhq/core'; import { assertEquals, assertErrorResult, assertNotSame, assertOkResult, assertResultValue, assertSame, assertTruthy, } from '../Asserts.js'; import { assertIsChangeValidations, assertIsComponents, assertIsReferences, } from '../SchemaTypes.js'; import { assertChangelogEventsConnection } from '../shared-entity/EventsTestUtils.js'; import { adminToPublishedEntity, LOCATIONS_CREATE, REFERENCES_ADMIN_ENTITY, REFERENCES_CREATE, STRINGS_CREATE, SUBJECT_ONLY_CREATE, TITLE_ONLY_CREATE, } from '../shared-entity/Fixtures.js'; import { createEntityWithInvalidComponent, createInvalidEntity, } from '../shared-entity/InvalidEntityUtils.js'; export const UpdateEntitySubSuite = [ updateEntity_minimal, updateEntity_noChange, updateEntity_minimalWithSubjectAuthKey, updateEntity_minimalWithoutProvidingSubjectAuthKey, updateEntity_updateAndPublishEntity, updateEntity_updateAndPublishEntityWithSubjectAuthKey, updateEntity_updateAndPublishEntityWithUniqueIndexValue, updateEntity_updateAndPublishEntityWithConflictingPublishedName, updateEntity_noChangeAndPublishDraftEntity, updateEntity_noChangeAndPublishPublishedEntity, updateEntity_updateEntityEvent, updateEntity_updateAndPublishEntityEvent, updateEntity_publishEntitiesEventDueToNoChangeAndPublish, updateEntity_fixInvalidEntity, updateEntity_fixInvalidComponent, updateEntity_withMultilineField, updateEntity_withTwoReferences, updateEntity_withMultipleLocations, updateEntity_removingUniqueIndexValueReleasesOwnership, updateEntity_errorInvalidId, updateEntity_errorDifferentType, updateEntity_errorTryingToChangeAuthKey, updateEntity_errorMultilineStringInTitle, updateEntity_errorPublishWithoutRequiredTitle, updateEntity_errorInvalidField, updateEntity_errorDuplicateUniqueIndexValue, updateEntity_errorReadonlySession, ]; async function updateEntity_minimal({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title: 'Updated title' } }); const { entity: { info: { updatedAt }, }, } = updateResult.valueOrThrow(); const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2, }, fields: { title: 'Updated title', }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_noChange({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id, fields: { title }, }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title } }); assertResultValue(updateResult, { effect: 'none', entity: createResult.value.entity, }); } async function updateEntity_minimalWithSubjectAuthKey({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(SUBJECT_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { authKey: 'subject' }, fields: { message: 'Updated message' }, }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2, }, fields: { message: 'Updated message', }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_minimalWithoutProvidingSubjectAuthKey({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(SUBJECT_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.valueOrThrow(); const updateResult = await client.updateEntity({ id, fields: { message: 'Updated message' }, }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2, }, fields: { message: 'Updated message', }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_updateAndPublishEntity({ clientProvider }) { const client = clientProvider.dossierClient(); const publishedClient = clientProvider.publishedClient(); const { entity: originalEntity } = (await client.createEntity(copyEntity(TITLE_ONLY_CREATE, { info: { name: 'Original name' } }))).valueOrThrow(); const updateResult = await client.updateEntity({ id: originalEntity.id, info: { name: 'Updated name' }, fields: { title: 'Updated title' } }, { publish: true }); const { entity: { info: { name: updatedName, updatedAt }, }, } = updateResult.valueOrThrow(); const expectedEntity = copyEntity(originalEntity, { info: { updatedAt, version: 2, name: updatedName, status: EntityStatus.published, validPublished: true, }, fields: { title: 'Updated title', }, }); assertResultValue(updateResult, { effect: 'updatedAndPublished', entity: expectedEntity, }); const getAdminResult = await client.getEntity({ id: originalEntity.id }); assertResultValue(getAdminResult, expectedEntity); const publishedEntity = (await publishedClient.getEntity({ id: originalEntity.id })).valueOrThrow(); assertTruthy(isEntityNameAsRequested(publishedEntity.info.name, 'Updated name')); assertSame(publishedEntity.info.name, updatedName); } async function updateEntity_updateAndPublishEntityWithSubjectAuthKey({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(SUBJECT_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { authKey: 'subject' }, fields: { message: 'Updated message' } }, { publish: true }); const { entity: { info: { updatedAt }, }, } = updateResult.valueOrThrow(); const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2, status: EntityStatus.published, validPublished: true, }, fields: { message: 'Updated message', }, }); assertResultValue(updateResult, { effect: 'updatedAndPublished', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_updateAndPublishEntityWithUniqueIndexValue({ clientProvider, }) { const client = clientProvider.dossierClient(); const publishedClient = clientProvider.publishedClient(); const schema = new Schema((await client.getSchemaSpecification()).valueOrThrow()); const createResult = await client.createEntity(STRINGS_CREATE); const { entity: { id }, } = createResult.valueOrThrow(); const unique = Math.random().toString(); const updateResult = await client.updateEntity({ id, fields: { unique } }, { publish: true }); assertOkResult(updateResult); const getAdminResult = await client.getEntity({ index: 'stringsUnique', value: unique }); assertResultValue(getAdminResult, updateResult.value.entity); const getPublishedResult = await publishedClient.getEntity({ index: 'stringsUnique', value: unique, }); assertResultValue(getPublishedResult, adminToPublishedEntity(schema, updateResult.value.entity)); } async function updateEntity_updateAndPublishEntityWithConflictingPublishedName({ clientProvider, }) { const client = clientProvider.dossierClient(); const publishedClient = clientProvider.publishedClient(); // Create/publish first entity const { entity: { id: firstId, info: { name: firstOriginalName }, }, } = (await client.createEntity(copyEntity(TITLE_ONLY_CREATE, { info: { name: 'Original name' } }), { publish: true, })).valueOrThrow(); // Update name (without publishing), that way we only conflict on the published name assertOkResult(await client.updateEntity({ id: firstId, info: { name: 'New name' }, fields: {} })); // Create second entity with same name (should be ok since we don't publish) const { entity: { id: secondId, info: { name: secondOriginalName }, }, } = (await client.createEntity(copyEntity(TITLE_ONLY_CREATE, { info: { name: firstOriginalName } }))).valueOrThrow(); assertSame(firstOriginalName, secondOriginalName); // Update and publish second entity const { entity: { info: { name: secondUpdatedName }, }, } = (await client.updateEntity({ id: secondId, fields: { title: 'Updated title' } }, { publish: true })).valueOrThrow(); assertNotSame(secondUpdatedName, secondOriginalName); // Changes since due to conflicting published name // Get second published entity const { info: { name: secondPublishedName }, } = (await publishedClient.getEntity({ id: secondId })).valueOrThrow(); assertSame(secondPublishedName, secondUpdatedName); } async function updateEntity_noChangeAndPublishDraftEntity({ clientProvider, }) { const client = clientProvider.dossierClient(); const publishedClient = clientProvider.publishedClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id, fields: { title }, }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title } }, { publish: true }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, status: EntityStatus.published, validPublished: true, }, }); assertResultValue(updateResult, { effect: 'published', entity: expectedEntity, }); const getAdminResult = await client.getEntity({ id }); assertResultValue(getAdminResult, expectedEntity); const publishedEntity = (await publishedClient.getEntity({ id })).valueOrThrow(); assertSame(publishedEntity.info.name, expectedEntity.info.name); } async function updateEntity_noChangeAndPublishPublishedEntity({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE, { publish: true, }); assertOkResult(createResult); const { entity: { id, fields: { title }, }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title } }, { publish: true }); assertOkResult(updateResult); assertResultValue(updateResult, { effect: 'none', entity: createResult.value.entity, }); } async function updateEntity_updateEntityEvent({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id, info: { name: originalName, createdAt }, }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { name: 'Updated name' }, fields: { title: 'Updated title' }, }); const { entity: { info: { updatedAt, name: updatedName }, }, } = updateResult.valueOrThrow(); const connectionResult = await client.getChangelogEvents({ entity: { id } }); assertChangelogEventsConnection(connectionResult, [ { type: EventType.createEntity, createdAt, createdBy: '', entities: [{ id, name: originalName, version: 1, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, { type: EventType.updateEntity, createdAt: updatedAt, createdBy: '', entities: [{ id, name: updatedName, version: 2, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, ]); } async function updateEntity_updateAndPublishEntityEvent({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id, info: { name: originalName, createdAt }, }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { name: 'Updated name' }, fields: { title: 'Updated title' }, }, { publish: true }); const { entity: { info: { updatedAt, name: updatedName }, }, } = updateResult.valueOrThrow(); const connectionResult = await client.getChangelogEvents({ entity: { id } }); assertChangelogEventsConnection(connectionResult, [ { type: EventType.createEntity, createdAt, createdBy: '', entities: [{ id, name: originalName, version: 1, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, { type: EventType.updateAndPublishEntity, createdAt: updatedAt, createdBy: '', entities: [{ id, name: updatedName, version: 2, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, ]); } async function updateEntity_publishEntitiesEventDueToNoChangeAndPublish({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); const { entity: { id, info: { name, createdAt }, }, } = createResult.valueOrThrow(); const updateResult = await client.updateEntity({ id, fields: {} }, { publish: true }); const { effect: updateEffect, entity: { info: { updatedAt }, }, } = updateResult.valueOrThrow(); assertEquals(updateEffect, 'published'); const connectionResult = await client.getChangelogEvents({ entity: { id } }); assertChangelogEventsConnection(connectionResult, [ { type: EventType.createEntity, createdAt, createdBy: '', entities: [{ id, name, version: 1, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, { type: EventType.publishEntities, createdAt: updatedAt, createdBy: '', entities: [{ id, name, version: 1, type: 'TitleOnly' }], unauthorizedEntityCount: 0, }, ]); } async function updateEntity_fixInvalidEntity({ clientProvider }) { const client = clientProvider.dossierClient(); const { entity } = (await createInvalidEntity(client, { matchPattern: 'no match' })).valueOrThrow(); const updateResult = await client.updateEntity({ id: entity.id, fields: { matchPattern: 'foo' }, }); const { entity: { info: { updatedAt }, }, } = updateResult.valueOrThrow(); const expectedEntity = copyEntity(entity, { info: { updatedAt, version: 2, valid: true, }, fields: { matchPattern: 'foo', }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getEntity = (await client.getEntity({ id: entity.id })).valueOrThrow(); assertIsChangeValidations(getEntity); assertEquals(getEntity, expectedEntity); } async function updateEntity_fixInvalidComponent({ clientProvider }) { const client = clientProvider.dossierClient(); const { entity } = (await createEntityWithInvalidComponent(client)).valueOrThrow(); const updateResult = await client.updateEntity({ id: entity.id, fields: { any: { type: 'ChangeValidationsComponent', matchPattern: 'foo' } }, }); const { entity: { info: { updatedAt }, }, } = updateResult.valueOrThrow(); const expectedEntity = copyEntity(entity, { info: { updatedAt, version: 2, valid: true }, fields: { any: { type: 'ChangeValidationsComponent', matchPattern: 'foo' } }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getEntity = (await client.getEntity({ id: entity.id })).valueOrThrow(); assertIsComponents(getEntity); assertEquals(getEntity, expectedEntity); } async function updateEntity_withMultilineField({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(STRINGS_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { multiline: 'one\ntwo\nthree!' } }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2, }, fields: { multiline: 'one\ntwo\nthree!', }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_withTwoReferences({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(REFERENCES_CREATE); const createTitleOnly1Result = await client.createEntity(TITLE_ONLY_CREATE); const createTitleOnly2Result = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); assertOkResult(createTitleOnly1Result); assertOkResult(createTitleOnly2Result); const { entity: { id, info: { name, createdAt }, }, } = createResult.value; const { entity: { id: idTitleOnly1 }, } = createTitleOnly1Result.value; const { entity: { id: idTitleOnly2 }, } = createTitleOnly2Result.value; const updateResult = await client.updateEntity({ id, fields: { any: { id: idTitleOnly1 }, titleOnly: { id: idTitleOnly2 } }, }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(REFERENCES_ADMIN_ENTITY, { id, info: { name, createdAt, updatedAt, version: 2, }, fields: { any: { id: idTitleOnly1 }, titleOnly: { id: idTitleOnly2 }, }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertOkResult(getResult); assertIsReferences(getResult.value); assertEquals(getResult.value, expectedEntity); } async function updateEntity_withMultipleLocations({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(LOCATIONS_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { location: { lat: 1, lng: 2 }, locationList: [ { lat: 3, lng: 4 }, { lat: -179, lng: -178 }, ], }, }); assertOkResult(updateResult); const { entity: { info: { updatedAt }, }, } = updateResult.value; const expectedEntity = copyEntity(createResult.value.entity, { info: { updatedAt, version: 2 }, fields: { location: { lat: 1, lng: 2 }, locationList: [ { lat: 3, lng: 4 }, { lat: -179, lng: -178 }, ], }, }); assertResultValue(updateResult, { effect: 'updated', entity: expectedEntity, }); const getResult = await client.getEntity({ id }); assertResultValue(getResult, expectedEntity); } async function updateEntity_removingUniqueIndexValueReleasesOwnership({ clientProvider, }) { const client = clientProvider.dossierClient(); const unique = Math.random().toString(); const createResult = await client.createEntity(copyEntity(STRINGS_CREATE, { fields: { unique } })); assertOkResult(createResult); const updateResult = await client.updateEntity({ id: createResult.value.entity.id, fields: { unique: null }, }); assertOkResult(updateResult); const otherResult = await client.createEntity(copyEntity(STRINGS_CREATE, { fields: { unique } })); assertOkResult(otherResult); } async function updateEntity_errorInvalidId({ clientProvider }) { const client = clientProvider.dossierClient(); const result = await client.updateEntity({ id: 'f773ac54-37db-42df-9b55-b6da8de344c3', info: { name: 'Updated name' }, fields: {}, }); assertErrorResult(result, ErrorType.NotFound, 'No such entity'); } async function updateEntity_errorDifferentType({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { type: 'References' }, fields: {} }); assertErrorResult(updateResult, ErrorType.BadRequest, 'entity.info.type: New type References doesn’t correspond to previous type TitleOnly'); } async function updateEntity_errorTryingToChangeAuthKey({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, info: { authKey: 'subject' }, fields: {}, }); assertErrorResult(updateResult, ErrorType.BadRequest, 'entity.info.authKey: New authKey doesn’t correspond to previous authKey (subject!=)'); const getResult = await client.getEntity({ id }); assertResultValue(getResult, createResult.value.entity); } async function updateEntity_errorMultilineStringInTitle({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title: 'Hello\nWorld' } }); assertErrorResult(updateResult, ErrorType.BadRequest, 'entity.fields.title: Value cannot contain line breaks'); const getResult = await client.getEntity({ id }); assertResultValue(getResult, createResult.value.entity); } async function updateEntity_errorPublishWithoutRequiredTitle({ clientProvider, }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { title: null } }, { publish: true }); assertErrorResult(updateResult, ErrorType.BadRequest, `entity(${id}).fields.title: Required field is empty`); const getResult = await client.getEntity({ id }); assertResultValue(getResult, createResult.value.entity); } async function updateEntity_errorInvalidField({ clientProvider }) { const client = clientProvider.dossierClient(); const createResult = await client.createEntity(TITLE_ONLY_CREATE); assertOkResult(createResult); const { entity: { id }, } = createResult.value; const updateResult = await client.updateEntity({ id, fields: { invalid: 'hello' }, }); assertErrorResult(updateResult, ErrorType.BadRequest, 'entity.fields: TitleOnly does not include the fields: invalid'); const getResult = await client.getEntity({ id }); assertResultValue(getResult, createResult.value.entity); } async function updateEntity_errorDuplicateUniqueIndexValue({ clientProvider, }) { const client = clientProvider.dossierClient(); const unique = Math.random().toString(); const otherResult = await client.createEntity(copyEntity(STRINGS_CREATE, { fields: { unique } })); assertOkResult(otherResult); const createResult = await client.createEntity(STRINGS_CREATE); assertOkResult(createResult); const updateResult = await client.updateEntity({ id: createResult.value.entity.id, fields: { unique }, }); assertErrorResult(updateResult, ErrorType.BadRequest, `entity.fields.unique: Value is not unique (stringsUnique:${unique})`); } async function updateEntity_errorReadonlySession({ clientProvider }) { const normalClient = clientProvider.dossierClient(); const readonlyClient = clientProvider.dossierClient('main', 'readonly'); const createResult = await normalClient.createEntity(TITLE_ONLY_CREATE); const { entity: { id }, } = createResult.valueOrThrow(); const updateResult = await readonlyClient.updateEntity({ id, info: { name: 'Updated name' }, fields: {}, }); assertErrorResult(updateResult, ErrorType.BadRequest, 'Readonly session used to update entity'); } //# sourceMappingURL=AdminEntityUpdateEntitySubSuite.js.map