Skip to content

Commit

Permalink
fix(stripe, hasura): forRootAsync dynamic controllers
Browse files Browse the repository at this point in the history
fix #148
  • Loading branch information
WonderPanda committed May 13, 2020
1 parent 75c72a7 commit 347e581
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 78 deletions.
2 changes: 1 addition & 1 deletion packages/hasura/src/hasura.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {

@Module({
imports: [DiscoveryModule],
controllers: [EventHandlerController],
})
export class HasuraModule
extends createConfigurableDynamicRootModule<HasuraModule, HasuraModuleConfig>(
Expand All @@ -44,7 +45,6 @@ export class HasuraModule
EventHandlerService,
HasuraEventHandlerHeaderGuard,
],
controllers: [EventHandlerController],
}
)
implements OnModuleInit {
Expand Down
45 changes: 31 additions & 14 deletions packages/hasura/src/tests/hasura.module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,40 @@ const eventPayloadMissingTable = {
table: { schema: 'public', name: 'userz' },
};

describe.each([undefined, 'customEndpoint'])(
'Hasura Module (e2e)',
(controllerPrefix) => {
type ModuleType = 'forRoot' | 'forRootAsync';
const cases: [ModuleType, string | undefined][] = [
['forRoot', undefined],
['forRoot', 'customEndpoint'],
['forRootAsync', undefined],
['forRootAsync', 'customEndpoint'],
];

describe.each(cases)(
'Hasura Module %p with controller prefix %p (e2e)',
(moduleType, controllerPrefix) => {
let app;
const hasuraEndpoint = controllerPrefix
? `/${controllerPrefix}/events`
: defaultHasuraEndpoint;

beforeEach(async () => {
const moduleImport =
moduleType === 'forRootAsync'
? HasuraModule.forRootAsync(HasuraModule, {
useFactory: () => ({
secretFactory: secret,
secretHeader: secretHeader,
controllerPrefix,
}),
})
: HasuraModule.forRoot(HasuraModule, {
secretFactory: secret,
secretHeader: secretHeader,
controllerPrefix,
});

const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
HasuraModule.forRoot(HasuraModule, {
secretFactory: secret,
secretHeader: secretHeader,
controllerPrefix,
}),
],
imports: [moduleImport],
providers: [UserEventService],
}).compile();

Expand All @@ -66,30 +83,30 @@ describe.each([undefined, 'customEndpoint'])(
eventHandlerFn.mockReset();
});

it('should return forbidden if the secret api header is missing', () => {
it(`should return forbidden if the secret api header is missing`, () => {
return request(app.getHttpServer())
.post(hasuraEndpoint)
.send(eventPayload)
.expect(403);
});

it('should return forbidden if the secret api header value does not match', () => {
it(`should return forbidden if the secret api header value does not match`, () => {
return request(app.getHttpServer())
.post(hasuraEndpoint)
.set(secretHeader, 'wrong Value')
.send(eventPayload)
.expect(403);
});

it('should return bad request if there is no event handler for the event', () => {
it(`should return bad request if there is no event handler for the event`, () => {
return request(app.getHttpServer())
.post(hasuraEndpoint)
.set(secretHeader, secret)
.send(eventPayloadMissingTable)
.expect(400);
});

it('should pass the event to the correct handler', () => {
it(`should pass the event to the correct handler`, () => {
return request(app.getHttpServer())
.post(hasuraEndpoint)
.set(secretHeader, secret)
Expand Down
5 changes: 3 additions & 2 deletions packages/stripe/src/stripe.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import { StripePayloadService } from './stripe.payload.service';
import { StripeWebhookController } from './stripe.webhook.controller';
import { StripeWebhookService } from './stripe.webhook.service';

@Module({})
@Module({
controllers: [StripeWebhookController],
})
export class StripeModule
extends createConfigurableDynamicRootModule<StripeModule, StripeModuleConfig>(
STRIPE_MODULE_CONFIG_TOKEN,
{
imports: [DiscoveryModule],
controllers: [StripeWebhookController],
providers: [
{
provide: Symbol('CONTROLLER_HACK'),
Expand Down
137 changes: 76 additions & 61 deletions packages/stripe/src/tests/stripe.webhook.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,74 +20,89 @@ class PaymentCreatedService {
}
}

const baseScenario: StripeModuleConfig['webhookConfig'] = {
stripeWebhookSecret: '123',
loggingConfiguration: {
logMatchingEventHandlers: true,
},
};

const scenarios: StripeModuleConfig['webhookConfig'][] = [
baseScenario,
{ ...baseScenario, controllerPrefix: 'stripez' },
type ModuleType = 'forRoot' | 'forRootAsync';
const cases: [ModuleType, string | undefined][] = [
['forRoot', undefined],
['forRoot', 'stripez'],
['forRootAsync', undefined],
['forRootAsync', 'stripez'],
];

describe.each(scenarios)('Stripe Module (e2e)', (scenario) => {
let app: INestApplication;
let hydratePayloadFn: jest.Mock<
{
type: string;
},
[string, Buffer]
>;
describe.each(cases)(
'Stripe Module %p with controller prefix %p (e2e)',
(moduleType, controllerPrefix) => {
let app: INestApplication;
let hydratePayloadFn: jest.Mock<
{
type: string;
},
[string, Buffer]
>;

const stripeWebhookEndpoint = controllerPrefix
? `/${controllerPrefix}/webhook`
: defaultStripeWebhookEndpoint;

const stripeWebhookEndpoint = scenario?.controllerPrefix
? `/${scenario?.controllerPrefix}/webhook`
: defaultStripeWebhookEndpoint;
const moduleConfig: StripeModuleConfig = {
apiKey: '123',
webhookConfig: {
stripeWebhookSecret: '123',
loggingConfiguration: {
logMatchingEventHandlers: true,
},
controllerPrefix,
},
};

beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
StripeModule.forRoot(StripeModule, {
apiKey: '123',
webhookConfig: scenario,
}),
],
providers: [PaymentCreatedService],
}).compile();
beforeEach(async () => {
const moduleImport =
moduleType === 'forRoot'
? StripeModule.forRoot(StripeModule, moduleConfig)
: StripeModule.forRootAsync(StripeModule, {
useFactory: () => moduleConfig,
});

app = moduleFixture.createNestApplication();
await app.init();
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [moduleImport],
providers: [PaymentCreatedService],
}).compile();

const stripePayloadService = app.get<StripePayloadService>(
StripePayloadService
);
app = moduleFixture.createNestApplication();
await app.init();

hydratePayloadFn = jest
.spyOn(stripePayloadService, 'tryHydratePayload')
.mockImplementationOnce((sig, buff) => buff as any);
});
const stripePayloadService = app.get<StripePayloadService>(
StripePayloadService
);

afterEach(() => jest.resetAllMocks());
hydratePayloadFn = jest
.spyOn(stripePayloadService, 'tryHydratePayload')
.mockImplementationOnce((sig, buff) => buff as any);
});

it('returns an error if the stripe signature is missing', () => {
return request(app.getHttpServer())
.post(stripeWebhookEndpoint)
.send(expectedEvent)
.expect(500);
});
it('returns an error if the stripe signature is missing', () => {
return request(app.getHttpServer())
.post(stripeWebhookEndpoint)
.send(expectedEvent)
.expect(500);
});

it('routes incoming events to their handlers based on event type', () => {
return request(app.getHttpServer())
.post(stripeWebhookEndpoint)
.send(expectedEvent)
.set('stripe-signature', stripeSig)
.expect(201)
.then(() => {
expect(testReceiveStripeFn).toHaveBeenCalledTimes(1);
expect(hydratePayloadFn).toHaveBeenCalledTimes(1);
expect(hydratePayloadFn).toHaveBeenCalledWith(stripeSig, expectedEvent);
expect(testReceiveStripeFn).toHaveBeenCalledWith(expectedEvent);
});
});
});
it('routes incoming events to their handlers based on event type', () => {
return request(app.getHttpServer())
.post(stripeWebhookEndpoint)
.send(expectedEvent)
.set('stripe-signature', stripeSig)
.expect(201)
.then(() => {
expect(testReceiveStripeFn).toHaveBeenCalledTimes(1);
expect(hydratePayloadFn).toHaveBeenCalledTimes(1);
expect(hydratePayloadFn).toHaveBeenCalledWith(
stripeSig,
expectedEvent
);
expect(testReceiveStripeFn).toHaveBeenCalledWith(expectedEvent);
});
});

afterEach(() => jest.resetAllMocks());
}
);

0 comments on commit 347e581

Please sign in to comment.