forked from mixi-inc/JavaScriptTraining
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtests.js
More file actions
342 lines (270 loc) · 11.1 KB
/
tests.js
File metadata and controls
342 lines (270 loc) · 11.1 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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
'use strict';
describe('ステージ5(意図通りに非同期処理を利用できる)', function() {
describe('Promise 編', function() {
it('resolve ハンドラーを書ける', function(testDone){
var promise = Promise.resolve('resolved!');
// チュートリアル
//
// ここに下記のコードを記述してください。
//
// promise.then(function(msg) {
// expect(msg).to.equal('resolved!');
// testDone();
// });
promise.then(function(msg) {
expect(msg).to.equal('resolved!');
testDone();
});
});
it('reject ハンドラーを書ける', function(testDone){
var promise = Promise.reject('rejected!');
// reject ハンドラーを使って、下の assertion が promise の
// エラー値を検証できるように記述してください。
//
// expect(msg).to.equal('rejected!');
// testDone();
// ここにコードを記述してください。
promise.catch(function(msg) {
expect(msg).to.equal('rejected!');
testDone();
});
});
it('複数の promise すべての完了を待つ promise を作成できる', function() {
var messageFragments = ['あなたと', 'java', '今すぐダウンロード'];
var promise1 = createWaitPromise(messageFragments[0], 10);
var promise2 = createWaitPromise(messageFragments[1], 20);
var promise3 = createWaitPromise(messageFragments[2], 30);
// 作成した promise を promise 変数に代入してください。
var promise = Promise.all([
promise1,
promise2,
promise3
]);
return expect(promise).to.eventually.deep.equal(messageFragments);
});
it('複数の promise のうち最も速く解決された値をもつ promise を作成できる', function() {
var messageFragments = ['30億の', 'デバイスで', '走るjava'];
var promise1 = createWaitPromise(messageFragments[0], 30);
var promise2 = createWaitPromise(messageFragments[1], 10);
var promise3 = createWaitPromise(messageFragments[2], 30);
// 作成した promise を promise 変数に代入してください。
var promise = Promise.race([
promise1,
promise2,
promise3
]);
return expect(promise).to.eventually.equal(messageFragments[1]);
});
});
describe('fetch API 編', function() {
it('/api/friends API を使って Sugar の友人を取得できる', function() {
var api = '/api/friends/';
var username = 'Sugar';
// チュートリアル
//
// ここに下記のコードを記述してください。
//
// var promisedFriends = fetch(api + username).then(function(res) {
// return res.json();
// });
var promisedFriends = fetch(api + username).then(function(res) {
return res.json();
});
return expect(promisedFriends).to.eventually.have.length(1)
.and.have.members(['PYXC-PJ']);
});
it('/api/friends API を使って Shen の友人を取得できる', function() {
var api = '/api/friends/';
var username = 'Shen';
// 作成した promise を promisedFriends 変数に代入してください。
var promisedFriends = fetch(api + username)
.then(function(res) {
return res.json();
});
return expect(promisedFriends).to.eventually.have.length(2)
.and.have.members(['jisp', 'TeJaS']);
});
it('/api/friends API を使って Shen の友人の友人を取得できる', function() {
var api = '/api/friends/';
var username = 'Shen';
// 作成した promise を promisedFriends 変数に代入してください。
/**
* 友人を取得する。
* @param {string} usernameToFetch 友人の取得対象のユーザー名。
* @return {Thenable<Array<string>>} 友人の配列。
*/
function getFriends(usernameToFetch) {
return fetch(api + usernameToFetch)
.then(function(response) {
return response.json();
});
}
/**
* 配列を平たくする。
* @param {Array<Array<T>>} arrayOfArray 配列の配列。
* @return {Array<T>} 平たくなった配列。
* @template T
*/
function flatMap(arrayOfArray) {
return arrayOfArray.reduce(function(flatArray, array) {
return flatArray.concat(array);
}, []);
}
var promisedFriends = getFriends(username)
.then(function(friends) {
return Promise.all(friends.map(getFriends));
})
.then(function(friendsArray) {
// [[friendName, ...], [friendName, ...], ...] という形式の構造に
// なっているので、平たい配列に整形してあげる必要があります。
return flatMap(friendsArray);
});
return expect(promisedFriends).to.eventually.have.length(1)
.and.have.members(['TypeScript']);
});
it('/api/friends API を使って CoffeeScript の友人を再帰的に取得できる', function() {
// 難易度高いので、自信のある人だけ挑戦してください。
// it.skip の .skip を消せば、テストが走るようになります。
var api = '/api/friends/';
/**
* 友人を取得する。
* @param {string} usernameToFetch 友人の取得対象のユーザー名。
* @return {Thenable<Array<string>>} 友人の配列。
*/
function getFriends(usernameToFetch) {
return fetch(api + usernameToFetch)
.then(function(response) {
return response.json();
});
}
/**
* 配列または配列をもつ promise を展開し、平たい配列をもつ promise を
* 返す。
* @param {Array<Thenable<T>|T>} arrayOfPromisedArray promise または、
* オブジェクトの配列。
* @return {Thenable<Array<T>>} 平たい配列をもつ promise。
* @template T
*/
function flatMap(arrayOfPromisedArray) {
return Promise.all(arrayOfPromisedArray)
.then(function(arrayOfArray) {
return arrayOfArray.reduce(function(flatArray, array) {
// JavaScript には破壊的な配列結合がないので、
// Array#push を悪用することが多いです。
Array.prototype.push.apply(flatArray, array);
return flatArray;
}, []);
});
}
/**
* 配列を結合する関数を返す。この関数の実行前に、結合する配列の片方を
* 指定する必要がある。
* @param {Array<T>} arrayA 関数の実行前に指定する、結合したい配列。
* @return {function(Array<T>): Array<T>} arrayA と arrayB を結合する関数。
* @template T
*/
function concat(arrayA) {
return function(arrayB) {
return arrayA.concat(arrayB);
};
}
/**
* 友人を再帰的に取得する。
* @param {string} usernameToFetch 友人の取得対象の名前。
* @return {Thenable<Array<string>>} 友人名の配列をもつ promise。
*/
function getFriendsRecursively(usernameToFetch) {
return getFriends(usernameToFetch)
.then(function(friends) {
if (friends.length === 0) return friends;
var promisedFriendsOfFriends = Promise.all(
friends.map(getFriendsRecursively));
return promisedFriendsOfFriends
.then(flatMap)
.then(concat(friends));
});
}
// 作成した promise を promisedFriends 変数に代入してください。
var promisedFriends = getFriendsRecursively('CoffeeScript');
return expect(promisedFriends).to.eventually.have.length(5)
.and.have.members([
'Taijilang',
'purescript',
'Wind.js',
'ScriptBlocks',
'jangaroo'
]);
});
it('Github の mixi-inc の organization の情報を取得できる', function() {
// 作成した promise を mixiOrg 変数に代入してください。
var mixiOrg = fetch('https://api.github.com/orgs/mixi-inc')
.then(function(response) {
return response.json();
});
return expect(mixiOrg).to.eventually.have.property('id', 1089312);
// Github API に関する参考情報
// https://developer.github.com/v3/orgs
});
it('Github API を使って、mixi-inc/JavaScriptTraining の情報を取得できる', function() {
var repository = 'mixi-inc/JavaScriptTraining';
// 作成した promise を mixiRepo 変数に代入してください。
var mixiRepo = fetch('https://api.github.com/repos/' + repository)
.then(function(response) {
return response.json();
});
return expect(mixiRepo).to.eventually.have.property('full_name', repository);
// Github API に関する参考情報
// https://developer.github.com/v3/repos/
});
it('Github API を使って、VimL、Emacs Lisp でスターが最も多いプロダクト名を' +
'それぞれ 1 つずつ取得できる', function() {
var languages = [ 'VimL', '"Emacs Lisp"' ];
/**
* オブジェクトから、query string を作成する。
* @param {Object<string, string>} queryMap パラメーターの辞書オブジェクト。
* @return {string} query string。
*/
function buildQueryString(queryMap) {
return Object.keys(queryMap)
.map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(queryMap[key]);
})
.join('&');
}
/**
* 指定された言語でもっともスターが多いリポジトリ名を返す。
* @param {string} lang 言語名。
* @return {Thenable<string>} もっともスター数が多いリポジトリ名をもつ
* promise。
*/
function searchMostPoluarRepoByLanguage(lang) {
var queryString = buildQueryString({
q: 'language:' + lang,
sort: 'stars'
});
return fetch('https://api.github.com/search/repositories?' + queryString)
.then(function(response) {
return response.json();
})
.then(function(result) {
return result.items[0].full_name;
});
}
// 作成した promise を mostPopularRepos 変数に代入してください。
var mostPopularRepos = Promise.all(
languages.map(searchMostPoluarRepoByLanguage));
return expect(mostPopularRepos).to.eventually.have.length(2)
.and.satisfy(function(names) {
return typeof names[0] === 'string' &&
typeof names[1] === 'string';
});
// Github API に関する参考情報
// https://developer.github.com/v3/search
});
});
function createWaitPromise(value, msec) {
return new Promise(function(resolve) {
setTimeout(resolve, msec, value);
});
}
});