-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotes.js
More file actions
234 lines (200 loc) · 8.21 KB
/
Copy pathNotes.js
File metadata and controls
234 lines (200 loc) · 8.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// What I expect to go over:
// - code coverage, why is it good?
// - code coverage, why is it bad?
// - testing code which give you different answers each time
// - mocking out web request/DB calls
// - diving into Mocha, the testing suite we use
// - Mocha and asyncrohous code (it's easy with async/await)
// - assert/expect from chai, some examples and and tips
// starting point
it('it gets a color', function () {
getColor();
});
// 100 %
it('it gets another color', function () {
getOtherColor();
});
// From 100% to 100%
// the above test only test if the function is bug free, not if they are correct
// Order is important, i.e. first is test value, 2nd is epxected value
it('it gets a color', function () {
const color = getColor();
assert.equal(color, 'red');
});
it('it gets another color', function () {
const color = getOtherColor();
assert.equal(color, 'green');
});
// Show an example of someone changing the color
// describe mocha lay out:
// looks for files with it functions in name
// async code, callbacks pass done - but we don't use those
// return a promise, will wait for promise to be resolved. can be easily done with async/await
// describe is for grouping tests together
// it is a test case
// describe typhon routes
// -- describe evaluation routes
// -- describe entity routes
// Lets now move on to requests
describe('Requests', function () {
it('it gets a url', function () {
// Use fake values
const url = marvel.getUrl('/myUrl');
console.log(url);
});
});
// show the URL changes evertime. we can't test this easily. we can't test certain values becuase they are always changing. we need to lock in the time
// sinon gives us an easy way to do this
// Fake timer
describe('Requests', function () {
it('it gets a url', function () {
// Use fake values
var clock = sinon.useFakeTimers();
const url = marvel.getUrl('/myUrl');
console.log(url);
clock.tick(100);
const laterUrl = marvel.getUrl('/myUrl');
console.log(laterUrl);
clock.restore();
});
});
// At the moment we are still only tesing the code is bug free. not that the return value is correct
// could we just use: assert.equal(url, 'https://gateway.marvel.com/myUrl?ts=0&apikey=Hello&hash=861f98ed61273bf9cd17950d739e12e4');
// you could and to be honest I would probably approve this test
// but what is this function actually doing:
// prepending https://gateway.marvel.com to the endpoint
// addpending endpoint to url
// adding get params
// so lets check the follow:
// includes the endpoint
// includes public ket
// DOES NOT include private key
// two urls with different timestamps aren't the same
// start with:
assert.include(url, 'NOT THIS');
// sometime mocha/chai have bad messages, not easy to see what's wrong. In all chai calls you can include a message
assert.include(url, 'NOT THIS', `Url does not include endpoint (${endpoint})`);
// OK thats nicer, finish it up
describe('Requests', function () {
it('it gets a url', function () {
// Use fake values
const endpoint = '/myUrl';
var clock = sinon.useFakeTimers();
const url = marvel.getUrl(endpoint);
clock.tick(100);
const laterUrl = marvel.getUrl(endpoint);
clock.restore();
// Make sure we include the end point and public key, also make sure we don't include private key.
assert.include(url, endpoint, `Url does not include endpoint (${endpoint})`);
assert.include(url, process.env.MARVEL_PUBLIC, `Url does not include public key (${process.env.MARVEL_PUBLIC})`);
assert.notInclude(url, process.env.MARVEL_SECRET, `Url includes private key (${process.env.MARVEL_SECRET})`);
// make URL changes over time due to including a timestamp and hash of timestamp, public key and private key
assert.notEqual(url, laterUrl);
});
});
// adding another test
// use before and after
// before, after, beforeEach and afterEach lets you do a number of things
// before, after sets up at very start/very end
// beforeEach, afterEach are before each test (its)
// https://samwize.com/2014/02/08/a-guide-to-mochas-describe-it-and-setup-hooks/
describe('Requests', function () {
before(function () {
fakeClock = sinon.useFakeTimers();
});
after(function () {
fakeClock.restore();
});
it('it gets a url', function () {
// Use fake values
const endpoint = '/myUrl';
const url = marvel.getUrl(endpoint);
fakeClock.tick(100);
const laterUrl = marvel.getUrl(endpoint);
// Make sure we include the end point and public key, also make sure we don't include private key.
assert.include(url, endpoint, `Url does not include endpoint (${endpoint})`);
assert.include(url, process.env.MARVEL_PUBLIC, `Url does not include public key (${process.env.MARVEL_PUBLIC})`);
assert.notInclude(url, process.env.MARVEL_SECRET, `Url includes private key (${process.env.MARVEL_SECRET})`);
// make URL changes over time due to including a timestamp and hash of timestamp, public key and private key
assert.notEqual(url, laterUrl);
});
});
// testing requests
it('it gets the Marvel characters', async function () {
const mavelCharacters = await marvel.getCharacters();
getStub.restore();
});
// This fails, due to:
// will have to include private key
// make actual requests, which could fail
// marvel could add new data which would break our tests
// can mock out a lot, like DB requests, or calls to libraries or even calls to other code you don't want to run
it('it gets the Marvel characters', async function () {
const getStub = sinon.stub(axios, 'get').resolves(mavelCharacterResponse);
const mavelCharacters = await marvel.getCharacters();
getStub.restore();
});
// testing return
// test array
// test length - not needed but good stepping stone
// test important data
it('it gets the Marvel characters', async function () {
const getStub = sinon.stub(axios, 'get').resolves(mavelCharacterResponse);
const mavelCharacters = await marvel.getCharacters();
assert.typeOf(mavelCharacters, 'array');
assert(mavelCharacters.length === 1);
assert.equal(mavelCharacters.length, 1);
assert.equal(mavelCharacters[0].name, 'Aginar');
getStub.restore();
});
// this is asynchronous code
// by using async keyword, node automatically returns new promise so about, is the same as this:
it('it gets the Marvel characters PROMISE', function () {
const getStub = sinon.stub(axios, 'get').resolves(mavelCharacterResponse);
return marvel.getCharacters().then((mavelCharacters) => {
assert.typeOf(mavelCharacters, 'array');
assert(mavelCharacters.length === 1);
assert.equal(mavelCharacters.length, 1);
assert.equal(mavelCharacters[0].name, 'Aginar');
getStub.restore();
});
});
// break the code, to show still a true test
// also noticed how the other code broke?
// if we don't return a promise?
getStub = sinon.stub(axios, 'get').resolves(mavelCharacterResponse);
urlSpy = sinon.spy(marvel, 'getUrl');
const mavelCharacters = marvel.getCharacters();
// assert.typeOf(mavelCharacters, 'array');
// assert(mavelCharacters.length === 1);
// assert.equal(mavelCharacters.length, 1);
// assert.equal(mavelCharacters[0].name, 'Aginar');
// assert.equal(urlSpy.callCount, 1, `getUrl expected to be called once, was call ${urlSpy.callCount} times`);
// spy (and stubbing) classes:
urlSpy = sinon.spy(marvel, 'getUrl');
assert.equal(urlSpy.callCount, 1, `getUrl expected to be called once, was call ${urlSpy.callCount} times`);
it('it gets the Marvel characters', function () {
const getStub = sinon.stub(axios, 'get').rejects(mavelCharacterResponse);
const mavelCharacters = marvel.getCharacters();
getStub.restore();
});
// NOT quite 100%
it('it throws an error on non 200 code', async function () {
const getStub = sinon.stub(axios, 'get').resolves(mavelCharacterResponseNon200);
await marvel.getCharacters()
getStub.restore();
});
// test for error
await expect(marvel.getCharacters()).to.be.rejectedWith(Error);
// test for specific error
await expect(marvel.getCharacters()).to.be.rejectedWith(Error, 'Unknown code returned: 300');
// final note, break shit
// don't affect other tests
// move getStub to top
// move tests into new describe
// add in after each which restores
afterEach(function () {
if (getStub && getStub.restore) {
getStub.restore();
}
});