Adds JS unit tests
Finishes tabs & table Updates e2e tests
This commit is contained in:
parent
554bf24b2a
commit
074fcb56bb
11 changed files with 98 additions and 86 deletions
|
@ -18,11 +18,11 @@ export default class ClusterTable {
|
||||||
this.container = '.js-clusters-list';
|
this.container = '.js-clusters-list';
|
||||||
document.querySelectorAll(`${this.container} .js-toggle-cluster-list`).forEach(button => button.addEventListener('click', e => ClusterTable.updateCluster(e)));
|
document.querySelectorAll(`${this.container} .js-toggle-cluster-list`).forEach(button => button.addEventListener('click', e => ClusterTable.updateCluster(e)));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
removeListeners() {
|
* When the toggle button is clicked,
|
||||||
document.querySelectorAll(`${this.container} .js-toggle-cluster-list`).forEach(button => button.removeEventListener('click'));
|
* updates the status and makes a request to the API to update the cluster
|
||||||
}
|
* @param {Event} e
|
||||||
|
*/
|
||||||
static updateCluster(e) {
|
static updateCluster(e) {
|
||||||
const toggleButton = e.currentTarget;
|
const toggleButton = e.currentTarget;
|
||||||
const value = toggleButton.classList.contains('checked').toString();
|
const value = toggleButton.classList.contains('checked').toString();
|
||||||
|
|
|
@ -8,3 +8,9 @@
|
||||||
// Wait for the Vue to kick-in and render the applications block
|
// Wait for the Vue to kick-in and render the applications block
|
||||||
min-height: 302px;
|
min-height: 302px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clusters-container {
|
||||||
|
.nav-bar-right {
|
||||||
|
padding: $gl-padding-top $gl-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class Projects::ClustersController < Projects::ApplicationController
|
||||||
|
|
||||||
def clusters
|
def clusters
|
||||||
scope = params[:scope] || :all
|
scope = params[:scope] || :all
|
||||||
@clusters = ClustersFinder.new(project, user, scope).execute
|
@clusters = ClustersFinder.new(project, current_user, scope).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_params
|
def create_params
|
||||||
|
|
|
@ -193,7 +193,7 @@
|
||||||
= nav_link(controller: :clusters) do
|
= nav_link(controller: :clusters) do
|
||||||
= link_to project_clusters_path(@project), title: 'Cluster', class: 'shortcuts-cluster' do
|
= link_to project_clusters_path(@project), title: 'Cluster', class: 'shortcuts-cluster' do
|
||||||
%span
|
%span
|
||||||
Cluster
|
Clusters
|
||||||
|
|
||||||
- if project_nav_tab? :wiki
|
- if project_nav_tab? :wiki
|
||||||
= nav_link(controller: :wikis) do
|
= nav_link(controller: :wikis) do
|
||||||
|
|
22
app/views/projects/clusters/_cluster.html.haml
Normal file
22
app/views/projects/clusters/_cluster.html.haml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
.gl-responsive-table-row
|
||||||
|
.table-section.section-30
|
||||||
|
.table-mobile-header{ role: 'rowheader' }= s_('ClusterIntegration|Cluster')
|
||||||
|
.table-mobile-content
|
||||||
|
= link_to cluster.name, namespace_project_cluster_path(@project.namespace, @project, cluster)
|
||||||
|
.table-section.section-30
|
||||||
|
.table-mobile-header{ role: 'rowheader' }= s_('ClusterIntegration|Environment pattern')
|
||||||
|
.table-mobile-content= cluster.environment_scope
|
||||||
|
.table-section.section-30
|
||||||
|
.table-mobile-header{ role: 'rowheader' }= s_('ClusterIntegration|Project namespace')
|
||||||
|
.table-mobile-content= cluster.platform_kubernetes&.namespace
|
||||||
|
.table-section.section-10
|
||||||
|
.table-mobile-header{ role: 'rowheader' }
|
||||||
|
.table-mobile-content
|
||||||
|
%button{ type: 'button',
|
||||||
|
class: "js-toggle-cluster-list project-feature-toggle #{'checked' unless !cluster.enabled?} #{'disabled' unless can?(current_user, :update_cluster, cluster)}",
|
||||||
|
'aria-label': s_('ClusterIntegration|Toggle Cluster'),
|
||||||
|
disabled: !can?(current_user, :update_cluster, cluster),
|
||||||
|
data: { 'enabled-text': 'Enabled',
|
||||||
|
'disabled-text': 'Disabled',
|
||||||
|
endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
|
||||||
|
= icon('spinner spin', class: 'hidden loading-icon')
|
|
@ -1,6 +1,6 @@
|
||||||
.row.empty-state
|
.row.empty-state
|
||||||
.col-xs-12
|
.col-xs-12
|
||||||
.svg-content= image_tag 'illustrations/labels.svg'
|
.svg-content= image_tag 'illustrations/clusters_empty.svg'
|
||||||
.col-xs-12.text-center
|
.col-xs-12.text-center
|
||||||
.text-content
|
.text-content
|
||||||
%h4= s_('ClusterIntegration|Integrate cluster automation')
|
%h4= s_('ClusterIntegration|Integrate cluster automation')
|
||||||
|
|
19
app/views/projects/clusters/_tabs.html.haml
Normal file
19
app/views/projects/clusters/_tabs.html.haml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
|
||||||
|
.fade-left= icon("angle-left")
|
||||||
|
.fade-right= icon("angle-right")
|
||||||
|
%ul.nav-links.scrolling-tabs
|
||||||
|
%li{ class: ('active' if @scope == 'enabled') }>
|
||||||
|
= link_to project_clusters_path(@project, scope: :enabled), class: "js-active-tab" do
|
||||||
|
= s_("ClusterIntegration|Active")
|
||||||
|
%span.badge= @active_count
|
||||||
|
|
||||||
|
%li{ class: ('active' if @scope == 'disabled') }>
|
||||||
|
= link_to project_clusters_path(@project, scope: :disabled), class: "js-inactive-tab #{'active' if @scope == 'disabled'}" do
|
||||||
|
= s_("ClusterIntegration|Inactive")
|
||||||
|
%span.badge= @inactive_count
|
||||||
|
%li{ class: ('active' if @scope.nil? || @scope == 'all') }>
|
||||||
|
= link_to project_clusters_path(@project, scope: :all), class: "js-all-tab #{'active' if @scope == 'all' || @scope.nil?}" do
|
||||||
|
= s_("ClusterIntegration|All")
|
||||||
|
%span.badge= @inactive_count
|
||||||
|
.pull-right.nav-bar-right
|
||||||
|
= link_to s_("ClusterIntegration|Add cluster"), new_project_cluster_path(@project), class: "btn btn-success disabled has-tooltip js-add-cluster", title: s_("ClusterIntegration|Multiple clusters are available in GitLab Entreprise Edition Premium and Ultimate")
|
|
@ -1,60 +1,20 @@
|
||||||
|
- breadcrumb_title "Clusters"
|
||||||
|
- page_title "Clusters"
|
||||||
|
|
||||||
|
.clusters-container
|
||||||
- if @clusters.empty?
|
- if @clusters.empty?
|
||||||
= render "empty_state"
|
= render "empty_state"
|
||||||
- else
|
- else
|
||||||
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
|
= render "tabs"
|
||||||
.fade-left= icon("angle-left")
|
|
||||||
.fade-right= icon("angle-right")
|
|
||||||
%ul.nav-links.scrolling-tabs
|
|
||||||
%li
|
|
||||||
%a.js-active-tab
|
|
||||||
=s_("ClusterIntegration|Active")
|
|
||||||
%span.badge
|
|
||||||
TODO
|
|
||||||
|
|
||||||
%li
|
|
||||||
%a.js-inactive-tab
|
|
||||||
= s_("ClusterIntegration|Inactive")
|
|
||||||
%span.badge
|
|
||||||
TODO
|
|
||||||
%li
|
|
||||||
%a.js-all-tab
|
|
||||||
= s_("ClusterIntegration|All")
|
|
||||||
%span.badge= @clusters_count
|
|
||||||
.nav-controls
|
|
||||||
= link_to s_('ClusterIntegration|Add cluster'), new_project_cluster_path(@project), class: "btn btn-success disabled has-tooltip js-add-cluster", title: s_("ClusterIntegration|Multiple clusters are available in GitLab Entreprise Edition Premium and Ultimate")
|
|
||||||
.ci-table.js-clusters-list
|
.ci-table.js-clusters-list
|
||||||
.gl-responsive-table-row.table-row-header{ role: 'row' }
|
.gl-responsive-table-row.table-row-header{ role: "row" }
|
||||||
.table-section.section-30{ role: 'rowheader' }
|
.table-section.section-30{ role: "rowheader" }
|
||||||
= s_('ClusterIntegration|Cluster')
|
= s_("ClusterIntegration|Cluster")
|
||||||
.table-section.section-30{ role: 'rowheader' }
|
.table-section.section-30{ role: "rowheader" }
|
||||||
= s_('ClusterIntegration|Environment pattern')
|
= s_("ClusterIntegration|Environment pattern")
|
||||||
.table-section.section-30{ role: 'rowheader' }
|
.table-section.section-30{ role: "rowheader" }
|
||||||
= s_('ClusterIntegration|Project namespace')
|
= s_("ClusterIntegration|Project namespace")
|
||||||
.table-section.section-10{ role: 'rowheader' }
|
.table-section.section-10{ role: "rowheader" }
|
||||||
- @clusters.each do |cluster|
|
- @clusters.each do |cluster|
|
||||||
.gl-responsive-table-row
|
= render "cluster", cluster: cluster
|
||||||
.table-section.section-30
|
= paginate @clusters, theme: 'gitlab'
|
||||||
.table-mobile-header{ role: 'rowheader' }= s_('ClusterIntegration|Cluster')
|
|
||||||
.table-mobile-content
|
|
||||||
= link_to cluster.name, namespace_project_cluster_path(@project.namespace, @project, cluster)
|
|
||||||
.table-section.section-30
|
|
||||||
.table-mobile-header{ role: 'rowheader' }
|
|
||||||
= s_('ClusterIntegration|Environment pattern')
|
|
||||||
.table-mobile-content= cluster.environment_scope
|
|
||||||
.table-section.section-30
|
|
||||||
.table-mobile-header{ role: 'rowheader' }
|
|
||||||
= s_('ClusterIntegration|Project namespace')
|
|
||||||
.table-mobile-content
|
|
||||||
Content goes here - TODO
|
|
||||||
.table-section.section-10
|
|
||||||
.table-mobile-header{ role: 'rowheader' }
|
|
||||||
.table-mobile-content
|
|
||||||
%button{ type: 'button',
|
|
||||||
class: "js-toggle-cluster-list project-feature-toggle #{'checked' unless !cluster.enabled?} #{'disabled' unless can?(current_user, :update_cluster, cluster)}",
|
|
||||||
'aria-label': s_('ClusterIntegration|Toggle Cluster'),
|
|
||||||
disabled: !can?(current_user, :update_cluster, cluster),
|
|
||||||
data: { 'enabled-text': 'Enabled',
|
|
||||||
'disabled-text': 'Disabled',
|
|
||||||
endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
|
|
||||||
= icon('spinner spin', class: 'hidden loading-icon')
|
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ feature 'Clusters', :js do
|
||||||
visit project_clusters_path(project)
|
visit project_clusters_path(project)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'user sees a new page' do
|
it 'user sees empty state' do
|
||||||
expect(page).to have_button('Add cluster')
|
expect(page).to have_link('Add cluster')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user opens opens create on gke page' do
|
context 'when user opens opens create on gke page' do
|
||||||
|
@ -99,7 +99,7 @@ feature 'Clusters', :js do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'user sees a disabled add cluster button ' do
|
it 'user sees a disabled add cluster button ' do
|
||||||
expect(page.find(:css, '.js-add-cluster')['disabled']).to eq('true')
|
expect(page).to have_selector('.js-add-cluster.disabled')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'user sees navigation tabs' do
|
it 'user sees navigation tabs' do
|
||||||
|
@ -244,7 +244,7 @@ feature 'Clusters', :js do
|
||||||
before do
|
before do
|
||||||
visit project_clusters_path(project)
|
visit project_clusters_path(project)
|
||||||
|
|
||||||
click_button 'Add cluster'
|
click_link 'Add cluster'
|
||||||
click_link 'Create on GKE'
|
click_link 'Create on GKE'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,17 +5,12 @@ import { setTimeout } from 'core-js/library/web/timers';
|
||||||
|
|
||||||
describe('Clusters table', () => {
|
describe('Clusters table', () => {
|
||||||
preloadFixtures('clusters/index_cluster.html.raw');
|
preloadFixtures('clusters/index_cluster.html.raw');
|
||||||
let ClustersClass;
|
|
||||||
let mock;
|
let mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
loadFixtures('clusters/index_cluster.html.raw');
|
loadFixtures('clusters/index_cluster.html.raw');
|
||||||
ClustersClass = new ClusterTable();
|
|
||||||
mock = new MockAdapter(axios);
|
mock = new MockAdapter(axios);
|
||||||
});
|
return new ClusterTable();
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
ClustersClass.removeListeners();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('update cluster', () => {
|
describe('update cluster', () => {
|
||||||
|
@ -39,11 +34,13 @@ describe('Clusters table', () => {
|
||||||
it('shows updated state after sucessfull request', (done) => {
|
it('shows updated state after sucessfull request', (done) => {
|
||||||
mock.onPut().reply(200, {}, {});
|
mock.onPut().reply(200, {}, {});
|
||||||
const button = document.querySelector('.js-toggle-cluster-list');
|
const button = document.querySelector('.js-toggle-cluster-list');
|
||||||
|
|
||||||
button.click();
|
button.click();
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
expect(button.classList).toContain('is-loading');
|
expect(button.classList).toContain('is-loading');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(button.classList).not.toContain('is-loading');
|
||||||
|
expect(button.classList).not.toContain('checked');
|
||||||
done();
|
done();
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
@ -53,9 +50,11 @@ describe('Clusters table', () => {
|
||||||
const button = document.querySelector('.js-toggle-cluster-list');
|
const button = document.querySelector('.js-toggle-cluster-list');
|
||||||
|
|
||||||
button.click();
|
button.click();
|
||||||
|
expect(button.classList).toContain('is-loading');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(button.classList).toContain('is-loading');
|
expect(button.classList).not.toContain('is-loading');
|
||||||
|
expect(button.classList).toContain('checked');
|
||||||
done();
|
done();
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,12 +32,18 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
|
||||||
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|
|
it 'clusters/index_cluster.html.raw' do |example|
|
||||||
get :index,
|
get :index,
|
||||||
namespace_id: project.namespace.to_param,
|
namespace_id: namespace,
|
||||||
project_id: project
|
project_id: project
|
||||||
|
|
||||||
expect(response).to be_success
|
expect(response).to be_success
|
||||||
store_frontend_fixture(response, example.description)
|
store_frontend_fixture(response, example.description)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in a new issue