Commit b24d7793 authored by Dan Davison's avatar Dan Davison

Merge branch 'ml-web-terminal-spec-qa' into 'master'

Add e2e test for web terminal

Closes gitlab-org/quality/testcases#85

See merge request gitlab-org/gitlab-ee!8186
parents 7943cea9 6cf43e67
......@@ -44,7 +44,7 @@ export default {
<template>
<div class="flash-container flash-container-page" @click="clickFlash">
<div class="flash-alert">
<div class="flash-alert" data-qa-selector="flash_alert">
<span v-html="message.text"> </span>
<button
v-if="message.action"
......
......@@ -89,7 +89,7 @@ export default {
</script>
<template>
<div class="multi-file-commit-panel ide-right-sidebar">
<div class="multi-file-commit-panel ide-right-sidebar" data-qa-selector="ide_right_sidebar">
<resizable-panel
v-show="isOpen"
:collapsible="false"
......@@ -120,6 +120,7 @@ export default {
}"
data-container="body"
data-placement="left"
:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`"
class="ide-sidebar-link is-right"
type="button"
@click="clickTab($event, tab)"
......
......@@ -47,7 +47,13 @@ export default {
<template v-else>
<p>{{ __('Run tests against your code live using the Web Terminal') }}</p>
<p>
<button :disabled="!isValid" class="btn btn-info" type="button" @click="onStart">
<button
:disabled="!isValid"
class="btn btn-info"
type="button"
data-qa-selector="start_web_terminal_button"
@click="onStart"
>
{{ __('Start Web Terminal') }}
</button>
</p>
......
......@@ -92,7 +92,7 @@ export default {
<template>
<div class="d-flex flex-column flex-fill min-height-0">
<div class="top-bar d-flex border-left-0 align-items-center">
<div v-if="loadingText">
<div v-if="loadingText" data-qa-selector="loading_container">
<gl-loading-icon :inline="true" />
<span>{{ loadingText }}</span>
</div>
......@@ -110,6 +110,7 @@ export default {
ref="terminal"
class="ide-terminal-trace flex-fill min-height-0 w-100"
:data-project-path="terminalPath"
data-qa-selector="terminal_screen"
></div>
</div>
</div>
......
......@@ -73,6 +73,7 @@ module QA
end
module Repository
autoload :Commit, 'qa/resource/repository/commit'
autoload :Push, 'qa/resource/repository/push'
autoload :ProjectPush, 'qa/resource/repository/project_push'
autoload :WikiPush, 'qa/resource/repository/wiki_push'
......@@ -346,6 +347,10 @@ module QA
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
end
module WebIDE
autoload :Alert, 'qa/page/component/web_ide/alert'
end
end
end
......
......@@ -12,6 +12,12 @@ module QA
end
module Page
module Component
module WebIDE
autoload :WebTerminalPanel, 'qa/ee/page/component/web_ide/web_terminal_panel'
end
end
module Dashboard
autoload :Projects, 'qa/ee/page/dashboard/projects'
end
......
# frozen_string_literal: true
module QA
module EE
module Page
module Component
module WebIDE
module WebTerminalPanel
def self.prepended(page)
page.module_eval do
view 'app/assets/javascripts/ide/components/panes/right.vue' do
element :ide_right_sidebar
element :terminal_tab_button, %q(:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`") # rubocop:disable QA/ElementWithPattern
end
view 'ee/app/assets/javascripts/ide/components/terminal/empty_state.vue' do
element :start_web_terminal_button
end
view 'ee/app/assets/javascripts/ide/components/terminal/terminal.vue' do
element :loading_container
element :terminal_screen
end
end
end
def has_finished_loading?
wait(reload: false) do
has_no_element? :loading_container
end
end
def has_terminal_screen?
wait(reload: false) do
within_element :terminal_screen do
# The DOM initially just includes the :terminal_screen element
# and then the xterm package dynamically loads when the user
# clicks the Start Web Terminal button. If it loads succesfully
# an element with the class `xterm` is added to the DOM.
# The xterm is a third-party library, so we can't add a selector
find(".xterm")
end
end
end
def start_web_terminal
within_element :ide_right_sidebar do
click_element :terminal_tab_button
end
click_element :start_web_terminal_button
has_element? :loading_container, text: "Starting"
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Component
module WebIDE
module Alert
def self.prepended(page)
page.module_eval do
view 'app/assets/javascripts/ide/components/error_message.vue' do
element :flash_alert
end
end
end
def has_no_alert?(message = nil)
return has_no_element?(:flash_alert) if message.nil?
within_element(:flash_alert) do
has_no_text?(message)
end
end
end
end
end
end
end
......@@ -5,6 +5,7 @@ module QA
module Project
module WebIDE
class Edit < Page::Base
prepend Page::Component::WebIDE::Alert
include Page::Component::DropdownFilter
view 'app/assets/javascripts/ide/components/activity_bar.vue' do
......@@ -123,3 +124,5 @@ module QA
end
end
end
QA::Page::Project::WebIDE::Edit.prepend_if_ee('QA::EE::Page::Component::WebIDE::WebTerminalPanel')
......@@ -15,6 +15,7 @@ module QA
attribute :add_name_uuid
attribute :description
attribute :standalone
attribute :runners_token
attribute :group do
Group.fabricate!
......
# frozen_string_literal: true
module QA
module Resource
module Repository
class Commit < Base
attr_accessor :author_email,
:author_name,
:branch,
:commit_message,
:file_path,
:sha
attribute :project do
Project.fabricate! do |resource|
resource.name = 'project-with-commit'
end
end
def initialize
@commit_message = 'QA Test - Commit message'
end
def files=(files)
if !files.is_a?(Array) ||
files.empty? ||
files.any? { |file| !file.has_key?(:file_path) || !file.has_key?(:content) }
raise ArgumentError, "Please provide an array of hashes e.g.: [{file_path: 'file1', content: 'foo'}]"
end
@files = files
end
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def api_get_path
"#{api_post_path}/#{@sha}"
end
def api_post_path
"/projects/#{CGI.escape(project.path_with_namespace)}/repository/commits"
end
def api_post_body
{
branch: @branch || "master",
author_email: @author_email || Runtime::User.default_email,
author_name: @author_name || Runtime::User.username,
commit_message: commit_message,
actions: actions
}
end
def actions
@files.map do |file|
file.merge({ action: "create" })
end
end
end
end
end
end
......@@ -6,9 +6,10 @@ module QA
module Resource
class Runner < Base
attr_writer :name, :tags, :image
attr_accessor :config
attribute :project do
Project.fabricate! do |resource|
Project.fabricate_via_api! do |resource|
resource.name = 'project-with-ci-cd'
resource.description = 'Project with CI/CD Pipelines'
end
......@@ -26,24 +27,27 @@ module QA
@image || 'gitlab/gitlab-runner:alpine'
end
def fabricate!
project.visit!
Page::Project::Menu.perform(&:go_to_ci_cd_settings)
def fabricate_via_api!
Service::Runner.new(name).tap do |runner|
Page::Project::Settings::CICD.perform do |settings|
settings.expand_runners_settings do |runners|
runner.pull
runner.token = runners.registration_token
runner.address = runners.coordinator_address
runner.tags = tags
runner.image = image
runner.register!
end
end
runner.pull
runner.token = project.runners_token
runner.address = Runtime::Scenario.gitlab_address
runner.tags = tags
runner.image = image
runner.config = config if config
runner.run_untagged = true
runner.register!
end
end
def api_get_path
end
def api_post_path
end
def api_post_body
end
end
end
end
......@@ -7,13 +7,25 @@ module QA
class Runner
include Service::Shellout
attr_accessor :token, :address, :tags, :image
attr_accessor :token, :address, :tags, :image, :run_untagged
attr_writer :config
def initialize(name)
@image = 'gitlab/gitlab-runner:alpine'
@name = name || "qa-runner-#{SecureRandom.hex(4)}"
@network = Runtime::Scenario.attributes[:network] || 'test'
@tags = %w[qa test]
@run_untagged = false
end
def config
@config ||= <<~END
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
END
end
def network
......@@ -32,19 +44,30 @@ module QA
shell <<~CMD.tr("\n", ' ')
docker run -d --rm --entrypoint=/bin/sh
--network #{network} --name #{@name}
-p 8093:8093
-e CI_SERVER_URL=#{@address}
-e REGISTER_NON_INTERACTIVE=true
-e REGISTRATION_TOKEN=#{@token}
-e RUNNER_EXECUTOR=shell
-e RUNNER_TAG_LIST=#{@tags.join(',')}
-e RUNNER_NAME=#{@name}
#{@image} -c 'gitlab-runner register && gitlab-runner run'
#{@image} -c "#{register_command}"
CMD
end
def remove!
shell "docker rm -f #{@name}"
end
private
def register_command
<<~CMD
printf '#{config.chomp.gsub(/\n/, "\\n").gsub('"', '\"')}' > /etc/gitlab-runner/config.toml &&
gitlab-runner register --run-untagged=#{@run_untagged} &&
gitlab-runner run
CMD
end
end
end
end
......@@ -15,11 +15,11 @@ module QA
Resource::Runner.fabricate! do |runner|
runner.name = executor
end
end.project.visit!
Page::Project::Menu.perform(&:go_to_ci_cd_settings)
Page::Project::Settings::CICD.perform do |settings|
sleep 5 # Runner should register within 5 seconds
settings.refresh
settings.expand_runners_settings do |page|
expect(page).to have_content(executor)
......
......@@ -17,7 +17,7 @@ module QA
@repository_location = @project.repository_ssh_location
Resource::Runner.fabricate_via_browser_ui! do |resource|
Resource::Runner.fabricate_via_api! do |resource|
resource.project = @project
resource.name = @runner_name
resource.tags = %w[qa docker]
......
# frozen_string_literal: true
module QA
# Quarantined because relative URL isn't supported
# See https://gitlab.com/gitlab-org/gitlab-ee/issues/13833
context 'Create', :quarantine do
describe 'Web IDE web terminal', :docker do
before do
project = Resource::Project.fabricate_via_api! do |project|
project.name = 'web-terminal-project'
end
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab/.gitlab-webide.yml'
commit.files = [
{
file_path: '.gitlab/.gitlab-webide.yml',
content: <<~YAML
terminal:
script: sleep 60
YAML
}
]
end
@runner = Resource::Runner.fabricate_via_api! do |runner|
runner.project = project
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = %w[qa docker web-ide]
runner.image = 'gitlab/gitlab-runner:latest'
runner.config = <<~END
concurrent = 1
[session_server]
listen_address = "0.0.0.0:8093"
advertise_address = "localhost:8093"
session_timeout = 120
END
end
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
project.visit!
end
after do
# Remove the runner even if the test fails
Service::Runner.new(@runner.name).remove! if @runner
end
it 'user starts the web terminal' do
Page::Project::Show.perform(&:open_web_ide!)
# Start the web terminal and check that there were no errors
# The terminal screen is a canvas element, so we can't read its content,
# so we infer that it's working if:
# a) The terminal JS package has loaded, and
# b) It's not stuck in a "Loading/Starting" state, and
# c) There's no alert stating there was a problem
#
# The terminal itself is a third-party package so we assume it is
# adequately tested elsewhere.
#
# There are also FE specs
# * ee/spec/javascripts/ide/components/terminal/terminal_spec.js
# * ee/spec/frontend/ide/components/terminal/terminal_controls_spec.js
Page::Project::WebIDE::Edit.perform do |edit|
edit.start_web_terminal
expect(edit).to have_no_alert
expect(edit).to have_finished_loading
expect(edit).to have_terminal_screen
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