feat(api): reveal the ash pit route from the watchpost hotspot
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
} from '../database/seeds/vertical-slice.constants';
|
||||
import { LocationMonster } from '../monsters/entities/location-monster.entity';
|
||||
import { TravelService } from '../travel/travel.service';
|
||||
import { WorldDiscoveryService } from './discovery/world-discovery.service';
|
||||
import { LocationConnection } from './entities/location-connection.entity';
|
||||
import { LocationDefinition } from './entities/location-definition.entity';
|
||||
import type { LocationPointOfInterestContent } from './local-location.types';
|
||||
@@ -92,9 +93,51 @@ function createService(
|
||||
} as unknown as Repository<Character>,
|
||||
{ find: jest.fn() } as unknown as Repository<LocationConnection>,
|
||||
{ find: jest.fn() } as unknown as Repository<LocationMonster>,
|
||||
{
|
||||
isTravelAllowed: () => Promise.resolve(true),
|
||||
discover: jest.fn(),
|
||||
} as unknown as WorldDiscoveryService,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a `WorldService` sitting at the Burned Road with the given points of
|
||||
* interest, and a stub `WorldDiscoveryService` whose `discover` mirrors the
|
||||
* real one: it returns the ash pit the first time and `null` once
|
||||
* `alreadyDiscovered` says the character already knows it.
|
||||
*/
|
||||
function buildService(options: {
|
||||
pointsOfInterest: LocationPointOfInterestContent[];
|
||||
alreadyDiscovered?: boolean;
|
||||
}) {
|
||||
const currentLocation = location(BURNED_ROAD_ID, options.pointsOfInterest);
|
||||
const discover = jest.fn().mockResolvedValue(
|
||||
options.alreadyDiscovered ? null : { key: 'ash-pit', name: 'Ash Pit' },
|
||||
);
|
||||
const worldDiscovery = {
|
||||
discover,
|
||||
isTravelAllowed: () => Promise.resolve(true),
|
||||
} as unknown as WorldDiscoveryService;
|
||||
|
||||
const service = new WorldService(
|
||||
{
|
||||
completeTravelIfDue: jest.fn().mockResolvedValue({ status: 'IDLE' }),
|
||||
} as unknown as TravelService,
|
||||
{
|
||||
findOne: jest.fn().mockResolvedValue({
|
||||
id: CHARACTER_ID,
|
||||
currentLocationId: currentLocation.id,
|
||||
currentLocation,
|
||||
}),
|
||||
} as unknown as Repository<Character>,
|
||||
{ find: jest.fn() } as unknown as Repository<LocationConnection>,
|
||||
{ find: jest.fn() } as unknown as Repository<LocationMonster>,
|
||||
worldDiscovery,
|
||||
);
|
||||
|
||||
return { service, discover };
|
||||
}
|
||||
|
||||
async function expectRejected(promise: Promise<unknown>): Promise<void> {
|
||||
await expect(promise).rejects.toBeInstanceOf(WorldDomainError);
|
||||
await expect(promise).rejects.toMatchObject({
|
||||
@@ -112,6 +155,7 @@ describe('WorldService.runLocalInteraction', () => {
|
||||
interactionKey: 'inspect-tracks',
|
||||
title: 'Suspicious Tracks',
|
||||
text: 'Between the ash and broken stones you make out several fresh bootprints.',
|
||||
discoveredLocation: null,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,6 +169,7 @@ describe('WorldService.runLocalInteraction', () => {
|
||||
title: 'Gate Watch',
|
||||
text: 'Only heard at the South Gate.',
|
||||
img: '/images/npcs/graufurt-gate-watch.png',
|
||||
discoveredLocation: null,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -171,4 +216,87 @@ describe('WorldService.runLocalInteraction', () => {
|
||||
service.runLocalInteraction(CHARACTER_ID, 'hunt-area'),
|
||||
);
|
||||
});
|
||||
|
||||
it('discovers the route the hotspot points at', async () => {
|
||||
const { service, discover } = buildService({
|
||||
pointsOfInterest: [
|
||||
{
|
||||
key: 'inspect-watchpost',
|
||||
title: 'The Watchpost',
|
||||
actionLabel: 'Inspect',
|
||||
type: 'INVESTIGATE',
|
||||
iconKey: 'investigate',
|
||||
xPercent: 50,
|
||||
yPercent: 50,
|
||||
enabled: true,
|
||||
resultTitle: 'The Watchpost',
|
||||
resultText: 'Fresh tracks lead east.',
|
||||
discoversLocationKey: 'ash-pit',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = await service.runLocalInteraction(
|
||||
CHARACTER_ID,
|
||||
'inspect-watchpost',
|
||||
);
|
||||
|
||||
expect(discover).toHaveBeenCalledWith(CHARACTER_ID, 'ash-pit');
|
||||
expect(result.discoveredLocation).toEqual({
|
||||
key: 'ash-pit',
|
||||
name: 'Ash Pit',
|
||||
});
|
||||
});
|
||||
|
||||
it('reports no discovery the second time the hotspot is used', async () => {
|
||||
const { service } = buildService({
|
||||
alreadyDiscovered: true,
|
||||
pointsOfInterest: [
|
||||
{
|
||||
key: 'inspect-watchpost',
|
||||
title: 'The Watchpost',
|
||||
type: 'INVESTIGATE',
|
||||
iconKey: 'investigate',
|
||||
xPercent: 50,
|
||||
yPercent: 50,
|
||||
enabled: true,
|
||||
resultText: 'Fresh tracks lead east.',
|
||||
discoversLocationKey: 'ash-pit',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = await service.runLocalInteraction(
|
||||
CHARACTER_ID,
|
||||
'inspect-watchpost',
|
||||
);
|
||||
|
||||
expect(result.discoveredLocation).toBeNull();
|
||||
expect(result.text).toBe('Fresh tracks lead east.');
|
||||
});
|
||||
|
||||
it('reports no discovery for a hotspot that reveals nothing', async () => {
|
||||
const { service, discover } = buildService({
|
||||
pointsOfInterest: [
|
||||
{
|
||||
key: 'search-quarters',
|
||||
title: 'Guard Quarters',
|
||||
type: 'SEARCH',
|
||||
iconKey: 'search',
|
||||
xPercent: 20,
|
||||
yPercent: 60,
|
||||
enabled: true,
|
||||
resultText: 'Nothing but ash.',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = await service.runLocalInteraction(
|
||||
CHARACTER_ID,
|
||||
'search-quarters',
|
||||
);
|
||||
|
||||
expect(discover).not.toHaveBeenCalled();
|
||||
expect(result.discoveredLocation).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user