feat: add brief concept party classification
This commit is contained in:
@@ -72,6 +72,12 @@ suite('level persistence API', () => {
|
||||
const folderId = randomUUID()
|
||||
const noteId = randomUUID()
|
||||
const eventId = randomUUID()
|
||||
const personConceptId = randomUUID()
|
||||
const organizationConceptId = randomUUID()
|
||||
state.brief = { body: 'Identify Ada Lovelace and Analytical Engines Ltd in the source material.', concepts: [
|
||||
{ id: personConceptId, label: 'Ada Lovelace', context: 'Named as the correspondent.', expectedPartyKind: 'person' },
|
||||
{ id: organizationConceptId, label: 'Analytical Engines Ltd', context: 'Issued the filing.', expectedPartyKind: 'organization' },
|
||||
] }
|
||||
state.documents = [{ id: documentId, title: 'Evidence', kind: 'IMAGE', date: '2021-04-17', publishedAt: '2021-04-17T12:00:00Z', body: ['Extracted body'], regions: [{ id: 'stamp', label: 'Date stamp', excerpt: '17 April 2021', date: '2021-04-17T09:00:00Z' }], fileType: 'image', metadata: {} }]
|
||||
state.evidence = [
|
||||
{ id: folderId, type: 'folder', title: 'Folder', content: 'Evidence folder', x: 685, y: 417, width: 260, config: { open: true }, containedDocumentIds: [documentId] },
|
||||
@@ -92,6 +98,10 @@ suite('level persistence API', () => {
|
||||
expect(loaded.viewport).toEqual(state.viewport)
|
||||
expect(loaded.evidence[0]).toMatchObject({ id: folderId, x: 685, y: 417, config: { open: true } })
|
||||
expect(loaded.relations[0]).toMatchObject({ id: `contains:${folderId}:${documentId}`, config: { x: 1051, y: 417 } })
|
||||
expect(loaded.brief.concepts).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ label: 'Ada Lovelace', expectedPartyKind: 'person' }),
|
||||
expect.objectContaining({ label: 'Analytical Engines Ltd', expectedPartyKind: 'organization' }),
|
||||
]))
|
||||
|
||||
const upload = new FormData()
|
||||
upload.append('file', new Blob(['OSINT smoke evidence'], { type: 'text/plain' }), 'smoke-evidence.txt')
|
||||
@@ -121,6 +131,15 @@ suite('level persistence API', () => {
|
||||
})
|
||||
|
||||
const playerState = await (await fetch(`${baseUrl}/api/levels/${state.id}`)).json() as CaseState
|
||||
expect(playerState.brief.concepts.every(concept => concept.expectedPartyKind === undefined)).toBe(true)
|
||||
const personPartyId = randomUUID()
|
||||
const organizationPartyId = randomUUID()
|
||||
playerState.evidence.push(
|
||||
{ id: personPartyId, type: 'party', partyKind: 'person', title: 'Ada Lovelace', content: 'Named as the correspondent.', aliases: ['A. A. L.'], relatedEvidenceIds: [documentId, noteId], x: 720, y: 250, width: 280 },
|
||||
{ id: organizationPartyId, type: 'party', partyKind: 'organization', organizationKind: 'business', title: 'Analytical Engines Ltd', content: 'Issued the filing.', aliases: ['AEL'], relatedEvidenceIds: [documentId], x: 1020, y: 250, width: 280 },
|
||||
)
|
||||
playerState.brief.concepts = playerState.brief.concepts.map(concept => ({ ...concept,
|
||||
resolvedPartyExhibitId: concept.id === personConceptId ? personPartyId : organizationPartyId }))
|
||||
playerState.viewport = { x: -150, y: 88, zoom: 1.1 }
|
||||
playerState.evidence[0] = { ...playerState.evidence[0], x: 812, y: 533 }
|
||||
const playerSave = await fetch(`${baseUrl}/api/levels/${state.id}`, {
|
||||
@@ -136,7 +155,7 @@ suite('level persistence API', () => {
|
||||
expect(sameLevelInEditView.viewport).toEqual(playerState.viewport)
|
||||
expect(sameLevelInEditView.evidence[0]).toMatchObject({ id: folderId, x: 812, y: 533 })
|
||||
|
||||
const normalized = await appPool.query<{ exhibits: string; documents: string; folders: string; memberships: string; metadata: string; sources: string; connections: string; events: string; event_evidence: string }>(`SELECT
|
||||
const normalized = await appPool.query<{ exhibits: string; documents: string; folders: string; memberships: string; metadata: string; sources: string; connections: string; events: string; event_evidence: string; parties: string; people: string; organizations: string; party_evidence: string; concepts: string; hidden_answers: string }>(`SELECT
|
||||
(SELECT COUNT(*) FROM osint.exhibits)::text AS exhibits,
|
||||
(SELECT COUNT(*) FROM osint.document_exhibits)::text AS documents,
|
||||
(SELECT COUNT(*) FROM osint.folder_exhibits)::text AS folders,
|
||||
@@ -145,8 +164,14 @@ suite('level persistence API', () => {
|
||||
(SELECT COUNT(*) FROM osint.exhibit_sources)::text AS sources,
|
||||
(SELECT COUNT(*) FROM osint.exhibit_connections)::text AS connections,
|
||||
(SELECT COUNT(*) FROM osint.event_exhibits)::text AS events,
|
||||
(SELECT COUNT(*) FROM osint.event_evidence)::text AS event_evidence`)
|
||||
expect(normalized.rows[0]).toEqual({ exhibits: '5', documents: '2', folders: '1', memberships: '1', metadata: '2', sources: '1', connections: '1', events: '1', event_evidence: '2' })
|
||||
(SELECT COUNT(*) FROM osint.event_evidence)::text AS event_evidence,
|
||||
(SELECT COUNT(*) FROM osint.party_exhibits)::text AS parties,
|
||||
(SELECT COUNT(*) FROM osint.person_parties)::text AS people,
|
||||
(SELECT COUNT(*) FROM osint.organization_parties)::text AS organizations,
|
||||
(SELECT COUNT(*) FROM osint.party_evidence)::text AS party_evidence,
|
||||
(SELECT COUNT(*) FROM osint.brief_concepts)::text AS concepts,
|
||||
(SELECT COUNT(*) FROM osint.brief_concepts WHERE expected_party_kind IS NOT NULL)::text AS hidden_answers`)
|
||||
expect(normalized.rows[0]).toEqual({ exhibits: '7', documents: '2', folders: '1', memberships: '1', metadata: '2', sources: '1', connections: '1', events: '1', event_evidence: '2', parties: '2', people: '1', organizations: '1', party_evidence: '3', concepts: '2', hidden_answers: '2' })
|
||||
|
||||
const resetResponse = await fetch(`${baseUrl}/api/levels/${state.id}/reset`, { method: 'POST' })
|
||||
expect(resetResponse.ok).toBe(true)
|
||||
@@ -186,6 +211,11 @@ suite('level persistence API', () => {
|
||||
expect(clonedEvent.supportingEvidenceIds).toHaveLength(2)
|
||||
expect(clonedEvent.supportingEvidenceIds).not.toContain(documentId)
|
||||
expect(clonedEvent.supportingEvidenceIds).not.toContain(noteId)
|
||||
expect(clone.evidence.filter(item => item.type === 'party')).toHaveLength(2)
|
||||
expect(clone.brief.concepts.every(concept => Boolean(concept.resolvedPartyExhibitId))).toBe(true)
|
||||
expect(clone.brief.concepts.map(concept => concept.resolvedPartyExhibitId)).not.toContain(personPartyId)
|
||||
const authoredClone = await (await fetch(`${baseUrl}/api/levels/${clone.id}?edit=1`)).json() as CaseState
|
||||
expect(authoredClone.brief.concepts.map(concept => concept.expectedPartyKind).sort()).toEqual(['organization', 'person'])
|
||||
|
||||
const clonedFolder = clone.evidence.find(item => item.type === 'folder')!
|
||||
clonedFolder.x = 1234
|
||||
|
||||
Reference in New Issue
Block a user