Commit 6c9e74ac authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'afontaine/new-environments-folder' into 'master'

Set up entry point for new environments table

See merge request gitlab-org/gitlab!73025
parents 6c172a07 cea54a80
<script>
export default {};
</script>
<template>
<div></div>
</template>
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import environmentApp from './queries/environmentApp.query.graphql';
import { resolvers } from './resolvers';
import typedefs from './typedefs.graphql';
export const apolloProvider = (endpoint) => {
const defaultClient = createDefaultClient(
resolvers(endpoint),
{
assumeImmutableResults: true,
},
typedefs,
);
const { cache } = defaultClient;
cache.writeQuery({
query: environmentApp,
data: {
availableCount: 0,
environments: [],
reviewApp: {},
stoppedCount: 0,
},
});
return new VueApollo({
defaultClient,
});
};
mutation($environment: Environment) {
cancelAutoStop(environment: $environment) @client {
errors
}
}
mutation($environment: Environment) {
deleteEnvironment(environment: $environment) @client {
errors
}
}
mutation($environment: Environment) {
rollbackEnvironment(environment: $environment) @client {
errors
}
}
mutation($environment: Environment) {
stopEnvironment(environment: $environment) @client {
errors
}
}
query getEnvironmentApp {
environmentApp @client {
availableCount
environments
reviewApp
stoppedCount
}
}
query getEnvironmentFolder($environment: NestedEnvironment) {
folder(environment: $environment) @client {
availableCount
environments
stoppedCount
}
}
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
const mapNestedEnvironment = (env) => ({
...convertObjectPropsToCamelCase(env, { deep: true }),
__typename: 'NestedEnvironment',
});
const mapEnvironment = (env) => ({
...convertObjectPropsToCamelCase(env),
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Environment',
});
export const resolvers = (endpoint) => ({
Query: {
environmentApp() {
return axios.get(endpoint, { params: { nested: true } }).then((res) => ({
availableCount: res.data.available_count,
environments: res.data.environments.map(mapNestedEnvironment),
reviewApp: {
...convertObjectPropsToCamelCase(res.data.review_app),
__typename: 'ReviewApp',
},
stoppedCount: res.data.stopped_count,
__typename: 'EnvironmentApp',
}));
},
folder(_, { environment: { folderPath } }) {
return axios.get(folderPath, { params: { per_page: 3 } }).then((res) => ({
availableCount: res.data.available_count,
environments: res.data.environments.map(mapEnvironment),
stoppedCount: res.data.stopped_count,
__typename: 'EnvironmentFolder',
}));
},
},
Mutations: {
stopEnvironment(_, { environment: { stopPath } }) {
return axios.post(stopPath);
},
deleteEnvironment(_, { environment: { deletePath } }) {
return axios.delete(deletePath);
},
rollbackEnvironment(_, { environment: { retryUrl } }) {
return axios.post(retryUrl);
},
cancelAutoStop(_, { environment: { autoStopPath } }) {
return axios.post(autoStopPath);
},
},
});
type Environment {
id: Int!
globalId: ID!
name: String!
folderPath: String
stopPath: String
deletePath: String
retryUrl: String
autoStopPath: String
}
type NestedEnvironment {
name: String!
size: Int!
latest: Environment!
}
type EnvironmentFolder {
environments: [Environment!]!
availableCount: Int!
stoppedCount: Int!
}
type ReviewApp {
canSetupReviewApp: Boolean!
allClustersEmpty: Boolean!
reviewSnippet: String
}
type EnvironmentApp {
stoppedCount: Int!
availableCount: Int!
environments: [NestedEnvironment!]!
reviewApp: ReviewApp!
}
...@@ -12,37 +12,40 @@ const apolloProvider = new VueApollo({ ...@@ -12,37 +12,40 @@ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
}); });
export default () => { export default (el) => {
const el = document.getElementById('environments-list-view'); if (el) {
return new Vue({ return new Vue({
el, el,
components: { components: {
environmentsComponent, environmentsComponent,
}, },
apolloProvider, apolloProvider,
provide: { provide: {
projectPath: el.dataset.projectPath, projectPath: el.dataset.projectPath,
defaultBranchName: el.dataset.defaultBranchName, defaultBranchName: el.dataset.defaultBranchName,
}, },
data() { data() {
const environmentsData = el.dataset; const environmentsData = el.dataset;
return { return {
endpoint: environmentsData.environmentsDataEndpoint, endpoint: environmentsData.environmentsDataEndpoint,
newEnvironmentPath: environmentsData.newEnvironmentPath, newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath, helpPagePath: environmentsData.helpPagePath,
canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment), canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
}; };
}, },
render(createElement) { render(createElement) {
return createElement('environments-component', { return createElement('environments-component', {
props: { props: {
endpoint: this.endpoint, endpoint: this.endpoint,
newEnvironmentPath: this.newEnvironmentPath, newEnvironmentPath: this.newEnvironmentPath,
helpPagePath: this.helpPagePath, helpPagePath: this.helpPagePath,
canCreateEnvironment: this.canCreateEnvironment, canCreateEnvironment: this.canCreateEnvironment,
}, },
}); });
}, },
}); });
}
return null;
}; };
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { parseBoolean } from '../lib/utils/common_utils';
import { apolloProvider } from './graphql/client';
import EnvironmentsApp from './components/new_environments_app.vue';
Vue.use(VueApollo);
export default (el) => {
if (el) {
const {
canCreateEnvironment,
endpoint,
newEnvironmentPath,
helpPagePath,
projectPath,
defaultBranchName,
} = el.dataset;
return new Vue({
el,
apolloProvider: apolloProvider(endpoint),
provide: {
projectPath,
defaultBranchName,
endpoint,
newEnvironmentPath,
helpPagePath,
canCreateEnvironment: parseBoolean(canCreateEnvironment),
},
render(h) {
return h(EnvironmentsApp);
},
});
}
return null;
};
import initEnvironments from '~/environments/'; import initEnvironments from '~/environments/';
import initNewEnvironments from '~/environments/new_index';
initEnvironments(); let el = document.getElementById('environments-list-view');
if (el) {
initEnvironments(el);
} else {
el = document.getElementById('environments-table');
initNewEnvironments(el);
}
- page_title _("Environments") - page_title _("Environments")
- add_page_specific_style 'page_bundles/environments'
#environments-list-view{ data: { environments_data: environments_list_data, - if Feature.enabled?(:new_environments_table)
"can-read-environment" => can?(current_user, :read_environment, @project).to_s, #environments-table{ data: { endpoint: project_environments_path(@project, format: :json),
"can-create-environment" => can?(current_user, :create_environment, @project).to_s, "can-read-environment" => can?(current_user, :read_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project), "can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"help-page-path" => help_page_path("ci/environments/index.md"), "new-environment-path" => new_project_environment_path(@project),
"project-path" => @project.full_path, "help-page-path" => help_page_path("ci/environments/index.md"),
"default-branch-name" => @project.default_branch_or_main } } "project-path" => @project.full_path,
"default-branch-name" => @project.default_branch_or_main } }
- else
- add_page_specific_style 'page_bundles/environments'
#environments-list-view{ data: { environments_data: environments_list_data,
"can-read-environment" => can?(current_user, :read_environment, @project).to_s,
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
"help-page-path" => help_page_path("ci/environments/index.md"),
"project-path" => @project.full_path,
"default-branch-name" => @project.default_branch_or_main } }
---
name: new_environments_table
introduced_by_url:
rollout_issue_url:
milestone: '14.4'
type: development
group: group::release
default_enabled: false
...@@ -8,6 +8,7 @@ RSpec.describe 'Environments page', :js do ...@@ -8,6 +8,7 @@ RSpec.describe 'Environments page', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
stub_feature_flags(new_environments_table: false)
allow(License).to receive(:feature_available?).and_call_original allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:protected_environments).and_return(true) allow(License).to receive(:feature_available?).with(:protected_environments).and_return(true)
project.add_maintainer(user) project.add_maintainer(user)
......
...@@ -8,6 +8,7 @@ RSpec.describe 'Environments page', :js do ...@@ -8,6 +8,7 @@ RSpec.describe 'Environments page', :js do
let(:role) { :developer } let(:role) { :developer }
before do before do
stub_feature_flags(new_environments_table: false)
project.add_role(user, role) project.add_role(user, role)
sign_in(user) sign_in(user)
end end
......
export const environmentsApp = {
environments: [
{
name: 'production',
size: 1,
latest: {
id: 8,
global_id: 'gid://gitlab/Environment/8',
name: 'production',
state: 'available',
external_url: 'https://example.org',
environment_type: null,
name_without_type: 'production',
last_deployment: {
id: 80,
iid: 24,
sha: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
ref: {
name: 'root-master-patch-18104',
ref_path: '/h5bp/html5-boilerplate/-/tree/root-master-patch-18104',
},
status: 'success',
created_at: '2021-10-08T19:53:54.543Z',
deployed_at: '2021-10-08T20:02:36.763Z',
tag: false,
'last?': true,
user: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
web_url: 'http://gdk.test:3000/root',
show_status: false,
path: '/root',
},
deployable: {
id: 911,
name: 'deploy-job',
started: '2021-10-08T19:54:00.658Z',
complete: true,
archived: false,
build_path: '/h5bp/html5-boilerplate/-/jobs/911',
retry_path: '/h5bp/html5-boilerplate/-/jobs/911/retry',
play_path: '/h5bp/html5-boilerplate/-/jobs/911/play',
playable: true,
scheduled: false,
created_at: '2021-10-08T19:53:54.482Z',
updated_at: '2021-10-08T20:02:36.730Z',
status: {
icon: 'status_success',
text: 'passed',
label: 'manual play action',
group: 'success',
tooltip: 'passed',
has_details: true,
details_path: '/h5bp/html5-boilerplate/-/jobs/911',
illustration: {
image:
'/assets/illustrations/manual_action-c55aee2c5f9ebe9f72751480af8bb307be1a6f35552f344cc6d1bf979d3422f6.svg',
size: 'svg-394',
title: 'This job requires a manual action',
content:
'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.',
},
favicon:
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
action: {
icon: 'play',
title: 'Play',
path: '/h5bp/html5-boilerplate/-/jobs/911/play',
method: 'post',
button_title: 'Trigger this manual action',
},
},
},
commit: {
id: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
short_id: '4ca03103',
created_at: '2021-10-08T19:27:01.000+00:00',
parent_ids: ['b385360b15bd61391a0efbd101788d4a80387270'],
title: 'Update .gitlab-ci.yml',
message: 'Update .gitlab-ci.yml',
author_name: 'Administrator',
author_email: 'admin@example.com',
authored_date: '2021-10-08T19:27:01.000+00:00',
committer_name: 'Administrator',
committer_email: 'admin@example.com',
committed_date: '2021-10-08T19:27:01.000+00:00',
trailers: {},
web_url:
'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
author: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
web_url: 'http://gdk.test:3000/root',
show_status: false,
path: '/root',
},
author_gravatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
commit_url:
'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
commit_path:
'/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
},
manual_actions: [],
scheduled_actions: [],
playable_build: {
retry_path: '/h5bp/html5-boilerplate/-/jobs/911/retry',
play_path: '/h5bp/html5-boilerplate/-/jobs/911/play',
},
cluster: null,
},
has_stop_action: false,
rollout_status: null,
environment_path: '/h5bp/html5-boilerplate/-/environments/8',
stop_path: '/h5bp/html5-boilerplate/-/environments/8/stop',
cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/8/cancel_auto_stop',
delete_path: '/api/v4/projects/8/environments/8',
folder_path: '/h5bp/html5-boilerplate/-/environments/folders/production',
created_at: '2021-06-17T15:09:38.599Z',
updated_at: '2021-10-08T19:50:44.445Z',
can_stop: true,
logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=production',
logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=production',
enable_advanced_logs_querying: false,
can_delete: false,
has_opened_alert: false,
},
},
{
name: 'review',
size: 2,
latest: {
id: 42,
global_id: 'gid://gitlab/Environment/42',
name: 'review/goodbye',
state: 'available',
external_url: 'https://example.org',
environment_type: 'review',
name_without_type: 'goodbye',
last_deployment: null,
has_stop_action: false,
rollout_status: null,
environment_path: '/h5bp/html5-boilerplate/-/environments/42',
stop_path: '/h5bp/html5-boilerplate/-/environments/42/stop',
cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
delete_path: '/api/v4/projects/8/environments/42',
folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
created_at: '2021-10-04T19:27:20.639Z',
updated_at: '2021-10-04T19:27:20.639Z',
can_stop: true,
logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
enable_advanced_logs_querying: false,
can_delete: false,
has_opened_alert: false,
},
},
{
name: 'staging',
size: 1,
latest: {
id: 7,
global_id: 'gid://gitlab/Environment/7',
name: 'staging',
state: 'available',
external_url: null,
environment_type: null,
name_without_type: 'staging',
last_deployment: null,
has_stop_action: false,
rollout_status: null,
environment_path: '/h5bp/html5-boilerplate/-/environments/7',
stop_path: '/h5bp/html5-boilerplate/-/environments/7/stop',
cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/7/cancel_auto_stop',
delete_path: '/api/v4/projects/8/environments/7',
folder_path: '/h5bp/html5-boilerplate/-/environments/folders/staging',
created_at: '2021-06-17T15:09:38.570Z',
updated_at: '2021-06-17T15:09:38.570Z',
can_stop: true,
logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=staging',
logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=staging',
enable_advanced_logs_querying: false,
can_delete: false,
has_opened_alert: false,
},
},
],
review_app: {
can_setup_review_app: true,
all_clusters_empty: true,
review_snippet:
'{"deploy_review"=>{"stage"=>"deploy", "script"=>["echo \\"Deploy a review app\\""], "environment"=>{"name"=>"review/$CI_COMMIT_REF_NAME", "url"=>"https://$CI_ENVIRONMENT_SLUG.example.com"}, "only"=>["branches"]}}',
},
available_count: 4,
stopped_count: 0,
};
export const resolvedEnvironmentsApp = {
availableCount: 4,
environments: [
{
name: 'production',
size: 1,
latest: {
id: 8,
globalId: 'gid://gitlab/Environment/8',
name: 'production',
state: 'available',
externalUrl: 'https://example.org',
environmentType: null,
nameWithoutType: 'production',
lastDeployment: {
id: 80,
iid: 24,
sha: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
ref: {
name: 'root-master-patch-18104',
refPath: '/h5bp/html5-boilerplate/-/tree/root-master-patch-18104',
},
status: 'success',
createdAt: '2021-10-08T19:53:54.543Z',
deployedAt: '2021-10-08T20:02:36.763Z',
tag: false,
'last?': true,
user: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
webUrl: 'http://gdk.test:3000/root',
showStatus: false,
path: '/root',
},
deployable: {
id: 911,
name: 'deploy-job',
started: '2021-10-08T19:54:00.658Z',
complete: true,
archived: false,
buildPath: '/h5bp/html5-boilerplate/-/jobs/911',
retryPath: '/h5bp/html5-boilerplate/-/jobs/911/retry',
playPath: '/h5bp/html5-boilerplate/-/jobs/911/play',
playable: true,
scheduled: false,
createdAt: '2021-10-08T19:53:54.482Z',
updatedAt: '2021-10-08T20:02:36.730Z',
status: {
icon: 'status_success',
text: 'passed',
label: 'manual play action',
group: 'success',
tooltip: 'passed',
hasDetails: true,
detailsPath: '/h5bp/html5-boilerplate/-/jobs/911',
illustration: {
image:
'/assets/illustrations/manual_action-c55aee2c5f9ebe9f72751480af8bb307be1a6f35552f344cc6d1bf979d3422f6.svg',
size: 'svg-394',
title: 'This job requires a manual action',
content:
'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.',
},
favicon:
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
action: {
icon: 'play',
title: 'Play',
path: '/h5bp/html5-boilerplate/-/jobs/911/play',
method: 'post',
buttonTitle: 'Trigger this manual action',
},
},
},
commit: {
id: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
shortId: '4ca03103',
createdAt: '2021-10-08T19:27:01.000+00:00',
parentIds: ['b385360b15bd61391a0efbd101788d4a80387270'],
title: 'Update .gitlab-ci.yml',
message: 'Update .gitlab-ci.yml',
authorName: 'Administrator',
authorEmail: 'admin@example.com',
authoredDate: '2021-10-08T19:27:01.000+00:00',
committerName: 'Administrator',
committerEmail: 'admin@example.com',
committedDate: '2021-10-08T19:27:01.000+00:00',
trailers: {},
webUrl:
'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
author: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
webUrl: 'http://gdk.test:3000/root',
showStatus: false,
path: '/root',
},
authorGravatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
commitUrl:
'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
commitPath: '/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
},
manualActions: [],
scheduledActions: [],
playableBuild: {
retryPath: '/h5bp/html5-boilerplate/-/jobs/911/retry',
playPath: '/h5bp/html5-boilerplate/-/jobs/911/play',
},
cluster: null,
},
hasStopAction: false,
rolloutStatus: null,
environmentPath: '/h5bp/html5-boilerplate/-/environments/8',
stopPath: '/h5bp/html5-boilerplate/-/environments/8/stop',
cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/8/cancel_auto_stop',
deletePath: '/api/v4/projects/8/environments/8',
folderPath: '/h5bp/html5-boilerplate/-/environments/folders/production',
createdAt: '2021-06-17T15:09:38.599Z',
updatedAt: '2021-10-08T19:50:44.445Z',
canStop: true,
logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=production',
logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=production',
enableAdvancedLogsQuerying: false,
canDelete: false,
hasOpenedAlert: false,
},
__typename: 'NestedEnvironment',
},
{
name: 'review',
size: 2,
latest: {
id: 42,
globalId: 'gid://gitlab/Environment/42',
name: 'review/goodbye',
state: 'available',
externalUrl: 'https://example.org',
environmentType: 'review',
nameWithoutType: 'goodbye',
lastDeployment: null,
hasStopAction: false,
rolloutStatus: null,
environmentPath: '/h5bp/html5-boilerplate/-/environments/42',
stopPath: '/h5bp/html5-boilerplate/-/environments/42/stop',
cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
deletePath: '/api/v4/projects/8/environments/42',
folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
createdAt: '2021-10-04T19:27:20.639Z',
updatedAt: '2021-10-04T19:27:20.639Z',
canStop: true,
logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
enableAdvancedLogsQuerying: false,
canDelete: false,
hasOpenedAlert: false,
},
__typename: 'NestedEnvironment',
},
{
name: 'staging',
size: 1,
latest: {
id: 7,
globalId: 'gid://gitlab/Environment/7',
name: 'staging',
state: 'available',
externalUrl: null,
environmentType: null,
nameWithoutType: 'staging',
lastDeployment: null,
hasStopAction: false,
rolloutStatus: null,
environmentPath: '/h5bp/html5-boilerplate/-/environments/7',
stopPath: '/h5bp/html5-boilerplate/-/environments/7/stop',
cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/7/cancel_auto_stop',
deletePath: '/api/v4/projects/8/environments/7',
folderPath: '/h5bp/html5-boilerplate/-/environments/folders/staging',
createdAt: '2021-06-17T15:09:38.570Z',
updatedAt: '2021-06-17T15:09:38.570Z',
canStop: true,
logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=staging',
logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=staging',
enableAdvancedLogsQuerying: false,
canDelete: false,
hasOpenedAlert: false,
},
__typename: 'NestedEnvironment',
},
],
reviewApp: {
canSetupReviewApp: true,
allClustersEmpty: true,
reviewSnippet:
'{"deploy_review"=>{"stage"=>"deploy", "script"=>["echo \\"Deploy a review app\\""], "environment"=>{"name"=>"review/$CI_COMMIT_REF_NAME", "url"=>"https://$CI_ENVIRONMENT_SLUG.example.com"}, "only"=>["branches"]}}',
__typename: 'ReviewApp',
},
stoppedCount: 0,
__typename: 'EnvironmentApp',
};
export const folder = {
environments: [
{
id: 42,
global_id: 'gid://gitlab/Environment/42',
name: 'review/goodbye',
state: 'available',
external_url: 'https://example.org',
environment_type: 'review',
name_without_type: 'goodbye',
last_deployment: null,
has_stop_action: false,
rollout_status: null,
environment_path: '/h5bp/html5-boilerplate/-/environments/42',
stop_path: '/h5bp/html5-boilerplate/-/environments/42/stop',
cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
delete_path: '/api/v4/projects/8/environments/42',
folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
created_at: '2021-10-04T19:27:20.639Z',
updated_at: '2021-10-04T19:27:20.639Z',
can_stop: true,
logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
enable_advanced_logs_querying: false,
can_delete: false,
has_opened_alert: false,
},
{
id: 41,
global_id: 'gid://gitlab/Environment/41',
name: 'review/hello',
state: 'available',
external_url: 'https://example.org',
environment_type: 'review',
name_without_type: 'hello',
last_deployment: null,
has_stop_action: false,
rollout_status: null,
environment_path: '/h5bp/html5-boilerplate/-/environments/41',
stop_path: '/h5bp/html5-boilerplate/-/environments/41/stop',
cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/41/cancel_auto_stop',
delete_path: '/api/v4/projects/8/environments/41',
folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
created_at: '2021-10-04T19:27:00.527Z',
updated_at: '2021-10-04T19:27:00.527Z',
can_stop: true,
logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fhello',
logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fhello',
enable_advanced_logs_querying: false,
can_delete: false,
has_opened_alert: false,
},
],
available_count: 2,
stopped_count: 0,
};
export const resolvedFolder = {
availableCount: 2,
environments: [
{
id: 42,
globalId: 'gid://gitlab/Environment/42',
name: 'review/goodbye',
state: 'available',
externalUrl: 'https://example.org',
environmentType: 'review',
nameWithoutType: 'goodbye',
lastDeployment: null,
hasStopAction: false,
rolloutStatus: null,
environmentPath: '/h5bp/html5-boilerplate/-/environments/42',
stopPath: '/h5bp/html5-boilerplate/-/environments/42/stop',
cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
deletePath: '/api/v4/projects/8/environments/42',
folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
createdAt: '2021-10-04T19:27:20.639Z',
updatedAt: '2021-10-04T19:27:20.639Z',
canStop: true,
logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
enableAdvancedLogsQuerying: false,
canDelete: false,
hasOpenedAlert: false,
__typename: 'Environment',
},
{
id: 41,
globalId: 'gid://gitlab/Environment/41',
name: 'review/hello',
state: 'available',
externalUrl: 'https://example.org',
environmentType: 'review',
nameWithoutType: 'hello',
lastDeployment: null,
hasStopAction: false,
rolloutStatus: null,
environmentPath: '/h5bp/html5-boilerplate/-/environments/41',
stopPath: '/h5bp/html5-boilerplate/-/environments/41/stop',
cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/41/cancel_auto_stop',
deletePath: '/api/v4/projects/8/environments/41',
folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
createdAt: '2021-10-04T19:27:00.527Z',
updatedAt: '2021-10-04T19:27:00.527Z',
canStop: true,
logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fhello',
logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fhello',
enableAdvancedLogsQuerying: false,
canDelete: false,
hasOpenedAlert: false,
__typename: 'Environment',
},
],
stoppedCount: 0,
__typename: 'EnvironmentFolder',
};
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { resolvers } from '~/environments/graphql/resolvers';
import { TEST_HOST } from 'helpers/test_constants';
import { environmentsApp, resolvedEnvironmentsApp, folder, resolvedFolder } from './mock_data';
const ENDPOINT = `${TEST_HOST}/environments`;
describe('~/frontend/environments/graphql/resolvers', () => {
let mockResolvers;
let mock;
beforeEach(() => {
mockResolvers = resolvers(ENDPOINT);
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.reset();
});
describe('environmentApp', () => {
it('should fetch environments and map them to frontend data', async () => {
mock.onGet(ENDPOINT, { params: { nested: true } }).reply(200, environmentsApp);
const app = await mockResolvers.Query.environmentApp();
expect(app).toEqual(resolvedEnvironmentsApp);
});
});
describe('folder', () => {
it('should fetch the folder url passed to it', async () => {
mock.onGet(ENDPOINT, { params: { per_page: 3 } }).reply(200, folder);
const environmentFolder = await mockResolvers.Query.folder(null, {
environment: { folderPath: ENDPOINT },
});
expect(environmentFolder).toEqual(resolvedFolder);
});
});
describe('stopEnvironment', () => {
it('should post to the stop environment path', async () => {
mock.onPost(ENDPOINT).reply(200);
await mockResolvers.Mutations.stopEnvironment(null, { environment: { stopPath: ENDPOINT } });
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
);
});
});
describe('rollbackEnvironment', () => {
it('should post to the retry environment path', async () => {
mock.onPost(ENDPOINT).reply(200);
await mockResolvers.Mutations.rollbackEnvironment(null, {
environment: { retryUrl: ENDPOINT },
});
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
);
});
});
describe('deleteEnvironment', () => {
it('should DELETE to the delete environment path', async () => {
mock.onDelete(ENDPOINT).reply(200);
await mockResolvers.Mutations.deleteEnvironment(null, {
environment: { deletePath: ENDPOINT },
});
expect(mock.history.delete).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'delete' }),
);
});
});
describe('cancelAutoStop', () => {
it('should post to the auto stop path', async () => {
mock.onPost(ENDPOINT).reply(200);
await mockResolvers.Mutations.cancelAutoStop(null, {
environment: { autoStopPath: ENDPOINT },
});
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
);
});
});
});
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