mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 17:52:32 +00:00
Secrets Sync UI: Refactor vercel-project destination to expect array from server (#24628)
* fix vercel project to expect array from server * add test * use reduce function!
This commit is contained in:
@@ -47,8 +47,9 @@ export default class SyncDestinationsVercelProjectModel extends SyncDestinationM
|
||||
})
|
||||
teamId;
|
||||
|
||||
// comma separated string, updated as array using deploymentEnvironmentsArray
|
||||
@attr({
|
||||
// commaString transforms param from the server's array type
|
||||
// to a comma string so changedAttributes() will track changes
|
||||
@attr('commaString', {
|
||||
subText: 'Deployment environments where the environment variables are available.',
|
||||
editType: 'checkboxList',
|
||||
possibleValues: ['development', 'preview', 'production'],
|
||||
@@ -56,9 +57,8 @@ export default class SyncDestinationsVercelProjectModel extends SyncDestinationM
|
||||
})
|
||||
deploymentEnvironments;
|
||||
|
||||
// Instead of using the 'array' attr transform, we keep deploymentEnvironments a string to leverage Ember's changedAttributes()
|
||||
// which only tracks updates to string types. However, arrays are easier for managing multi-option selection so
|
||||
// the fieldValue is used to get/set the deploymentEnvironments attribute to/from an array
|
||||
// Arrays are easier for managing multi-option selection
|
||||
// these get/set the deploymentEnvironments attribute via arrays
|
||||
get deploymentEnvironmentsArray() {
|
||||
// if undefined or an empty string, return empty array
|
||||
return !this.deploymentEnvironments ? [] : this.deploymentEnvironments.split(',');
|
||||
|
||||
@@ -12,17 +12,15 @@ export default class SyncDestinationSerializer extends ApplicationSerializer {
|
||||
};
|
||||
|
||||
serialize(snapshot) {
|
||||
// special serialization only for PATCH requests
|
||||
if (snapshot.isNew) return super.serialize(snapshot);
|
||||
const data = super.serialize(snapshot);
|
||||
if (snapshot.isNew) return data;
|
||||
|
||||
// only send changed values
|
||||
const data = {};
|
||||
for (const attr in snapshot.changedAttributes()) {
|
||||
// first array element is the old value
|
||||
const [, newValue] = snapshot.changedAttributes()[attr];
|
||||
data[decamelize(attr)] = newValue;
|
||||
}
|
||||
return data;
|
||||
// only send changed parameters for PATCH requests
|
||||
const changedKeys = Object.keys(snapshot.changedAttributes()).map((key) => decamelize(key));
|
||||
return changedKeys.reduce((payload, key) => {
|
||||
payload[key] = data[key];
|
||||
return payload;
|
||||
}, {});
|
||||
}
|
||||
|
||||
// interrupt application's normalizeItems, which is called in normalizeResponse by application serializer
|
||||
|
||||
27
ui/app/transforms/comma-string.js
Normal file
27
ui/app/transforms/comma-string.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Transform from '@ember-data/serializer/transform';
|
||||
|
||||
/**
|
||||
* transforms array types from the server to a comma separated string
|
||||
* useful when using changedAttributes() in the serializer to track attribute changes for PATCH requests
|
||||
* because arrays are not trackable and strings are!
|
||||
*/
|
||||
export default class CommaString extends Transform {
|
||||
deserialize(serialized) {
|
||||
if (Array.isArray(serialized)) {
|
||||
return serialized.join(',');
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
serialize(deserialized) {
|
||||
if (typeof deserialized === 'string') {
|
||||
return deserialized.split(',');
|
||||
}
|
||||
return deserialized;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,6 @@ export default Factory.extend({
|
||||
access_token: '*****',
|
||||
project_id: 'prj_12345',
|
||||
team_id: 'team_12345',
|
||||
deployment_environments: 'development,preview', // 'production' is also an option, but left out for testing to assert form changes value
|
||||
deployment_environments: ['development', 'preview'], // 'production' is also an option, but left out for testing to assert form changes value
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -212,6 +212,16 @@ module('Integration | Component | sync | Secrets::Page::Destinations::CreateAndE
|
||||
gh: ['accessToken'],
|
||||
'vercel-project': ['accessToken', 'teamId', 'deploymentEnvironments'],
|
||||
};
|
||||
const EXPECTED_VALUE = (key) => {
|
||||
switch (key) {
|
||||
case 'deployment_environments':
|
||||
return ['production'];
|
||||
default:
|
||||
// for all string type parameters
|
||||
return `new-${key}-value`;
|
||||
}
|
||||
};
|
||||
|
||||
for (const destination of SYNC_DESTINATIONS) {
|
||||
const { type, maskedParams } = destination;
|
||||
module(`edit destination: ${type}`, function (hooks) {
|
||||
@@ -237,9 +247,7 @@ module('Integration | Component | sync | Secrets::Page::Destinations::CreateAndE
|
||||
const expectedKeys = editable.map((k) => decamelize(k));
|
||||
assert.propEqual(payloadKeys, expectedKeys, `${type} payload only contains editable attrs`);
|
||||
expectedKeys.forEach((key) => {
|
||||
// deploymentEnvironment field fixed possible options
|
||||
const expectedValue = key === 'deployment_environments' ? 'production' : `new-${key}-value`;
|
||||
assert.strictEqual(payload[key], expectedValue, `destination: ${type} updates key: ${key}`);
|
||||
assert.deepEqual(payload[key], EXPECTED_VALUE(key), `destination: ${type} updates key: ${key}`);
|
||||
});
|
||||
return { payload };
|
||||
});
|
||||
|
||||
40
ui/tests/unit/transforms/comma-string-test.js
Normal file
40
ui/tests/unit/transforms/comma-string-test.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'vault/tests/helpers';
|
||||
|
||||
module('Unit | Transform | comma string', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.transform = this.owner.lookup('transform:comma-string');
|
||||
});
|
||||
|
||||
test('it serializes correctly for API', function (assert) {
|
||||
const serialized = this.transform.serialize('one,two,three');
|
||||
assert.propEqual(serialized, ['one', 'two', 'three'], 'it serializes from string to array');
|
||||
assert.propEqual(
|
||||
this.transform.serialize(['not a string']),
|
||||
['not a string'],
|
||||
'it returns original value if not a string'
|
||||
);
|
||||
assert.propEqual(
|
||||
this.transform.serialize('no commas'),
|
||||
['no commas'],
|
||||
'it splits a string without commas'
|
||||
);
|
||||
});
|
||||
|
||||
test('it deserializes correctly from API', function (assert) {
|
||||
const deserialized = this.transform.deserialize(['one', 'two', 'three']);
|
||||
assert.strictEqual(deserialized, 'one,two,three', 'it deserializes from array to string');
|
||||
assert.strictEqual(
|
||||
this.transform.deserialize('not an array'),
|
||||
'not an array',
|
||||
'it returns original value if not an array'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user