From f16c89585ae9a87d4c57bc7f1addbdda722f0394 Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Wed, 18 Sep 2024 12:19:53 -0600 Subject: [PATCH] DRYD-1355: Deaccession Procedure (#238) --- .../recordTypes/deaccession/advancedSearch.js | 21 ++ .../recordTypes/deaccession/columns.js | 48 +++ src/plugins/recordTypes/deaccession/fields.js | 327 ++++++++++++++++++ .../recordTypes/deaccession/forms/default.jsx | 67 ++++ .../recordTypes/deaccession/forms/index.js | 5 + .../recordTypes/deaccession/idGenerators.js | 13 + src/plugins/recordTypes/deaccession/index.js | 23 ++ .../recordTypes/deaccession/messages.js | 26 ++ .../recordTypes/deaccession/serviceConfig.js | 8 + src/plugins/recordTypes/deaccession/title.js | 26 ++ src/plugins/recordTypes/index.js | 2 + .../deaccession/advancedSearch.spec.js | 16 + .../recordTypes/deaccession/columns.spec.js | 15 + .../deaccession/forms/default.spec.js | 14 + .../recordTypes/deaccession/index.spec.js | 29 ++ .../recordTypes/deaccession/messages.spec.js | 17 + .../deaccession/serviceConfig.spec.js | 13 + .../recordTypes/deaccession/title.spec.js | 76 ++++ 18 files changed, 746 insertions(+) create mode 100644 src/plugins/recordTypes/deaccession/advancedSearch.js create mode 100644 src/plugins/recordTypes/deaccession/columns.js create mode 100644 src/plugins/recordTypes/deaccession/fields.js create mode 100644 src/plugins/recordTypes/deaccession/forms/default.jsx create mode 100644 src/plugins/recordTypes/deaccession/forms/index.js create mode 100644 src/plugins/recordTypes/deaccession/idGenerators.js create mode 100644 src/plugins/recordTypes/deaccession/index.js create mode 100644 src/plugins/recordTypes/deaccession/messages.js create mode 100644 src/plugins/recordTypes/deaccession/serviceConfig.js create mode 100644 src/plugins/recordTypes/deaccession/title.js create mode 100644 test/specs/plugins/recordTypes/deaccession/advancedSearch.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/columns.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/forms/default.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/index.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/messages.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/serviceConfig.spec.js create mode 100644 test/specs/plugins/recordTypes/deaccession/title.spec.js diff --git a/src/plugins/recordTypes/deaccession/advancedSearch.js b/src/plugins/recordTypes/deaccession/advancedSearch.js new file mode 100644 index 000000000..6af8080bd --- /dev/null +++ b/src/plugins/recordTypes/deaccession/advancedSearch.js @@ -0,0 +1,21 @@ +export default (configContext) => { + const { + OP_CONTAIN, + } = configContext.searchOperators; + + const { + defaultAdvancedSearchBooleanOp, + extensions, + } = configContext.config; + + return { + op: defaultAdvancedSearchBooleanOp, + value: [ + { + op: OP_CONTAIN, + path: 'ns2:deaccessions_common/deaccessionNumber', + }, + ...extensions.core.advancedSearch, + ], + }; +}; diff --git a/src/plugins/recordTypes/deaccession/columns.js b/src/plugins/recordTypes/deaccession/columns.js new file mode 100644 index 000000000..770b47646 --- /dev/null +++ b/src/plugins/recordTypes/deaccession/columns.js @@ -0,0 +1,48 @@ +import { defineMessages } from 'react-intl'; + +export default (configContext) => { + const { + formatRefName, + formatTimestamp, + } = configContext.formatHelpers; + + return { + default: { + deaccessionNumber: { + messages: defineMessages({ + label: { + id: 'column.deaccession.default.deaccessionNumber', + defaultMessage: 'Deaccession number', + }, + }), + order: 10, + sortBy: 'deaccessions_common:deaccessionNumber', + width: 200, + }, + deaccessionApprovalIndividual: { + formatValue: formatRefName, + messages: defineMessages({ + label: { + id: 'column.deaccession.default.deaccessionApprovalIndividual', + defaultMessage: 'Individual', + }, + }), + order: 20, + sortBy: 'deaccessions_common:deaccessionApprovalGroupList/0/deaccessionApprovalIndividual', + width: 450, + }, + updatedAt: { + formatValue: formatTimestamp, + messages: defineMessages({ + label: { + id: 'column.deaccession.default.updatedAt', + defaultMessage: 'Updated', + }, + }), + order: 30, + sortBy: 'collectionspace_core:updatedAt', + width: 150, + }, + }, + }; +}; diff --git a/src/plugins/recordTypes/deaccession/fields.js b/src/plugins/recordTypes/deaccession/fields.js new file mode 100644 index 000000000..36f0018cc --- /dev/null +++ b/src/plugins/recordTypes/deaccession/fields.js @@ -0,0 +1,327 @@ +import { defineMessages } from 'react-intl'; + +export default (configContext) => { + const { + AutocompleteInput, + CompoundInput, + DateInput, + IDGeneratorInput, + TermPickerInput, + TextInput, + } = configContext.inputComponents; + + const { + configKey: config, + } = configContext.configHelpers; + + const { + DATA_TYPE_DATE, + } = configContext.dataTypes; + + const { + extensions, + } = configContext.config; + + const { + validateNotInUse, + } = configContext.validationHelpers; + + return { + document: { + [config]: { + view: { + type: CompoundInput, + props: { + defaultChildSubpath: 'ns2:deaccessions_common', + }, + }, + }, + ...extensions.core.fields, + 'ns2:deaccessions_common': { + [config]: { + service: { + ns: 'http://collectionspace.org/services/deaccession', + }, + }, + deaccessionNumber: { + [config]: { + cloneable: false, + messages: defineMessages({ + inUse: { + id: 'field.deaccessions_common.deaccessionNumber.inUse', + defaultMessage: 'The identification number {value} is in use by another record.', + }, + name: { + id: 'field.deaccessions_common.deaccessionNumber.name', + defaultMessage: 'Deaccession number', + }, + }), + required: true, + searchView: { + type: TextInput, + }, + validate: (validationContext) => validateNotInUse({ + configContext, + validationContext, + fieldName: 'deaccessions_common:deaccessionNumber', + }), + view: { + type: IDGeneratorInput, + props: { + source: 'deaccession', + }, + }, + }, + }, + deaccessionReasons: { + [config]: { + view: { + type: CompoundInput, + }, + }, + deaccessionReason: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.deaccessionReason.name', + defaultMessage: 'Deaccession reason', + }, + }), + repeating: true, + view: { + type: TermPickerInput, + props: { + source: 'deaccessionreason', + }, + }, + }, + }, + }, + deaccessionDate: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.deaccessionDate.name', + defaultMessage: 'Deaccession date', + }, + }), + dataType: DATA_TYPE_DATE, + view: { + type: DateInput, + }, + }, + }, + deaccessionRationale: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.deaccessionRationale.name', + defaultMessage: 'Deaccession rationale', + }, + }), + view: { + type: TextInput, + props: { + multiline: true, + }, + }, + }, + }, + deaccessionNote: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.deaccessionNote.name', + defaultMessage: 'Deaccession note', + }, + }), + view: { + type: TextInput, + props: { + multiline: true, + }, + }, + }, + }, + deaccessionApprovalGroupList: { + [config]: { + view: { + type: CompoundInput, + }, + }, + deaccessionApprovalGroup: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.deaccessionApprovalGroup.name', + defaultMessage: 'Deaccession approval', + }, + }), + repeating: true, + view: { + type: CompoundInput, + }, + }, + deaccessionApprovalGroup: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.deaccessions_common.deaccessionApprovalGroup.deaccessionApprovalGroup.fullName', + defaultMessage: 'Deaccession approval group', + }, + name: { + id: 'field.deaccessions_common.deaccessionApprovalGroup.deaccessionApprovalGroup.name', + defaultMessage: 'Group', + }, + }), + view: { + type: TermPickerInput, + props: { + source: 'deaccessionapprovalgroup', + }, + }, + }, + }, + deaccessionApprovalIndividual: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.deaccessions_common.deaccessionApprovalIndividual.fullName', + defaultMessage: 'Deaccession approval individual', + }, + name: { + id: 'field.deaccessions_common.deaccessionApprovalIndividual.name', + defaultMessage: 'Individual', + }, + }), + view: { + type: AutocompleteInput, + props: { + source: 'person/local', + }, + }, + }, + }, + deaccessionApprovalStatus: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.deaccessions_common.deaccessionApprovalStatus.fullName', + defaultMessage: 'Deaccession approval status', + }, + name: { + id: 'field.deaccessions_common.deaccessionApprovalStatus.name', + defaultMessage: 'Status', + }, + }), + view: { + type: TermPickerInput, + props: { + source: 'deaccessionapprovalstatus', + }, + }, + }, + }, + deaccessionApprovalDate: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.deaccessions_common.deaccessionApprovalDate.fullName', + defaultMessage: 'Deaccession approval date', + }, + name: { + id: 'field.deaccessions_common.deaccessionApprovalDate.name', + defaultMessage: 'Date', + }, + }), + dataType: DATA_TYPE_DATE, + view: { + type: DateInput, + }, + }, + }, + deaccessionApprovalNote: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.deaccessions_common.deaccessionApprovalNote.fullName', + defaultMessage: 'Deaccession approval note', + }, + name: { + id: 'field.deaccessions_common.deaccessionApprovalNote.name', + defaultMessage: 'Note', + }, + }), + view: { + type: TextInput, + }, + }, + }, + }, + }, + exitDate: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.exitDate.name', + defaultMessage: 'Exit date', + }, + }), + dataType: DATA_TYPE_DATE, + view: { + type: DateInput, + }, + }, + }, + exitRecipients: { + [config]: { + view: { + type: CompoundInput, + }, + }, + exitRecipient: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.exitRecipient.name', + defaultMessage: 'Exit recipient', + }, + }), + repeating: true, + view: { + type: AutocompleteInput, + props: { + source: 'person/local,organization/local', + }, + }, + }, + }, + }, + exitMethods: { + [config]: { + view: { + type: CompoundInput, + }, + }, + exitMethod: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.deaccessions_common.exitMethod.name', + defaultMessage: 'Exit method', + }, + }), + repeating: true, + view: { + type: TermPickerInput, + props: { + source: 'disposalmethod', + }, + }, + }, + }, + }, + }, + }, + }; +}; diff --git a/src/plugins/recordTypes/deaccession/forms/default.jsx b/src/plugins/recordTypes/deaccession/forms/default.jsx new file mode 100644 index 000000000..6285afe72 --- /dev/null +++ b/src/plugins/recordTypes/deaccession/forms/default.jsx @@ -0,0 +1,67 @@ +import { defineMessages } from 'react-intl'; + +const template = (configContext) => { + const { + React, + } = configContext.lib; + + const { + Panel, + Row, + } = configContext.layoutComponents; + + const { + Field, + } = configContext.recordComponents; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default (configContext) => ({ + messages: defineMessages({ + name: { + id: 'form.deaccession.default.name', + defaultMessage: 'Standard Template', + }, + }), + template: template(configContext), +}); diff --git a/src/plugins/recordTypes/deaccession/forms/index.js b/src/plugins/recordTypes/deaccession/forms/index.js new file mode 100644 index 000000000..b04a0c7df --- /dev/null +++ b/src/plugins/recordTypes/deaccession/forms/index.js @@ -0,0 +1,5 @@ +import defaultForm from './default'; + +export default (configContext) => ({ + default: defaultForm(configContext), +}); diff --git a/src/plugins/recordTypes/deaccession/idGenerators.js b/src/plugins/recordTypes/deaccession/idGenerators.js new file mode 100644 index 000000000..b3ee146f4 --- /dev/null +++ b/src/plugins/recordTypes/deaccession/idGenerators.js @@ -0,0 +1,13 @@ +import { defineMessages } from 'react-intl'; + +export default { + deaccession: { + csid: '0b508d05-67df-4b63-b4ce-7319a3029baa', + messages: defineMessages({ + type: { + id: 'idGenerator.deaccession.type', + defaultMessage: 'Deaccession', + }, + }), + }, +}; diff --git a/src/plugins/recordTypes/deaccession/index.js b/src/plugins/recordTypes/deaccession/index.js new file mode 100644 index 000000000..81051209f --- /dev/null +++ b/src/plugins/recordTypes/deaccession/index.js @@ -0,0 +1,23 @@ +import advancedSearch from './advancedSearch'; +import columns from './columns'; +import fields from './fields'; +import forms from './forms'; +import idGenerators from './idGenerators'; +import messages from './messages'; +import serviceConfig from './serviceConfig'; +import title from './title'; + +export default () => (configContext) => ({ + idGenerators, + recordTypes: { + deaccession: { + messages, + serviceConfig, + advancedSearch: advancedSearch(configContext), + columns: columns(configContext), + fields: fields(configContext), + forms: forms(configContext), + title: title(configContext), + }, + }, +}); diff --git a/src/plugins/recordTypes/deaccession/messages.js b/src/plugins/recordTypes/deaccession/messages.js new file mode 100644 index 000000000..9db07eafe --- /dev/null +++ b/src/plugins/recordTypes/deaccession/messages.js @@ -0,0 +1,26 @@ +import { defineMessages } from 'react-intl'; + +export default { + record: defineMessages({ + name: { + id: 'record.deaccession.name', + description: 'The name of the record type', + defaultMessage: 'Deaccession', + }, + collectionName: { + id: 'record.deaccession.collectionName', + description: 'The name of a collection of records of the type.', + defaultMessage: 'Deaccessions', + }, + }), + panel: defineMessages({ + info: { + id: 'panel.deaccession.info', + defaultMessage: 'Deaccession Information', + }, + exit: { + id: 'panel.deaccession.exit', + defaultMessage: 'Proposed Exit Details', + }, + }), +}; diff --git a/src/plugins/recordTypes/deaccession/serviceConfig.js b/src/plugins/recordTypes/deaccession/serviceConfig.js new file mode 100644 index 000000000..73db60bd2 --- /dev/null +++ b/src/plugins/recordTypes/deaccession/serviceConfig.js @@ -0,0 +1,8 @@ +export default { + serviceName: 'Deaccession', + servicePath: 'deaccessions', + serviceType: 'procedure', + + objectName: 'Deaccession', + documentName: 'Deaccessions', +}; diff --git a/src/plugins/recordTypes/deaccession/title.js b/src/plugins/recordTypes/deaccession/title.js new file mode 100644 index 000000000..4cac31c1f --- /dev/null +++ b/src/plugins/recordTypes/deaccession/title.js @@ -0,0 +1,26 @@ +export default (configContext) => (data) => { + const { + getPart, + deepGet, + } = configContext.recordDataHelpers; + + const { + getDisplayName, + } = configContext.refNameHelpers; + + if (!data) { + return ''; + } + + const common = getPart(data, 'deaccessions_common'); + + if (!common) { + return ''; + } + + // do we want a second field to be used for the title? + const referenceNumber = common.get('deaccessionNumber'); + const approvalIndividual = getDisplayName(deepGet(common, ['deaccessionApprovalGroupList', 'deaccessionApprovalGroup', 0, 'deaccessionApprovalIndividual'])); + + return [referenceNumber, approvalIndividual].filter((part) => !!part).join(' – '); +}; diff --git a/src/plugins/recordTypes/index.js b/src/plugins/recordTypes/index.js index 48549fb63..341ae0347 100644 --- a/src/plugins/recordTypes/index.js +++ b/src/plugins/recordTypes/index.js @@ -15,6 +15,7 @@ import conditioncheck from './conditioncheck'; import conservation from './conservation'; import consultation from './consultation'; import contact from './contact'; +import deaccession from './deaccession'; import dutyofcare from './dutyofcare'; import exhibition from './exhibition'; import exxport from './export'; @@ -67,6 +68,7 @@ export default [ conservation, consultation, contact, + deaccession, dutyofcare, exhibition, exxport, diff --git a/test/specs/plugins/recordTypes/deaccession/advancedSearch.spec.js b/test/specs/plugins/recordTypes/deaccession/advancedSearch.spec.js new file mode 100644 index 000000000..8090844cf --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/advancedSearch.spec.js @@ -0,0 +1,16 @@ +import createConfigContext from '../../../../../src/helpers/createConfigContext'; +import advancedSearch from '../../../../../src/plugins/recordTypes/deaccession/advancedSearch'; + +chai.should(); + +describe('deaccession record advanced search', () => { + const configContext = createConfigContext(); + + it('should contain a top level property `op`', () => { + advancedSearch(configContext).should.have.property('op'); + }); + + it('should contain a top level property `value` that is an array', () => { + advancedSearch(configContext).should.have.property('value').that.is.an('array'); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/columns.spec.js b/test/specs/plugins/recordTypes/deaccession/columns.spec.js new file mode 100644 index 000000000..5fc99ebe1 --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/columns.spec.js @@ -0,0 +1,15 @@ +import deaccessionRecordTypePluginFactory from '../../../../../src/plugins/recordTypes/deaccession'; +import createColumns from '../../../../../src/plugins/recordTypes/deaccession/columns'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('deaccession record columns', () => { + const deaccessionRecordTypePlugin = deaccessionRecordTypePluginFactory({}); + const configContext = createConfigContext(deaccessionRecordTypePlugin); + const columns = createColumns(configContext); + + it('should have the correct shape', () => { + columns.should.have.property('default').that.is.an('object'); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/forms/default.spec.js b/test/specs/plugins/recordTypes/deaccession/forms/default.spec.js new file mode 100644 index 000000000..4e3d0cfff --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/forms/default.spec.js @@ -0,0 +1,14 @@ +import Field from '../../../../../../src/components/record/Field'; +import form from '../../../../../../src/plugins/recordTypes/deaccession/forms/default'; +import createConfigContext from '../../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('deaccession record default form', () => { + it('should be a Field', () => { + const configContext = createConfigContext(); + const { template } = form(configContext); + + template.type.should.equal(Field); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/index.spec.js b/test/specs/plugins/recordTypes/deaccession/index.spec.js new file mode 100644 index 000000000..e98fbf699 --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/index.spec.js @@ -0,0 +1,29 @@ +import deaccessionRecordTypePluginFactory from '../../../../../src/plugins/recordTypes/deaccession'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('deaccession record plugin', () => { + const config = {}; + const deaccessionRecordTypePlugin = deaccessionRecordTypePluginFactory(config); + const configContext = createConfigContext(deaccessionRecordTypePlugin); + + it('should have the correct shape', () => { + const pluginConfiguration = deaccessionRecordTypePlugin(configContext); + + const { + recordTypes, + } = pluginConfiguration; + + recordTypes.should.have.property('deaccession'); + + const deaccessionRecordType = recordTypes.deaccession; + + deaccessionRecordType.should.have.property('title').that.is.a('function'); + deaccessionRecordType.should.have.property('forms').that.is.an('object'); + deaccessionRecordType.should.have.property('messages').that.is.an('object'); + deaccessionRecordType.should.have.property('serviceConfig').that.is.an('object'); + + deaccessionRecordType.title().should.be.a('string'); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/messages.spec.js b/test/specs/plugins/recordTypes/deaccession/messages.spec.js new file mode 100644 index 000000000..f773e018e --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/messages.spec.js @@ -0,0 +1,17 @@ +import messages from '../../../../../src/plugins/recordTypes/deaccession/messages'; + +chai.should(); + +describe('deaccession record messages', () => { + it('should contain properties with an id and defaultMessage properties', () => { + messages.should.be.an('object'); + + Object.keys(messages).forEach((deaccessionName) => { + const deaccessionMessages = messages[deaccessionName]; + + Object.keys(deaccessionMessages).forEach((name) => { + deaccessionMessages[name].should.contain.all.keys(['id', 'defaultMessage']); + }); + }); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/serviceConfig.spec.js b/test/specs/plugins/recordTypes/deaccession/serviceConfig.spec.js new file mode 100644 index 000000000..becd81abd --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/serviceConfig.spec.js @@ -0,0 +1,13 @@ +import serviceConfig from '../../../../../src/plugins/recordTypes/deaccession/serviceConfig'; + +chai.should(); + +describe('deaccession record serviceConfig', () => { + it('should have a servicePath property', () => { + serviceConfig.should.have.property('servicePath').that.is.a('string'); + serviceConfig.should.have.property('serviceName').that.is.a('string'); + serviceConfig.should.have.property('serviceType').that.is.a('string'); + serviceConfig.should.have.property('objectName').that.is.a('string'); + serviceConfig.should.have.property('documentName').that.is.a('string'); + }); +}); diff --git a/test/specs/plugins/recordTypes/deaccession/title.spec.js b/test/specs/plugins/recordTypes/deaccession/title.spec.js new file mode 100644 index 000000000..150b6b511 --- /dev/null +++ b/test/specs/plugins/recordTypes/deaccession/title.spec.js @@ -0,0 +1,76 @@ +import Immutable from 'immutable'; +import createTitleGetter from '../../../../../src/plugins/recordTypes/deaccession/title'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('deaccession record title', () => { + const configContext = createConfigContext(); + const title = createTitleGetter(configContext); + + it('should return the deaccession number and deaccession approval individual when both are present', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:deaccessions_common': { + deaccessionNumber: 'DE', + deaccessionApprovalGroupList: { + deaccessionApprovalGroup: [{ + deaccessionApprovalIndividual: 'urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(Party)\'Party\'', + }, { + deaccessionApprovalIndividual: 'urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(OtherParty)\'OtherParty\'', + }], + }, + }, + }, + }); + + title(data).should.equal('DE – Party'); + }); + + it('should return the deaccession number only when the deaccession approval individual is missing', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:deaccessions_common': { + deaccessionNumber: 'DE', + }, + }, + }); + + title(data).should.equal('DE'); + }); + + it('should return the deaccession approval individual only when the deaccession number is missing', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:deaccessions_common': { + deaccessionApprovalGroupList: { + deaccessionApprovalGroup: [{ + deaccessionApprovalIndividual: 'urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(Party)\'Party\'', + }, { + deaccessionApprovalIndividual: 'urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(OtherParty)\'OtherParty\'', + }], + }, + }, + }, + }); + + title(data).should.equal('Party'); + }); + + it('should return an empty string if no document is passed', () => { + title(null).should.equal(''); + title(undefined).should.equal(''); + }); + + it('should return an empty string if the common part is not present', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:deaccessions_extension': { + deaccessionAltTitle: 'Alt deaccession title', + }, + }, + }); + + title(data).should.equal(''); + }); +});