Merge branch 'generalize-js-toggle-buttons' into 'master'
Generalize toggle_buttons for JavaScript usage See merge request gitlab-org/gitlab-ce!16689
This commit is contained in:
commit
dc325c672e
|
@ -14,6 +14,7 @@ import {
|
||||||
import ClustersService from './services/clusters_service';
|
import ClustersService from './services/clusters_service';
|
||||||
import ClustersStore from './stores/clusters_store';
|
import ClustersStore from './stores/clusters_store';
|
||||||
import applications from './components/applications.vue';
|
import applications from './components/applications.vue';
|
||||||
|
import setupToggleButtons from '../toggle_buttons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cluster page has 2 separate parts:
|
* Cluster page has 2 separate parts:
|
||||||
|
@ -48,12 +49,9 @@ export default class Clusters {
|
||||||
installPrometheusEndpoint: installPrometheusPath,
|
installPrometheusEndpoint: installPrometheusPath,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.toggle = this.toggle.bind(this);
|
|
||||||
this.installApplication = this.installApplication.bind(this);
|
this.installApplication = this.installApplication.bind(this);
|
||||||
this.showToken = this.showToken.bind(this);
|
this.showToken = this.showToken.bind(this);
|
||||||
|
|
||||||
this.toggleButton = document.querySelector('.js-toggle-cluster');
|
|
||||||
this.toggleInput = document.querySelector('.js-toggle-input');
|
|
||||||
this.errorContainer = document.querySelector('.js-cluster-error');
|
this.errorContainer = document.querySelector('.js-cluster-error');
|
||||||
this.successContainer = document.querySelector('.js-cluster-success');
|
this.successContainer = document.querySelector('.js-cluster-success');
|
||||||
this.creatingContainer = document.querySelector('.js-cluster-creating');
|
this.creatingContainer = document.querySelector('.js-cluster-creating');
|
||||||
|
@ -63,6 +61,7 @@ export default class Clusters {
|
||||||
this.tokenField = document.querySelector('.js-cluster-token');
|
this.tokenField = document.querySelector('.js-cluster-token');
|
||||||
|
|
||||||
initSettingsPanels();
|
initSettingsPanels();
|
||||||
|
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
|
||||||
this.initApplications();
|
this.initApplications();
|
||||||
|
|
||||||
if (this.store.state.status !== 'created') {
|
if (this.store.state.status !== 'created') {
|
||||||
|
@ -101,13 +100,11 @@ export default class Clusters {
|
||||||
}
|
}
|
||||||
|
|
||||||
addListeners() {
|
addListeners() {
|
||||||
this.toggleButton.addEventListener('click', this.toggle);
|
|
||||||
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
|
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
|
||||||
eventHub.$on('installApplication', this.installApplication);
|
eventHub.$on('installApplication', this.installApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeListeners() {
|
removeListeners() {
|
||||||
this.toggleButton.removeEventListener('click', this.toggle);
|
|
||||||
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
|
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
|
||||||
eventHub.$off('installApplication', this.installApplication);
|
eventHub.$off('installApplication', this.installApplication);
|
||||||
}
|
}
|
||||||
|
@ -151,11 +148,6 @@ export default class Clusters {
|
||||||
this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason);
|
this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
|
||||||
this.toggleButton.classList.toggle('is-checked');
|
|
||||||
this.toggleInput.setAttribute('value', this.toggleButton.classList.contains('is-checked').toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
showToken() {
|
showToken() {
|
||||||
const type = this.tokenField.getAttribute('type');
|
const type = this.tokenField.getAttribute('type');
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,20 @@
|
||||||
import Flash from '../flash';
|
import Flash from '../flash';
|
||||||
import { s__ } from '../locale';
|
import { s__ } from '../locale';
|
||||||
|
import setupToggleButtons from '../toggle_buttons';
|
||||||
import ClustersService from './services/clusters_service';
|
import ClustersService from './services/clusters_service';
|
||||||
/**
|
|
||||||
* Toggles loading and disabled classes.
|
export default () => {
|
||||||
* @param {HTMLElement} button
|
const clusterList = document.querySelector('.js-clusters-list');
|
||||||
*/
|
// The empty state won't have a clusterList
|
||||||
const toggleLoadingButton = (button) => {
|
if (clusterList) {
|
||||||
if (button.getAttribute('disabled')) {
|
setupToggleButtons(
|
||||||
button.removeAttribute('disabled');
|
document.querySelector('.js-clusters-list'),
|
||||||
} else {
|
(value, toggle) =>
|
||||||
button.setAttribute('disabled', true);
|
ClustersService.updateCluster(toggle.dataset.endpoint, { cluster: { enabled: value } })
|
||||||
|
.catch((err) => {
|
||||||
|
Flash(s__('ClusterIntegration|Something went wrong on our end.'));
|
||||||
|
throw err;
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.classList.toggle('is-loading');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles checked class for the given button
|
|
||||||
* @param {HTMLElement} button
|
|
||||||
*/
|
|
||||||
const toggleValue = (button) => {
|
|
||||||
button.classList.toggle('is-checked');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles toggle buttons in the cluster's table.
|
|
||||||
*
|
|
||||||
* When the user clicks the toggle button for each cluster, it:
|
|
||||||
* - toggles the button
|
|
||||||
* - shows a loading and disables button
|
|
||||||
* - Makes a put request to the given endpoint
|
|
||||||
* Once we receive the response, either:
|
|
||||||
* 1) Show updated status in case of successfull response
|
|
||||||
* 2) Show initial status in case of failed response
|
|
||||||
*/
|
|
||||||
export default function setClusterTableToggles() {
|
|
||||||
document.querySelectorAll('.js-toggle-cluster-list')
|
|
||||||
.forEach(button => button.addEventListener('click', (e) => {
|
|
||||||
const toggleButton = e.currentTarget;
|
|
||||||
const endpoint = toggleButton.getAttribute('data-endpoint');
|
|
||||||
|
|
||||||
toggleValue(toggleButton);
|
|
||||||
toggleLoadingButton(toggleButton);
|
|
||||||
|
|
||||||
const value = toggleButton.classList.contains('is-checked');
|
|
||||||
|
|
||||||
ClustersService.updateCluster(endpoint, { cluster: { enabled: value } })
|
|
||||||
.then(() => {
|
|
||||||
toggleLoadingButton(toggleButton);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
toggleLoadingButton(toggleButton);
|
|
||||||
toggleValue(toggleButton);
|
|
||||||
Flash(s__('ClusterIntegration|Something went wrong on our end.'));
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import $ from 'jquery';
|
||||||
|
import Flash from './flash';
|
||||||
|
import { __ } from './locale';
|
||||||
|
import { convertPermissionToBoolean } from './lib/utils/common_utils';
|
||||||
|
|
||||||
|
/*
|
||||||
|
example HAML:
|
||||||
|
```
|
||||||
|
%button.js-project-feature-toggle.project-feature-toggle{ type: "button",
|
||||||
|
class: "#{'is-checked' if enabled?}",
|
||||||
|
'aria-label': _('Toggle Cluster') }
|
||||||
|
%input{ type: "hidden", class: 'js-project-feature-toggle-input', value: enabled? }
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
|
||||||
|
function updatetoggle(toggle, isOn) {
|
||||||
|
toggle.classList.toggle('is-checked', isOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onToggleClicked(toggle, input, clickCallback) {
|
||||||
|
const previousIsOn = convertPermissionToBoolean(input.value);
|
||||||
|
|
||||||
|
// Visually change the toggle and start loading
|
||||||
|
updatetoggle(toggle, !previousIsOn);
|
||||||
|
toggle.setAttribute('disabled', true);
|
||||||
|
toggle.classList.toggle('is-loading', true);
|
||||||
|
|
||||||
|
Promise.resolve(clickCallback(!previousIsOn, toggle))
|
||||||
|
.then(() => {
|
||||||
|
// Actually change the input value
|
||||||
|
input.setAttribute('value', !previousIsOn);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// Revert the visuals if something goes wrong
|
||||||
|
updatetoggle(toggle, previousIsOn);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Remove the loading indicator in any case
|
||||||
|
toggle.removeAttribute('disabled');
|
||||||
|
toggle.classList.toggle('is-loading', false);
|
||||||
|
|
||||||
|
$(input).trigger('trigger-change');
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Flash(__('Something went wrong when toggling the button'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function setupToggleButtons(container, clickCallback = () => {}) {
|
||||||
|
const toggles = container.querySelectorAll('.js-project-feature-toggle');
|
||||||
|
|
||||||
|
toggles.forEach((toggle) => {
|
||||||
|
const input = toggle.querySelector('.js-project-feature-toggle-input');
|
||||||
|
const isOn = convertPermissionToBoolean(input.value);
|
||||||
|
|
||||||
|
// Get the visible toggle in sync with the hidden input
|
||||||
|
updatetoggle(toggle, isOn);
|
||||||
|
|
||||||
|
toggle.addEventListener('click', onToggleClicked.bind(null, toggle, input, clickCallback));
|
||||||
|
});
|
||||||
|
}
|
|
@ -12,11 +12,12 @@
|
||||||
.table-section.section-10
|
.table-section.section-10
|
||||||
.table-mobile-header{ role: "rowheader" }
|
.table-mobile-header{ role: "rowheader" }
|
||||||
.table-mobile-content
|
.table-mobile-content
|
||||||
%button{ type: "button",
|
%button.js-project-feature-toggle.project-feature-toggle{ type: "button",
|
||||||
class: "js-toggle-cluster-list project-feature-toggle #{'is-checked' if cluster.enabled?} #{'is-disabled' if !cluster.can_toggle_cluster?}",
|
class: "#{'is-checked' if cluster.enabled?} #{'is-disabled' if !cluster.can_toggle_cluster?}",
|
||||||
"aria-label": s_("ClusterIntegration|Toggle Cluster"),
|
"aria-label": s_("ClusterIntegration|Toggle Cluster"),
|
||||||
disabled: !cluster.can_toggle_cluster?,
|
disabled: !cluster.can_toggle_cluster?,
|
||||||
data: { endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
|
data: { endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
|
||||||
|
%input.js-project-feature-toggle-input{ type: "hidden", value: cluster.enabled? }
|
||||||
= icon("spinner spin", class: "loading-icon")
|
= icon("spinner spin", class: "loading-icon")
|
||||||
%span.toggle-icon
|
%span.toggle-icon
|
||||||
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
|
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
|
||||||
|
|
|
@ -10,13 +10,12 @@
|
||||||
= s_('ClusterIntegration|Cluster integration is enabled for this project.')
|
= s_('ClusterIntegration|Cluster integration is enabled for this project.')
|
||||||
- else
|
- else
|
||||||
= s_('ClusterIntegration|Cluster integration is disabled for this project.')
|
= s_('ClusterIntegration|Cluster integration is disabled for this project.')
|
||||||
%label.append-bottom-10
|
%label.append-bottom-10.js-cluster-enable-toggle-area
|
||||||
= field.hidden_field :enabled, { class: 'js-toggle-input'}
|
|
||||||
|
|
||||||
%button{ type: 'button',
|
%button{ type: 'button',
|
||||||
class: "js-toggle-cluster project-feature-toggle #{'is-checked' unless !@cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
|
class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if @cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
|
||||||
"aria-label": s_("ClusterIntegration|Toggle Cluster"),
|
"aria-label": s_("ClusterIntegration|Toggle Cluster"),
|
||||||
disabled: !can?(current_user, :update_cluster, @cluster) }
|
disabled: !can?(current_user, :update_cluster, @cluster) }
|
||||||
|
= field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
|
||||||
%span.toggle-icon
|
%span.toggle-icon
|
||||||
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
|
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
|
||||||
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
|
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
|
||||||
|
|
|
@ -95,7 +95,7 @@ feature 'Gcp Cluster', :js do
|
||||||
|
|
||||||
context 'when user disables the cluster' do
|
context 'when user disables the cluster' do
|
||||||
before do
|
before do
|
||||||
page.find(:css, '.js-toggle-cluster').click
|
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
||||||
page.within('#cluster-integration') { click_button 'Save changes' }
|
page.within('#cluster-integration') { click_button 'Save changes' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ feature 'User Cluster', :js do
|
||||||
|
|
||||||
context 'when user disables the cluster' do
|
context 'when user disables the cluster' do
|
||||||
before do
|
before do
|
||||||
page.find(:css, '.js-toggle-cluster').click
|
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
||||||
fill_in 'cluster_name', with: 'dev-cluster'
|
fill_in 'cluster_name', with: 'dev-cluster'
|
||||||
page.within('#cluster-integration') { click_button 'Save changes' }
|
page.within('#cluster-integration') { click_button 'Save changes' }
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,13 +37,13 @@ feature 'Clusters', :js do
|
||||||
|
|
||||||
context 'inline update of cluster' do
|
context 'inline update of cluster' do
|
||||||
it 'user can update cluster' do
|
it 'user can update cluster' do
|
||||||
expect(page).to have_selector('.js-toggle-cluster-list')
|
expect(page).to have_selector('.js-project-feature-toggle')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with sucessfull request' do
|
context 'with sucessfull request' do
|
||||||
it 'user sees updated cluster' do
|
it 'user sees updated cluster' do
|
||||||
expect do
|
expect do
|
||||||
page.find('.js-toggle-cluster-list').click
|
page.find('.js-project-feature-toggle').click
|
||||||
wait_for_requests
|
wait_for_requests
|
||||||
end.to change { cluster.reload.enabled }
|
end.to change { cluster.reload.enabled }
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ feature 'Clusters', :js do
|
||||||
expect_any_instance_of(Clusters::UpdateService).to receive(:execute).and_call_original
|
expect_any_instance_of(Clusters::UpdateService).to receive(:execute).and_call_original
|
||||||
allow_any_instance_of(Clusters::Cluster).to receive(:valid?) { false }
|
allow_any_instance_of(Clusters::Cluster).to receive(:valid?) { false }
|
||||||
|
|
||||||
page.find('.js-toggle-cluster-list').click
|
page.find('.js-project-feature-toggle').click
|
||||||
|
|
||||||
expect(page).to have_content('Something went wrong on our end.')
|
expect(page).to have_content('Something went wrong on our end.')
|
||||||
expect(page).to have_selector('.is-checked')
|
expect(page).to have_selector('.is-checked')
|
||||||
|
|
|
@ -23,16 +23,24 @@ describe('Clusters', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toggle', () => {
|
describe('toggle', () => {
|
||||||
it('should update the button and the input field on click', () => {
|
it('should update the button and the input field on click', (done) => {
|
||||||
cluster.toggleButton.click();
|
const toggleButton = document.querySelector('.js-cluster-enable-toggle-area .js-project-feature-toggle');
|
||||||
|
const toggleInput = document.querySelector('.js-cluster-enable-toggle-area .js-project-feature-toggle-input');
|
||||||
|
|
||||||
expect(
|
toggleButton.click();
|
||||||
cluster.toggleButton.classList,
|
|
||||||
).not.toContain('is-checked');
|
|
||||||
|
|
||||||
expect(
|
getSetTimeoutPromise()
|
||||||
cluster.toggleInput.getAttribute('value'),
|
.then(() => {
|
||||||
).toEqual('false');
|
expect(
|
||||||
|
toggleButton.classList,
|
||||||
|
).not.toContain('is-checked');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
toggleInput.getAttribute('value'),
|
||||||
|
).toEqual('false');
|
||||||
|
})
|
||||||
|
.then(done)
|
||||||
|
.catch(done.fail);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import axios from '~/lib/utils/axios_utils';
|
|
||||||
import setClusterTableToggles from '~/clusters/clusters_index';
|
|
||||||
import { setTimeout } from 'core-js/library/web/timers';
|
|
||||||
|
|
||||||
describe('Clusters table', () => {
|
|
||||||
preloadFixtures('clusters/index_cluster.html.raw');
|
|
||||||
let mock;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
loadFixtures('clusters/index_cluster.html.raw');
|
|
||||||
mock = new MockAdapter(axios);
|
|
||||||
setClusterTableToggles();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('update cluster', () => {
|
|
||||||
it('renders loading state while request is made', () => {
|
|
||||||
const button = document.querySelector('.js-toggle-cluster-list');
|
|
||||||
|
|
||||||
button.click();
|
|
||||||
|
|
||||||
expect(button.classList).toContain('is-loading');
|
|
||||||
expect(button.getAttribute('disabled')).toEqual('true');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
mock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows updated state after sucessfull request', (done) => {
|
|
||||||
mock.onPut().reply(200, {}, {});
|
|
||||||
const button = document.querySelector('.js-toggle-cluster-list');
|
|
||||||
button.click();
|
|
||||||
|
|
||||||
expect(button.classList).toContain('is-loading');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
expect(button.classList).not.toContain('is-loading');
|
|
||||||
expect(button.classList).not.toContain('is-checked');
|
|
||||||
done();
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows inital state after failed request', (done) => {
|
|
||||||
mock.onPut().reply(500, {}, {});
|
|
||||||
const button = document.querySelector('.js-toggle-cluster-list');
|
|
||||||
|
|
||||||
button.click();
|
|
||||||
expect(button.classList).toContain('is-loading');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
expect(button.classList).not.toContain('is-loading');
|
|
||||||
expect(button.classList).toContain('is-checked');
|
|
||||||
done();
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -31,19 +31,4 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
|
||||||
expect(response).to be_success
|
expect(response).to be_success
|
||||||
store_frontend_fixture(response, example.description)
|
store_frontend_fixture(response, example.description)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'rendering non-empty state' do
|
|
||||||
before do
|
|
||||||
cluster
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'clusters/index_cluster.html.raw' do |example|
|
|
||||||
get :index,
|
|
||||||
namespace_id: namespace,
|
|
||||||
project_id: project
|
|
||||||
|
|
||||||
expect(response).to be_success
|
|
||||||
store_frontend_fixture(response, example.description)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
import setupToggleButtons from '~/toggle_buttons';
|
||||||
|
import getSetTimeoutPromise from './helpers/set_timeout_promise_helper';
|
||||||
|
|
||||||
|
function generateMarkup(isChecked = true) {
|
||||||
|
return `
|
||||||
|
<button type="button" class="${isChecked ? 'is-checked' : ''} js-project-feature-toggle">
|
||||||
|
<input type="hidden" class="js-project-feature-toggle-input" value="${isChecked}" />
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupFixture(isChecked, clickCallback) {
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.innerHTML = generateMarkup(isChecked);
|
||||||
|
|
||||||
|
setupToggleButtons(wrapper, clickCallback);
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ToggleButtons', () => {
|
||||||
|
describe('when input value is true', () => {
|
||||||
|
it('should initialize as checked', () => {
|
||||||
|
const wrapper = setupFixture(true);
|
||||||
|
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked')).toEqual(true);
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle to unchecked when clicked', (done) => {
|
||||||
|
const wrapper = setupFixture(true);
|
||||||
|
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
||||||
|
|
||||||
|
toggleButton.click();
|
||||||
|
|
||||||
|
getSetTimeoutPromise()
|
||||||
|
.then(() => {
|
||||||
|
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('false');
|
||||||
|
})
|
||||||
|
.then(done)
|
||||||
|
.catch(done.fail);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when input value is false', () => {
|
||||||
|
it('should initialize as unchecked', () => {
|
||||||
|
const wrapper = setupFixture(false);
|
||||||
|
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked')).toEqual(false);
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('false');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle to checked when clicked', (done) => {
|
||||||
|
const wrapper = setupFixture(false);
|
||||||
|
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
||||||
|
|
||||||
|
toggleButton.click();
|
||||||
|
|
||||||
|
getSetTimeoutPromise()
|
||||||
|
.then(() => {
|
||||||
|
expect(toggleButton.classList.contains('is-checked')).toEqual(true);
|
||||||
|
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('true');
|
||||||
|
})
|
||||||
|
.then(done)
|
||||||
|
.catch(done.fail);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit `trigger-change` event', (done) => {
|
||||||
|
const changeSpy = jasmine.createSpy('changeEventHandler');
|
||||||
|
const wrapper = setupFixture(false);
|
||||||
|
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
||||||
|
const input = wrapper.querySelector('.js-project-feature-toggle-input');
|
||||||
|
|
||||||
|
$(input).on('trigger-change', changeSpy);
|
||||||
|
|
||||||
|
toggleButton.click();
|
||||||
|
|
||||||
|
getSetTimeoutPromise()
|
||||||
|
.then(() => {
|
||||||
|
expect(changeSpy).toHaveBeenCalled();
|
||||||
|
})
|
||||||
|
.then(done)
|
||||||
|
.catch(done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('clickCallback', () => {
|
||||||
|
it('should show loading indicator while waiting', (done) => {
|
||||||
|
const isChecked = true;
|
||||||
|
const clickCallback = (newValue, toggleButton) => {
|
||||||
|
const input = toggleButton.querySelector('.js-project-feature-toggle-input');
|
||||||
|
|
||||||
|
expect(newValue).toEqual(false);
|
||||||
|
|
||||||
|
// Check for the loading state
|
||||||
|
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
||||||
|
expect(toggleButton.classList.contains('is-loading')).toEqual(true);
|
||||||
|
expect(toggleButton.disabled).toEqual(true);
|
||||||
|
expect(input.value).toEqual('true');
|
||||||
|
|
||||||
|
// After the callback finishes, check that the loading state is gone
|
||||||
|
getSetTimeoutPromise()
|
||||||
|
.then(() => {
|
||||||
|
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
||||||
|
expect(toggleButton.classList.contains('is-loading')).toEqual(false);
|
||||||
|
expect(toggleButton.disabled).toEqual(false);
|
||||||
|
expect(input.value).toEqual('false');
|
||||||
|
})
|
||||||
|
.then(done)
|
||||||
|
.catch(done.fail);
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = setupFixture(isChecked, clickCallback);
|
||||||
|
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
||||||
|
|
||||||
|
toggleButton.click();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue