Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit 2c8d5ac

Browse files
Merge pull request #380 from Shopify/kos/add_saving_param_to_serialize
Adds support for read-only attributes to serialize
2 parents 841abd9 + 2bad7ef commit 2c8d5ac

File tree

7 files changed

+57
-17
lines changed

7 files changed

+57
-17
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

88
## Unreleased
99

10+
- Add optional `saving` parameter to `serialize` of `Base` class - default is `false` and will include read-only attributes in returned object; `true` used for `save` when committing via API to Shopify.
11+
1012
### Fixed
1113
- Fixes [#363](https://github.com/Shopify/shopify-node-api/issues/363)
1214
- Webhooks `register` now checks for any attempt to register a GDPR topic (not done via API but by Partner Dashboard), provides an error message in response

src/__tests__/base-rest-resource.test.ts

+33-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ describe('Base REST resource', () => {
198198
id: 1,
199199
attribute: 'attribute',
200200
has_one_attribute: {attribute: 'attribute1'},
201-
has_many_attribute: [{attribute: 'attribute2'}],
201+
has_many_attribute: [
202+
{attribute: 'attribute2'},
203+
{attribute: 'attribute3'},
204+
],
202205
},
203206
};
204207
fetchMock.mockResponseOnce(JSON.stringify({}));
@@ -209,11 +212,14 @@ describe('Base REST resource', () => {
209212
const child2 = new FakeResource({session});
210213
child2.attribute = 'attribute2';
211214

215+
const child3 = new FakeResource({session});
216+
child3.attribute = 'attribute3';
217+
212218
const resource = new FakeResource({session});
213219
resource.id = 1;
214220
resource.attribute = 'attribute';
215221
resource.has_one_attribute = child1;
216-
resource.has_many_attribute = [child2];
222+
resource.has_many_attribute = [child2, child3];
217223

218224
await resource.save();
219225

@@ -446,4 +452,29 @@ describe('Base REST resource', () => {
446452
),
447453
);
448454
});
455+
456+
it('includes unsaveable attributes when default serialize called', async () => {
457+
const resource = new FakeResource({session});
458+
resource.attribute = 'attribute';
459+
resource.unsaveable_attribute = 'unsaveable_attribute';
460+
461+
const hash = resource.serialize();
462+
463+
expect(hash).toHaveProperty('unsaveable_attribute', 'unsaveable_attribute');
464+
expect(hash).toHaveProperty('attribute', 'attribute');
465+
});
466+
467+
it('excludes unsaveable attributes when serialize called for saving', async () => {
468+
const resource = new FakeResource({session});
469+
resource.attribute = 'attribute';
470+
resource.unsaveable_attribute = 'unsaveable_attribute';
471+
472+
const hash = resource.serialize(true);
473+
474+
expect(hash).not.toHaveProperty(
475+
'unsaveable_attribute',
476+
'unsaveable_attribute',
477+
);
478+
expect(hash).toHaveProperty('attribute', 'attribute');
479+
});
449480
});

src/auth/session/storage/__tests__/mongodb.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const dbName = 'shopitest';
1515

1616
// SORRY NOT SORRY. Docker containers can take quite a while to get ready,
1717
// especially on CI. This is hopefully enough.
18-
jest.setTimeout(20000);
18+
jest.setTimeout(25000);
1919

2020
describe('MongoDBSessionStorage', () => {
2121
let storage: MongoDBSessionStorage;

src/auth/session/storage/__tests__/mysql.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const dbURL = new URL('mysql://shopify:passify@localhost/shopitest');
1414

1515
// SORRY NOT SORRY. Docker containers can take quite a while to get ready,
1616
// especially on CI. This is hopefully enough.
17-
jest.setTimeout(20000);
17+
jest.setTimeout(25000);
1818

1919
describe('MySQLSessionStorage', () => {
2020
let storage: MySQLSessionStorage;

src/auth/session/storage/__tests__/postgresql.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const dbURL = new URL('postgres://shopify:passify@localhost/shopitest');
1414

1515
// SORRY NOT SORRY. Docker containers can take quite a while to get ready,
1616
// especially on CI. This is hopefully enough.
17-
jest.setTimeout(20000);
17+
jest.setTimeout(25000);
1818

1919
describe('PostgreSQLSessionStorage', () => {
2020
let storage: PostgreSQLSessionStorage;

src/auth/session/storage/__tests__/redis.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const dbURL = new URL('redis://shopify:passify@localhost/1');
1414

1515
// SORRY NOT SORRY. Docker containers can take quite a while to get ready,
1616
// especially on CI. This is hopefully enough.
17-
jest.setTimeout(20000);
17+
jest.setTimeout(25000);
1818

1919
describe('RedisSessionStorage', () => {
2020
let storage: RedisSessionStorage | undefined;

src/base-rest-resource.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class Base {
256256
const {PRIMARY_KEY, NAME} = this.resource();
257257
const method = this[PRIMARY_KEY] ? 'put' : 'post';
258258

259-
const data = this.serialize();
259+
const data = this.serialize(true);
260260

261261
const response = await this.resource().request({
262262
http_method: method,
@@ -288,25 +288,24 @@ class Base {
288288
});
289289
}
290290

291-
public serialize(): Body {
291+
public serialize(saving = false): Body {
292292
const {HAS_MANY, HAS_ONE, READ_ONLY_ATTRIBUTES} = this.resource();
293293

294294
return Object.entries(this).reduce((acc: Body, [attribute, value]) => {
295295
if (
296-
['session'].includes(attribute) ||
297-
READ_ONLY_ATTRIBUTES.includes(attribute)
296+
saving &&
297+
(['session'].includes(attribute) ||
298+
READ_ONLY_ATTRIBUTES.includes(attribute))
298299
) {
299300
return acc;
300301
}
301302

302303
if (attribute in HAS_MANY && value) {
303-
acc[attribute] = value.reduce(
304-
(attrAcc: Body, entry: Base) =>
305-
attrAcc.concat(entry.serialize ? entry.serialize() : entry),
306-
[],
307-
);
308-
} else if (attribute in HAS_ONE && value && value.serialize) {
309-
acc[attribute] = (value as Base).serialize();
304+
acc[attribute] = value.reduce((attrAcc: Body, entry: Base) => {
305+
return attrAcc.concat(this.serializeSubAttribute(entry, saving));
306+
}, []);
307+
} else if (attribute in HAS_ONE && value) {
308+
acc[attribute] = this.serializeSubAttribute(value, saving);
310309
} else {
311310
acc[attribute] = value;
312311
}
@@ -342,6 +341,14 @@ class Base {
342341
private resource(): typeof Base {
343342
return this.constructor as unknown as typeof Base;
344343
}
344+
345+
private serializeSubAttribute(attribute: Base, saving: boolean): Body {
346+
return attribute.serialize
347+
? attribute.serialize(saving)
348+
: this.resource()
349+
.createInstance(this.session, attribute)
350+
.serialize(saving);
351+
}
345352
}
346353

347354
export default Base;

0 commit comments

Comments
 (0)