Commit 2739bd1d authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '228845-agent-list' into 'master'

Add Agent List to Cluster List View

Closes #228845

See merge request gitlab-org/gitlab!42115
parents cd3842c3 4e9b05a2
import Vue from 'vue';
import Clusters from './components/clusters.vue';
import { createStore } from './store';
import loadClusters from './load_clusters';
export default () => {
const entryPoint = document.querySelector('#js-clusters-list-app');
if (!entryPoint) {
return;
}
// eslint-disable-next-line no-new
new Vue({
el: '#js-clusters-list-app',
store: createStore(entryPoint.dataset),
render(createElement) {
return createElement(Clusters);
},
});
loadClusters(Vue);
};
import Clusters from './components/clusters.vue';
import { createStore } from './store';
export default Vue => {
const el = document.querySelector('#js-clusters-list-app');
if (!el) {
return null;
}
return new Vue({
el,
store: createStore(el.dataset),
render(createElement) {
return createElement(Clusters);
},
});
};
import initClustersListApp from 'ee_else_ce/clusters_list';
import PersistentUserCallout from '~/persistent_user_callout';
import initClustersListApp from '~/clusters_list';
document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.gcp-signup-offer');
......
......@@ -12,6 +12,18 @@ module ClustersHelper
end
end
def display_cluster_agents?(_clusterable)
false
end
def js_cluster_agents_list_data(clusterable_project)
{
default_branch_name: clusterable_project.default_branch,
empty_state_image: image_path('illustrations/clusters_empty.svg'),
project_path: clusterable_project.full_path
}
end
def js_clusters_list_data(path = nil)
{
ancestor_help_path: help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'),
......
- if clusters.empty?
= render 'empty_state'
- else
.top-area.adjust
.gl-display-block.gl-text-right.gl-my-4.gl-w-full
- if clusterable.can_add_cluster?
= link_to s_('ClusterIntegration|Connect cluster with certificate'), clusterable.new_path, class: 'btn gl-button btn-success js-add-cluster gl-py-2', qa_selector: :integrate_kubernetes_cluster_button
- else
%span.btn.gl-button.btn-success.js-add-cluster.disabled.gl-py-2
= s_("ClusterIntegration|Connect cluster with certificate")
#js-clusters-list-app{ data: js_clusters_list_data(clusterable.index_path(format: :json)) }
......@@ -3,12 +3,12 @@
.svg-content= image_tag 'illustrations/clusters_empty.svg'
.col-12
.text-content
%h4.text-center= s_('ClusterIntegration|Integrate Kubernetes cluster automation')
%p
%h4.gl-text-center= s_('ClusterIntegration|Integrate Kubernetes with a cluster certificate')
%p.gl-text-center
= s_('ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way.')
= clusterable.empty_state_help_text
= clusterable.learn_more_link
- if clusterable.can_add_cluster?
.text-center
= link_to s_('ClusterIntegration|Add Kubernetes cluster'), clusterable.new_path, class: 'btn btn-success'
.gl-text-center
= link_to s_('ClusterIntegration|Integrate with a cluster certificate'), clusterable.new_path, class: 'btn btn-success'
......@@ -3,18 +3,24 @@
= render_gcp_signup_offer
.clusters-container
- if @clusters.empty?
= render "empty_state"
- else
.top-area.adjust
.nav-text
= s_('ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project')
.nav-controls
- if clusterable.can_add_cluster?
= link_to s_('ClusterIntegration|Add Kubernetes cluster'), clusterable.new_path, class: 'btn gl-button btn-success js-add-cluster'
- else
%span.btn.gl-button.btn-success.js-add-cluster.disabled
= s_("ClusterIntegration|Add Kubernetes cluster")
.clusters-container.gl-my-2
- if display_cluster_agents?(clusterable)
.js-toggle-container
%ul.nav-links.nav-tabs.nav{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
%a.nav-link.active{ href: "#certificate-clusters-pane", id: "certificate-clusters-tab", data: { toggle: 'tab' }, role: 'tab' }
%span= s_('ClusterIntegration|Clusters connected with a certificate')
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: "#agent-clusters-pane", id: "agent-clusters-tab", data: { toggle: 'tab' }, role: 'tab' }
%span= s_('ClusterIntegration|GitLab Agent managed clusters')
#js-clusters-list-app{ data: js_clusters_list_data(clusterable.index_path(format: :json)) }
.tab-content
.tab-pane.active{ id: 'certificate-clusters-pane', role: 'tabpanel' }
= render 'cluster_list', clusters: @clusters
.tab-pane{ id: 'agent-clusters-pane', role: 'tabpanel' }
#js-cluster-agents-list{ data: js_cluster_agents_list_data(clusterable) }
- else
= render 'cluster_list', clusters: @clusters
---
name: cluster_agent_list
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/228845
rollout_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/3834
group: group::configure
type: development
default_enabled: true
<script>
import { GlButton, GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
export default {
components: {
GlButton,
GlEmptyState,
GlLink,
GlSprintf,
},
props: {
image: {
type: String,
required: true,
},
},
};
</script>
<template>
<gl-empty-state
:svg-path="image"
:title="s__('ClusterAgents|Integrate Kubernetes with a GitLab Agent')"
>
<template #description>
<p>
<gl-sprintf
:message="
s__(
'ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}',
)
"
>
<template #link="{ content }">
<gl-link href="https://docs.gitlab.com/ee/user/clusters/agent/" target="_blank">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
<p>
<gl-sprintf
:message="
s__(
'ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}',
)
"
>
<template #link="{ content }">
<gl-link
href="https://docs.gitlab.com/ee/user/clusters/agent/#install-the-agent-server"
target="_blank"
>
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
</template>
<template #actions>
<gl-button
category="primary"
variant="success"
href="https://docs.gitlab.com/ee/user/clusters/agent/#get-started-with-gitops-and-the-gitlab-agent"
target="_blank"
>
{{ s__('ClusterAgents|Integrate with the GitLab Agent') }}
</gl-button>
</template>
</gl-empty-state>
</template>
<script>
import { GlButton, GlLink, GlTable } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
components: {
GlButton,
GlLink,
GlTable,
},
props: {
agents: {
required: true,
type: Array,
},
},
computed: {
fields() {
return [
{
key: 'name',
label: s__('ClusterAgents|Name'),
},
{
key: 'configuration',
label: s__('ClusterAgents|Configuration'),
},
];
},
},
};
</script>
<template>
<div>
<div class="gl-display-block gl-text-right gl-my-4">
<gl-button
category="primary"
href="https://docs.gitlab.com/ee/user/clusters/agent/#get-started-with-gitops-and-the-gitlab-agent"
target="_blank"
variant="success"
>
{{ s__('ClusterAgents|Connect your cluster with the GitLab Agent') }}
</gl-button>
</div>
<gl-table :items="agents" :fields="fields" stacked="md" data-testid="cluster-agent-list-table">
<template #cell(configuration)=" { item }">
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
<gl-link v-if="item.configFolder" :href="item.configFolder.webPath">
.gitlab/agents/{{ item.name }}
</gl-link>
<p v-else>.gitlab/agents/{{ item.name }}</p>
</template>
</gl-table>
</div>
</template>
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { sortBy } from 'lodash';
import AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
export default {
apollo: {
agents: {
query: getAgentsQuery,
variables() {
return {
defaultBranchName: this.defaultBranchName,
projectPath: this.projectPath,
};
},
update: data => {
let agentList = data.project.clusterAgents.nodes;
const configFolders = data.project.repository.tree?.trees?.nodes;
if (configFolders) {
agentList = agentList.map(agent => {
const configFolder = configFolders.find(({ name }) => name === agent.name);
return { ...agent, configFolder };
});
}
return sortBy(agentList, 'name');
},
},
},
components: {
AgentEmptyState,
AgentTable,
GlLoadingIcon,
},
props: {
emptyStateImage: {
required: true,
type: String,
},
defaultBranchName: {
default: '.noBranch',
required: false,
type: String,
},
projectPath: {
required: true,
type: String,
},
},
};
</script>
<template>
<section v-if="agents" class="gl-mt-3">
<AgentTable v-if="agents.length" :agents="agents" />
<AgentEmptyState v-else :image="emptyStateImage" />
</section>
<gl-loading-icon v-else size="md" class="gl-mt-3" />
</template>
query getAgents($defaultBranchName: String!, $projectPath: ID!) {
project(fullPath: $projectPath) {
clusterAgents {
nodes {
id
name
}
}
repository {
tree(path: ".gitlab/agents", ref: $defaultBranchName) {
trees {
nodes {
name
path
webPath
}
}
}
}
}
}
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import loadAgents from './load_agents';
import loadClusters from '~/clusters_list/load_clusters';
Vue.use(VueApollo);
export default () => {
loadClusters(Vue);
loadAgents(Vue, VueApollo);
};
import Agents from './components/agents.vue';
import createDefaultClient from '~/lib/graphql';
export default (Vue, VueApollo) => {
const el = document.querySelector('#js-cluster-agents-list');
if (!el) {
return null;
}
const defaultClient = createDefaultClient();
defaultClient.cache.writeData({
/* eslint-disable @gitlab/require-i18n-strings */
data: {
project: {
__typename: 'Project',
clusterAgents: {
__typename: 'ClusterAgents',
nodes: [],
},
repository: {
__typename: 'Repository',
tree: {
__typename: 'Tree',
trees: {
__typename: 'Trees',
nodes: [],
},
},
},
},
},
});
const { emptyStateImage, defaultBranchName, projectPath } = el.dataset;
return new Vue({
el,
apolloProvider: new VueApollo({ defaultClient }),
render(createElement) {
return createElement(Agents, {
props: {
emptyStateImage,
defaultBranchName,
projectPath,
},
});
},
});
};
# frozen_string_literal: true
module EE
module ClustersHelper
extend ::Gitlab::Utils::Override
override :display_cluster_agents?
def display_cluster_agents?(clusterable)
return unless ::Feature.enabled?(:cluster_agent_list, default_enabled: true)
clusterable.is_a?(Project) && clusterable.feature_available?(:cluster_agents)
end
end
end
---
title: Add Agent List to Cluster List View
merge_request: 42115
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'ClusterAgents', :js do
let_it_be(:agent) { create(:cluster_agent) }
let(:project) { agent.project }
let(:user) { project.creator }
before do
gitlab_sign_in(user)
end
context 'non-premium user' do
before do
stub_licensed_features(cluster_agents: false)
end
context 'when user visits agents index page' do
before do
visit project_clusters_path(project)
end
it 'does not display agent information', :aggregate_failures do
expect(page).to have_content('Integrate with a cluster certificate')
expect(page).not_to have_content('GitLab Agent managed clusters')
end
end
end
context 'premium user' do
before do
stub_licensed_features(cluster_agents: true)
end
context 'when user does not have any agents and visits the index page' do
let(:empty_project) { create(:project) }
before do
empty_project.add_maintainer(user)
visit project_clusters_path(empty_project)
end
it 'displays empty state', :aggregate_failures do
click_link 'GitLab Agent managed clusters'
expect(page).to have_link('Integrate with the GitLab Agent')
expect(page).to have_selector('.empty-state')
end
end
context 'when user has an agent and visits the index page' do
before do
visit project_clusters_path(project)
end
it 'displays a table with agent', :aggregate_failures do
click_link 'GitLab Agent managed clusters'
expect(page).to have_content(agent.name)
expect(page).to have_selector('[data-testid="cluster-agent-list-table"] tbody tr', count: 1)
end
end
end
end
import { GlEmptyState, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AgentEmptyState from 'ee/clusters_list/components/agent_empty_state.vue';
describe('AgentEmptyStateComponent', () => {
let wrapper;
const propsData = {
image: '/image/path',
};
beforeEach(() => {
wrapper = shallowMount(AgentEmptyState, { propsData, stubs: { GlEmptyState, GlSprintf } });
});
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
it('should render content', () => {
expect(wrapper.find(GlEmptyState).exists()).toBe(true);
expect(wrapper.text()).toContain('Integrate with the GitLab Agent');
});
});
import { GlButton, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import AgentTable from 'ee/clusters_list/components/agent_table.vue';
const propsData = {
agents: [
{
name: 'agent-1',
configFolder: {
webPath: '/agent/full/path',
},
},
{
name: 'agent-2',
},
],
};
describe('AgentTable', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(AgentTable, { propsData });
});
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
it('displays header button', () => {
expect(wrapper.find(GlButton).text()).toBe('Connect your cluster with the GitLab Agent');
});
describe('agent table', () => {
it.each`
agentName | lineNumber
${'agent-1'} | ${0}
${'agent-2'} | ${1}
`('displays agent name', ({ agentName, lineNumber }) => {
const agents = wrapper.findAll(
'[data-testid="cluster-agent-list-table"] tbody tr > td:first-child',
);
const agent = agents.at(lineNumber);
expect(agent.text()).toBe(agentName);
});
it.each`
agentPath | hasLink | lineNumber
${'.gitlab/agents/agent-1'} | ${true} | ${0}
${'.gitlab/agents/agent-2'} | ${false} | ${1}
`('displays config file path', ({ agentPath, hasLink, lineNumber }) => {
const agents = wrapper.findAll(
'[data-testid="cluster-agent-list-table"] tbody tr > td:nth-child(2)',
);
const agent = agents.at(lineNumber);
expect(agent.find(GlLink).exists()).toBe(hasLink);
expect(agent.text()).toBe(agentPath);
});
});
});
import { createLocalVue, shallowMount } from '@vue/test-utils';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo';
import Agents from 'ee/clusters_list/components/agents.vue';
import AgentEmptyState from 'ee/clusters_list/components/agent_empty_state.vue';
import AgentTable from 'ee/clusters_list/components/agent_table.vue';
import getAgentsQuery from 'ee/clusters_list/graphql/queries/get_agents.query.graphql';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('Agents', () => {
let wrapper;
const createWrapper = ({ agents }) => {
const apolloQueryResponse = {
data: {
project: {
clusterAgents: { nodes: agents },
repository: { tree: { trees: { nodes: [] } } },
},
},
};
const apolloProvider = createMockApollo([
[getAgentsQuery, jest.fn().mockResolvedValue(apolloQueryResponse)],
]);
wrapper = shallowMount(Agents, {
localVue,
apolloProvider,
propsData: {
emptyStateImage: '/path/to/image',
defaultBranchName: 'default',
projectPath: 'path/to/project',
},
});
return wrapper.vm.$nextTick();
};
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('when there is a list of agents', () => {
const agents = [
{
id: '1',
name: 'agent-1',
},
{
id: '2',
name: 'agent-2',
},
];
beforeEach(() => {
return createWrapper({ agents });
});
it('should render agent table', () => {
expect(wrapper.find(AgentTable).exists()).toBe(true);
expect(wrapper.find(AgentEmptyState).exists()).toBe(false);
});
});
describe('when the agent list is empty', () => {
beforeEach(() => {
return createWrapper({ agents: [] });
});
it('should render empty state', () => {
expect(wrapper.find(AgentTable).exists()).toBe(false);
expect(wrapper.find(AgentEmptyState).exists()).toBe(true);
});
});
});
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ClustersHelper do
describe '#display_cluster_agents?' do
let(:clusterable) { build(:project) }
subject { helper.display_cluster_agents?(clusterable) }
context 'without premium license' do
it 'does not allows agents to display' do
expect(subject).to be_falsey
end
end
context 'with premium license' do
before do
stub_licensed_features(cluster_agents: true)
end
context 'when clusterable is a project' do
it 'allows agents to display' do
expect(subject).to be_truthy
end
end
context 'when clusterable is a group' do
let(:clusterable) { build(:group) }
it 'does not allows agents to display' do
expect(subject).to be_falsey
end
end
context 'when cluster_agent_list feature flag is disabled' do
before do
stub_feature_flags(cluster_agent_list: false)
end
it 'does not allows agents to display' do
expect(subject).to be_falsey
end
end
end
end
end
......@@ -5337,6 +5337,27 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
msgstr ""
msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
msgid "ClusterAgents|Name"
msgstr ""
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
......@@ -5511,6 +5532,12 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|Clusters connected with a certificate"
msgstr ""
msgid "ClusterIntegration|Connect cluster with certificate"
msgstr ""
msgid "ClusterIntegration|Connect existing cluster"
msgstr ""
......@@ -5667,6 +5694,9 @@ msgstr ""
msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
msgstr ""
msgid "ClusterIntegration|GitLab Agent managed clusters"
msgstr ""
msgid "ClusterIntegration|GitLab Container Network Policies"
msgstr ""
......@@ -5742,7 +5772,10 @@ msgstr ""
msgid "ClusterIntegration|Instance type"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
msgstr ""
msgid "ClusterIntegration|Integrate with a cluster certificate"
msgstr ""
msgid "ClusterIntegration|Issuer Email"
......@@ -5790,9 +5823,6 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr ""
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
......
......@@ -7,11 +7,11 @@ module QA
module Kubernetes
class Index < Page::Base
view 'app/views/clusters/clusters/_empty_state.html.haml' do
element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add Kubernetes cluster')" # rubocop:disable QA/ElementWithPattern
element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Integrate with a cluster certificate')" # rubocop:disable QA/ElementWithPattern
end
def add_kubernetes_cluster
click_on 'Add Kubernetes cluster'
click_on 'Connect cluster with certificate'
end
def has_cluster?(cluster)
......
......@@ -13,7 +13,7 @@ RSpec.describe 'Instance-level AWS EKS Cluster', :js do
before do
visit admin_clusters_path
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
end
context 'when user creates a cluster on AWS EKS' do
......
......@@ -19,7 +19,7 @@ RSpec.describe 'Group AWS EKS Cluster', :js do
before do
visit group_clusters_path(group)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
end
context 'when user creates a cluster on AWS EKS' do
......
......@@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do
before do
visit group_clusters_path(group)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
click_link 'Connect existing cluster'
end
......@@ -129,7 +129,7 @@ RSpec.describe 'User Cluster', :js do
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
expect(page).to have_link('Add Kubernetes cluster')
expect(page).to have_link('Integrate with a cluster certificate')
end
end
end
......
......@@ -19,7 +19,7 @@ RSpec.describe 'AWS EKS Cluster', :js do
before do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
end
context 'when user creates a cluster on AWS EKS' do
......
......@@ -33,7 +33,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
before do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
click_link 'Create new cluster'
click_link 'Google GKE'
end
......@@ -143,7 +143,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
before do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
click_link 'Connect cluster with certificate'
click_link 'Connect existing cluster'
end
......@@ -162,7 +162,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
expect(page).to have_link('Add Kubernetes cluster')
expect(page).to have_link('Integrate with a cluster certificate')
end
end
end
......@@ -178,7 +178,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
end
it 'user sees offer on cluster create page' do
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
expect(page).to have_css('.gcp-signup-offer')
end
......@@ -195,7 +195,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
find('.gcp-signup-offer .js-close').click
wait_for_requests
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
expect(page).not_to have_css('.gcp-signup-offer')
end
......
......@@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do
before do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
click_link 'Connect existing cluster'
end
......@@ -116,7 +116,7 @@ RSpec.describe 'User Cluster', :js do
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
expect(page).to have_link('Add Kubernetes cluster')
expect(page).to have_link('Integrate with a cluster certificate')
end
end
end
......
......@@ -19,7 +19,7 @@ RSpec.describe 'Clusters', :js do
end
it 'sees empty state' do
expect(page).to have_link('Add Kubernetes cluster')
expect(page).to have_link('Integrate with a cluster certificate')
expect(page).to have_selector('.empty-state')
end
end
......@@ -41,7 +41,7 @@ RSpec.describe 'Clusters', :js do
context 'when user filled form with environment scope' do
before do
click_link 'Add Kubernetes cluster'
click_link 'Connect cluster with certificate'
click_link 'Connect existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
......@@ -70,7 +70,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
click_link 'Add Kubernetes cluster'
click_link 'Connect cluster with certificate'
click_link 'Connect existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
......@@ -116,7 +116,7 @@ RSpec.describe 'Clusters', :js do
context 'when user filled form with environment scope' do
before do
click_link 'Add Kubernetes cluster'
click_link 'Connect cluster with certificate'
click_link 'Create new cluster'
click_link 'Google GKE'
......@@ -161,7 +161,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
click_link 'Add Kubernetes cluster'
click_link 'Connect cluster with certificate'
click_link 'Create new cluster'
click_link 'Google GKE'
......@@ -214,7 +214,7 @@ RSpec.describe 'Clusters', :js do
before do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
click_link 'Integrate with a cluster certificate'
click_link 'Create new cluster'
end
......
......@@ -59,6 +59,24 @@ RSpec.describe ClustersHelper do
end
end
describe '#js_cluster_agents_list_data' do
let_it_be(:project) { build(:project, :repository) }
subject { helper.js_cluster_agents_list_data(project) }
it 'displays project default branch' do
expect(subject[:default_branch_name]).to eq(project.default_branch)
end
it 'displays image path' do
expect(subject[:empty_state_image]).to match(%r(/illustrations/logos/clusters_empty|svg))
end
it 'displays project path' do
expect(subject[:project_path]).to eq(project.full_path)
end
end
describe '#js_clusters_list_data' do
subject { helper.js_clusters_list_data('/path') }
......
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