Commit de111aa6 authored by Eric Eastwood's avatar Eric Eastwood

Update secret_values to support dynamic elements within parent

Used in https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4110
which introduces a dynamic variable list and needs secrets.

We use the valueSelector/placeholderSelector options to avoid selecting
the last empty row.
parent ae5fd31f
...@@ -2,18 +2,19 @@ import { n__ } from '../locale'; ...@@ -2,18 +2,19 @@ import { n__ } from '../locale';
import { convertPermissionToBoolean } from '../lib/utils/common_utils'; import { convertPermissionToBoolean } from '../lib/utils/common_utils';
export default class SecretValues { export default class SecretValues {
constructor(container) { constructor({
container,
valueSelector = '.js-secret-value',
placeholderSelector = '.js-secret-value-placeholder',
}) {
this.container = container; this.container = container;
this.valueSelector = valueSelector;
this.placeholderSelector = placeholderSelector;
} }
init() { init() {
this.values = this.container.querySelectorAll('.js-secret-value');
this.placeholders = this.container.querySelectorAll('.js-secret-value-placeholder');
this.revealButton = this.container.querySelector('.js-secret-value-reveal-button'); this.revealButton = this.container.querySelector('.js-secret-value-reveal-button');
this.revealText = n__('Reveal value', 'Reveal values', this.values.length);
this.hideText = n__('Hide value', 'Hide values', this.values.length);
const isRevealed = convertPermissionToBoolean(this.revealButton.dataset.secretRevealStatus); const isRevealed = convertPermissionToBoolean(this.revealButton.dataset.secretRevealStatus);
this.updateDom(isRevealed); this.updateDom(isRevealed);
...@@ -28,15 +29,17 @@ export default class SecretValues { ...@@ -28,15 +29,17 @@ export default class SecretValues {
} }
updateDom(isRevealed) { updateDom(isRevealed) {
this.values.forEach((value) => { const values = this.container.querySelectorAll(this.valueSelector);
values.forEach((value) => {
value.classList.toggle('hide', !isRevealed); value.classList.toggle('hide', !isRevealed);
}); });
this.placeholders.forEach((placeholder) => { const placeholders = this.container.querySelectorAll(this.placeholderSelector);
placeholders.forEach((placeholder) => {
placeholder.classList.toggle('hide', isRevealed); placeholder.classList.toggle('hide', isRevealed);
}); });
this.revealButton.textContent = isRevealed ? this.hideText : this.revealText; this.revealButton.textContent = isRevealed ? n__('Hide value', 'Hide values', values.length) : n__('Reveal value', 'Reveal values', values.length);
this.revealButton.dataset.secretRevealStatus = isRevealed; this.revealButton.dataset.secretRevealStatus = isRevealed;
} }
} }
...@@ -3,7 +3,9 @@ import SecretValues from '~/behaviors/secret_values'; ...@@ -3,7 +3,9 @@ import SecretValues from '~/behaviors/secret_values';
export default () => { export default () => {
const secretVariableTable = document.querySelector('.js-secret-variable-table'); const secretVariableTable = document.querySelector('.js-secret-variable-table');
if (secretVariableTable) { if (secretVariableTable) {
const secretVariableTableValues = new SecretValues(secretVariableTable); const secretVariableTableValues = new SecretValues({
container: secretVariableTable,
});
secretVariableTableValues.init(); secretVariableTableValues.init();
} }
}; };
...@@ -6,13 +6,17 @@ export default function () { ...@@ -6,13 +6,17 @@ export default function () {
initSettingsPanels(); initSettingsPanels();
const runnerToken = document.querySelector('.js-secret-runner-token'); const runnerToken = document.querySelector('.js-secret-runner-token');
if (runnerToken) { if (runnerToken) {
const runnerTokenSecretValue = new SecretValues(runnerToken); const runnerTokenSecretValue = new SecretValues({
container: runnerToken,
});
runnerTokenSecretValue.init(); runnerTokenSecretValue.init();
} }
const secretVariableTable = document.querySelector('.js-secret-variable-table'); const secretVariableTable = document.querySelector('.js-secret-variable-table');
if (secretVariableTable) { if (secretVariableTable) {
const secretVariableTableValues = new SecretValues(secretVariableTable); const secretVariableTableValues = new SecretValues({
container: secretVariableTable,
});
secretVariableTableValues.init(); secretVariableTableValues.init();
} }
} }
import SecretValues from '~/behaviors/secret_values'; import SecretValues from '~/behaviors/secret_values';
function generateFixtureMarkup(secrets, isRevealed) { function generateValueMarkup(
secret,
valueClass = 'js-secret-value',
placeholderClass = 'js-secret-value-placeholder',
) {
return ` return `
<div class="js-secret-container"> <div class="${placeholderClass}">
${secrets.map(secret => `
<div class="js-secret-value-placeholder">
*** ***
</div> </div>
<div class="hide js-secret-value"> <div class="hide ${valueClass}">
${secret} ${secret}
</div> </div>
`).join('')} `;
}
function generateFixtureMarkup(secrets, isRevealed, valueClass, placeholderClass) {
return `
<div class="js-secret-container">
${secrets.map(secret => generateValueMarkup(secret, valueClass, placeholderClass)).join('')}
<button <button
class="js-secret-value-reveal-button" class="js-secret-value-reveal-button"
data-secret-reveal-status="${isRevealed}" data-secret-reveal-status="${isRevealed}"
...@@ -21,11 +29,25 @@ function generateFixtureMarkup(secrets, isRevealed) { ...@@ -21,11 +29,25 @@ function generateFixtureMarkup(secrets, isRevealed) {
`; `;
} }
function setupSecretFixture(secrets, isRevealed) { function setupSecretFixture(
secrets,
isRevealed,
valueClass = 'js-secret-value',
placeholderClass = 'js-secret-value-placeholder',
) {
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
wrapper.innerHTML = generateFixtureMarkup(secrets, isRevealed); wrapper.innerHTML = generateFixtureMarkup(
secrets,
const secretValues = new SecretValues(wrapper.querySelector('.js-secret-container')); isRevealed,
valueClass,
placeholderClass,
);
const secretValues = new SecretValues({
container: wrapper.querySelector('.js-secret-container'),
valueSelector: `.${valueClass}`,
placeholderSelector: `.${placeholderClass}`,
});
secretValues.init(); secretValues.init();
return wrapper; return wrapper;
...@@ -49,7 +71,7 @@ describe('setupSecretValues', () => { ...@@ -49,7 +71,7 @@ describe('setupSecretValues', () => {
expect(revealButton.textContent).toEqual('Hide value'); expect(revealButton.textContent).toEqual('Hide value');
}); });
it('should value hidden initially', () => { it('should have value hidden initially', () => {
const wrapper = setupSecretFixture(secrets, false); const wrapper = setupSecretFixture(secrets, false);
const values = wrapper.querySelectorAll('.js-secret-value'); const values = wrapper.querySelectorAll('.js-secret-value');
const placeholders = wrapper.querySelectorAll('.js-secret-value-placeholder'); const placeholders = wrapper.querySelectorAll('.js-secret-value-placeholder');
...@@ -143,4 +165,64 @@ describe('setupSecretValues', () => { ...@@ -143,4 +165,64 @@ describe('setupSecretValues', () => {
}); });
}); });
}); });
describe('with dynamic secrets', () => {
const secrets = ['mysecret123', 'happygoat456', 'tanuki789'];
it('should toggle values and placeholders', () => {
const wrapper = setupSecretFixture(secrets, false);
// Insert the new dynamic row
wrapper.querySelector('.js-secret-container').insertAdjacentHTML('afterbegin', generateValueMarkup('foobarbazdynamic'));
const revealButton = wrapper.querySelector('.js-secret-value-reveal-button');
const values = wrapper.querySelectorAll('.js-secret-value');
const placeholders = wrapper.querySelectorAll('.js-secret-value-placeholder');
revealButton.click();
expect(values.length).toEqual(4);
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(false);
});
expect(placeholders.length).toEqual(4);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(true);
});
revealButton.click();
expect(values.length).toEqual(4);
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(4);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
});
describe('selector options', () => {
const secrets = ['mysecret123'];
it('should respect `valueSelector` and `placeholderSelector` options', () => {
const valueClass = 'js-some-custom-placeholder-selector';
const placeholderClass = 'js-some-custom-value-selector';
const wrapper = setupSecretFixture(secrets, false, valueClass, placeholderClass);
const values = wrapper.querySelectorAll(`.${valueClass}`);
const placeholders = wrapper.querySelectorAll(`.${placeholderClass}`);
const revealButton = wrapper.querySelector('.js-secret-value-reveal-button');
expect(values.length).toEqual(1);
expect(placeholders.length).toEqual(1);
revealButton.click();
expect(values.length).toEqual(1);
expect(values[0].classList.contains('hide')).toEqual(false);
expect(placeholders.length).toEqual(1);
expect(placeholders[0].classList.contains('hide')).toEqual(true);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment