From 4469ab762e0ef963e9c3e2701c6ddf58ce38a9cc Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 26 Aug 2020 13:52:54 -0400 Subject: [PATCH] add custom add/delete host set support to targets --- addons/api/addon/models/target.js | 32 +++++++++++++-- addons/api/addon/serializers/target.js | 19 ++++----- addons/api/tests/unit/models/target-test.js | 39 ++++++++++++++++-- .../api/tests/unit/serializers/target-test.js | 6 +-- ui/core/mirage/config.js | 40 +++++++++++-------- 5 files changed, 100 insertions(+), 36 deletions(-) diff --git a/addons/api/addon/models/target.js b/addons/api/addon/models/target.js index 0dad6ba7a..e9d3ac018 100644 --- a/addons/api/addon/models/target.js +++ b/addons/api/addon/models/target.js @@ -30,16 +30,40 @@ export default class TargetModel extends GeneratedTargetModel { // =methods /** - * Saves the `host_set_ids` array on the via the `set-hosts` method. + * Adds host sets via the `add-host-sets` method. * See serializer and adapter for more information. * @param {object} options * @param {object} options.adapterOptions * @return {Promise} */ - saveHostSets(options={ adapterOptions: {} }) { + addHostSets(hostSets, options={ adapterOptions: {} }) { const defaultAdapterOptions = { - method: 'set-host-sets', - serializeHostSets: true + method: 'add-host-sets', + hostSets + }; + // There is no "deep merge" in ES. + // All of this nonsense is here to ensure we get + // a decent merge of `adapterOptions`. + return this.save({ + ...options, + adapterOptions: { + ...defaultAdapterOptions, + ...options.adapterOptions + } + }); + } + + /** + * Delete host sets via the `delete-host-sets` method. + * See serializer and adapter for more information. + * @param {object} options + * @param {object} options.adapterOptions + * @return {Promise} + */ + deleteHostSets(hostSets, options={ adapterOptions: {} }) { + const defaultAdapterOptions = { + method: 'delete-host-sets', + hostSets }; // There is no "deep merge" in ES. // All of this nonsense is here to ensure we get diff --git a/addons/api/addon/serializers/target.js b/addons/api/addon/serializers/target.js index fefaf0fcb..5d45fec4d 100644 --- a/addons/api/addon/serializers/target.js +++ b/addons/api/addon/serializers/target.js @@ -5,30 +5,31 @@ export default class TargetSerializer extends ApplicationSerializer { // =methods /** - * If `adapterOptions.serializeHostSets` is true, the serialization should - * include **only host sets** and the version. Normally, host sets are not - * serialized. + * If `adapterOptions.hostSets` is set to an array of host set models, + * the resulting target serialization should include **only host sets** + * and the version. Normally, host sets are not serialized. * @override * @param {Snapshot} snapshot * @return {object} */ serialize(snapshot) { - const serializeHostSets = snapshot?.adapterOptions?.serializeHostSets; let serialized = super.serialize(...arguments); - if (serializeHostSets) serialized = this.serializeWithHostSets(snapshot); + const hostSets = snapshot?.adapterOptions?.hostSets; + if (hostSets) serialized = this.serializeWithHostSets(snapshot, hostSets); return serialized; } /** - * Returns a payload containing only the host_set_ids array. + * Returns a payload containing only the host_set_ids array using host sets + * passed into the function (rather than existing host sets on the model). * @param {Snapshot} snapshot + * @param {[HostSetModel]} hostSets * @return {object} */ - serializeWithHostSets(snapshot) { + serializeWithHostSets(snapshot, hostSets) { return { version: snapshot.attr('version'), - host_set_ids: - snapshot.attr('host_sets').map(hostSet => hostSet.attr('host_set_id')) + host_set_ids: hostSets.map(({ id }) => id) }; } diff --git a/addons/api/tests/unit/models/target-test.js b/addons/api/tests/unit/models/target-test.js index 04baf1bab..581150946 100644 --- a/addons/api/tests/unit/models/target-test.js +++ b/addons/api/tests/unit/models/target-test.js @@ -57,9 +57,42 @@ module('Unit | Model | target', function (hooks) { assert.ok(target.hostSets[0].hostCatalog, 'Host catalog is resolved'); }); - test('it has a `saveHostSets` method that targets a specific POST API endpoint and serialization', async function (assert) { + test('it has an `addHostSets` method that targets a specific POST API endpoint and serialization', async function (assert) { assert.expect(1); - this.server.post('/v1/scopes/o_1/targets/123abc:set-host-sets', (schema, request) => { + this.server.post('/v1/scopes/o_1/targets/123abc:add-host-sets', (schema, request) => { + const body = JSON.parse(request.requestBody); + assert.deepEqual(body, { + host_set_ids: ['123_abc', 'foobar'], + version: 1 + }); + }); + const store = this.owner.lookup('service:store'); + store.push({ + data: { + id: '123abc', + type: 'target', + attributes: { + name: 'Target', + description: 'Description', + host_sets: [ + { host_set_id: '1', host_catalog_id: '2' }, + { host_set_id: '3', host_catalog_id: '4' } + ], + version: 1, + scope: { + scope_id: 'o_1', + type: 'scope' + } + } + } + }); + const model = store.peekRecord('target', '123abc'); + await model.addHostSets([{id: '123_abc'}, {id: 'foobar'}]); + }); + + test('it has a `deleteHostSets` method that targets a specific POST API endpoint and serialization', async function (assert) { + assert.expect(1); + this.server.post('/v1/scopes/o_1/targets/123abc:delete-host-sets', (schema, request) => { const body = JSON.parse(request.requestBody); assert.deepEqual(body, { host_set_ids: ['1', '3'], @@ -87,6 +120,6 @@ module('Unit | Model | target', function (hooks) { } }); const model = store.peekRecord('target', '123abc'); - await model.saveHostSets(); + await model.deleteHostSets([{id: '1'}, {id: '3'}]); }); }); diff --git a/addons/api/tests/unit/serializers/target-test.js b/addons/api/tests/unit/serializers/target-test.js index a3ca9bd69..a38737ac9 100644 --- a/addons/api/tests/unit/serializers/target-test.js +++ b/addons/api/tests/unit/serializers/target-test.js @@ -29,7 +29,7 @@ module('Unit | Serializer | target', function(hooks) { }); - test('it serializes only host sets when `adapterOptions.serializeHostSets` is true', function (assert) { + test('it serializes only host sets and version when an `adapterOptions.hostSets` array is passed', function (assert) { assert.expect(1); const store = this.owner.lookup('service:store'); const serializer = store.serializerFor('target'); @@ -44,11 +44,11 @@ module('Unit | Serializer | target', function(hooks) { }); const snapshot = record._createSnapshot(); snapshot.adapterOptions = { - serializeHostSets: true + hostSets: [{id: '4'}, {id: '5'}] }; const serializedRecord = serializer.serialize(snapshot); assert.deepEqual(serializedRecord, { - host_set_ids: ['1', '3'], + host_set_ids: ['4', '5'], version: 1 }); }); diff --git a/ui/core/mirage/config.js b/ui/core/mirage/config.js index 68ef3f031..8a3e0fdc1 100644 --- a/ui/core/mirage/config.js +++ b/ui/core/mirage/config.js @@ -130,25 +130,31 @@ export default function() { this.get('/scopes/:scope_id/targets/:id'); this.patch('/scopes/:scope_id/targets/:id'); this.del('/scopes/:scope_id/targets/:id'); - - // host-set in a target - this.get('/scopes/:scope_id/targets/:targetId/host-sets', function ({ hostSets }, { params: { targetId } }) { - return hostSets.where({ targetId }); - }); - this.post('/scopes/:scope_id/targets/:targetId/host-sets', function ({ hostSets }, { params: { targetId } }) { - const attrs = this.normalizedRequestAttrs(); - attrs.targetId = targetId; - return hostSets.create(attrs); - }); - this.get('/scopes/:scope_id/targets/:targetId/host-sets/:id'); - this.patch('/scopes/:scope_id/targets/:targetId/host-sets/:id'); - this.del('/scopes/:scope_id/targets/:targetId/host-sets/:id'); - this.post('/scopes/:scope_id/targets/:targetId/host-sets/:idMethod', function ({ hostSets }, { params: { idMethod } }) { + this.post('/scopes/:scope_id/targets/:idMethod', function ({ targets }, { params: { idMethod } }) { const attrs = this.normalizedRequestAttrs(); const id = idMethod.split(':')[0]; - const hostSet = hostSets.find(id); - attrs.id = id; - return hostSet.update(attrs); + const method = idMethod.split(':')[1]; + const target = targets.find(id); + const updatedAttrs = { + version: attrs.version, + hostSetIds: target.hostSetIds + }; + // If adding host sets, push them into the array + if (method === 'add-host-sets') { + attrs.hostSetIds.forEach(id => { + if (!updatedAttrs.hostSetIds.includes(id)) { + updatedAttrs.hostSetIds.push(id); + } + }); + } + // If deleting host sets, filter them out of the array + if (method === 'delete-host-sets') { + console.log(method, attrs); + updatedAttrs.hostSetIds = updatedAttrs.hostSetIds.filter(id => { + return !attrs.hostSetIds.includes(id); + }); + } + return target.update(updatedAttrs); }); // Uncomment the following line and the Response import above