Adds JS unit tests

Finishes tabs & table
Updates e2e tests
This commit is contained in:
Filipa Lacerda 2017-11-27 17:18:55 +00:00
parent 554bf24b2a
commit 074fcb56bb
No known key found for this signature in database
GPG key ID: 9CA3FDE4D1E2F1C8
11 changed files with 98 additions and 86 deletions

View file

@ -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();

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View 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')

View file

@ -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')

View 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")

View file

@ -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')

View file

@ -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

View file

@ -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);
}); });

View file

@ -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