parent
4f2b7efb98
commit
aad2c81993
@ -1,15 +1,40 @@ |
||||
import { Test, TestingModuleBuilder } from '@nestjs/testing'; |
||||
import { GeocodingProvider } from './clients/geocoding/types'; |
||||
import { WeatherProvider } from './clients/weather/types'; |
||||
import { PackagesService } from './packages.service'; |
||||
import { PackagesRepository } from './storage/types'; |
||||
|
||||
export const packagesRepositoryDependency = Symbol('packages repository'); |
||||
export const geocodingProviderDependency = Symbol('geocoding provider'); |
||||
export const weatherProviderDependency = Symbol('weather provider'); |
||||
export const packagesServiceDependency = Symbol('packages service'); |
||||
|
||||
export type Dependencies = { |
||||
[packagesRepositoryDependency]: PackagesRepository; |
||||
[geocodingProviderDependency]: GeocodingProvider; |
||||
[weatherProviderDependency]: WeatherProvider; |
||||
[packagesServiceDependency]: Pick<PackagesService, keyof PackagesService>; |
||||
}; |
||||
|
||||
export type Dependency<T extends keyof Dependencies> = Dependencies[T]; |
||||
|
||||
type ProviderDictionary = { |
||||
[TKey in keyof Dependencies]: { |
||||
provide: TKey; |
||||
useValue: Dependencies[TKey]; |
||||
}; |
||||
}; |
||||
|
||||
type Provider = ProviderDictionary[keyof ProviderDictionary]; |
||||
|
||||
type ModuleMetadata = { |
||||
// Quick workaround instead of extracting relevant types from @nestjs/types
|
||||
// (which are not really very different from `any` anyway)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
controllers?: any[]; |
||||
providers?: Provider[]; |
||||
}; |
||||
|
||||
export const createTestingModule: ( |
||||
metadata: ModuleMetadata, |
||||
) => TestingModuleBuilder = Test.createTestingModule.bind(Test); |
||||
|
@ -0,0 +1,69 @@ |
||||
import { TestingModule } from '@nestjs/testing'; |
||||
import request from 'supertest'; |
||||
import { PackagesController } from './packages.controller'; |
||||
import { createTestingModule, packagesServiceDependency } from './dependencies'; |
||||
import { PackageInfo } from './storage/types'; |
||||
|
||||
describe('AppController', () => { |
||||
it('returns a result from packages service', async () => { |
||||
const testTrackingNumber = 'test-tracking-number'; |
||||
const testPackageResponse = { |
||||
packageData: <PackageInfo>{ |
||||
articleName: 'fake name', |
||||
articlePrice: 123, |
||||
articleQuantity: 456, |
||||
senderAddress: 'fake address', |
||||
SKU: 'fake sku', |
||||
status: 'delivery', |
||||
carrier: 'DHL', |
||||
trackingNumber: testTrackingNumber, |
||||
receiverAddress: 'fake recipient address', |
||||
}, |
||||
receiverWeather: { |
||||
temperature: 'fake temperature', |
||||
apparentTemperature: 'fake apparent temperature', |
||||
relativeHumidity: 'fake relative humidity', |
||||
}, |
||||
}; |
||||
const moduleFixture: TestingModule = await createTestingModule({ |
||||
controllers: [PackagesController], |
||||
providers: [ |
||||
{ |
||||
provide: packagesServiceDependency, |
||||
useValue: { |
||||
getPackageInfoWithWeather: ( |
||||
carrier, |
||||
trackingNumber, |
||||
) => { |
||||
if ( |
||||
carrier === 'DHL' && |
||||
trackingNumber === testTrackingNumber |
||||
) { |
||||
return Promise.resolve(testPackageResponse); |
||||
} |
||||
|
||||
return Promise.resolve(null); |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
}).compile(); |
||||
|
||||
const app = moduleFixture.createNestApplication(); |
||||
await app.init(); |
||||
|
||||
try { |
||||
const appRequest = request(app.getHttpServer()); |
||||
await appRequest |
||||
.get(`/packages/DHL/${testTrackingNumber}`) |
||||
.expect(200) |
||||
.expect(testPackageResponse); |
||||
await appRequest |
||||
.get(`/packages/UPS/${testTrackingNumber}`) |
||||
.expect(404); |
||||
await appRequest.get(`/packages/DHL/non-existent`).expect(404); |
||||
} finally { |
||||
await app.close(); |
||||
} |
||||
}); |
||||
}); |
@ -0,0 +1,33 @@ |
||||
import { |
||||
Controller, |
||||
Get, |
||||
Inject, |
||||
NotFoundException, |
||||
Param, |
||||
} from '@nestjs/common'; |
||||
import { Dependencies, packagesServiceDependency } from './dependencies'; |
||||
import { CarrierType } from './types'; |
||||
|
||||
@Controller('packages') |
||||
export class PackagesController { |
||||
constructor( |
||||
@Inject(packagesServiceDependency) |
||||
private readonly packagesService: Dependencies[typeof packagesServiceDependency], |
||||
) {} |
||||
|
||||
@Get(':carrier/:trackingNumber') |
||||
async getPackageInfoWithWeather( |
||||
@Param('carrier') carrier: string, |
||||
@Param('trackingNumber') trackingNumber: string, |
||||
) { |
||||
const result = await this.packagesService.getPackageInfoWithWeather( |
||||
carrier as CarrierType, |
||||
trackingNumber, |
||||
); |
||||
if (!result) { |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
} |
Loading…
Reference in new issue