Commit ca88e653 authored by pburdette's avatar pburdette

Fix XSS on jobs view

Fix the XSS vulnerablity
on the jobs view.
parent ca7acc9f
<script> <script>
import { escape, isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { sprintf, __ } from '../../locale'; import { __ } from '../../locale';
import { GlSprintf, GlLink } from '@gitlab/ui';
export default { export default {
creatingEnvironment: 'creating',
components: { components: {
CiIcon, CiIcon,
GlSprintf,
GlLink,
}, },
props: { props: {
deploymentStatus: { deploymentStatus: {
...@@ -31,7 +35,7 @@ export default { ...@@ -31,7 +35,7 @@ export default {
return this.outOfDateEnvironmentMessage(); return this.outOfDateEnvironmentMessage();
case 'failed': case 'failed':
return this.failedEnvironmentMessage(); return this.failedEnvironmentMessage();
case 'creating': case this.$options.creatingEnvironment:
return this.creatingEnvironmentMessage(); return this.creatingEnvironmentMessage();
default: default:
return ''; return '';
...@@ -39,17 +43,12 @@ export default { ...@@ -39,17 +43,12 @@ export default {
}, },
environmentLink() { environmentLink() {
if (this.hasEnvironment) { if (this.hasEnvironment) {
return sprintf( return {
'%{startLink}%{name}%{endLink}', link: this.deploymentStatus.environment.environment_path,
{ name: this.deploymentStatus.environment.name,
startLink: `<a href="${this.deploymentStatus.environment.environment_path}" class="js-environment-link">`, };
name: escape(this.deploymentStatus.environment.name),
endLink: '</a>',
},
false,
);
} }
return ''; return {};
}, },
hasLastDeployment() { hasLastDeployment() {
return this.hasEnvironment && this.deploymentStatus.environment.last_deployment; return this.hasEnvironment && this.deploymentStatus.environment.last_deployment;
...@@ -74,201 +73,107 @@ export default { ...@@ -74,201 +73,107 @@ export default {
} }
const { name, path } = this.deploymentCluster; const { name, path } = this.deploymentCluster;
const escapedName = escape(name);
const escapedPath = escape(path);
if (!escapedPath) {
return escapedName;
}
return sprintf( return {
'%{startLink}%{name}%{endLink}', path,
{ name,
startLink: `<a href="${escapedPath}" class="js-job-cluster-link">`, };
name: escapedName,
endLink: '</a>',
},
false,
);
}, },
kubernetesNamespace() { kubernetesNamespace() {
return this.hasCluster ? this.deploymentCluster.kubernetes_namespace : null; return this.hasCluster ? this.deploymentCluster.kubernetes_namespace : null;
}, },
deploymentLink() {
return {
path: this.lastDeploymentPath,
name:
this.deploymentStatus.status === this.$options.creatingEnvironment
? __('latest deployment')
: __('most recent deployment'),
};
},
}, },
methods: { methods: {
deploymentLink(name) {
return sprintf(
'%{startLink}%{name}%{endLink}',
{
startLink: `<a href="${this.lastDeploymentPath}" class="js-job-deployment-link">`,
name,
endLink: '</a>',
},
false,
);
},
failedEnvironmentMessage() { failedEnvironmentMessage() {
const { environmentLink } = this; return __('The deployment of this job to %{environmentLink} did not succeed.');
return sprintf(
__('The deployment of this job to %{environmentLink} did not succeed.'),
{ environmentLink },
false,
);
}, },
lastEnvironmentMessage() { lastEnvironmentMessage() {
const { environmentLink, clusterNameOrLink, hasCluster, kubernetesNamespace } = this; if (this.hasCluster) {
if (hasCluster) { if (this.kubernetesNamespace) {
if (kubernetesNamespace) { return __(
return sprintf( 'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
__(
'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
); );
} }
// we know the cluster but not the namespace // we know the cluster but not the namespace
return sprintf( return __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.');
__('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.'),
{ environmentLink, clusterNameOrLink },
false,
);
} }
// not a cluster deployment // not a cluster deployment
return sprintf(__('This job is deployed to %{environmentLink}.'), { environmentLink }, false); return __('This job is deployed to %{environmentLink}.');
}, },
outOfDateEnvironmentMessage() { outOfDateEnvironmentMessage() {
const { if (this.hasLastDeployment) {
hasLastDeployment, if (this.hasCluster) {
hasCluster, if (this.kubernetesNamespace) {
environmentLink, return __(
clusterNameOrLink, 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.',
kubernetesNamespace,
} = this;
if (hasLastDeployment) {
const deploymentLink = this.deploymentLink(__('most recent deployment'));
if (hasCluster) {
if (kubernetesNamespace) {
return sprintf(
__(
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink },
false,
); );
} }
// we know the cluster but not the namespace // we know the cluster but not the namespace
return sprintf( return __(
__( 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.',
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, deploymentLink },
false,
); );
} }
// not a cluster deployment // not a cluster deployment
return sprintf( return __(
__( 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.',
'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.',
),
{ environmentLink, deploymentLink },
false,
); );
} }
// no last deployment, i.e. this is the first deployment // no last deployment, i.e. this is the first deployment
if (hasCluster) { if (this.hasCluster) {
if (kubernetesNamespace) { if (this.kubernetesNamespace) {
return sprintf( return __(
__( 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
); );
} }
// we know the cluster but not the namespace // we know the cluster but not the namespace
return sprintf( return __(
__( 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
),
{ environmentLink, clusterNameOrLink },
false,
); );
} }
// not a cluster deployment // not a cluster deployment
return sprintf( return __('This job is an out-of-date deployment to %{environmentLink}.');
__('This job is an out-of-date deployment to %{environmentLink}.'),
{ environmentLink },
false,
);
}, },
creatingEnvironmentMessage() { creatingEnvironmentMessage() {
const { if (this.hasLastDeployment) {
hasLastDeployment, if (this.hasCluster) {
hasCluster, if (this.kubernetesNamespace) {
environmentLink, return __(
clusterNameOrLink, 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.',
kubernetesNamespace,
} = this;
if (hasLastDeployment) {
const deploymentLink = this.deploymentLink(__('latest deployment'));
if (hasCluster) {
if (kubernetesNamespace) {
return sprintf(
__(
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink },
false,
); );
} }
// we know the cluster but not the namespace // we know the cluster but not the namespace
return sprintf( return __(
__( 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.',
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, deploymentLink },
false,
); );
} }
// not a cluster deployment // not a cluster deployment
return sprintf( return __(
__( 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.',
'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.',
),
{ environmentLink, deploymentLink },
false,
); );
} }
// no last deployment, i.e. this is the first deployment // no last deployment, i.e. this is the first deployment
if (hasCluster) { if (this.hasCluster) {
if (kubernetesNamespace) { if (this.kubernetesNamespace) {
return sprintf( return __(
__( 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
); );
} }
// we know the cluster but not the namespace // we know the cluster but not the namespace
return sprintf( return __(
__( 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
),
{ environmentLink, clusterNameOrLink },
false,
); );
} }
// not a cluster deployment // not a cluster deployment
return sprintf( return __('This job is creating a deployment to %{environmentLink}.');
__('This job is creating a deployment to %{environmentLink}.'),
{ environmentLink },
false,
);
}, },
}, },
}; };
...@@ -277,7 +182,37 @@ export default { ...@@ -277,7 +182,37 @@ export default {
<div class="prepend-top-default append-bottom-default js-environment-container"> <div class="prepend-top-default append-bottom-default js-environment-container">
<div class="environment-information"> <div class="environment-information">
<ci-icon :status="iconStatus" /> <ci-icon :status="iconStatus" />
<p class="inline gl-mb-0" v-html="environment"></p> <p class="inline gl-mb-0">
<gl-sprintf :message="environment">
<template #environmentLink>
<gl-link
v-if="hasEnvironment"
:href="environmentLink.link"
data-testid="job-environment-link"
v-text="environmentLink.name"
/>
</template>
<template #clusterNameOrLink>
<gl-link
v-if="clusterNameOrLink.path"
:href="clusterNameOrLink.path"
data-testid="job-cluster-link"
v-text="clusterNameOrLink.name"
/>
<template v-else>{{ clusterNameOrLink.name }}</template>
</template>
<template #kubernetesNamespace>
<template>{{ kubernetesNamespace }}</template>
</template>
<template #deploymentLink>
<gl-link
:href="deploymentLink.path"
data-testid="job-deployment-link"
v-text="deploymentLink.name"
/>
</template>
</gl-sprintf>
</p>
</div> </div>
</div> </div>
</template> </template>
---
title: Fix xss vulnerability on jobs view
merge_request:
author:
type: security
...@@ -551,7 +551,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -551,7 +551,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows deployment message' do it 'shows deployment message' do
expect(page).to have_content 'This job is deployed to production' expect(page).to have_content 'This job is deployed to production'
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
context 'when there is a cluster used for the deployment' do context 'when there is a cluster used for the deployment' do
...@@ -583,7 +583,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -583,7 +583,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows a link for the job' do it 'shows a link for the job' do
expect(page).to have_link environment.name expect(page).to have_link environment.name
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
end end
...@@ -593,7 +593,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -593,7 +593,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows a link to latest deployment' do it 'shows a link to latest deployment' do
expect(page).to have_link environment.name expect(page).to have_link environment.name
expect(page).to have_content 'This job is creating a deployment' expect(page).to have_content 'This job is creating a deployment'
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
end end
end end
...@@ -645,15 +645,15 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -645,15 +645,15 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end end
it 'renders a link to the most recent deployment' do it 'renders a link to the most recent deployment' do
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
expect(find('.js-job-deployment-link')['href']).to include(second_deployment.deployable.project.path, second_deployment.deployable_id.to_s) expect(find('[data-testid="job-deployment-link"]')['href']).to include(second_deployment.deployable.project.path, second_deployment.deployable_id.to_s)
end end
context 'when deployment does not have a deployable' do context 'when deployment does not have a deployable' do
let!(:second_deployment) { create(:deployment, :success, environment: environment, deployable: nil) } let!(:second_deployment) { create(:deployment, :success, environment: environment, deployable: nil) }
it 'has an empty href' do it 'has an empty href' do
expect(find('.js-job-deployment-link')['href']).to be_empty expect(find('[data-testid="job-deployment-link"]')['href']).to be_empty
end end
end end
end end
...@@ -679,7 +679,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -679,7 +679,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
expected_text = 'This job is creating a deployment to staging' expected_text = 'This job is creating a deployment to staging'
expect(page).to have_css('.environment-information', text: expected_text) expect(page).to have_css('.environment-information', text: expected_text)
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
context 'when it has deployment' do context 'when it has deployment' do
...@@ -690,7 +690,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -690,7 +690,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_css('.environment-information', text: expected_text) expect(page).to have_css('.environment-information', text: expected_text)
expect(page).to have_css('.environment-information', text: 'latest deployment') expect(page).to have_css('.environment-information', text: 'latest deployment')
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
end end
end end
...@@ -705,7 +705,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -705,7 +705,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
'.environment-information', text: expected_text) '.environment-information', text: expected_text)
expect(page).not_to have_css( expect(page).not_to have_css(
'.environment-information', text: 'latest deployment') '.environment-information', text: 'latest deployment')
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('[data-testid="job-environment-link"]')['href']).to match("environments/#{environment.id}")
end end
end end
end end
......
import Vue from 'vue'; import { mount } from '@vue/test-utils';
import component from '~/jobs/components/environments_block.vue'; import EnvironmentsBlock from '~/jobs/components/environments_block.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
const TEST_CLUSTER_NAME = 'test_cluster'; const TEST_CLUSTER_NAME = 'test_cluster';
const TEST_CLUSTER_PATH = 'path/to/test_cluster'; const TEST_CLUSTER_PATH = 'path/to/test_cluster';
const TEST_KUBERNETES_NAMESPACE = 'this-is-a-kubernetes-namespace'; const TEST_KUBERNETES_NAMESPACE = 'this-is-a-kubernetes-namespace';
describe('Environments block', () => { describe('Environments block', () => {
const Component = Vue.extend(component); let wrapper;
let vm;
const status = { const status = {
group: 'success', group: 'success',
icon: 'status_success', icon: 'status_success',
...@@ -38,20 +37,23 @@ describe('Environments block', () => { ...@@ -38,20 +37,23 @@ describe('Environments block', () => {
}); });
const createComponent = (deploymentStatus = {}, deploymentCluster = {}) => { const createComponent = (deploymentStatus = {}, deploymentCluster = {}) => {
vm = mountComponent(Component, { wrapper = mount(EnvironmentsBlock, {
deploymentStatus, propsData: {
deploymentCluster, deploymentStatus,
iconStatus: status, deploymentCluster,
iconStatus: status,
},
}); });
}; };
const findText = () => vm.$el.textContent.trim(); const findText = () => wrapper.find(EnvironmentsBlock).text();
const findJobDeploymentLink = () => vm.$el.querySelector('.js-job-deployment-link'); const findJobDeploymentLink = () => wrapper.find('[data-testid="job-deployment-link"]');
const findEnvironmentLink = () => vm.$el.querySelector('.js-environment-link'); const findEnvironmentLink = () => wrapper.find('[data-testid="job-environment-link"]');
const findClusterLink = () => vm.$el.querySelector('.js-job-cluster-link'); const findClusterLink = () => wrapper.find('[data-testid="job-cluster-link"]');
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('with last deployment', () => { describe('with last deployment', () => {
...@@ -61,7 +63,7 @@ describe('Environments block', () => { ...@@ -61,7 +63,7 @@ describe('Environments block', () => {
environment, environment,
}); });
expect(findText()).toEqual('This job is deployed to environment.'); expect(findText()).toBe('This job is deployed to environment.');
}); });
describe('when there is a cluster', () => { describe('when there is a cluster', () => {
...@@ -74,7 +76,7 @@ describe('Environments block', () => { ...@@ -74,7 +76,7 @@ describe('Environments block', () => {
createDeploymentWithCluster(), createDeploymentWithCluster(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`, `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
); );
}); });
...@@ -89,7 +91,7 @@ describe('Environments block', () => { ...@@ -89,7 +91,7 @@ describe('Environments block', () => {
createDeploymentWithClusterAndKubernetesNamespace(), createDeploymentWithClusterAndKubernetesNamespace(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}.`, `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}.`,
); );
}); });
...@@ -105,11 +107,11 @@ describe('Environments block', () => { ...@@ -105,11 +107,11 @@ describe('Environments block', () => {
environment: createEnvironmentWithLastDeployment(), environment: createEnvironmentWithLastDeployment(),
}); });
expect(findText()).toEqual( expect(findText()).toBe(
'This job is an out-of-date deployment to environment. View the most recent deployment.', 'This job is an out-of-date deployment to environment. View the most recent deployment.',
); );
expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar'); expect(findJobDeploymentLink().attributes('href')).toBe('bar');
}); });
describe('when there is a cluster', () => { describe('when there is a cluster', () => {
...@@ -122,7 +124,7 @@ describe('Environments block', () => { ...@@ -122,7 +124,7 @@ describe('Environments block', () => {
createDeploymentWithCluster(), createDeploymentWithCluster(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`, `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`,
); );
}); });
...@@ -137,7 +139,7 @@ describe('Environments block', () => { ...@@ -137,7 +139,7 @@ describe('Environments block', () => {
createDeploymentWithClusterAndKubernetesNamespace(), createDeploymentWithClusterAndKubernetesNamespace(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}. View the most recent deployment.`, `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}. View the most recent deployment.`,
); );
}); });
...@@ -152,7 +154,7 @@ describe('Environments block', () => { ...@@ -152,7 +154,7 @@ describe('Environments block', () => {
environment, environment,
}); });
expect(findText()).toEqual('This job is an out-of-date deployment to environment.'); expect(findText()).toBe('This job is an out-of-date deployment to environment.');
}); });
}); });
}); });
...@@ -164,7 +166,7 @@ describe('Environments block', () => { ...@@ -164,7 +166,7 @@ describe('Environments block', () => {
environment, environment,
}); });
expect(findText()).toEqual('The deployment of this job to environment did not succeed.'); expect(findText()).toBe('The deployment of this job to environment did not succeed.');
}); });
}); });
...@@ -176,13 +178,15 @@ describe('Environments block', () => { ...@@ -176,13 +178,15 @@ describe('Environments block', () => {
environment: createEnvironmentWithLastDeployment(), environment: createEnvironmentWithLastDeployment(),
}); });
expect(findText()).toEqual( expect(findText()).toBe(
'This job is creating a deployment to environment. This will overwrite the latest deployment.', 'This job is creating a deployment to environment. This will overwrite the latest deployment.',
); );
expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar'); expect(findEnvironmentLink().attributes('href')).toBe(environment.environment_path);
expect(findEnvironmentLink().getAttribute('href')).toEqual(environment.environment_path);
expect(findClusterLink()).toBeNull(); expect(findJobDeploymentLink().attributes('href')).toBe('bar');
expect(findClusterLink().exists()).toBe(false);
}); });
}); });
...@@ -193,7 +197,7 @@ describe('Environments block', () => { ...@@ -193,7 +197,7 @@ describe('Environments block', () => {
environment, environment,
}); });
expect(findText()).toEqual('This job is creating a deployment to environment.'); expect(findText()).toBe('This job is creating a deployment to environment.');
}); });
describe('when there is a cluster', () => { describe('when there is a cluster', () => {
...@@ -206,7 +210,7 @@ describe('Environments block', () => { ...@@ -206,7 +210,7 @@ describe('Environments block', () => {
createDeploymentWithCluster(), createDeploymentWithCluster(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is creating a deployment to environment using cluster ${TEST_CLUSTER_NAME}.`, `This job is creating a deployment to environment using cluster ${TEST_CLUSTER_NAME}.`,
); );
}); });
...@@ -220,7 +224,7 @@ describe('Environments block', () => { ...@@ -220,7 +224,7 @@ describe('Environments block', () => {
environment: null, environment: null,
}); });
expect(findEnvironmentLink()).toBeNull(); expect(findEnvironmentLink().exists()).toBe(false);
}); });
}); });
}); });
...@@ -235,11 +239,11 @@ describe('Environments block', () => { ...@@ -235,11 +239,11 @@ describe('Environments block', () => {
createDeploymentWithCluster(), createDeploymentWithCluster(),
); );
expect(findText()).toEqual( expect(findText()).toBe(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`, `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
); );
expect(findClusterLink().getAttribute('href')).toEqual(TEST_CLUSTER_PATH); expect(findClusterLink().attributes('href')).toBe(TEST_CLUSTER_PATH);
}); });
describe('when the cluster is missing the path', () => { describe('when the cluster is missing the path', () => {
...@@ -254,7 +258,7 @@ describe('Environments block', () => { ...@@ -254,7 +258,7 @@ describe('Environments block', () => {
expect(findText()).toContain('using cluster the-cluster.'); expect(findText()).toContain('using cluster the-cluster.');
expect(findClusterLink()).toBeNull(); expect(findClusterLink().exists()).toBe(false);
}); });
}); });
}); });
......
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