mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +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;
|
teamId;
|
||||||
|
|
||||||
// comma separated string, updated as array using deploymentEnvironmentsArray
|
// commaString transforms param from the server's array type
|
||||||
@attr({
|
// to a comma string so changedAttributes() will track changes
|
||||||
|
@attr('commaString', {
|
||||||
subText: 'Deployment environments where the environment variables are available.',
|
subText: 'Deployment environments where the environment variables are available.',
|
||||||
editType: 'checkboxList',
|
editType: 'checkboxList',
|
||||||
possibleValues: ['development', 'preview', 'production'],
|
possibleValues: ['development', 'preview', 'production'],
|
||||||
@@ -56,9 +57,8 @@ export default class SyncDestinationsVercelProjectModel extends SyncDestinationM
|
|||||||
})
|
})
|
||||||
deploymentEnvironments;
|
deploymentEnvironments;
|
||||||
|
|
||||||
// Instead of using the 'array' attr transform, we keep deploymentEnvironments a string to leverage Ember's changedAttributes()
|
// Arrays are easier for managing multi-option selection
|
||||||
// which only tracks updates to string types. However, arrays are easier for managing multi-option selection so
|
// these get/set the deploymentEnvironments attribute via arrays
|
||||||
// the fieldValue is used to get/set the deploymentEnvironments attribute to/from an array
|
|
||||||
get deploymentEnvironmentsArray() {
|
get deploymentEnvironmentsArray() {
|
||||||
// if undefined or an empty string, return empty array
|
// if undefined or an empty string, return empty array
|
||||||
return !this.deploymentEnvironments ? [] : this.deploymentEnvironments.split(',');
|
return !this.deploymentEnvironments ? [] : this.deploymentEnvironments.split(',');
|
||||||
|
|||||||
@@ -12,17 +12,15 @@ export default class SyncDestinationSerializer extends ApplicationSerializer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
serialize(snapshot) {
|
serialize(snapshot) {
|
||||||
// special serialization only for PATCH requests
|
const data = super.serialize(snapshot);
|
||||||
if (snapshot.isNew) return super.serialize(snapshot);
|
if (snapshot.isNew) return data;
|
||||||
|
|
||||||
// only send changed values
|
// only send changed parameters for PATCH requests
|
||||||
const data = {};
|
const changedKeys = Object.keys(snapshot.changedAttributes()).map((key) => decamelize(key));
|
||||||
for (const attr in snapshot.changedAttributes()) {
|
return changedKeys.reduce((payload, key) => {
|
||||||
// first array element is the old value
|
payload[key] = data[key];
|
||||||
const [, newValue] = snapshot.changedAttributes()[attr];
|
return payload;
|
||||||
data[decamelize(attr)] = newValue;
|
}, {});
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupt application's normalizeItems, which is called in normalizeResponse by application serializer
|
// 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: '*****',
|
access_token: '*****',
|
||||||
project_id: 'prj_12345',
|
project_id: 'prj_12345',
|
||||||
team_id: 'team_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'],
|
gh: ['accessToken'],
|
||||||
'vercel-project': ['accessToken', 'teamId', 'deploymentEnvironments'],
|
'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) {
|
for (const destination of SYNC_DESTINATIONS) {
|
||||||
const { type, maskedParams } = destination;
|
const { type, maskedParams } = destination;
|
||||||
module(`edit destination: ${type}`, function (hooks) {
|
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));
|
const expectedKeys = editable.map((k) => decamelize(k));
|
||||||
assert.propEqual(payloadKeys, expectedKeys, `${type} payload only contains editable attrs`);
|
assert.propEqual(payloadKeys, expectedKeys, `${type} payload only contains editable attrs`);
|
||||||
expectedKeys.forEach((key) => {
|
expectedKeys.forEach((key) => {
|
||||||
// deploymentEnvironment field fixed possible options
|
assert.deepEqual(payload[key], EXPECTED_VALUE(key), `destination: ${type} updates key: ${key}`);
|
||||||
const expectedValue = key === 'deployment_environments' ? 'production' : `new-${key}-value`;
|
|
||||||
assert.strictEqual(payload[key], expectedValue, `destination: ${type} updates key: ${key}`);
|
|
||||||
});
|
});
|
||||||
return { payload };
|
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