Add tests for providers/index, factories and google provider

This commit is contained in:
Raghunandan
2020-05-21 14:55:58 +02:00
parent 2c6b883006
commit e2179d979c
7 changed files with 193 additions and 33 deletions
@@ -0,0 +1,72 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import express from 'express';
import passport from 'passport';
import { AuthProvider, AuthProviderRouteHandlers } from './types';
import { ProviderFactories } from './factories';
class MyAuthProvider implements AuthProvider, AuthProviderRouteHandlers {
strategy(): passport.Strategy {
return new passport.Strategy();
}
start(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): Promise<any> {
return new Promise(resolve => {
res.send('start');
resolve();
});
}
frameHandler(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): Promise<any> {
return new Promise(resolve => {
res.send('frameHandler');
resolve();
});
}
logout(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): Promise<any> {
return new Promise(resolve => {
res.send('logout');
resolve();
});
}
}
describe('getProviderFactory', () => {
it('makes a provider for MyAuthProvider', () => {
jest
.spyOn(ProviderFactories, 'getProviderFactory')
.mockReturnValueOnce(MyAuthProvider);
const provider = ProviderFactories.getProviderFactory('a');
expect(provider).toBeDefined();
});
it('throws an error when provider implementation does not exist', () => {
expect(() => {
ProviderFactories.getProviderFactory('b');
}).toThrow('Provider Implementation missing for : b auth provider');
});
});
@@ -17,6 +17,18 @@
import { AuthProviderFactories } from './types';
import { GoogleAuthProvider } from './google/provider';
export const providerFactories: AuthProviderFactories = {
google: GoogleAuthProvider,
};
export class ProviderFactories {
private static readonly providerFactories: AuthProviderFactories = {
google: GoogleAuthProvider,
};
public static getProviderFactory(providerId: string) {
const ProviderImpl = ProviderFactories.providerFactories.providerId;
if (!ProviderImpl) {
throw Error(
`Provider Implementation missing for : ${providerId} auth provider`,
);
}
return ProviderImpl;
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GoogleAuthProvider } from './provider';
import passport from 'passport';
const googleAuthProviderConfig = {
provider: 'google',
options: {},
};
const googleAuthProviderConfigInvalid = {
provider: 'google',
};
describe('GoogleAuthProvider', () => {
describe('create a new provider', () => {
it('should succeed with valid config', () => {
const googleAuthProvider = new GoogleAuthProvider(
googleAuthProviderConfig,
);
expect(googleAuthProvider).toBeDefined();
expect(googleAuthProvider.start).toBeDefined();
expect(googleAuthProvider.logout).toBeDefined();
expect(googleAuthProvider.frameHandler).toBeDefined();
expect(googleAuthProvider.strategy).toBeDefined();
});
});
});
@@ -62,7 +62,7 @@ export class GoogleAuthProvider
}
logout(_req: express.Request, res: express.Response) {
return new Promise((resolve) => {
return new Promise(resolve => {
res.send('logout!');
resolve();
});
@@ -16,10 +16,20 @@
import passport from 'passport';
import express from 'express';
import { makeProvider } from '.';
import { AuthProvider, AuthProviderRouteHandlers } from './types';
import { makeProvider, defaultRouter } from '.';
import {
AuthProvider,
AuthProviderRouteHandlers,
AuthProviderConfig,
} from './types';
import { ProviderFactories } from './factories';
class MyAuthProvider implements AuthProvider, AuthProviderRouteHandlers {
private readonly providerConfig: AuthProviderConfig;
constructor(providerConfig: AuthProviderConfig) {
this.providerConfig = providerConfig;
}
strategy(): passport.Strategy {
return new passport.Strategy();
}
@@ -28,27 +38,45 @@ class MyAuthProvider implements AuthProvider, AuthProviderRouteHandlers {
res: express.Response,
next: express.NextFunction,
): Promise<any> {
return new Promise((res, rej) => res());
return new Promise(resolve => {
res.send('start');
resolve();
});
}
frameHandler(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): express.Response<any> {
return res.send('frameHandler');
): Promise<any> {
return new Promise(resolve => {
res.send('frameHandler');
resolve();
});
}
logout(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): express.Response<any> {
return res.send('logout');
): Promise<any> {
return new Promise(resolve => {
res.send('logout');
resolve();
});
}
}
const providerFactories = {
a: MyAuthProvider,
};
class MyAuthProviderWithRefresh extends MyAuthProvider {
refresh(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): Promise<any> {
return new Promise(resolve => {
res.send('logout');
resolve();
});
}
}
const providerConfig = {
provider: 'a',
@@ -66,7 +94,10 @@ const providerConfigInvalid = {
describe('makeProvider', () => {
it('makes a provider for Myauthprovider', () => {
const provider = makeProvider(providerFactories, providerConfig);
jest
.spyOn(ProviderFactories, 'getProviderFactory')
.mockReturnValueOnce(MyAuthProvider);
const provider = makeProvider(providerConfig);
expect(provider.providerId).toEqual('a');
expect(provider.strategy).toBeDefined();
expect(provider.providerRouter).toBeDefined();
@@ -74,7 +105,23 @@ describe('makeProvider', () => {
it('throws an error when provider implementation does not exist', () => {
expect(() => {
makeProvider(providerFactories, providerConfigInvalid);
makeProvider(providerConfigInvalid);
}).toThrow('Provider Implementation missing for : b auth provider');
});
});
describe('defaultRouter', () => {
it('make router for auth provider without refresh', () => {
expect(
defaultRouter(new MyAuthProvider({ provider: 'a', options: {} })),
).toBeDefined();
});
it('make router for auth provider with refresh', () => {
expect(
defaultRouter(
new MyAuthProviderWithRefresh({ provider: 'b', options: {} }),
),
).toBeDefined();
});
});
+4 -15
View File
@@ -15,11 +15,8 @@
*/
import Router from 'express-promise-router';
import {
AuthProviderRouteHandlers,
AuthProviderFactories,
AuthProviderConfig,
} from './types';
import { AuthProviderRouteHandlers, AuthProviderConfig } from './types';
import { ProviderFactories } from './factories';
export const defaultRouter = (provider: AuthProviderRouteHandlers) => {
const router = Router();
@@ -32,17 +29,9 @@ export const defaultRouter = (provider: AuthProviderRouteHandlers) => {
return router;
};
export const makeProvider = (
providerFactories: AuthProviderFactories,
config: any,
) => {
export const makeProvider = (config: AuthProviderConfig) => {
const providerId = config.provider;
const ProviderImpl = providerFactories[providerId];
if (!ProviderImpl) {
throw Error(
`Provider Implementation missing for : ${providerId} auth provider`,
);
}
const ProviderImpl = ProviderFactories.getProviderFactory(providerId);
const providerInstance = new ProviderImpl(config);
const strategy = providerInstance.strategy();
const providerRouter = defaultRouter(providerInstance);
@@ -19,7 +19,6 @@ import Router from 'express-promise-router';
import passport from 'passport';
import { Logger } from 'winston';
import { providers } from './../providers/config';
import { providerFactories } from './../providers/factories';
import { makeProvider } from '../providers';
export interface RouterOptions {
@@ -36,7 +35,6 @@ export async function createRouter(
// configure all the providers
for (const providerConfig of providers) {
const { providerId, strategy, providerRouter } = makeProvider(
providerFactories,
providerConfig,
);
logger.info(`Configuring provider: ${providerId}`);