Add tests for providers/index, factories and google provider
This commit is contained in:
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user