feat: Use ETagHandler for ETag generation and comparison

This commit is contained in:
Joachim Van Herwegen
2023-07-27 09:38:46 +02:00
parent 5ec6eddbfa
commit afcbfdaacf
31 changed files with 367 additions and 234 deletions

View File

@@ -6,6 +6,7 @@ import type { Notification } from '../../../../src/server/notifications/Notifica
import type { NotificationChannel } from '../../../../src/server/notifications/NotificationChannel';
import type { NotificationEmitter } from '../../../../src/server/notifications/NotificationEmitter';
import type { NotificationSerializer } from '../../../../src/server/notifications/serialize/NotificationSerializer';
import type { ETagHandler } from '../../../../src/storage/conditions/ETagHandler';
describe('A ComposedNotificationHandler', (): void => {
const topic: ResourceIdentifier = { path: 'http://example.com/foo' };
@@ -25,6 +26,7 @@ describe('A ComposedNotificationHandler', (): void => {
let generator: jest.Mocked<NotificationGenerator>;
let serializer: jest.Mocked<NotificationSerializer>;
let emitter: jest.Mocked<NotificationEmitter>;
let eTagHandler: jest.Mocked<ETagHandler>;
let handler: ComposedNotificationHandler;
beforeEach(async(): Promise<void> => {
@@ -47,7 +49,13 @@ describe('A ComposedNotificationHandler', (): void => {
handleSafe: jest.fn(),
} as any;
handler = new ComposedNotificationHandler({ generator, serializer, emitter });
eTagHandler = {
getETag: jest.fn(),
matchesETag: jest.fn(),
sameResourceState: jest.fn().mockReturnValue(false),
};
handler = new ComposedNotificationHandler({ generator, serializer, emitter, eTagHandler });
});
it('can only handle input supported by the generator.', async(): Promise<void> => {
@@ -68,6 +76,7 @@ describe('A ComposedNotificationHandler', (): void => {
it('does not emit the notification if it has the same resource state as the channel.', async(): Promise<void> => {
channel.state = '"123456-application/ld+json"';
eTagHandler.sameResourceState.mockReturnValue(true);
await expect(handler.handle({ channel, topic })).resolves.toBeUndefined();
expect(generator.handle).toHaveBeenCalledTimes(1);
expect(generator.handle).toHaveBeenLastCalledWith({ channel, topic });

View File

@@ -5,6 +5,7 @@ import {
ActivityNotificationGenerator,
} from '../../../../../src/server/notifications/generate/ActivityNotificationGenerator';
import type { NotificationChannel } from '../../../../../src/server/notifications/NotificationChannel';
import type { ETagHandler } from '../../../../../src/storage/conditions/ETagHandler';
import type { ResourceStore } from '../../../../../src/storage/ResourceStore';
import { AS, CONTENT_TYPE, DC, LDP, RDF } from '../../../../../src/util/Vocabularies';
@@ -23,6 +24,7 @@ describe('An ActivityNotificationGenerator', (): void => {
[CONTENT_TYPE]: 'text/turtle',
});
let store: jest.Mocked<ResourceStore>;
let eTagHandler: jest.Mocked<ETagHandler>;
let generator: ActivityNotificationGenerator;
beforeEach(async(): Promise<void> => {
@@ -30,7 +32,13 @@ describe('An ActivityNotificationGenerator', (): void => {
getRepresentation: jest.fn().mockResolvedValue(new BasicRepresentation('', metadata)),
} as any;
generator = new ActivityNotificationGenerator(store);
eTagHandler = {
getETag: jest.fn().mockReturnValue('ETag'),
matchesETag: jest.fn(),
sameResourceState: jest.fn(),
};
generator = new ActivityNotificationGenerator(store, eTagHandler);
});
it('only handles defined activities.', async(): Promise<void> => {
@@ -52,7 +60,7 @@ describe('An ActivityNotificationGenerator', (): void => {
id: `urn:${ms}:http://example.com/foo`,
type: 'Update',
object: 'http://example.com/foo',
state: expect.stringMatching(/"\d+-text\/turtle"/u),
state: 'ETag',
published: date,
});

View File

@@ -5,6 +5,7 @@ import {
AddRemoveNotificationGenerator,
} from '../../../../../src/server/notifications/generate/AddRemoveNotificationGenerator';
import type { NotificationChannel } from '../../../../../src/server/notifications/NotificationChannel';
import type { ETagHandler } from '../../../../../src/storage/conditions/ETagHandler';
import type { ResourceStore } from '../../../../../src/storage/ResourceStore';
import { AS, CONTENT_TYPE, DC, LDP, RDF } from '../../../../../src/util/Vocabularies';
@@ -18,6 +19,7 @@ describe('An AddRemoveNotificationGenerator', (): void => {
};
let metadata: RepresentationMetadata;
let store: jest.Mocked<ResourceStore>;
let eTagHandler: jest.Mocked<ETagHandler>;
let generator: AddRemoveNotificationGenerator;
beforeEach(async(): Promise<void> => {
@@ -33,7 +35,13 @@ describe('An AddRemoveNotificationGenerator', (): void => {
getRepresentation: jest.fn().mockResolvedValue(new BasicRepresentation('', responseMetadata)),
} as any;
generator = new AddRemoveNotificationGenerator(store);
eTagHandler = {
getETag: jest.fn().mockReturnValue('ETag'),
matchesETag: jest.fn(),
sameResourceState: jest.fn(),
};
generator = new AddRemoveNotificationGenerator(store, eTagHandler);
});
it('only handles Add/Remove activities.', async(): Promise<void> => {
@@ -73,7 +81,7 @@ describe('An AddRemoveNotificationGenerator', (): void => {
type: 'Add',
object: 'http://example.com/foo',
target: 'http://example.com/',
state: expect.stringMatching(/"\d+-text\/turtle"/u),
state: 'ETag',
published: date,
});