,
82 | ) => void,
83 | ): void
84 |
85 | has_header(response: Response, header: string): boolean
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/test/shopify.js:
--------------------------------------------------------------------------------
1 | var should = require('chai').should(),
2 | expect = require('chai').expect,
3 | nock = require('nock'),
4 | shopifyAPI = require('../lib/shopify.js'),
5 | zlib = require('zlib');
6 |
7 | describe('Constructor Function: #shopifyAPI', function(){
8 |
9 | it('throws error if no config object is passed in', function(){
10 | var msg = "ShopifyAPI module expects a config object\nPlease see documentation at: https://github.com/sinechris/shopify-node-api\n";
11 | expect(function(){
12 | var Shopify = new shopifyAPI();
13 | }).to.throw(msg);
14 | });
15 |
16 | it('returns instanceof shopifyAPI with "new" keyword', function(){
17 | var Shopify = new shopifyAPI({});
18 | expect(Shopify).to.be.a.instanceof(shopifyAPI);
19 | });
20 |
21 | it('returns instanceof shopifyAPI without "new" keyword', function(){
22 | var Shopify = shopifyAPI({});
23 | expect(Shopify).to.be.a.instanceof(shopifyAPI);
24 | });
25 |
26 | });
27 |
28 | describe('#buildAuthURL', function(){
29 |
30 | var Shopify = new shopifyAPI({
31 | shop: 'MYSHOP',
32 | shopify_api_key: 'abc123',
33 | shopify_shared_secret: 'asdf1234',
34 | shopify_scope: 'write_products',
35 | redirect_uri: 'http://localhost:3000/finish_auth',
36 | nonce: 'abc123'
37 | });
38 |
39 |
40 | it('builds correct string', function(){
41 | var auth_url = Shopify.buildAuthURL(),
42 | correct_auth_url = 'https://MYSHOP.myshopify.com/admin/oauth/authorize?client_id=abc123&scope=write_products&redirect_uri=http://localhost:3000/finish_auth&state=abc123';
43 | auth_url.should.equal(correct_auth_url);
44 | });
45 |
46 | });
47 |
48 | describe('#set_access_token', function(){
49 | var Shopify = new shopifyAPI({});
50 |
51 | it('should not have access_token property initially', function(){
52 | Shopify.config.should.not.have.property('access_token');
53 | });
54 |
55 | it('should add correct access token to config object', function(){
56 | Shopify.config.should.not.have.property('access_token');
57 | var fake_token = '123456789';
58 | Shopify.set_access_token(fake_token);
59 | Shopify
60 | .config
61 | .should
62 | .have
63 | .property('access_token')
64 | .with
65 | .length(fake_token.length);
66 | Shopify
67 | .config
68 | .access_token
69 | .should
70 | .equal(fake_token);
71 | });
72 |
73 | });
74 |
75 | describe('#is_valid_signature', function(){
76 | it('should return correct signature', function(){
77 |
78 | // Values used below were pre-calculated and not part
79 | // of an actual shop.
80 |
81 | var Shopify = shopifyAPI({
82 | shopify_shared_secret: 'hush',
83 | nonce: 'abc123'
84 | }),
85 | params = {
86 | 'shop': 'some-shop.myshopify.com',
87 | 'code': 'a94a110d86d2452eb3e2af4cfb8a3828',
88 | 'timestamp': '1337178173',
89 | 'signature': '6e39a2ea9e497af6cb806720da1f1bf3',
90 | 'hmac': '62c96e47cdef32a33c6fa78d761e049b3578b8fc115188a9ffcd774937ab7c78',
91 | 'state': 'abc123'
92 | };
93 |
94 | expect(Shopify.is_valid_signature(params)).to.equal(true);
95 | });
96 |
97 | it('should ignore the state/nonce when non_state is true', function(){
98 |
99 | // Values used below were pre-calculated and not part
100 | // of an actual shop.
101 |
102 | var Shopify = shopifyAPI({
103 | shopify_shared_secret: 'hush',
104 | }),
105 | params = {
106 | 'shop': 'some-shop.myshopify.com',
107 | 'code': 'a94a110d86d2452eb3e2af4cfb8a3828',
108 | 'timestamp': '1337178173',
109 | 'signature': '6e39a2ea9e497af6cb806720da1f1bf3',
110 | 'hmac': '2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2',
111 | };
112 |
113 | expect(Shopify.is_valid_signature(params, true)).to.equal(true);
114 | });
115 | });
116 |
117 | describe('#exchange_temporary_token', function(){
118 | it('should exchange a temporary token', function(done){
119 |
120 | // Values used below were pre-calculated and not part
121 | // of an actual shop.
122 |
123 | var Shopify = shopifyAPI({
124 | shop: 'myshop',
125 | shopify_api_key: 'abc123',
126 | shopify_shared_secret: 'hush',
127 | verbose: false,
128 | nonce: 'abc123'
129 | }),
130 | params = {
131 | 'shop': 'some-shop.myshopify.com',
132 | 'code': 'a94a110d86d2452eb3e2af4cfb8a3828',
133 | 'timestamp': '1337178173',
134 | 'signature': '6e39a2ea9e497af6cb806720da1f1bf3',
135 | 'hmac': '62c96e47cdef32a33c6fa78d761e049b3578b8fc115188a9ffcd774937ab7c78',
136 | 'state': 'abc123'
137 | };
138 |
139 | var shopifyTokenFetch = nock('https://myshop.myshopify.com')
140 | .post('/admin/oauth/access_token')
141 | .reply(200, {
142 | "access_token": "abcd"
143 | });
144 |
145 | Shopify.exchange_temporary_token(params, function(err, res) {
146 | if (err) {
147 | return done(err);
148 | }
149 | shopifyTokenFetch.done();
150 | done();
151 | });
152 | });
153 |
154 | it('should return an error object with a legible message', function(done) {
155 | var Shopify = shopifyAPI({
156 | shop: 'myshop',
157 | shopify_api_key: 'abc123',
158 | shopify_shared_secret: 'hush',
159 | verbose: false,
160 | nonce: 'abc123'
161 | }),
162 | params = {
163 | 'shop': 'some-shop.myshopify.com',
164 | 'code': 'a94a110d86d2452eb3e2af4cfb8a3828',
165 | 'timestamp': '1337178173',
166 | 'signature': '6e39a2ea9e497af6cb806720da1f1bf3',
167 | 'hmac': '62c96e47cdef32a33c6fa78d761e049b3578b8fc115188a9ffcd774937ab7c78',
168 | 'state': 'abc123'
169 | };
170 |
171 | // Shopify will return an invalid request in some cases, e.g. if a code
172 | // is not valid for exchanging to a permanent token.
173 | var shopifyTokenFetch = nock('https://myshop.myshopify.com')
174 | .post('/admin/oauth/access_token')
175 | .reply(400, {
176 | error: "invalid_request"
177 | });
178 |
179 | Shopify.exchange_temporary_token(params, function(err, res) {
180 | shopifyTokenFetch.done();
181 | expect(err).to.be.instanceof(Error);
182 | expect(err.message).to.equal("invalid_request");
183 | done();
184 | });
185 | });
186 | });
187 |
188 | describe('#get', function(){
189 | it('should return correct response', function(done){
190 |
191 | var shopify_get = nock('https://myshop.myshopify.com')
192 | .get('/admin/products/count.json')
193 | .reply(200, {
194 | "count": 2
195 | });
196 |
197 | var Shopify = shopifyAPI({
198 | shop: 'myshop',
199 | shopify_api_key: 'abc123',
200 | shopify_shared_secret: 'asdf1234',
201 | shopify_scope: 'write_products',
202 | redirect_uri: 'http://localhost:3000/finish_auth',
203 | verbose: false
204 | });
205 |
206 | Shopify.get('/admin/products/count.json', function(err, data, headers){
207 | expect(data).to.deep.equal({"count": 2});
208 | done();
209 | });
210 |
211 | });
212 |
213 | it('should parse a gzip response', function(done){
214 | var buf = new Buffer(JSON.stringify({ count: 2 }));
215 | zlib.gzip(buf, function(err, res) {
216 | if (err) {
217 | return done(err);
218 | }
219 | var shopify_get = nock('https://myshop.myshopify.com')
220 | .get('/admin/products/count.json')
221 | .reply(200, res, {
222 | 'X-Transfer-Length': String(res.length),
223 | 'Content-Length': undefined,
224 | 'Content-Encoding': 'gzip',
225 | 'Content-Type': 'application/json'
226 | });
227 |
228 | var Shopify = shopifyAPI({
229 | shop: 'myshop',
230 | shopify_api_key: 'abc123',
231 | shopify_shared_secret: 'asdf1234',
232 | shopify_scope: 'write_products',
233 | redirect_uri: 'http://localhost:3000/finish_auth',
234 | verbose: false
235 | });
236 |
237 | Shopify.get('/admin/products/count.json', function(err, data, headers){
238 | expect(data).to.deep.equal({"count": 2});
239 | done();
240 | });
241 | });
242 | });
243 |
244 | it('should parse a number too large for javascript into a string', function(done) {
245 | var shopify_get = nock('https://myshop.myshopify.com')
246 | .get('/admin/orders.json')
247 | .reply(200, '{"id": 9223372036854775807}');
248 |
249 | var Shopify = shopifyAPI({
250 | shop: 'myshop',
251 | shopify_api_key: 'abc123',
252 | shopify_shared_secret: 'asdf1234',
253 | shopify_scope: 'write_products',
254 | redirect_uri: 'http://localhost:3000/finish_auth',
255 | verbose: false
256 | });
257 |
258 |
259 | Shopify.get('/admin/orders.json', function(err, data, headers){
260 | expect(data.id.toString()).to.equal('9223372036854775807');
261 | done();
262 | });
263 | });
264 |
265 | it('should accept an agent for https', function(done) {
266 | var Agent = require('https').Agent;
267 | var agent = new Agent({
268 | keepAlive: true,
269 | keepAliveMsecs: 1000 * 10,
270 | maxSockets: 10,
271 | maxFreeSockets: 10
272 | });
273 | var shopify_get = nock('https://myshop.myshopify.com')
274 | .get('/admin/orders.json')
275 | .reply(200, '{"id": 1}');
276 |
277 | var Shopify = shopifyAPI({
278 | shop: 'myshop',
279 | shopify_api_key: 'abc123',
280 | shopify_shared_secret: 'asdf1234',
281 | shopify_scope: 'write_products',
282 | redirect_uri: 'http://localhost:3000/finish_auth',
283 | verbose: false,
284 | agent: agent
285 | });
286 |
287 | Shopify.get('/admin/orders.json', function(err, data, headers, opts) {
288 | expect(err).to.not.exist();
289 | expect(opts.agent).to.equal(agent);
290 | return done();
291 | });
292 | });
293 |
294 | it('should parse data argument into a querystring and append it to endpoint', function(done) {
295 | var shopify_get = nock('https://myshop.myshopify.com')
296 | .get('/admin/products.json')
297 | .query(true)
298 | .reply(200, function(uri, reqBody) {
299 | return {uri: uri};
300 | });
301 |
302 | var Shopify = shopifyAPI({
303 | shop: 'myshop',
304 | shopify_api_key: 'abc123',
305 | shopify_shared_secret: 'asdf1234',
306 | shopify_scope: 'write_products',
307 | redirect_uri: 'http://localhost:3000/finish_auth',
308 | verbose: false
309 | });
310 |
311 |
312 | Shopify.get('/admin/products.json', {page: 2, limit: 15}, function(err, data, headers){
313 | expect(data.uri).to.equal('/admin/products.json?page=2&limit=15');
314 | done();
315 | });
316 | });
317 |
318 | it('should use error_description when available', function(done) {
319 | var shopify_get = nock('https://myshop.myshopify.com')
320 | .get('/')
321 | .reply(400, function(uri, reqBody) {
322 | return {'error':'abc','error_description':'xyz'};
323 | });
324 |
325 | var Shopify = shopifyAPI({
326 | shop: 'myshop',
327 | shopify_api_key: 'abc123',
328 | shopify_shared_secret: 'asdf1234',
329 | shopify_scope: 'write_products',
330 | redirect_uri: 'http://localhost:3000/finish_auth',
331 | verbose: false
332 | });
333 |
334 | Shopify.get('/', function(err, data, headers){
335 | expect(err).to.deep.equal({ error: 'xyz', code: 400 });
336 | done();
337 | });
338 | });
339 |
340 | it('should use error when error_description is not available', function(done) {
341 | var shopify_get = nock('https://myshop.myshopify.com')
342 | .get('/')
343 | .reply(400, function(uri, reqBody) {
344 | return {'error':'abc'};
345 | });
346 |
347 | var Shopify = shopifyAPI({
348 | shop: 'myshop',
349 | shopify_api_key: 'abc123',
350 | shopify_shared_secret: 'asdf1234',
351 | shopify_scope: 'write_products',
352 | redirect_uri: 'http://localhost:3000/finish_auth',
353 | verbose: false
354 | });
355 |
356 | Shopify.get('/', function(err, data, headers){
357 | expect(err).to.deep.equal({ error: 'abc', code: 400 });
358 | done();
359 | });
360 | });
361 |
362 | it('should use errors when error_description and error is not available', function(done) {
363 | var shopify_get = nock('https://myshop.myshopify.com')
364 | .get('/')
365 | .reply(400, function(uri, reqBody) {
366 | return {'errors':'abc'};
367 | });
368 |
369 | var Shopify = shopifyAPI({
370 | shop: 'myshop',
371 | shopify_api_key: 'abc123',
372 | shopify_shared_secret: 'asdf1234',
373 | shopify_scope: 'write_products',
374 | redirect_uri: 'http://localhost:3000/finish_auth',
375 | verbose: false
376 | });
377 |
378 | Shopify.get('/', function(err, data, headers){
379 | expect(err).to.deep.equal({ error: 'abc', code: 400 });
380 | done();
381 | });
382 | });
383 | });
384 |
385 | describe('#post', function(){
386 | it('should return correct response', function(done){
387 |
388 | var post_data = {
389 | "product": {
390 | "title": "Burton Custom Freestlye 151",
391 | "body_html": "Good snowboard!",
392 | "vendor": "Burton",
393 | "product_type": "Snowboard",
394 | "variants": [
395 | {
396 | "option1": "First",
397 | "price": "10.00",
398 | "sku": 123
399 | },
400 | {
401 | "option1": "Second",
402 | "price": "20.00",
403 | "sku": "123"
404 | }
405 | ]
406 | }
407 | },
408 | response = {
409 | "product": {
410 | "body_html": "Good snowboard!",
411 | "created_at": "2014-05-23T14:18:12-04:00",
412 | "handle": "burton-custom-freestlye-151",
413 | "id": 1071559674,
414 | "product_type": "Snowboard",
415 | "published_at": "2014-05-23T14:18:12-04:00",
416 | "published_scope": "global",
417 | "template_suffix": null,
418 | "title": "Burton Custom Freestlye 151",
419 | "updated_at": "2014-05-23T14:18:12-04:00",
420 | "vendor": "Burton",
421 | "tags": "",
422 | "variants": [
423 | {
424 | "barcode": null,
425 | "compare_at_price": null,
426 | "created_at": "2014-05-23T14:18:12-04:00",
427 | "fulfillment_service": "manual",
428 | "grams": 0,
429 | "id": 1044399349,
430 | "inventory_management": null,
431 | "inventory_policy": "deny",
432 | "option1": "First",
433 | "option2": null,
434 | "option3": null,
435 | "position": 1,
436 | "price": "10.00",
437 | "product_id": 1071559674,
438 | "requires_shipping": true,
439 | "sku": "123",
440 | "taxable": true,
441 | "title": "First",
442 | "updated_at": "2014-05-23T14:18:12-04:00",
443 | "inventory_quantity": 1,
444 | "old_inventory_quantity": 1
445 | },
446 | {
447 | "barcode": null,
448 | "compare_at_price": null,
449 | "created_at": "2014-05-23T14:18:12-04:00",
450 | "fulfillment_service": "manual",
451 | "grams": 0,
452 | "id": 1044399350,
453 | "inventory_management": null,
454 | "inventory_policy": "deny",
455 | "option1": "Second",
456 | "option2": null,
457 | "option3": null,
458 | "position": 2,
459 | "price": "20.00",
460 | "product_id": 1071559674,
461 | "requires_shipping": true,
462 | "sku": "123",
463 | "taxable": true,
464 | "title": "Second",
465 | "updated_at": "2014-05-23T14:18:12-04:00",
466 | "inventory_quantity": 1,
467 | "old_inventory_quantity": 1
468 | }
469 | ],
470 | "options": [
471 | {
472 | "id": 1020890454,
473 | "name": "Title",
474 | "position": 1,
475 | "product_id": 1071559674
476 | }
477 | ],
478 | "images": [
479 |
480 | ]
481 | }
482 | };
483 |
484 | var shopify_get = nock('https://myshop.myshopify.com')
485 | .post('/admin/products.json')
486 | .reply(200, response);
487 |
488 | var Shopify = shopifyAPI({
489 | shop: 'myshop',
490 | shopify_api_key: 'abc123',
491 | shopify_shared_secret: 'asdf1234',
492 | shopify_scope: 'write_products',
493 | redirect_uri: 'http://localhost:3000/finish_auth',
494 | verbose: false
495 | });
496 |
497 | Shopify.post('/admin/products.json', post_data, function(err, data, headers){
498 | expect(data).to.deep.equal(response);
499 | done();
500 | });
501 |
502 | });
503 | });
504 |
505 | describe('#put', function(){
506 | it('should return correct response', function(done){
507 |
508 | var put_data = {
509 | "product": {
510 | "id": 632910392,
511 | "title": "New product title"
512 | }
513 | },
514 | response = {
515 | "product": {
516 | "body_html": "It's the small iPod with one very big idea: Video. Now the world's most popular music player, available in 4GB and 8GB models, lets you enjoy TV shows, movies, video podcasts, and more. The larger, brighter display means amazing picture quality. In six eye-catching colors, iPod nano is stunning all around. And with models starting at just $149, little speaks volumes.
",
517 | "created_at": "2014-05-23T14:17:55-04:00",
518 | "handle": "ipod-nano",
519 | "id": 632910392,
520 | "product_type": "Cult Products",
521 | "published_at": "2007-12-31T19:00:00-05:00",
522 | "published_scope": "global",
523 | "template_suffix": null,
524 | "title": "New product title",
525 | "updated_at": "2014-05-23T14:18:15-04:00",
526 | "vendor": "Apple",
527 | "tags": "Emotive, Flash Memory, MP3, Music",
528 | "variants": [
529 | {
530 | "barcode": "1234_pink",
531 | "compare_at_price": null,
532 | "created_at": "2014-05-23T14:17:55-04:00",
533 | "fulfillment_service": "manual",
534 | "grams": 200,
535 | "id": 808950810,
536 | "inventory_management": "shopify",
537 | "inventory_policy": "continue",
538 | "option1": "Pink",
539 | "option2": null,
540 | "option3": null,
541 | "position": 1,
542 | "price": "199.00",
543 | "product_id": 632910392,
544 | "requires_shipping": true,
545 | "sku": "IPOD2008PINK",
546 | "taxable": true,
547 | "title": "Pink",
548 | "updated_at": "2014-05-23T14:17:55-04:00",
549 | "inventory_quantity": 10,
550 | "old_inventory_quantity": 10
551 | },
552 | {
553 | "barcode": "1234_red",
554 | "compare_at_price": null,
555 | "created_at": "2014-05-23T14:17:55-04:00",
556 | "fulfillment_service": "manual",
557 | "grams": 200,
558 | "id": 49148385,
559 | "inventory_management": "shopify",
560 | "inventory_policy": "continue",
561 | "option1": "Red",
562 | "option2": null,
563 | "option3": null,
564 | "position": 2,
565 | "price": "199.00",
566 | "product_id": 632910392,
567 | "requires_shipping": true,
568 | "sku": "IPOD2008RED",
569 | "taxable": true,
570 | "title": "Red",
571 | "updated_at": "2014-05-23T14:17:55-04:00",
572 | "inventory_quantity": 20,
573 | "old_inventory_quantity": 20
574 | },
575 | {
576 | "barcode": "1234_green",
577 | "compare_at_price": null,
578 | "created_at": "2014-05-23T14:17:55-04:00",
579 | "fulfillment_service": "manual",
580 | "grams": 200,
581 | "id": 39072856,
582 | "inventory_management": "shopify",
583 | "inventory_policy": "continue",
584 | "option1": "Green",
585 | "option2": null,
586 | "option3": null,
587 | "position": 3,
588 | "price": "199.00",
589 | "product_id": 632910392,
590 | "requires_shipping": true,
591 | "sku": "IPOD2008GREEN",
592 | "taxable": true,
593 | "title": "Green",
594 | "updated_at": "2014-05-23T14:17:55-04:00",
595 | "inventory_quantity": 30,
596 | "old_inventory_quantity": 30
597 | },
598 | {
599 | "barcode": "1234_black",
600 | "compare_at_price": null,
601 | "created_at": "2014-05-23T14:17:55-04:00",
602 | "fulfillment_service": "manual",
603 | "grams": 200,
604 | "id": 457924702,
605 | "inventory_management": "shopify",
606 | "inventory_policy": "continue",
607 | "option1": "Black",
608 | "option2": null,
609 | "option3": null,
610 | "position": 4,
611 | "price": "199.00",
612 | "product_id": 632910392,
613 | "requires_shipping": true,
614 | "sku": "IPOD2008BLACK",
615 | "taxable": true,
616 | "title": "Black",
617 | "updated_at": "2014-05-23T14:17:55-04:00",
618 | "inventory_quantity": 40,
619 | "old_inventory_quantity": 40
620 | }
621 | ],
622 | "options": [
623 | {
624 | "id": 594680422,
625 | "name": "Title",
626 | "position": 1,
627 | "product_id": 632910392
628 | }
629 | ],
630 | "images": [
631 | {
632 | "created_at": "2014-05-23T14:17:55-04:00",
633 | "id": 850703190,
634 | "position": 1,
635 | "product_id": 632910392,
636 | "updated_at": "2014-05-23T14:17:55-04:00",
637 | "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1400869075"
638 | },
639 | {
640 | "created_at": "2014-05-23T14:17:55-04:00",
641 | "id": 562641783,
642 | "position": 2,
643 | "product_id": 632910392,
644 | "updated_at": "2014-05-23T14:17:55-04:00",
645 | "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano-2.png?v=1400869075"
646 | }
647 | ],
648 | "image": {
649 | "created_at": "2014-05-23T14:17:55-04:00",
650 | "id": 850703190,
651 | "position": 1,
652 | "product_id": 632910392,
653 | "updated_at": "2014-05-23T14:17:55-04:00",
654 | "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1400869075"
655 | }
656 | }
657 | };
658 |
659 | var shopify_get = nock('https://myshop.myshopify.com')
660 | .put('/admin/products/12345.json')
661 | .reply(200, response);
662 |
663 | var Shopify = shopifyAPI({
664 | shop: 'myshop',
665 | shopify_api_key: 'abc123',
666 | shopify_shared_secret: 'asdf1234',
667 | shopify_scope: 'write_products',
668 | redirect_uri: 'http://localhost:3000/finish_auth',
669 | verbose: false
670 | });
671 |
672 | Shopify.put('/admin/products/12345.json', put_data, function(err, data, headers){
673 | expect(data).to.deep.equal(response);
674 | done();
675 | });
676 |
677 | });
678 | });
679 |
680 | describe('#delete', function(){
681 | it('should return correct response', function(done){
682 |
683 | var shopify_get = nock('https://myshop.myshopify.com')
684 | .delete('/admin/products/12345.json')
685 | .reply(200, {});
686 |
687 | var Shopify = shopifyAPI({
688 | shop: 'myshop',
689 | shopify_api_key: 'abc123',
690 | shopify_shared_secret: 'asdf1234',
691 | shopify_scope: 'write_products',
692 | redirect_uri: 'http://localhost:3000/finish_auth',
693 | verbose: false
694 | });
695 |
696 | Shopify.delete('/admin/products/12345.json', function(err, data, headers){
697 | expect(data).to.deep.equal({});
698 | done();
699 | });
700 |
701 | });
702 | });
703 |
704 | describe('#graphql', function(){
705 | it('should return correct response', function(done){
706 |
707 | var graphql_data = {
708 | query: '{shop{id}}',
709 | variables: {}
710 | }
711 | response = {
712 | data: {
713 | shop: {
714 | id: 'gid:\/\/shopify\/Shop\/1234567'
715 | }
716 | },
717 | extensions: {
718 | cost: {
719 | requestedQueryCost: 1,
720 | actualQueryCost: 1,
721 | throttleStatus: {
722 | maximumAvailable: 1000.0,
723 | currentlyAvailable: 999,
724 | restoreRate: 50.0
725 | }
726 | }
727 | }
728 | };
729 |
730 | var shopify_get = nock('https://myshop.myshopify.com')
731 | .post('/admin/api/graphql.json')
732 | .reply(200, response);
733 |
734 | var Shopify = shopifyAPI({
735 | shop: 'myshop',
736 | shopify_api_key: 'abc123',
737 | shopify_shared_secret: 'asdf1234',
738 | shopify_scope: 'write_products',
739 | redirect_uri: 'http://localhost:3000/finish_auth',
740 | verbose: false
741 | });
742 |
743 | Shopify.graphql(graphql_data, function(err, data, headers){
744 | expect(data).to.deep.equal(response);
745 | done();
746 | });
747 | });
748 | });
749 |
--------------------------------------------------------------------------------