/** * @jest-environment jsdom * */ import { UpdateManager, Store, Fetcher, sym } from 'rdflib' import { createAclLogic } from '../src/acl/aclLogic' import { createInboxLogic } from '../src/inbox/inboxLogic' import { createProfileLogic } from '../src/profile/profileLogic' import { createContainerLogic } from '../src/util/containerLogic' import { createUtilityLogic } from '../src/util/utilityLogic' const alice = sym('https://alice.example.com/profile/card#me') const bob = sym('https://bob.example.com/profile/card#me') describe('Inbox logic', () => { let store let inboxLogic beforeEach(() => { fetchMock.resetMocks() fetchMock.mockResponse('Not Found', { status: 404, }) store = new Store() store.fetcher = new Fetcher(store, { fetch: fetch }) store.updater = new UpdateManager(store) const authn = { currentUser: () => { return alice }, } const containerLogic = createContainerLogic(store) const aclLogic = createAclLogic(store) const util = createUtilityLogic(store, aclLogic, containerLogic) const profile = createProfileLogic(store, authn, util) inboxLogic = createInboxLogic(store, profile, util, containerLogic, aclLogic) }) describe('getNewMessages', () => { describe('When inbox is empty', () => { let result beforeEach(async () => { bobHasAnInbox() inboxIsEmpty() result = await inboxLogic.getNewMessages(bob) }) it('Resolves to an empty array', () => { expect(result).toEqual([]) }) }) describe('When container has some containment triples', () => { let result beforeEach(async () => { bobHasAnInbox() inboxHasSomeContainmentTriples() const messages = await inboxLogic.getNewMessages(bob) result = messages.map(oneMessage => oneMessage.value) }) it('Resolves to an array with URLs of non-container resources in inbox', () => { expect(result.sort()).toEqual([ 'https://container.com/foo.txt' ].sort()) }) }) }) describe('createInboxFor', () => { beforeEach(async () => { aliceHasValidProfile() // First for the PUT: fetchMock.mockOnceIf( 'https://alice.example.com/p2p-inboxes/Peer%20Person/', 'Created', { status: 201 } ) // Then for the GET to read the ACL link: fetchMock.mockOnceIf( 'https://alice.example.com/p2p-inboxes/Peer%20Person/', ' ', { status: 200, headers: { Link: '; rel="acl"', } } ) fetchMock.mockIf('https://some/acl', 'Created', { status: 201 }) await inboxLogic.createInboxFor('https://peer.com/#me', 'Peer Person') }) it('creates the inbox', () => { expect(fetchMock.mock.calls).toEqual([ [ 'https://alice.example.com/profile/card', fetchMock.mock.calls[0][1] ], [ 'https://alice.example.com/p2p-inboxes/Peer%20Person/', { body: ' ', headers: { 'Content-Type': 'text/turtle', 'If-None-Match': '*', Link: '; rel="type"', }, method: 'PUT' }], [ 'https://alice.example.com/p2p-inboxes/Peer%20Person/', fetchMock.mock.calls[2][1] ], [ 'https://some/acl', { body: '@prefix acl: .\n' + '\n' + '<#alice> a acl:Authorization;\n' + ' acl:agent ;\n' + ' acl:accessTo ;\n' + ' acl:default ;\n' + ' acl:mode acl:Read, acl:Write, acl:Control.\n' + '<#bobAccessTo> a acl:Authorization;\n' + ' acl:agent ;\n' + ' acl:accessTo ;\n' + ' acl:mode acl:Append.\n', headers: [ [ 'Content-Type', 'text/turtle' ] ], method: 'PUT' }] ]) }) }) describe('markAsRead', () => { beforeEach(async () => { fetchMock.mockOnceIf( 'https://container.com/item.ttl', '<#some> <#inbox> <#item> .', { headers: { 'Content-Type': 'text/turtle' }, } ) fetchMock.mockOnceIf( 'https://container.com/archive/2111/03/31/item.ttl', 'Created', { status: 201, headers: { 'Content-Type': 'text/turtle' }, } ) await inboxLogic.markAsRead('https://container.com/item.ttl', new Date('31 March 2111 UTC')) }) it('moves the item to archive', async () => { expect(fetchMock.mock.calls).toEqual([ [ 'https://container.com/item.ttl' ], [ 'https://container.com/archive/2111/03/31/item.ttl', { 'body': '<#some> <#inbox> <#item> .', 'headers': [ [ 'Content-Type', 'text/turtle', ], ], 'method': 'PUT', }, ], [ 'https://container.com/item.ttl', { method: 'DELETE' } ], ]) }) }) function aliceHasValidProfile() { fetchMock.mockOnceIf( 'https://alice.example.com/profile/card', ` ; ; .`, { headers: { 'Content-Type': 'text/turtle', }, } ) } function bobHasAnInbox() { fetchMock.mockOnceIf( 'https://bob.example.com/profile/card', '.', { headers: { 'Content-Type': 'text/turtle' }, } ) } function inboxIsEmpty() { fetchMock.mockOnceIf( 'https://container.com/', ' ', // FIXME: https://github.com/jefflau/jest-fetch-mock/issues/189 { headers: { 'Content-Type': 'text/turtle' }, } ) } function inboxHasSomeContainmentTriples() { fetchMock.mockOnceIf( 'https://container.com/', '<.> <./foo.txt>, <./bar/> .', { headers: { 'Content-Type': 'text/turtle' }, } ) } })