Skip to content
This repository was archived by the owner on Oct 16, 2019. It is now read-only.

Commit 7c93ef5

Browse files
committed
feat(mocks): add mocks infrastructure
Closes #76
1 parent 6adcfd0 commit 7c93ef5

14 files changed

+156
-40
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"isomorphic-fetch": "2.2.1"
6363
},
6464
"devDependencies": {
65+
"atlas-mocks": "0.0.1",
6566
"babel-core": "^6.24.1",
6667
"babel-eslint": "^7.2.3",
6768
"babel-register": "^6.24.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import test from 'ava';
2+
import AtlasSDK from '../../index';
3+
import AtlasMocks from 'atlas-mocks';
4+
5+
/* eslint no-magic-numbers: 0 */
6+
7+
test('Should load config', async t => {
8+
const sdk = await AtlasSDK.configure({
9+
client_id: 'CLIENT_ID',
10+
sales_channel: 'SALES_CHANNEL',
11+
environment: 'development',
12+
mocks: AtlasMocks
13+
});
14+
15+
const config = sdk.config;
16+
17+
t.truthy(config.catalogApi);
18+
t.truthy(config.atlasCheckoutGateway);
19+
t.truthy(config.salesChannels);
20+
t.truthy(config.recommendations);
21+
t.is(config.clientId, 'CLIENT_ID');
22+
t.is(config.salesChannel, 'SALES_CHANNEL');
23+
t.is(config.environment, 'development');
24+
});
25+
26+
test('Should get article', async t => {
27+
const sdk = await AtlasSDK.configure({
28+
client_id: 'CLIENT_ID',
29+
sales_channel: 'SALES_CHANNEL',
30+
environment: 'development',
31+
mocks: AtlasMocks
32+
});
33+
34+
const article = await sdk.getArticle('DP521C129-Q11');
35+
36+
const thumbnail = 'https://mosaic01.ztat.net/vgs/media/pdp-thumb/DP/52/1C/12/9Q/11/DP521C129-Q11@10.jpg';
37+
38+
t.is(article.id, 'DP521C129-Q11');
39+
t.is(article.name, 'Jerseykleid - black');
40+
t.is(article.brand.name, 'Dorothy Perkins');
41+
t.is(article.attributes[0].name, 'Material Oberstoff');
42+
t.is(article.attributes[0].values[0], '96% Baumwolle, 4% Elasthan');
43+
t.is(article.images[0].mediaCharacter, 'NON_MODEL');
44+
t.is(article.images[0].resolutions.thumbnail, thumbnail);
45+
});
46+
47+
test('Should get recommendations', async t => {
48+
const sdk = await AtlasSDK.configure({
49+
client_id: 'CLIENT_ID',
50+
sales_channel: 'SALES_CHANNEL',
51+
environment: 'development',
52+
mocks: AtlasMocks
53+
});
54+
55+
const recos = await sdk.getRecommendations('DP521C129-Q11');
56+
57+
const firstReco = recos[0];
58+
59+
t.is(recos.length, 10);
60+
61+
t.is(firstReco.id, 'DP521C0XN-A11');
62+
t.is(firstReco.name, 'Jerseykleid - ivory');
63+
t.is(firstReco.brand.name, 'Dorothy Perkins');
64+
});

src/api/__tests__/catalog_service_tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test('Should fetch article successfully after configuring SDK', async t => {
1414
const sdk = await AtlasSDK.configure({
1515
client_id: 'CLIENT_ID',
1616
sales_channel: 'SALES_CHANNEL',
17-
is_sandbox: true
17+
environment: 'staging'
1818
});
1919

2020
const article = await sdk.getArticle('AD112B0F6-A11');

src/api/__tests__/config_service_tests.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ test('Should configure AtlasSDK successfully', async t => {
1212
const sdk = await AtlasSDK.configure({
1313
client_id: 'CLIENT_ID',
1414
sales_channel: 'SALES_CHANNEL',
15-
is_sandbox: true
15+
environment: 'staging'
1616
}).catch(error => {
1717
t.fail(error);
1818
});
@@ -31,7 +31,7 @@ test('Should return current locale, language and country code according to Sales
3131
const sdk = await AtlasSDK.configure({
3232
client_id: 'CLIENT_ID',
3333
sales_channel: 'SALES_CHANNEL',
34-
is_sandbox: true
34+
environment: 'staging'
3535
}).catch(error => {
3636
t.fail(error);
3737
});

src/api/__tests__/get_guestcheckout_response.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('Should create guest checkout with Prepayment successfully', async t => {
1616
const sdk = await AtlasSDK.configure({
1717
client_id: 'CLIENT_ID',
1818
sales_channel: 'SALES_CHANNEL',
19-
is_sandbox: true
19+
environment: 'staging'
2020
});
2121

2222
const getCheckoutResponse = {
@@ -68,7 +68,7 @@ test('Should create guest checkout with Prepayment successfully', async t => {
6868
latest: '2016-12-17T15:22:11.823Z'
6969
}
7070
};
71-
const getCheckoutObject = await sdk.getCheckout('123', '123');
71+
const getCheckoutObject = await sdk.getGuestCheckout('123', '123');
7272

7373
t.is(getCheckoutObject.delivery.service, getCheckoutResponse.delivery.service);
7474
fetchMock.restore();

src/api/__tests__/guest_checkout_service_tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('Should create guest checkout with Prepayment successfully', async t => {
1616
const sdk = await AtlasSDK.configure({
1717
client_id: 'CLIENT_ID',
1818
sales_channel: 'SALES_CHANNEL',
19-
is_sandbox: true
19+
environment: 'staging'
2020
});
2121

2222
const createOrderRequestJson = {

src/api/__tests__/recommendation_models_tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test('Article should be initialized from JSON object', async t => {
1919
const sdk = await AtlasSDK.configure({
2020
client_id: 'CLIENT_ID',
2121
sales_channel: 'SALES_CHANNEL',
22-
is_sandbox: true
22+
environment: 'staging'
2323
});
2424

2525
const recommendedArticles = await sdk.getRecommendations('AD112B0F6-A11',

src/api/atlas_sdk_client.js

+45-22
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,21 @@ const checkRedirect = (response) => {
4747
return response;
4848
};
4949

50-
function fetchEndpoint(endpoint) {
51-
return fetch(endpoint.url, {
52-
method: endpoint.method,
53-
mode: endpoint.mode,
54-
redirect: endpoint.redirect,
55-
headers: endpoint.headers,
56-
body: endpoint.body
50+
function fetchEndpoint(request) {
51+
return fetch(request.url, {
52+
method: request.method,
53+
mode: request.mode,
54+
redirect: request.redirect,
55+
headers: request.headers,
56+
body: request.body
5757
})
5858
.then(checkStatus)
5959
.then(checkRedirect)
6060
.then(response => {
6161
return response.json();
6262
})
6363
.then(response => {
64-
return endpoint.transform(response);
64+
return request.transform(Object.assign({}, response));
6565
}).catch(error => {
6666
console.error(error); /* eslint no-console: 0 */
6767
throw error;
@@ -78,9 +78,32 @@ class AtlasSDKClient {
7878
* Creates an AtlasSDK instance from config provided by config-api
7979
* @constructor {ignore}
8080
* @param {Object} config - config from config-api
81+
* @param {Object} options
82+
* @param {Object} options.mocksAPI - a service that intercepts fetch calls and provides it's own response
8183
*/
82-
constructor(config) {
84+
constructor(config, options = {}) {
8385
this.config = config;
86+
this.mocks = options.mocks;
87+
}
88+
89+
fetchEndpoint(endpoint, request) {
90+
const config = this.getConfig();
91+
92+
if (config.environment === 'development') {
93+
const mocks = this.mocks;
94+
95+
return new Promise((resolve, reject) => {
96+
try {
97+
const mock = mocks.fetch(endpoint, request);
98+
99+
return resolve(request.transform(Object.assign({}, mock)));
100+
} catch (e) {
101+
return reject(e);
102+
}
103+
});
104+
}
105+
106+
return fetchEndpoint(request);
84107
}
85108

86109
/**
@@ -176,7 +199,7 @@ class AtlasSDKClient {
176199
*/
177200
getArticle(sku, options = {}) {
178201
const url = `${this.config.catalogApi.url}/articles/${sku}?client_id=${this.config.clientId}`;
179-
const CatalogEndpoint = {
202+
const CatalogRequest = {
180203
url: url,
181204
method: 'GET',
182205
headers: {
@@ -191,7 +214,7 @@ class AtlasSDKClient {
191214
}
192215
};
193216

194-
return fetchEndpoint(CatalogEndpoint).then(article => {
217+
return this.fetchEndpoint('getArticle', CatalogRequest).then(article => {
195218
return article;
196219
});
197220
}
@@ -205,9 +228,9 @@ class AtlasSDKClient {
205228
* @param {String} token
206229
* @return {GetCheckoutResponse} guest checkout object
207230
*/
208-
getCheckout(checkoutId, token) {
231+
getGuestCheckout(checkoutId, token) {
209232
const url = `${this.config.atlasCheckoutGateway.url}/guest-checkout/api/checkouts/${checkoutId}/${token}`;
210-
const GetCheckoutEndpoint = {
233+
const GetCheckoutRequest = {
211234
url: url,
212235
method: 'GET',
213236
headers: {
@@ -223,8 +246,8 @@ class AtlasSDKClient {
223246
}
224247
};
225248

226-
return fetchEndpoint(GetCheckoutEndpoint).then(getCheckoutResponse => {
227-
return getCheckoutResponse;
249+
return this.fetchEndpoint('getGuestCheckout', GetCheckoutRequest).then(getGuestCheckoutResponse => {
250+
return getGuestCheckoutResponse;
228251
});
229252
}
230253

@@ -236,13 +259,13 @@ class AtlasSDKClient {
236259
* @param {String} token
237260
* @return {CreateOrderResponse} object with order information
238261
*/
239-
createOrder(checkoutId, token) {
262+
createGuestOrder(checkoutId, token) {
240263
const url = `${this.config.atlasCheckoutGateway.url}/guest-checkout/api/orders`;
241264
const body = JSON.stringify({
242265
checkout_id: checkoutId,
243266
token: token
244267
});
245-
const CreateOrderEndpoint = {
268+
const CreateOrderRequest = {
246269
url: url,
247270
method: 'POST',
248271
headers: {
@@ -257,7 +280,7 @@ class AtlasSDKClient {
257280
}
258281
};
259282

260-
return fetchEndpoint(CreateOrderEndpoint).then(createOrderResponse => {
283+
return this.fetchEndpoint('createGuestOrder', CreateOrderRequest).then(createOrderResponse => {
261284
return createOrderResponse;
262285
});
263286
}
@@ -332,7 +355,7 @@ class AtlasSDKClient {
332355
const catalogUrl = config.catalogApi.url;
333356
const type = config.recommendations[0].type;
334357
const url = `${catalogUrl}/articles/${sku}/recommendations/?client_id=${config.clientId}&anon_id=${options.reco_id}`; /* eslint max-len: 0 */
335-
const GetRecommendationsEndpoint = {
358+
const GetRecommendationsRequest = {
336359
url: url,
337360
method: 'GET',
338361
headers: {
@@ -357,7 +380,7 @@ class AtlasSDKClient {
357380
}
358381
};
359382

360-
return fetchEndpoint(GetRecommendationsEndpoint).then(recommendedArticles => {
383+
return this.fetchEndpoint('getRecommendations', GetRecommendationsRequest).then(recommendedArticles => {
361384
return recommendedArticles;
362385
});
363386
}
@@ -372,7 +395,7 @@ class AtlasSDKClient {
372395
*/
373396
createGuestCheckout(json) {
374397
const url = `${this.config.atlasCheckoutGateway.url}/guest-checkout/api/orders`;
375-
const GuestCheckoutEndpoint = {
398+
const GuestCheckoutRequest = {
376399
url: url,
377400
method: 'POST',
378401
mode: 'cors',
@@ -393,7 +416,7 @@ class AtlasSDKClient {
393416
}
394417
};
395418

396-
return fetchEndpoint(GuestCheckoutEndpoint).then(guestCheckoutResponse => {
419+
return this.fetchEndpoint('createGuestCheckout', GuestCheckoutRequest).then(guestCheckoutResponse => {
397420
return guestCheckoutResponse;
398421
});
399422
}

src/index.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import * as models from './models/index.js';
22
import { AtlasSDKClient, fetchEndpoint } from './api/atlas_sdk_client.js';
33
import { Config } from './models/config_models';
44

5+
const ENVIRONMENTS = ['development', 'staging', 'production'];
6+
7+
const isValidEnv = (type) => ENVIRONMENTS.indexOf(type) !== -1; /* eslint no-magic-numbers: [0] */
8+
59
/**
610
* AtlasSDK is a global namespace.
711
* @namespace AtlasSDK
@@ -28,13 +32,34 @@ const AtlasSDK = {
2832
* const sdk = await AtlasSDK.configure({
2933
* client_id: 'CLIENT_ID',
3034
* sales_channel: 'SALES_CHANNEL',
31-
* is_sandBox: true
35+
* environment: 'dev',
36+
* mocks: mocks
3237
* });
3338
*/
3439
configure(options = {}) {
35-
const env = options.is_sandbox ? 'staging' : 'production';
40+
const env = options.environment;
41+
const mocks = options.mocks;
42+
43+
if (!isValidEnv(env)) {
44+
throw new Error('Please choose one of the available environments: "development", "staging", "production"');
45+
}
46+
3647
const url = `https://atlas-config-api.dc.zalan.do/api/config/${options.client_id}-${env}.json`;
3748

49+
if (env === 'development') {
50+
if (!mocks) {
51+
throw new Error('Please provide a mocks service through "options.mocks"');
52+
}
53+
54+
if (!mocks.fetch) {
55+
throw new Error('The mocks service must expose a "fetch" method');
56+
}
57+
58+
const mockConfig = mocks.fetch('config');
59+
60+
return Promise.resolve(new AtlasSDKClient(new Config(Object.assign(mockConfig, options)), { mocks }));
61+
}
62+
3863
const ConfigEndpoint = {
3964
url: url,
4065
method: 'GET',
@@ -53,3 +78,4 @@ const AtlasSDK = {
5378
};
5479

5580
export default Object.assign(AtlasSDK, models);
81+
export { AtlasSDKClient };

src/models/__tests__/config_service_models_tests.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ test('Config should be initialized from JSON object', t => {
2828
const json = {
2929
client_id: 'CLIENT_ID',
3030
sales_channel: 'SALES_CHANNEL',
31-
is_sandbox: true,
31+
environment: 'staging',
3232
'atlas-catalog-api': {
3333
url: 'https://catalog_api.com/api'
3434
},
@@ -56,7 +56,7 @@ test('Config should be initialized from JSON object', t => {
5656

5757
t.is(config.clientId, 'CLIENT_ID');
5858
t.is(config.salesChannel, 'SALES_CHANNEL');
59-
t.is(config.isSandbox, true);
59+
t.is(config.environment, 'staging');
6060
t.is(config.catalogApi.url, 'https://catalog_api.com/api');
6161
t.is(config.atlasCheckoutGateway.url, 'https://atlas-checkout-gateway.com');
6262
t.is(config.salesChannels[0].locale, 'de_DE');

src/models/config_models.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const Config = createModel({
4949
clientId: { key: 'client_id', type: 'string' },
5050
salesChannel: { key: 'sales_channel', type: 'string' },
5151
recommendations: { key: 'recommendations', type: 'object', model: Recommendations },
52-
isSandbox: { key: 'is_sandbox', type: 'boolean' }
52+
environment: { key: 'environment', type: 'string' }
5353
});
5454

5555
export { SalesChannel, Config };

webpack.config.base.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ const baseConfig = {
3232
{
3333
test: /\.(js)$/,
3434
loader: 'babel-loader',
35-
include: srcPath
36-
},
37-
{
38-
test: /\.json$/,
39-
loader: 'json-loader'
35+
include: srcPath,
36+
options: {
37+
plugins: [
38+
'syntax-dynamic-import'
39+
]
40+
}
4041
}
4142
]
4243
},

0 commit comments

Comments
 (0)