Skip to content

Commit 306823d

Browse files
Merge pull request #46 from bufferoverflow/chore/automated-testing
chore: automated unit testing with jest
2 parents c50d4a8 + b506d7a commit 306823d

File tree

7 files changed

+333
-9
lines changed

7 files changed

+333
-9
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ script:
88
- commitlint-travis
99
- yarn license
1010
- yarn lint
11+
- yarn test:all

src/authcache.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ export class AuthCache {
1414

1515
static get DEFAULT_TTL() { return 300; }
1616

17-
constructor(logger: Logger, ttl: number) {
17+
static _generateKeyHash(username: string, password: string) {
18+
const sha = Crypto.createHash('sha256');
19+
sha.update(JSON.stringify({ username: username, password: password }));
20+
return sha.digest('hex');
21+
}
22+
23+
constructor(logger: Logger, ttl?: number) {
1824
this.logger = logger;
1925
this.ttl = ttl || AuthCache.DEFAULT_TTL;
2026

@@ -30,17 +36,11 @@ export class AuthCache {
3036
}
3137

3238
findUser(username: string, password: string): UserData {
33-
return this.storage.get(this._generateKeyHash(username, password));
39+
return this.storage.get(AuthCache._generateKeyHash(username, password));
3440
}
3541

3642
storeUser(username: string, password: string, userData: UserData): boolean {
37-
return this.storage.set(this._generateKeyHash(username, password), userData);
38-
}
39-
40-
_generateKeyHash(username: string, password: string) {
41-
const sha = Crypto.createHash('sha256');
42-
sha.update(JSON.stringify({ username: username, password: password }));
43-
return sha.digest('hex');
43+
return this.storage.set(AuthCache._generateKeyHash(username, password), userData);
4444
}
4545
}
4646

test/__mocks__/gitlab.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const mock = jest.fn().mockImplementation(() => {
2+
return {
3+
Users: {
4+
current: () => {
5+
return Promise.resolve({
6+
username: 'myUser'
7+
});
8+
}
9+
},
10+
Groups: {
11+
all: (params) => { // eslint-disable-line no-unused-vars
12+
return Promise.resolve([{
13+
path: 'myGroup',
14+
full_path: 'myGroup'
15+
}]);
16+
}
17+
}
18+
};
19+
});
20+
21+
export default mock;

test/unit/authcache.spec.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// @flow
2+
3+
import type { Logger } from '@verdaccio/types';
4+
import type { UserDataGroups } from '../../src/authcache.js';
5+
6+
import { AuthCache, UserData } from '../../src/authcache.js';
7+
8+
9+
const logger: Logger = {
10+
error: jest.fn(),
11+
info: jest.fn(),
12+
debug: jest.fn(),
13+
child: jest.fn(),
14+
warn: jest.fn(),
15+
http: jest.fn(),
16+
trace: jest.fn()
17+
};
18+
19+
describe('AuthCache Unit Tests', () => {
20+
test('should create an AuthCache instance', () => {
21+
const authCache: AuthCache = new AuthCache(logger, AuthCache.DEFAULT_TTL);
22+
23+
expect(authCache).toBeTruthy();
24+
});
25+
26+
test('should create an AuthCache instance with default ttl', () => {
27+
const authCache: AuthCache = new AuthCache(logger);
28+
29+
expect(authCache).toBeTruthy();
30+
expect(authCache).toHaveProperty('ttl', AuthCache.DEFAULT_TTL);
31+
});
32+
33+
test('should store and find some user data', () => {
34+
const authCache: AuthCache = new AuthCache(logger);
35+
const user: string = 'fooUser';
36+
const pass: string = 'fooPass';
37+
const dataGroups: UserDataGroups = {
38+
publish: ['fooGroup1', 'fooGroup2']
39+
};
40+
const data: UserData = new UserData(user, dataGroups);
41+
42+
authCache.storeUser(user, pass, data);
43+
const returnedData: UserData = authCache.findUser(user, pass);
44+
45+
expect(returnedData).toEqual(data);
46+
});
47+
48+
test('should store and find some user data when ttl is unlimited', () => {
49+
const UNLIMITED_TTL: number = 0;
50+
const authCache: AuthCache = new AuthCache(logger, UNLIMITED_TTL);
51+
const user: string = 'fooUser';
52+
const pass: string = 'fooPass';
53+
const dataGroups: UserDataGroups = {
54+
publish: ['fooGroup1', 'fooGroup2']
55+
};
56+
const data: UserData = new UserData(user, dataGroups);
57+
58+
authCache.storeUser(user, pass, data);
59+
const returnedData: UserData = authCache.findUser(user, pass);
60+
61+
expect(returnedData).toEqual(data);
62+
});
63+
});

test/unit/gitlab.spec.js

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// @flow
2+
3+
import type { Callback, RemoteUser } from '@verdaccio/types';
4+
import type { VerdaccioGitlabPackageAccess } from "../../src/gitlab";
5+
6+
import VerdaccioGitlab from '../../src/gitlab.js';
7+
import { defaultConfig } from './partials/config.js';
8+
import logger from './partials/logger.js';
9+
10+
// Do not remove, this mocks the gitlab library
11+
import Gitlab from 'gitlab'; // eslint-disable-line no-unused-vars
12+
const options = {
13+
// $FlowFixMe
14+
config: {},
15+
logger: logger
16+
};
17+
18+
describe('Gitlab Auth Plugin Unit Tests', () => {
19+
test('should create a plugin instance', () => {
20+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
21+
22+
expect(verdaccioGitlab).toBeDefined();
23+
});
24+
25+
test('should authenticate a user', done => {
26+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
27+
const user: string = 'myUser';
28+
const pass: string = 'myPass';
29+
30+
const cb: Callback = (err, data) => {
31+
expect(err).toBeFalsy();
32+
expect(data.sort()).toEqual(['myGroup', 'myUser'].sort());
33+
done();
34+
};
35+
36+
verdaccioGitlab.authenticate(user, pass, cb);
37+
});
38+
39+
test('should fail authentication with wrong pass', done => {
40+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
41+
const user: string = 'myUser';
42+
const pass: string = 'anotherPass';
43+
44+
const cb: Callback = (err, data) => {
45+
expect(err).toBeTruthy();
46+
expect(data).toBeFalsy();
47+
done();
48+
};
49+
50+
verdaccioGitlab.authenticate(user, pass, cb);
51+
});
52+
53+
test('should fail authentication with not existing user', done => {
54+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
55+
const user: string = 'anotherUser';
56+
const pass: string = 'myPass';
57+
58+
const cb: Callback = (err, data) => {
59+
expect(err).toBeTruthy();
60+
expect(data).toBeFalsy();
61+
done();
62+
};
63+
64+
verdaccioGitlab.authenticate(user, pass, cb);
65+
});
66+
67+
test('should allow access to package based on user group', done => {
68+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
69+
const user: RemoteUser = {
70+
real_groups: ['myGroup', 'myUser'],
71+
groups: ['myGroup', 'myUser'],
72+
name: 'myUser'
73+
};
74+
const _package: VerdaccioGitlabPackageAccess = {
75+
name: '@myGroup/myPackage',
76+
access: ['$authenticated'],
77+
gitlab: true
78+
};
79+
80+
const cb: Callback = (err, data) => {
81+
expect(err).toBeFalsy();
82+
expect(data).toBe(true);
83+
done();
84+
};
85+
86+
verdaccioGitlab.allow_access(user, _package, cb);
87+
});
88+
89+
test('should allow access to package based on user name', done => {
90+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
91+
const user: RemoteUser = {
92+
real_groups: ['myGroup', 'myUser'],
93+
groups: ['myGroup', 'myUser'],
94+
name: 'myUser'
95+
};
96+
const _package: VerdaccioGitlabPackageAccess = {
97+
name: 'myUser',
98+
access: ['$authenticated'],
99+
gitlab: true
100+
};
101+
102+
const cb: Callback = (err, data) => {
103+
expect(err).toBeFalsy();
104+
expect(data).toBe(true);
105+
done();
106+
};
107+
108+
verdaccioGitlab.allow_access(user, _package, cb);
109+
});
110+
111+
test('should allow publish of package based on user group', done => {
112+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
113+
const user: RemoteUser = {
114+
real_groups: ['myGroup', 'myUser'],
115+
groups: ['myGroup', 'myUser'],
116+
name: 'myUser'
117+
};
118+
const _package: VerdaccioGitlabPackageAccess = {
119+
name: '@myGroup/myPackage',
120+
gitlab: true
121+
};
122+
123+
const cb: Callback = (err, data) => {
124+
expect(err).toBeFalsy();
125+
expect(data).toBe(false);
126+
done();
127+
};
128+
129+
verdaccioGitlab.allow_publish(user, _package, cb);
130+
});
131+
132+
test('should allow publish of package based on user name', done => {
133+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
134+
const user: RemoteUser = {
135+
real_groups: ['myGroup', 'myUser'],
136+
groups: ['myGroup', 'myUser'],
137+
name: 'myUser'
138+
};
139+
const _package: VerdaccioGitlabPackageAccess = {
140+
name: 'myUser',
141+
gitlab: true
142+
};
143+
144+
const cb: Callback = (err, data) => {
145+
expect(err).toBeFalsy();
146+
expect(data).toBe(false);
147+
done();
148+
};
149+
150+
verdaccioGitlab.allow_publish(user, _package, cb);
151+
});
152+
153+
test('should deny publish of package based on unauthenticated', done => {
154+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
155+
const user: RemoteUser = {
156+
real_groups: [],
157+
groups: [],
158+
name: undefined
159+
};
160+
const _package: VerdaccioGitlabPackageAccess = {
161+
name: 'myUser',
162+
gitlab: true
163+
};
164+
165+
const cb: Callback = (err, data) => {
166+
expect(err).toBeTruthy();
167+
expect(data).toBeFalsy();
168+
done();
169+
};
170+
171+
verdaccioGitlab.allow_publish(user, _package, cb);
172+
});
173+
174+
test('should deny publish of package based on group', done => {
175+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
176+
const user: RemoteUser = {
177+
real_groups: ['myGroup', 'myUser'],
178+
groups: ['myGroup', 'myUser'],
179+
name: 'myUser'
180+
};
181+
const _package: VerdaccioGitlabPackageAccess = {
182+
name: '@anotherGroup/myPackage',
183+
gitlab: true
184+
};
185+
186+
const cb: Callback = (err, data) => {
187+
expect(err).toBeTruthy();
188+
expect(data).toBeFalsy();
189+
done();
190+
};
191+
192+
verdaccioGitlab.allow_publish(user, _package, cb);
193+
});
194+
195+
test('should deny publish of package based on user', done => {
196+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(defaultConfig, options);
197+
const user: RemoteUser = {
198+
real_groups: ['myGroup', 'myUser'],
199+
groups: ['myGroup', 'myUser'],
200+
name: 'myUser'
201+
};
202+
const _package: VerdaccioGitlabPackageAccess = {
203+
name: 'anotherUser',
204+
gitlab: true
205+
};
206+
207+
const cb: Callback = (err, data) => {
208+
expect(err).toBeTruthy();
209+
expect(data).toBeFalsy();
210+
done();
211+
};
212+
213+
verdaccioGitlab.allow_publish(user, _package, cb);
214+
});
215+
});

test/unit/partials/config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@flow
2+
3+
import type { VerdaccioGitlabConfig } from '../../../src/gitlab.js';
4+
5+
6+
export const defaultConfig: VerdaccioGitlabConfig = {
7+
url: 'myUrl',
8+
9+
};

test/unit/partials/logger.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@flow
2+
3+
import type { Logger } from '@verdaccio/types';
4+
5+
const logger: Logger = {
6+
error: jest.fn(),
7+
info: jest.fn(),
8+
debug: jest.fn(),
9+
child: jest.fn(),
10+
warn: jest.fn(),
11+
http: jest.fn(),
12+
trace: jest.fn()
13+
};
14+
15+
export default logger;

0 commit comments

Comments
 (0)