Skip to content

Commit 31530e8

Browse files
author
Ilya Radchenko
committed
Merge pull request #26 from saraf/unit
Added unit test cases for api and webapp
2 parents e36fa08 + 275cf42 commit 31530e8

18 files changed

+2126
-8
lines changed

lib/api.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var _ = require('lodash');
22
var async = require('async');
33
var superagent = require('superagent');
44
var debug = require('debug')('strider-gitlab:api');
5+
var util = require('util');
56

67
module.exports = {
78
get: get,
@@ -39,8 +40,13 @@ function get(config, uri, done) {
3940
.set('User-Agent', 'StriderCD (http://stridercd.com)')
4041
.end(function (error, res) {
4142
res = res || {};
43+
44+
if (error) {
45+
return done(error, null, null);
46+
}
47+
4248
debug('Response body type: ' + typeof res.body);
43-
debug('Response body received: ' + JSON.stringify(res.body));
49+
debug('Response body received: ' + util.inspect(res.body, false, 10, true));
4450
if (res.error) {
4551
return done(res.error, null, res);
4652
}
@@ -103,6 +109,10 @@ function deleteHooks(config, repo_id, url, callback) {
103109
.end(function (err, res) {
104110
var deleted = false;
105111

112+
if (err) {
113+
return callback(err);
114+
}
115+
106116
if (!res) {
107117
return callback(new Error("Empty response."));
108118
}
@@ -156,6 +166,11 @@ function removeDeployKey(config, repo_id, title, callback) {
156166
.query(qpm)
157167
.set('User-Agent', 'StriderCD (http://stridercd.com)')
158168
.end(function (err, res) {
169+
170+
if (err) {
171+
return callback(err);
172+
}
173+
159174
var deleted = false;
160175

161176
if (!res) {

lib/webapp.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ module.exports = {
3030
api.get(config, 'projects', function (err, repos) {
3131
if (err) return done(err);
3232

33-
if(!repos) {
34-
return done(new Error("Could not get a list of projects from the GitLab repository. Please check the configuration in Account->GitLab."));
33+
if (!repos) {
34+
return done(new Error("Could not get a list of projects from the GitLab repository. Please check the configuration in Account->GitLab."));
3535
}
3636

3737
// Parse and filter only git repos
@@ -59,7 +59,7 @@ module.exports = {
5959

6060
debug("Getting URI " + uri);
6161
api.get(account, uri, function (err, branches) {
62-
debug("We get the following as branches: " + JSON.stringify(branches));
62+
debug("We get the following as branches: " + util.inspect(branches, false, 10, true));
6363

6464
done(err, _.map(branches || [], function (branch) {
6565
return branch.name;

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@
3737
"inline_icon": "bitbucket"
3838
},
3939
"devDependencies": {
40-
"jshint": "~2.1.11",
4140
"expect.js": "~0.2.0",
42-
"mocha": "~1.13.0"
41+
"jshint": "~2.1.11",
42+
"mocha": "~2.2.3",
43+
"nock": "^2.10.0"
4344
},
4445
"dependencies": {
4546
"async": "~0.2.9",
@@ -48,7 +49,7 @@
4849
"lodash": "~2.2.0",
4950
"step": "0.0.5",
5051
"strider-git": "^0.2.4",
51-
"superagent": "~0.15.4"
52+
"superagent": "~1.3.0"
5253
},
5354
"bugs": {
5455
"url": "https://github.com/meric426/strider-gitlab/issues"

test/README.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,80 @@
11
strider-gitlab tests
22
====================
33

4-
The tests use mocha for testing and nock for mocking responses from a gitlab server.
4+
The tests use mocha for testing and [nock](https://github.com/pgte/nock) for mocking responses from a gitlab server.
5+
6+
Start out by writing an outline of what you want to test by adding pending tests to a .js file in the test directory,
7+
(inside the appropriate describe blocks)
8+
9+
like:
10+
11+
```
12+
it('should do xyz when abc happens');
13+
it('should do lmn when opq happens');
14+
... as many as necessary
15+
```
16+
17+
Now running npm test will show your tests as "pending" and marked with a "-".
18+
19+
Next, observe the "happy path", the existing behavior of the code by using util.inspect to log the parameters passed to
20+
the function to be tested when the codepath is run (ensure that the codepath is run by using the Strider web gui if needed),
21+
in order to understand what needs to be passed to the function you want to test in the test file.
22+
23+
In order to sniff and record the http traffic so that you can create a nock mock of the gitlab server,
24+
use code similar to the following inside the codepath that you want to test:
25+
26+
```
27+
In file lib/api.js ...
28+
29+
var nock = require('nock');
30+
...
31+
32+
//for example, inside the removeDeployKey function in lib/api.js
33+
var appendLogToFile = function(content) {
34+
fs.appendFile('/noderoot/gitlab_remove_deploykey.txt', content);
35+
};
36+
37+
nock.recorder.rec({
38+
logging: appendLogToFile,
39+
});
40+
```
41+
42+
In the above example, the file gitlab_remove_deploykey.txt file will contain the statements generated by nock.
43+
44+
Next write out the body of the pending tests, one at a time.
45+
After writing out the body of a test, do an 'npm test' run, with nock still recording.
46+
Before doing the npm test run, ensure that only the current describe() block is active by adding the .only suffix.
47+
Like so,
48+
```
49+
describe.only('parseRepo', function(){
50+
it('should correctly parse repo information as received from gitlab server into a repo object');
51+
it('should throw an error if it gets an empty parameter as repo ?');
52+
...
53+
54+
```
55+
This will ensure that only the tests for functionality currently under consideration will be run.
56+
Also, mark all tests other than the current one to be inactive by changing the "it('should ..." to "xit('should ...".
57+
Else, you can ensure that only the current test is run by changing 'it(' to 'it.only('
58+
59+
Before the run, you must also comment out any code that asks nock to intercept calls - the usual place for which is in
60+
the before, after or beforeEach/afterEach blocks. For example, comment out all the lines inside the following blocks
61+
```
62+
before('Setup the mock gitlab server', function setupNock() {
63+
nock.cleanAll(); //remove all interceptors
64+
nock.disableNetConnect(); //prevent all network call from going to the actual server
65+
require('./mocks/gitlab_add_key.js')(); //pull in the mock code to simulate the server for this block
66+
});
67+
68+
after('Tear down mock Gitlab server', function tearDownNock() {
69+
nock.cleanAll(); //remove all interceptors
70+
});
71+
```
72+
This will ensure that the actual interaction between our code and the gitlab server will be recorded by nock.
73+
Copy out the code generated by nock into a .js file in the mocks subdirectory (see existing files in mocks/ for example)
74+
75+
Before moving on to writing the next test, empty out the file used by nock for recording, and mark the test already
76+
written with a "xit(" or a "it.skip("
77+
78+
After you are done with writing the tests, remove or comment out the nock.recorder.rec code so that nock stops recording.
79+
Then, enable all the tests in the block and enable/de-comment out the code that asks nock to
80+
disableNetConnect and mock, and re-run "npm test" to see all your tests run with the gitlab server mocked out of the picture.

test/mocks/gitlab_add_key.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
Simulation of responses from server when we
3+
request the addition of a deploy key.
4+
5+
nock will simulate a gitlab server running at
6+
localhost:80, where Strider Tester, a user is
7+
registered with the name "stridertester", and
8+
has been registered with api token - zRtVsmeznn7ySatTrnrp
9+
stridertester is an "owner" of a group named "testunion"
10+
and has admin access to three projects -
11+
testunion / unionproject1
12+
Strider Tester / pubproject1
13+
Strider Tester / privproject1
14+
*/
15+
16+
var nock = require('nock');
17+
18+
module.exports = function () {
19+
//--------------------------------------------------------------------------------------
20+
//simulate a Created 201 response when we try to deploy ssh keys for a project
21+
nock('http://localhost:80')
22+
.post('/api/v3/projects/5/keys', {
23+
"title": "strider-stridertester/privproject1",
24+
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAMoSHhKfeE3/oXanAQEZO0Sq20SMjvjmJlTy+CaGz/1uk+glLXi9u2RKtfPRZDceAgyEtRUpqya9Uo1v9bjkIckGLhQwXdSo2G6O3QuzpE3gc6AXTDPQ0ZkkXbSdU9VGL1Zzr+maBnvfwK6IlsNz3fLa4lNV7vz1LaGCg9D1jP+nufZjuDiCAno7D607oG1iHQ3x/BqzphUATav3DFQFT2FBmmittQT0l0mMJ4XsQCQXkwNbDjkLYNon8FYPm9U3AOlzicOGteebt5mhsQtfl9+lL99B8+fk8b24pEEbOxZ4l0HcwMI1R5OLoTzPwSvVw+bp3YPhH2IzfFwK5NUk7 stridertester/[email protected]\n"
25+
})
26+
.query({"private_token": "zRtVsmeznn7ySatTrnrp"})
27+
.reply(201, {
28+
"id": 12,
29+
"title": "strider-stridertester/privproject1",
30+
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAMoSHhKfeE3/oXanAQEZO0Sq20SMjvjmJlTy+CaGz/1uk+glLXi9u2RKtfPRZDceAgyEtRUpqya9Uo1v9bjkIckGLhQwXdSo2G6O3QuzpE3gc6AXTDPQ0ZkkXbSdU9VGL1Zzr+maBnvfwK6IlsNz3fLa4lNV7vz1LaGCg9D1jP+nufZjuDiCAno7D607oG1iHQ3x/BqzphUATav3DFQFT2FBmmittQT0l0mMJ4XsQCQXkwNbDjkLYNon8FYPm9U3AOlzicOGteebt5mhsQtfl9+lL99B8+fk8b24pEEbOxZ4l0HcwMI1R5OLoTzPwSvVw+bp3YPhH2IzfFwK5NUk7 stridertester/[email protected]",
31+
"created_at": "2015-08-19T03:35:01.863Z"
32+
}, {
33+
server: 'nginx',
34+
date: 'Wed, 19 Aug 2015 03:35:01 GMT',
35+
'content-type': 'application/json',
36+
'content-length': '534',
37+
connection: 'close',
38+
status: '201 Created',
39+
etag: '"5a11f9a2bf20878df6e3de77364e297c"',
40+
'cache-control': 'max-age=0, private, must-revalidate',
41+
'x-request-id': '565d54e9-f03b-4077-8cf4-a93503060889',
42+
'x-runtime': '0.099917'
43+
});
44+
45+
//--------------------------------------------------------------------------------------
46+
//simulate a 400 Bad Request response when an invalid key is sent
47+
nock('http://localhost:80')
48+
.post('/api/v3/projects/5/keys', {"title": "strider-stridertester/privproject1", "key": "invalid-key"})
49+
.query({"private_token": "zRtVsmeznn7ySatTrnrp"})
50+
.reply(400, {"message": {"key": ["is invalid"], "fingerprint": ["cannot be generated"]}}, {
51+
server: 'nginx',
52+
date: 'Wed, 19 Aug 2015 04:35:26 GMT',
53+
'content-type': 'application/json',
54+
'content-length': '72',
55+
connection: 'close',
56+
status: '400 Bad Request',
57+
'cache-control': 'no-cache',
58+
'x-request-id': '907e7139-cb13-407a-864f-a91ce108e419',
59+
'x-runtime': '0.054109'
60+
});
61+
62+
//--------------------------------------------------------------------------------------
63+
//simulate a 401 Unauthorized response when invalid credentials are used
64+
nock('http://localhost:80')
65+
.post('/api/v3/projects/5/keys', {
66+
"title": "strider-stridertester/privproject1",
67+
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAMoSHhKfeE3/oXanAQEZO0Sq20SMjvjmJlTy+CaGz/1uk+glLXi9u2RKtfPRZDceAgyEtRUpqya9Uo1v9bjkIckGLhQwXdSo2G6O3QuzpE3gc6AXTDPQ0ZkkXbSdU9VGL1Zzr+maBnvfwK6IlsNz3fLa4lNV7vz1LaGCg9D1jP+nufZjuDiCAno7D607oG1iHQ3x/BqzphUATav3DFQFT2FBmmittQT0l0mMJ4XsQCQXkwNbDjkLYNon8FYPm9U3AOlzicOGteebt5mhsQtfl9+lL99B8+fk8b24pEEbOxZ4l0HcwMI1R5OLoTzPwSvVw+bp3YPhH2IzfFwK5NUk7 stridertester/[email protected]\n"
68+
})
69+
.query({"private_token": "zRtVsmeznn7ySatTrnra"})
70+
.reply(401, {"message": "401 Unauthorized"}, {
71+
server: 'nginx',
72+
date: 'Wed, 19 Aug 2015 05:03:45 GMT',
73+
'content-type': 'application/json',
74+
'content-length': '30',
75+
connection: 'close',
76+
status: '401 Unauthorized',
77+
'cache-control': 'no-cache',
78+
'x-request-id': '282a2411-dd11-4026-90b3-8a36560c0512',
79+
'x-runtime': '0.004726'
80+
});
81+
82+
//--------------------------------------------------------------------------------------
83+
//simulate a 404 response when project could not be found
84+
nock('http://localhost:80')
85+
.post('/api/v3/projects/wrong%20repo%20id/keys', {
86+
"title": "strider-stridertester/privproject1",
87+
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAMoSHhKfeE3/oXanAQEZO0Sq20SMjvjmJlTy+CaGz/1uk+glLXi9u2RKtfPRZDceAgyEtRUpqya9Uo1v9bjkIckGLhQwXdSo2G6O3QuzpE3gc6AXTDPQ0ZkkXbSdU9VGL1Zzr+maBnvfwK6IlsNz3fLa4lNV7vz1LaGCg9D1jP+nufZjuDiCAno7D607oG1iHQ3x/BqzphUATav3DFQFT2FBmmittQT0l0mMJ4XsQCQXkwNbDjkLYNon8FYPm9U3AOlzicOGteebt5mhsQtfl9+lL99B8+fk8b24pEEbOxZ4l0HcwMI1R5OLoTzPwSvVw+bp3YPhH2IzfFwK5NUk7 stridertester/[email protected]\n"
88+
})
89+
.query({"private_token": "zRtVsmeznn7ySatTrnrp"})
90+
.reply(404, ["1f8b0800000000000003ab56ca4d2d2e4e4c4f55b252323130510828cacf4a4d2e51f0cb2f5170cb2fcd4b51aa050037095a2823000000"], {
91+
server: 'nginx',
92+
date: 'Wed, 19 Aug 2015 05:25:00 GMT',
93+
'content-type': 'application/json',
94+
'transfer-encoding': 'chunked',
95+
connection: 'close',
96+
status: '404 Not Found',
97+
'cache-control': 'no-cache',
98+
'x-request-id': '2c64ae26-d7b1-4caf-8efd-300893dedf37',
99+
'x-runtime': '0.005714',
100+
'content-encoding': 'gzip'
101+
});
102+
}

0 commit comments

Comments
 (0)