Commit d36055cb authored by Mark Lapierre's avatar Mark Lapierre

Add tests of adding file templates

Adds tests that adds new files via file templates via the Files view
and the Web IDE.

Includes changes to page objects and associated code

Fetches template content from the API rather than hardcoding strings
that will need to be updated if the templates change. Some of the
content is stored as flat files but we can't use them because they're
not included in the docker images gitlab-qa uses.
parent eeb0baff
...@@ -117,7 +117,7 @@ export default { ...@@ -117,7 +117,7 @@ export default {
<button <button
:disabled="!hasChanges" :disabled="!hasChanges"
type="button" type="button"
class="btn btn-primary btn-sm btn-block" class="btn btn-primary btn-sm btn-block qa-begin-commit-button"
@click="toggleIsSmall" @click="toggleIsSmall"
> >
{{ __('Commit…') }} {{ __('Commit…') }}
...@@ -147,7 +147,7 @@ export default { ...@@ -147,7 +147,7 @@ export default {
<loading-button <loading-button
:loading="submitCommitLoading" :loading="submitCommitLoading"
:label="commitButtonText" :label="commitButtonText"
container-class="btn btn-success btn-sm float-left" container-class="btn btn-success btn-sm float-left qa-commit-button"
@click="commitChanges" @click="commitChanges"
/> />
<button <button
......
...@@ -47,7 +47,7 @@ export default { ...@@ -47,7 +47,7 @@ export default {
</script> </script>
<template> <template>
<div class="d-flex align-items-center ide-file-templates"> <div class="d-flex align-items-center ide-file-templates qa-file-templates-bar">
<strong class="append-right-default"> <strong class="append-right-default">
{{ __('File templates') }} {{ __('File templates') }}
</strong> </strong>
...@@ -63,7 +63,7 @@ export default { ...@@ -63,7 +63,7 @@ export default {
:is-async-data="true" :is-async-data="true"
:searchable="true" :searchable="true"
:title="__('File templates')" :title="__('File templates')"
class="mr-2" class="mr-2 qa-file-template-dropdown"
@click="selectTemplate" @click="selectTemplate"
/> />
<transition name="fade"> <transition name="fade">
......
...@@ -92,7 +92,7 @@ export default { ...@@ -92,7 +92,7 @@ export default {
v-model="search" v-model="search"
:placeholder="__('Filter...')" :placeholder="__('Filter...')"
type="search" type="search"
class="dropdown-input-field" class="dropdown-input-field qa-dropdown-filter-input"
/> />
<i <i
aria-hidden="true" aria-hidden="true"
......
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
<new-entry-button <new-entry-button
:label="__('New file')" :label="__('New file')"
:show-label="false" :show-label="false"
class="d-flex border-0 p-0 mr-3" class="d-flex border-0 p-0 mr-3 qa-new-file"
icon="doc-new" icon="doc-new"
@click="openNewEntryModal({ type: 'blob' })" @click="openNewEntryModal({ type: 'blob' })"
/> />
......
...@@ -43,7 +43,7 @@ export default { ...@@ -43,7 +43,7 @@ export default {
<template> <template>
<div <div
class="ide-file-list" class="ide-file-list qa-file-list"
> >
<template v-if="showLoading"> <template v-if="showLoading">
<div <div
......
...@@ -110,12 +110,12 @@ export default { ...@@ -110,12 +110,12 @@ export default {
ref="fieldName" ref="fieldName"
v-model="entryName" v-model="entryName"
type="text" type="text"
class="form-control" class="form-control qa-full-file-path"
placeholder="/dir/file_name" placeholder="/dir/file_name"
/> />
<ul <ul
v-if="isCreatingNew" v-if="isCreatingNew"
class="prepend-top-default list-inline" class="prepend-top-default list-inline qa-template-list"
> >
<li <li
v-for="(template, index) in templateTypes" v-for="(template, index) in templateTypes"
......
...@@ -41,10 +41,14 @@ export default { ...@@ -41,10 +41,14 @@ export default {
}, },
}, },
mounted() { mounted() {
$(this.$el).on('shown.bs.modal', this.opened).on('hidden.bs.modal', this.closed); $(this.$el)
.on('shown.bs.modal', this.opened)
.on('hidden.bs.modal', this.closed);
}, },
beforeDestroy() { beforeDestroy() {
$(this.$el).off('shown.bs.modal', this.opened).off('hidden.bs.modal', this.closed); $(this.$el)
.off('shown.bs.modal', this.opened)
.off('hidden.bs.modal', this.closed);
}, },
methods: { methods: {
emitCancel(event) { emitCancel(event) {
...@@ -103,7 +107,7 @@ export default { ...@@ -103,7 +107,7 @@ export default {
<slot name="footer"> <slot name="footer">
<button <button
type="button" type="button"
class="btn js-modal-cancel-action" class="btn js-modal-cancel-action qa-modal-cancel-button"
data-dismiss="modal" data-dismiss="modal"
@click="emitCancel($event)" @click="emitCancel($event)"
> >
...@@ -112,7 +116,7 @@ export default { ...@@ -112,7 +116,7 @@ export default {
<button <button
:class="`btn-${footerPrimaryButtonVariant}`" :class="`btn-${footerPrimaryButtonVariant}`"
type="button" type="button"
class="btn js-modal-primary-action" class="btn js-modal-primary-action qa-modal-primary-button"
data-dismiss="modal" data-dismiss="modal"
@click="emitSubmit($event)" @click="emitSubmit($event)"
> >
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
Template Template
.template-selector-dropdowns-wrap .template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden .template-type-selector.js-template-type-selector-wrap.hidden
= dropdown_tag("Choose type", options: { toggle_class: 'js-template-type-selector', title: "Choose a template type" } ) = dropdown_tag("Choose type", options: { toggle_class: 'js-template-type-selector qa-template-type-dropdown', title: "Choose a template type" } )
.license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden .license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag("Apply a license template", options: { toggle_class: 'js-license-selector', title: "Apply a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } ) = dropdown_tag("Apply a license template", options: { toggle_class: 'js-license-selector qa-license-dropdown', title: "Apply a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
.gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden .gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag("Apply a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) = dropdown_tag("Apply a .gitignore template", options: { toggle_class: 'js-gitignore-selector qa-gitignore-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag("Apply a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) = dropdown_tag("Apply a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
.dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden .dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag("Apply a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } ) = dropdown_tag("Apply a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector qa-dockerfile-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } )
.template-selectors-undo-menu.hidden .template-selectors-undo-menu.hidden
%span.text-info Template applied %span.text-info Template applied
%button.btn.btn-sm.btn-info Undo %button.btn.btn-sm.btn-info Undo
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
- if show_menu - if show_menu
.project-action-button.dropdown.inline .project-action-button.dropdown.inline
%a.btn.dropdown-toggle.has-tooltip{ href: '#', title: _('Create new...'), 'data-toggle' => 'dropdown', 'data-container' => 'body', 'aria-label' => _('Create new...'), 'data-display' => 'static' } %a.btn.dropdown-toggle.has-tooltip.qa-create-new-dropdown{ href: '#', title: _('Create new...'), 'data-toggle' => 'dropdown', 'data-container' => 'body', 'aria-label' => _('Create new...'), 'data-display' => 'static' }
= icon('plus') = icon('plus')
= icon("caret-down") = icon("caret-down")
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
%li.dropdown-header= _('This repository') %li.dropdown-header= _('This repository')
- if can_push_code - if can_push_code
%li= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master') %li.qa-new-file-option= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
- unless @project.empty_repo? - unless @project.empty_repo?
%li= link_to _('New branch'), new_project_branch_path(@project) %li= link_to _('New branch'), new_project_branch_path(@project)
%li= link_to _('New tag'), new_project_tag_path(@project) %li= link_to _('New tag'), new_project_tag_path(@project)
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
- if can_collaborate - if can_collaborate
= succeed " " do = succeed " " do
= link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default' do = link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE') = _('Web IDE')
= render 'projects/buttons/download', project: @project, ref: @ref = render 'projects/buttons/download', project: @project, ref: @ref
...@@ -16,6 +16,8 @@ module QA ...@@ -16,6 +16,8 @@ module QA
autoload :Browser, 'qa/runtime/browser' autoload :Browser, 'qa/runtime/browser'
autoload :Env, 'qa/runtime/env' autoload :Env, 'qa/runtime/env'
autoload :Address, 'qa/runtime/address' autoload :Address, 'qa/runtime/address'
autoload :Path, 'qa/runtime/path'
autoload :Fixtures, 'qa/runtime/fixtures'
module API module API
autoload :Client, 'qa/runtime/api/client' autoload :Client, 'qa/runtime/api/client'
...@@ -214,6 +216,10 @@ module QA ...@@ -214,6 +216,10 @@ module QA
autoload :New, 'qa/page/project/wiki/new' autoload :New, 'qa/page/project/wiki/new'
autoload :Show, 'qa/page/project/wiki/show' autoload :Show, 'qa/page/project/wiki/show'
end end
module WebIDE
autoload :Edit, 'qa/page/project/web_ide/edit'
end
end end
module Profile module Profile
...@@ -257,6 +263,8 @@ module QA ...@@ -257,6 +263,8 @@ module QA
autoload :Dropzone, 'qa/page/component/dropzone' autoload :Dropzone, 'qa/page/component/dropzone'
autoload :GroupsFilter, 'qa/page/component/groups_filter' autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2' autoload :Select2, 'qa/page/component/select2'
autoload :DropdownFilter, 'qa/page/component/dropdown_filter'
module Issuable module Issuable
autoload :Common, 'qa/page/component/issuable/common' autoload :Common, 'qa/page/component/issuable/common'
end end
......
# frozen_string_literal: true
module QA module QA
module Factory module Factory
module Resource module Resource
...@@ -19,7 +21,7 @@ module QA ...@@ -19,7 +21,7 @@ module QA
def fabricate! def fabricate!
project.visit! project.visit!
Page::Project::Show.act { go_to_new_file! } Page::Project::Show.act { create_new_file! }
Page::File::Form.perform do |page| Page::File::Form.perform do |page|
page.add_name(@name) page.add_name(@name)
......
# frozen_string_literal: true
require 'capybara/dsl' require 'capybara/dsl'
module QA module QA
...@@ -7,6 +9,8 @@ module QA ...@@ -7,6 +9,8 @@ module QA
include Scenario::Actable include Scenario::Actable
extend SingleForwardable extend SingleForwardable
ElementNotFound = Class.new(RuntimeError)
def_delegators :evaluator, :view, :views def_delegators :evaluator, :view, :views
def refresh def refresh
......
# frozen_string_literal: true
module QA
module Page
module Component
module DropdownFilter
def filter_and_select(item)
wait(reload: false) do
page.has_css?('.dropdown-input-field')
end
find('.dropdown-input-field').set(item)
click_link item
end
end
end
end
end
...@@ -3,6 +3,7 @@ module QA ...@@ -3,6 +3,7 @@ module QA
module File module File
class Form < Page::Base class Form < Page::Base
include Shared::CommitMessage include Shared::CommitMessage
include Page::Component::DropdownFilter
view 'app/views/projects/blob/_editor.html.haml' do view 'app/views/projects/blob/_editor.html.haml' do
element :file_name, "text_field_tag 'file_name'" element :file_name, "text_field_tag 'file_name'"
...@@ -13,6 +14,14 @@ module QA ...@@ -13,6 +14,14 @@ module QA
element :commit_changes, "button_tag 'Commit changes'" element :commit_changes, "button_tag 'Commit changes'"
end end
view 'app/views/projects/blob/_template_selectors.html.haml' do
element :template_type_dropdown
element :gitignore_dropdown
element :gitlab_ci_yml_dropdown
element :dockerfile_dropdown
element :license_dropdown
end
def add_name(name) def add_name(name)
fill_in 'file_name', with: name fill_in 'file_name', with: name
end end
...@@ -29,6 +38,25 @@ module QA ...@@ -29,6 +38,25 @@ module QA
click_on 'Commit changes' click_on 'Commit changes'
end end
def select_template(template_type, template)
click_element :template_type_dropdown
click_link template_type
case template_type
when '.gitignore'
click_element :gitignore_dropdown
when '.gitlab-ci.yml'
click_element :gitlab_ci_yml_dropdown
when 'Dockerfile'
click_element :dockerfile_dropdown
when 'LICENSE'
click_element :license_dropdown
else
raise %Q(Unsupported template_type "#{template_type}". Please confirm that it is a valid option.)
end
filter_and_select template
end
private private
def text_area def text_area
......
# frozen_string_literal: true
module QA module QA
module Page module Page
module Project module Project
...@@ -31,16 +33,22 @@ module QA ...@@ -31,16 +33,22 @@ module QA
element :tree_holder, '.tree-holder' element :tree_holder, '.tree-holder'
end end
view 'app/presenters/project_presenter.rb' do view 'app/views/projects/buttons/_dropdown.html.haml' do
element :new_file_button, "_('New file')," element :create_new_dropdown
element :new_file_option
end
view 'app/views/projects/tree/_tree_header.html.haml' do
element :web_ide_button
end end
def project_name def project_name
find('.qa-project-name').text find('.qa-project-name').text
end end
def go_to_new_file! def create_new_file!
click_on 'New file' click_element :create_new_dropdown
click_element :new_file_option
end end
def switch_to_branch(branch_name) def switch_to_branch(branch_name)
...@@ -78,6 +86,10 @@ module QA ...@@ -78,6 +86,10 @@ module QA
def fork_project def fork_project
click_on 'Fork' click_on 'Fork'
end end
def open_web_ide!
click_element :web_ide_button
end
end end
end end
end end
......
# frozen_string_literal: true
module QA
module Page
module Project
module WebIDE
class Edit < Page::Base
include Page::Component::DropdownFilter
view 'app/assets/javascripts/ide/components/ide_tree.vue' do
element :new_file
end
view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do
element :file_list
end
view 'app/assets/javascripts/ide/components/new_dropdown/modal.vue' do
element :full_file_path
element :template_list
end
view 'app/assets/javascripts/ide/components/file_templates/bar.vue' do
element :file_templates_bar
element :file_template_dropdown
end
view 'app/assets/javascripts/ide/components/file_templates/dropdown.vue' do
element :dropdown_filter_input
end
view 'app/assets/javascripts/ide/components/commit_sidebar/form.vue' do
element :begin_commit_button
element :commit_button
end
def has_file?(file_name)
within_element(:file_list) do
page.has_content? file_name
end
end
def create_new_file_from_template(file_name, template)
click_element :new_file
within_element(:template_list) do
begin
click_on file_name
rescue Capybara::ElementNotFound
raise ElementNotFound, %Q(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.)
end
end
wait(reload: false) do
within_element(:file_templates_bar) do
click_element :file_template_dropdown
fill_element :dropdown_filter_input, template
begin
click_on template
rescue Capybara::ElementNotFound
raise ElementNotFound, %Q(Couldn't find template "#{template}" for #{file_name}. Please confirm that it exists in the list of templates.)
end
end
end
end
def commit_changes
click_element :begin_commit_button
click_element :commit_button
wait(reload: false) do
page.has_content?('Your changes have been committed')
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Runtime
module Fixtures
def fetch_template_from_api(api_path, key)
request = Runtime::API::Request.new(api_client, "/templates/#{api_path}/#{key}")
get request.url
json_body[:content]
end
private
def api_client
@api_client ||= Runtime::API::Client.new(:gitlab)
end
end
end
end
# frozen_string_literal: true
module QA
module Runtime
module Path
extend self
def qa_root
::File.expand_path('../../', __dir__)
end
end
end
end
# frozen_string_literal: true
module QA
context :create do
describe 'File templates' do
include Runtime::Fixtures
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
end
before(:all) do
login
@project = Factory::Resource::Project.fabricate! do |project|
project.name = 'file-template-project'
project.description = 'Add file templates via the Files view'
end
Page::Menu::Main.act { sign_out }
end
templates = [
{
file_name: '.gitignore',
name: 'Android',
api_path: 'gitignores',
api_key: 'Android'
},
{
file_name: '.gitlab-ci.yml',
name: 'Julia',
api_path: 'gitlab_ci_ymls',
api_key: 'Julia'
},
{
file_name: 'Dockerfile',
name: 'Python',
api_path: 'dockerfiles',
api_key: 'Python'
},
{
file_name: 'LICENSE',
name: 'Mozilla Public License 2.0',
api_path: 'licenses',
api_key: 'mpl-2.0'
}
]
templates.each do |template|
it "user adds #{template[:file_name]} via file template #{template[:name]}" do
content = fetch_template_from_api(template[:api_path], template[:api_key])
login
@project.visit!
Page::Project::Show.act { create_new_file! }
Page::File::Form.perform do |page|
page.select_template template[:file_name], template[:name]
end
expect(page).to have_content('Template applied')
expect(page).to have_button('Undo')
expect(page).to have_content(content[0..100])
Page::File::Form.perform(&:commit_changes)
expect(page).to have_content('The file has been successfully created.')
expect(page).to have_content(template[:file_name])
expect(page).to have_content('Add new file')
expect(page).to have_content(content[0..100])
end
end
end
end
end
# frozen_string_literal: true
module QA
context :create do
describe 'Web IDE file templates' do
include Runtime::Fixtures
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
end
before(:all) do
login
@project = Factory::Resource::Project.fabricate! do |project|
project.name = 'file-template-project'
project.description = 'Add file templates via the Web IDE'
end
# Add a file via the regular Files view because the Web IDE isn't
# available unless there is a file present
Page::Project::Show.act { create_new_file! }
Page::File::Form.perform do |page|
page.add_name('dummy')
page.add_content('Enable the Web IDE')
page.commit_changes
end
Page::Menu::Main.act { sign_out }
end
templates = [
{
file_name: '.gitignore',
name: 'Android',
api_path: 'gitignores',
api_key: 'Android'
},
{
file_name: '.gitlab-ci.yml',
name: 'Julia',
api_path: 'gitlab_ci_ymls',
api_key: 'Julia'
},
{
file_name: 'Dockerfile',
name: 'Python',
api_path: 'dockerfiles',
api_key: 'Python'
},
{
file_name: 'LICENSE',
name: 'Mozilla Public License 2.0',
api_path: 'licenses',
api_key: 'mpl-2.0'
}
]
templates.each do |template|
it "user adds #{template[:file_name]} via file template #{template[:name]}" do
content = fetch_template_from_api(template[:api_path], template[:api_key])
login
@project.visit!
Page::Project::Show.act { open_web_ide! }
Page::Project::WebIDE::Edit.perform do |page|
page.create_new_file_from_template template[:file_name], template[:name]
expect(page.has_file?(template[:file_name])).to be_truthy
end
expect(page).to have_button('Undo')
expect(page).to have_content(content[0..100])
Page::Project::WebIDE::Edit.perform do |page|
page.commit_changes
end
expect(page).to have_content(template[:file_name])
expect(page).to have_content(content[0..100])
end
end
end
end
end
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