Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
fe2a5493
Commit
fe2a5493
authored
Apr 12, 2022
by
Alex Buijs
Committed by
Jose Ivan Vargas
Apr 13, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor pipeline empty state ci templates
So we can re-use ci templates individually
parent
da10c4a7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
188 additions
and
120 deletions
+188
-120
app/assets/javascripts/pipeline_editor/constants.js
app/assets/javascripts/pipeline_editor/constants.js
+0
-2
app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
...ripts/pipelines/components/pipelines_list/empty_state.vue
+1
-1
app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
...es/components/pipelines_list/empty_state/ci_templates.vue
+81
-0
app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue
...nts/pipelines_list/empty_state/pipelines_ci_templates.vue
+7
-55
spec/frontend/pipelines/empty_state/ci_templates_spec.js
spec/frontend/pipelines/empty_state/ci_templates_spec.js
+85
-0
spec/frontend/pipelines/empty_state/pipelines_ci_templates_spec.js
...tend/pipelines/empty_state/pipelines_ci_templates_spec.js
+12
-60
spec/frontend/pipelines/empty_state_spec.js
spec/frontend/pipelines/empty_state_spec.js
+1
-1
spec/frontend/pipelines/pipelines_spec.js
spec/frontend/pipelines/pipelines_spec.js
+1
-1
No files found.
app/assets/javascripts/pipeline_editor/constants.js
View file @
fe2a5493
...
...
@@ -100,7 +100,5 @@ export const I18N = {
subtitle
:
s__
(
"
Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD.
"
,
),
description
:
s__
(
'
Pipelines|CI/CD template to test and deploy your %{name} project.
'
),
cta
:
s__
(
'
Pipelines|Use template
'
),
},
};
app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
View file @
fe2a5493
<
script
>
import
{
GlEmptyState
}
from
'
@gitlab/ui
'
;
import
{
s__
}
from
'
~/locale
'
;
import
PipelinesCiTemplates
from
'
./pipelines_ci_templates.vue
'
;
import
PipelinesCiTemplates
from
'
./
empty_state/
pipelines_ci_templates.vue
'
;
export
default
{
i18n
:
{
...
...
app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
0 → 100644
View file @
fe2a5493
<
script
>
import
{
GlAvatar
,
GlButton
}
from
'
@gitlab/ui
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
mergeUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
{
AVATAR_SHAPE_OPTION_RECT
}
from
'
~/vue_shared/constants
'
;
import
Tracking
from
'
~/tracking
'
;
export
default
{
components
:
{
GlAvatar
,
GlButton
,
},
mixins
:
[
Tracking
.
mixin
()],
inject
:
[
'
pipelineEditorPath
'
,
'
suggestedCiTemplates
'
],
data
()
{
const
templates
=
this
.
suggestedCiTemplates
.
map
(({
name
,
logo
})
=>
{
return
{
name
,
logo
,
link
:
mergeUrlParams
({
template
:
name
},
this
.
pipelineEditorPath
),
description
:
sprintf
(
this
.
$options
.
i18n
.
description
,
{
name
}),
};
});
return
{
templates
,
};
},
methods
:
{
trackEvent
(
template
)
{
this
.
track
(
'
template_clicked
'
,
{
label
:
template
,
});
},
},
i18n
:
{
description
:
s__
(
'
Pipelines|CI/CD template to test and deploy your %{name} project.
'
),
cta
:
s__
(
'
Pipelines|Use template
'
),
},
AVATAR_SHAPE_OPTION_RECT
,
};
</
script
>
<
template
>
<ul
class=
"gl-list-style-none gl-pl-0"
>
<li
v-for=
"template in templates"
:key=
"template.name"
>
<div
class=
"gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
>
<div
class=
"gl-display-flex gl-flex-direction-row gl-align-items-center"
>
<gl-avatar
:src=
"template.logo"
:size=
"48"
class=
"gl-mr-5 gl-bg-white dark-mode-override"
:shape=
"$options.AVATAR_SHAPE_OPTION_RECT"
:alt=
"template.name"
data-testid=
"template-logo"
/>
<div
class=
"gl-flex-direction-row"
>
<div
class=
"gl-mb-3"
>
<strong
class=
"gl-text-gray-800"
data-testid=
"template-name"
>
{{
template
.
name
}}
</strong>
</div>
<p
class=
"gl-mb-0 gl-font-sm"
data-testid=
"template-description"
>
{{
template
.
description
}}
</p>
</div>
</div>
<gl-button
category=
"primary"
variant=
"confirm"
:href=
"template.link"
data-testid=
"template-link"
@
click=
"trackEvent(template.name)"
>
{{
$options
.
i18n
.
cta
}}
</gl-button>
</div>
</li>
</ul>
</
template
>
app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
→
app/assets/javascripts/pipelines/components/pipelines_list/
empty_state/
pipelines_ci_templates.vue
View file @
fe2a5493
<
script
>
import
{
Gl
Avatar
,
Gl
Button
,
GlCard
,
GlSprintf
,
GlIcon
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
GlButton
,
GlCard
,
GlSprintf
,
GlIcon
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
mergeUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
{
sprintf
}
from
'
~/locale
'
;
import
{
AVATAR_SHAPE_OPTION_RECT
}
from
'
~/vue_shared/constants
'
;
import
{
STARTER_TEMPLATE_NAME
,
RUNNERS_AVAILABILITY_SECTION_EXPERIMENT_NAME
,
...
...
@@ -11,21 +9,22 @@ import {
RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT
,
I18N
,
}
from
'
~/pipeline_editor/constants
'
;
import
Tracking
from
'
~/tracking
'
;
import
{
helpPagePath
}
from
'
~/helpers/help_page_helper
'
;
import
{
isExperimentVariant
}
from
'
~/experimentation/utils
'
;
import
GitlabExperiment
from
'
~/experimentation/components/gitlab_experiment.vue
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
{
isExperimentVariant
}
from
'
~/experimentation/utils
'
;
import
Tracking
from
'
~/tracking
'
;
import
CiTemplates
from
'
./ci_templates.vue
'
;
export
default
{
components
:
{
GlAvatar
,
GlButton
,
GlCard
,
GlSprintf
,
GlIcon
,
GlLink
,
GitlabExperiment
,
CiTemplates
,
},
mixins
:
[
Tracking
.
mixin
()],
STARTER_TEMPLATE_NAME
,
...
...
@@ -34,8 +33,7 @@ export default {
RUNNERS_DOCUMENTATION_LINK_CLICKED_EVENT
,
RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT
,
I18N
,
AVATAR_SHAPE_OPTION_RECT
,
inject
:
[
'
pipelineEditorPath
'
,
'
suggestedCiTemplates
'
],
inject
:
[
'
pipelineEditorPath
'
],
props
:
{
ciRunnerSettingsPath
:
{
type
:
String
,
...
...
@@ -49,17 +47,7 @@ export default {
},
},
data
()
{
const
templates
=
this
.
suggestedCiTemplates
.
map
(({
name
,
logo
})
=>
{
return
{
name
,
logo
,
link
:
mergeUrlParams
({
template
:
name
},
this
.
pipelineEditorPath
),
description
:
sprintf
(
this
.
$options
.
I18N
.
templates
.
description
,
{
name
}),
};
});
return
{
templates
,
gettingStartedTemplateUrl
:
mergeUrlParams
(
{
template
:
STARTER_TEMPLATE_NAME
},
this
.
pipelineEditorPath
,
...
...
@@ -179,43 +167,7 @@ export default {
<h2
class=
"gl-font-lg gl-text-gray-900"
>
{{ $options.I18N.templates.title }}
</h2>
<p
class=
"gl-text-gray-800 gl-mb-6"
>
{{ $options.I18N.templates.subtitle }}
</p>
<ul
class=
"gl-list-style-none gl-pl-0"
>
<li
v-for=
"template in templates"
:key=
"template.name"
>
<div
class=
"gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
>
<div
class=
"gl-display-flex gl-flex-direction-row gl-align-items-center"
>
<gl-avatar
:src=
"template.logo"
:size=
"48"
class=
"gl-mr-5 gl-bg-white dark-mode-override"
:shape=
"$options.AVATAR_SHAPE_OPTION_RECT"
:alt=
"template.name"
data-testid=
"template-logo"
/>
<div
class=
"gl-flex-direction-row"
>
<div
class=
"gl-mb-3"
>
<strong
class=
"gl-text-gray-800"
data-testid=
"template-name"
>
{{ template.name }}
</strong>
</div>
<p
class=
"gl-mb-0 gl-font-sm"
data-testid=
"template-description"
>
{{ template.description }}
</p>
</div>
</div>
<gl-button
category=
"primary"
variant=
"confirm"
:href=
"template.link"
data-testid=
"template-link"
@
click=
"trackEvent(template.name)"
>
{{ $options.I18N.templates.cta }}
</gl-button>
</div>
</li>
</ul>
<ci-templates
/>
</template>
</div>
</template>
spec/frontend/pipelines/empty_state/ci_templates_spec.js
0 → 100644
View file @
fe2a5493
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
mockTracking
,
unmockTracking
}
from
'
helpers/tracking_helper
'
;
import
CiTemplates
from
'
~/pipelines/components/pipelines_list/empty_state/ci_templates.vue
'
;
const
pipelineEditorPath
=
'
/-/ci/editor
'
;
const
suggestedCiTemplates
=
[
{
name
:
'
Android
'
,
logo
:
'
/assets/illustrations/logos/android.svg
'
},
{
name
:
'
Bash
'
,
logo
:
'
/assets/illustrations/logos/bash.svg
'
},
{
name
:
'
C++
'
,
logo
:
'
/assets/illustrations/logos/c_plus_plus.svg
'
},
];
describe
(
'
CI Templates
'
,
()
=>
{
let
wrapper
;
let
trackingSpy
;
const
createWrapper
=
()
=>
{
return
shallowMountExtended
(
CiTemplates
,
{
provide
:
{
pipelineEditorPath
,
suggestedCiTemplates
,
},
});
};
const
findTemplateDescription
=
()
=>
wrapper
.
findByTestId
(
'
template-description
'
);
const
findTemplateLink
=
()
=>
wrapper
.
findByTestId
(
'
template-link
'
);
const
findTemplateName
=
()
=>
wrapper
.
findByTestId
(
'
template-name
'
);
const
findTemplateLogo
=
()
=>
wrapper
.
findByTestId
(
'
template-logo
'
);
beforeEach
(()
=>
{
wrapper
=
createWrapper
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
renders template list
'
,
()
=>
{
it
(
'
renders all suggested templates
'
,
()
=>
{
const
content
=
wrapper
.
text
();
expect
(
content
).
toContain
(
'
Android
'
,
'
Bash
'
,
'
C++
'
);
});
it
(
'
has the correct template name
'
,
()
=>
{
expect
(
findTemplateName
().
text
()).
toBe
(
'
Android
'
);
});
it
(
'
links to the correct template
'
,
()
=>
{
expect
(
findTemplateLink
().
attributes
(
'
href
'
)).
toBe
(
pipelineEditorPath
.
concat
(
'
?template=Android
'
),
);
});
it
(
'
has the description of the template
'
,
()
=>
{
expect
(
findTemplateDescription
().
text
()).
toBe
(
'
CI/CD template to test and deploy your Android project.
'
,
);
});
it
(
'
has the right logo of the template
'
,
()
=>
{
expect
(
findTemplateLogo
().
attributes
(
'
src
'
)).
toBe
(
'
/assets/illustrations/logos/android.svg
'
);
});
});
describe
(
'
tracking
'
,
()
=>
{
beforeEach
(()
=>
{
trackingSpy
=
mockTracking
(
undefined
,
wrapper
.
element
,
jest
.
spyOn
);
});
afterEach
(()
=>
{
unmockTracking
();
});
it
(
'
sends an event when template is clicked
'
,
()
=>
{
findTemplateLink
().
vm
.
$emit
(
'
click
'
);
expect
(
trackingSpy
).
toHaveBeenCalledTimes
(
1
);
expect
(
trackingSpy
).
toHaveBeenCalledWith
(
undefined
,
'
template_clicked
'
,
{
label
:
'
Android
'
,
});
});
});
});
spec/frontend/pipelines/pipelines_ci_templates_spec.js
→
spec/frontend/pipelines/
empty_state/
pipelines_ci_templates_spec.js
View file @
fe2a5493
import
'
~/commons
'
;
import
{
GlButton
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
sprintf
}
from
'
~/locale
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
mockTracking
}
from
'
helpers/tracking_helper
'
;
import
{
mockTracking
,
unmockTracking
}
from
'
helpers/tracking_helper
'
;
import
{
stubExperiments
}
from
'
helpers/experimentation_helper
'
;
import
GitlabExperiment
from
'
~/experimentation/components/gitlab_experiment.vue
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
PipelinesCiTemplate
from
'
~/pipelines/components/pipelines_list/pipelines_ci_templates.vue
'
;
import
PipelinesCiTemplates
from
'
~/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue
'
;
import
CiTemplates
from
'
~/pipelines/components/pipelines_list/empty_state/ci_templates.vue
'
;
import
{
RUNNERS_AVAILABILITY_SECTION_EXPERIMENT_NAME
,
RUNNERS_SETTINGS_LINK_CLICKED_EVENT
,
...
...
@@ -16,11 +16,6 @@ import {
}
from
'
~/pipeline_editor/constants
'
;
const
pipelineEditorPath
=
'
/-/ci/editor
'
;
const
suggestedCiTemplates
=
[
{
name
:
'
Android
'
,
logo
:
'
/assets/illustrations/logos/android.svg
'
},
{
name
:
'
Bash
'
,
logo
:
'
/assets/illustrations/logos/bash.svg
'
},
{
name
:
'
C++
'
,
logo
:
'
/assets/illustrations/logos/c_plus_plus.svg
'
},
];
jest
.
mock
(
'
~/experimentation/experiment_tracking
'
);
...
...
@@ -29,21 +24,17 @@ describe('Pipelines CI Templates', () => {
let
trackingSpy
;
const
createWrapper
=
(
propsData
=
{},
stubs
=
{})
=>
{
return
shallowMountExtended
(
PipelinesCiTemplate
,
{
return
shallowMountExtended
(
PipelinesCiTemplate
s
,
{
provide
:
{
pipelineEditorPath
,
suggestedCiTemplates
,
},
propsData
,
stubs
,
});
};
const
findTestTemplateLinks
=
()
=>
wrapper
.
findAll
(
'
[data-testid="test-template-link"]
'
);
const
findTemplateDescriptions
=
()
=>
wrapper
.
findAll
(
'
[data-testid="template-description"]
'
);
const
findTemplateLinks
=
()
=>
wrapper
.
findAll
(
'
[data-testid="template-link"]
'
);
const
findTemplateNames
=
()
=>
wrapper
.
findAll
(
'
[data-testid="template-name"]
'
);
const
findTemplateLogos
=
()
=>
wrapper
.
findAll
(
'
[data-testid="template-logo"]
'
);
const
findTestTemplateLink
=
()
=>
wrapper
.
findByTestId
(
'
test-template-link
'
);
const
findCiTemplates
=
()
=>
wrapper
.
findComponent
(
CiTemplates
);
const
findSettingsLink
=
()
=>
wrapper
.
findByTestId
(
'
settings-link
'
);
const
findDocumentationLink
=
()
=>
wrapper
.
findByTestId
(
'
documentation-link
'
);
const
findSettingsButton
=
()
=>
wrapper
.
findByTestId
(
'
settings-button
'
);
...
...
@@ -59,63 +50,24 @@ describe('Pipelines CI Templates', () => {
});
it
(
'
links to the getting started template
'
,
()
=>
{
expect
(
findTestTemplateLink
s
().
at
(
0
).
attributes
(
'
href
'
)).
toBe
(
expect
(
findTestTemplateLink
(
).
attributes
(
'
href
'
)).
toBe
(
pipelineEditorPath
.
concat
(
'
?template=Getting-Started
'
),
);
});
});
describe
(
'
renders template list
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createWrapper
();
});
it
(
'
renders all suggested templates
'
,
()
=>
{
const
content
=
wrapper
.
text
();
expect
(
content
).
toContain
(
'
Android
'
,
'
Bash
'
,
'
C++
'
);
});
it
(
'
has the correct template name
'
,
()
=>
{
expect
(
findTemplateNames
().
at
(
0
).
text
()).
toBe
(
'
Android
'
);
});
it
(
'
links to the correct template
'
,
()
=>
{
expect
(
findTemplateLinks
().
at
(
0
).
attributes
(
'
href
'
)).
toBe
(
pipelineEditorPath
.
concat
(
'
?template=Android
'
),
);
});
it
(
'
has the description of the template
'
,
()
=>
{
expect
(
findTemplateDescriptions
().
at
(
0
).
text
()).
toBe
(
sprintf
(
I18N
.
templates
.
description
,
{
name
:
'
Android
'
}),
);
});
it
(
'
has the right logo of the template
'
,
()
=>
{
expect
(
findTemplateLogos
().
at
(
0
).
attributes
(
'
src
'
)).
toBe
(
'
/assets/illustrations/logos/android.svg
'
,
);
});
});
describe
(
'
tracking
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createWrapper
();
trackingSpy
=
mockTracking
(
undefined
,
wrapper
.
element
,
jest
.
spyOn
);
});
it
(
'
sends an event when template is clicked
'
,
()
=>
{
findTemplateLinks
().
at
(
0
).
vm
.
$emit
(
'
click
'
);
expect
(
trackingSpy
).
toHaveBeenCalledTimes
(
1
);
expect
(
trackingSpy
).
toHaveBeenCalledWith
(
undefined
,
'
template_clicked
'
,
{
label
:
'
Android
'
,
});
afterEach
(()
=>
{
unmockTracking
();
});
it
(
'
sends an event when Getting-Started template is clicked
'
,
()
=>
{
findTestTemplateLink
s
().
at
(
0
).
vm
.
$emit
(
'
click
'
);
findTestTemplateLink
(
).
vm
.
$emit
(
'
click
'
);
expect
(
trackingSpy
).
toHaveBeenCalledTimes
(
1
);
expect
(
trackingSpy
).
toHaveBeenCalledWith
(
undefined
,
'
template_clicked
'
,
{
...
...
@@ -198,8 +150,8 @@ describe('Pipelines CI Templates', () => {
});
it
(
`renders the templates:
${
templatesRendered
}
`
,
()
=>
{
expect
(
findTestTemplateLink
s
().
exists
()).
toBe
(
templatesRendered
);
expect
(
find
TemplateLink
s
().
exists
()).
toBe
(
templatesRendered
);
expect
(
findTestTemplateLink
().
exists
()).
toBe
(
templatesRendered
);
expect
(
find
CiTemplate
s
().
exists
()).
toBe
(
templatesRendered
);
});
},
);
...
...
spec/frontend/pipelines/empty_state_spec.js
View file @
fe2a5493
import
'
~/commons
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
EmptyState
from
'
~/pipelines/components/pipelines_list/empty_state.vue
'
;
import
PipelinesCiTemplates
from
'
~/pipelines/components/pipelines_list/pipelines_ci_templates.vue
'
;
import
PipelinesCiTemplates
from
'
~/pipelines/components/pipelines_list/
empty_state/
pipelines_ci_templates.vue
'
;
describe
(
'
Pipelines Empty State
'
,
()
=>
{
let
wrapper
;
...
...
spec/frontend/pipelines/pipelines_spec.js
View file @
fe2a5493
...
...
@@ -14,7 +14,7 @@ import createFlash from '~/flash';
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
NavigationControls
from
'
~/pipelines/components/pipelines_list/nav_controls.vue
'
;
import
PipelinesComponent
from
'
~/pipelines/components/pipelines_list/pipelines.vue
'
;
import
PipelinesCiTemplates
from
'
~/pipelines/components/pipelines_list/pipelines_ci_templates.vue
'
;
import
PipelinesCiTemplates
from
'
~/pipelines/components/pipelines_list/
empty_state/
pipelines_ci_templates.vue
'
;
import
PipelinesTableComponent
from
'
~/pipelines/components/pipelines_list/pipelines_table.vue
'
;
import
{
RAW_TEXT_WARNING
}
from
'
~/pipelines/constants
'
;
import
Store
from
'
~/pipelines/stores/pipelines_store
'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment