Skip to content

Commit c9e5942

Browse files
test(core): add test for some providers, increase coverage (#50)
1 parent ae9f840 commit c9e5942

File tree

15 files changed

+459
-35
lines changed

15 files changed

+459
-35
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ node_modules/
22
dist/
33
coverage/
44
api-docs/
5+
typing/
56

67
index.*
78
.cz-config.js

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## Description
2+
3+
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
4+
5+
Fixes # (issue)
6+
7+
## Type of change
8+
9+
Please delete options that are not relevant.
10+
11+
- [ ] Bug fix (non-breaking change which fixes an issue)
12+
- [ ] New feature (non-breaking change which adds functionality)
13+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
14+
- [ ] Intermediate change (work in progress)
15+
16+
## How Has This Been Tested?
17+
18+
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
19+
20+
- [ ] Test A
21+
- [ ] Test B
22+
23+
## Checklist:
24+
25+
- [ ] Performed a self-review of my own code
26+
- [ ] npm test passes on your machine
27+
- [ ] New tests added or existing tests modified to cover all changes
28+
- [ ] Code conforms with the style guide
29+
- [ ] API Documentation in code was updated
30+
- [ ] Any dependent changes have been merged and published in downstream modules

.nycrc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
2-
"extends": "@istanbuljs/nyc-config-typescript",
3-
"all": true,
4-
"reporter": ["html"]
2+
"include": ["dist"],
3+
"exclude": ["dist/__tests__/"],
4+
"extension": [".js", ".ts"],
5+
"reporter": ["text", "html"],
6+
"exclude-after-remap": false
57
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"build": "npm run clean && lb-tsc",
1717
"build:watch": "lb-tsc --watch",
1818
"clean": "lb-clean dist *.tsbuildinfo",
19-
"coverage": "nyc --reporter=html npm run test",
2019
"lint": "npm run prettier:check && npm run eslint",
2120
"lint:fix": "npm run eslint:fix && npm run prettier:fix",
2221
"prettier:cli": "lb-prettier \"**/*.ts\" \"**/*.js\"",
@@ -26,6 +25,8 @@
2625
"eslint:fix": "npm run eslint -- --fix",
2726
"pretest": "npm run build",
2827
"test": "lb-mocha --allow-console-logs \"dist/__tests__\"",
28+
"coverage": "lb-nyc npm run test",
29+
"coverage:ci": "lb-nyc report --reporter=text-lcov | coveralls",
2930
"posttest": "npm run lint",
3031
"test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js && npm run posttest",
3132
"prepublishOnly": "npm run test",
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {Client, createClientForHandler} from '@loopback/testlab';
2+
import {RestServer} from '@loopback/rest';
3+
import {Application, Provider} from '@loopback/core';
4+
import {get} from '@loopback/openapi-v3';
5+
import {authenticate} from '../../../decorators';
6+
import {STRATEGY} from '../../../strategy-name.enum';
7+
import {getApp} from '../helpers/helpers';
8+
import {MyAuthenticationSequence} from '../../fixtures/sequences/authentication.sequence';
9+
import {Strategies} from '../../../strategies/keys';
10+
import {VerifyFunction} from '../../../strategies';
11+
import {userWithoutReqObj} from '../../fixtures/data/bearer-data';
12+
import {Request} from '@loopback/rest';
13+
import AppleStrategy, {DecodedIdToken} from 'passport-apple';
14+
15+
describe('getting apple oauth2 strategy with options', () => {
16+
let app: Application;
17+
let server: RestServer;
18+
beforeEach(givenAServer);
19+
beforeEach(givenAuthenticatedSequence);
20+
afterEach(closeServer);
21+
22+
it('should return 200 when client id is passed and passReqToCallback is set true', async () => {
23+
getAuthVerifier();
24+
class TestController {
25+
@get('/test')
26+
@authenticate(STRATEGY.APPLE_OAUTH2, {
27+
clientID: 'string',
28+
clientSecret: 'string',
29+
passReqToCallback: true,
30+
})
31+
test() {
32+
return 'test successful';
33+
}
34+
}
35+
36+
app.controller(TestController);
37+
38+
await whenIMakeRequestTo(server).get('/test').expect(200);
39+
});
40+
41+
function whenIMakeRequestTo(restServer: RestServer): Client {
42+
return createClientForHandler(restServer.requestHandler);
43+
}
44+
45+
async function givenAServer() {
46+
app = getApp();
47+
server = await app.getServer(RestServer);
48+
}
49+
50+
function getAuthVerifier() {
51+
app
52+
.bind(Strategies.Passport.APPLE_OAUTH2_VERIFIER)
53+
.toProvider(AppleAuthVerifyProvider);
54+
}
55+
56+
function closeServer() {
57+
app.close();
58+
}
59+
60+
function givenAuthenticatedSequence() {
61+
// bind user defined sequence
62+
server.sequence(MyAuthenticationSequence);
63+
}
64+
});
65+
66+
class AppleAuthVerifyProvider implements Provider<VerifyFunction.AppleAuthFn> {
67+
constructor() {}
68+
69+
value(): VerifyFunction.AppleAuthFn {
70+
return async (
71+
accessToken: string,
72+
refreshToken: string,
73+
decodedIdToken: DecodedIdToken,
74+
profile: AppleStrategy.Profile,
75+
cd: AppleStrategy.VerifyCallback,
76+
req?: Request,
77+
) => {
78+
return userWithoutReqObj;
79+
};
80+
}
81+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {Client, createClientForHandler} from '@loopback/testlab';
2+
import {RestServer} from '@loopback/rest';
3+
import {Application, Provider} from '@loopback/core';
4+
import {get} from '@loopback/openapi-v3';
5+
import {authenticate} from '../../../decorators';
6+
import {STRATEGY} from '../../../strategy-name.enum';
7+
import {getApp} from '../helpers/helpers';
8+
import {MyAuthenticationSequence} from '../../fixtures/sequences/authentication.sequence';
9+
import {Strategies} from '../../../strategies/keys';
10+
import {Keycloak, VerifyFunction} from '../../../strategies';
11+
import {userWithoutReqObj} from '../../fixtures/data/bearer-data';
12+
import {Request} from '@loopback/rest';
13+
import {IAuthUser} from '../../../types';
14+
15+
describe('getting keycloak oauth2 strategy with options', () => {
16+
let app: Application;
17+
let server: RestServer;
18+
beforeEach(givenAServer);
19+
beforeEach(givenAuthenticatedSequence);
20+
beforeEach(getAuthVerifier);
21+
22+
it('should return 200 when host and client id is passed and passReqToCallback is set true', async () => {
23+
class TestController {
24+
@get('/test')
25+
@authenticate(STRATEGY.KEYCLOAK, {
26+
host: 'localhost',
27+
realm: 'localhost',
28+
callbackURL: 'localhost',
29+
authorizationURL: 'localhost',
30+
tokenURL: 'localhost',
31+
userInfoURL: 'localhost',
32+
clientID: 'string',
33+
clientSecret: 'string',
34+
passReqToCallback: true,
35+
})
36+
test() {
37+
return 'test successful';
38+
}
39+
}
40+
41+
app.controller(TestController);
42+
43+
await whenIMakeRequestTo(server).get('/test').expect(200);
44+
});
45+
46+
function whenIMakeRequestTo(restServer: RestServer): Client {
47+
return createClientForHandler(restServer.requestHandler);
48+
}
49+
50+
async function givenAServer() {
51+
app = getApp();
52+
server = await app.getServer(RestServer);
53+
}
54+
55+
function getAuthVerifier() {
56+
app
57+
.bind(Strategies.Passport.KEYCLOAK_VERIFIER)
58+
.toProvider(KeycloakAuthVerifyProvider);
59+
}
60+
61+
function givenAuthenticatedSequence() {
62+
// bind user defined sequence
63+
server.sequence(MyAuthenticationSequence);
64+
}
65+
});
66+
67+
class KeycloakAuthVerifyProvider
68+
implements Provider<VerifyFunction.KeycloakAuthFn> {
69+
constructor() {}
70+
71+
value(): VerifyFunction.KeycloakAuthFn {
72+
return async (
73+
accessToken: string,
74+
refreshToken: string,
75+
profile: Keycloak.Profile,
76+
cd: (err?: string | Error, user?: IAuthUser) => void,
77+
req?: Request,
78+
) => {
79+
return userWithoutReqObj;
80+
};
81+
}
82+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {IAuthUser} from '../../../types';
2+
import {expect} from '@loopback/testlab';
3+
import {
4+
AppleAuthStrategyFactory,
5+
AppleAuthStrategyFactoryProvider,
6+
} from '../../../strategies';
7+
import AppleStrategy, {
8+
AuthenticateOptions,
9+
AuthenticateOptionsWithRequest,
10+
} from 'passport-apple';
11+
12+
describe('getting apple-auth strategy with options', () => {
13+
it('should return strategy by passing options and passReqToCallback as true', async () => {
14+
const strategyVerifier: AppleAuthStrategyFactory = await getStrategy();
15+
16+
const options: AuthenticateOptions | AuthenticateOptionsWithRequest = {
17+
scope: '',
18+
teamID: '',
19+
keyID: '',
20+
clientID: 'string',
21+
clientSecret: 'string',
22+
passReqToCallback: true,
23+
};
24+
25+
const appleAuthStrategyVerifier = strategyVerifier(options);
26+
27+
expect(appleAuthStrategyVerifier).to.have.property('name');
28+
expect(appleAuthStrategyVerifier)
29+
.to.have.property('authenticate')
30+
.which.is.a.Function();
31+
});
32+
33+
it('should return strategy by passing options and passReqToCallback as false', async () => {
34+
const strategyVerifier: AppleAuthStrategyFactory = await getStrategy();
35+
36+
const options: AuthenticateOptions | AuthenticateOptionsWithRequest = {
37+
scope: '',
38+
teamID: '',
39+
keyID: '',
40+
clientID: 'string',
41+
clientSecret: 'string',
42+
passReqToCallback: true,
43+
};
44+
45+
const appleAuthStrategyVerifier = strategyVerifier(options);
46+
47+
expect(appleAuthStrategyVerifier).to.have.property('name');
48+
expect(appleAuthStrategyVerifier)
49+
.to.have.property('authenticate')
50+
.which.is.a.Function();
51+
});
52+
});
53+
54+
async function getStrategy() {
55+
const provider = new AppleAuthStrategyFactoryProvider(verifierBearer);
56+
57+
//this fuction will return a function which will then accept options.
58+
return provider.value();
59+
}
60+
61+
//returning a user
62+
function verifierBearer(
63+
accessToken: string,
64+
refreshToken: string,
65+
profile: AppleStrategy.Profile,
66+
): Promise<IAuthUser | null> {
67+
const userToPass: IAuthUser = {
68+
id: 1,
69+
username: 'xyz',
70+
password: 'pass',
71+
};
72+
73+
return new Promise(function (resolve, reject) {
74+
if (userToPass) {
75+
resolve(userToPass);
76+
}
77+
});
78+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {IAuthUser} from '../../../types';
2+
import {expect} from '@loopback/testlab';
3+
import {
4+
Keycloak,
5+
KeycloakStrategyFactory,
6+
KeycloakStrategyFactoryProvider,
7+
} from '../../../strategies';
8+
9+
describe('getting keycloak-auth strategy with options', () => {
10+
it('should return strategy by passing required options', async () => {
11+
const strategyVerifier: KeycloakStrategyFactory = await getStrategy();
12+
13+
const options: Keycloak.StrategyOptions = {
14+
host: 'localhost',
15+
realm: '/',
16+
clientID: 'string',
17+
clientSecret: 'string',
18+
callbackURL: 'localhost',
19+
authorizationURL: 'localhost',
20+
tokenURL: 'localhost',
21+
userInfoURL: 'localhost',
22+
};
23+
24+
const keycloakAuthStrategyVerifier = strategyVerifier(options);
25+
26+
expect(keycloakAuthStrategyVerifier).to.have.property('name');
27+
expect(keycloakAuthStrategyVerifier)
28+
.to.have.property('authenticate')
29+
.which.is.a.Function();
30+
});
31+
});
32+
33+
async function getStrategy() {
34+
const provider = new KeycloakStrategyFactoryProvider(verifierBearer);
35+
36+
//this fuction will return a function which will then accept options.
37+
return provider.value();
38+
}
39+
40+
//returning a user
41+
function verifierBearer(
42+
accessToken: string,
43+
refreshToken: string,
44+
profile: Keycloak.Profile,
45+
): Promise<IAuthUser | null> {
46+
const userToPass: IAuthUser = {
47+
id: 1,
48+
username: 'xyz',
49+
password: 'pass',
50+
};
51+
52+
return new Promise(function (resolve, reject) {
53+
if (userToPass) {
54+
resolve(userToPass);
55+
}
56+
});
57+
}

0 commit comments

Comments
 (0)