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
cac4831e
Commit
cac4831e
authored
Sep 16, 2020
by
Kushal Pandya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Test Case Create Form
Adds `test_case_create` app to show Create Test Case form UI in `/new` route.
parent
4b59a5aa
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
454 additions
and
3 deletions
+454
-3
app/assets/javascripts/issuable_create/components/issuable_form.vue
.../javascripts/issuable_create/components/issuable_form.vue
+6
-1
ee/app/assets/javascripts/pages/projects/quality/test_cases/new/index.js
...avascripts/pages/projects/quality/test_cases/new/index.js
+7
-0
ee/app/assets/javascripts/test_case_create/components/test_case_create_root.vue
...pts/test_case_create/components/test_case_create_root.vue
+96
-0
ee/app/assets/javascripts/test_case_create/queries/create_test_case.mutation.graphql
...est_case_create/queries/create_test_case.mutation.graphql
+6
-0
ee/app/assets/javascripts/test_case_create/test_case_create_bundle.js
...s/javascripts/test_case_create/test_case_create_bundle.js
+29
-0
ee/app/views/projects/quality/test_cases/index.html.haml
ee/app/views/projects/quality/test_cases/index.html.haml
+2
-2
ee/spec/features/projects/quality/test_case_create_spec.rb
ee/spec/features/projects/quality/test_case_create_spec.rb
+86
-0
ee/spec/frontend/test_case_create/components/test_case_create_root_spec.js
...test_case_create/components/test_case_create_root_spec.js
+212
-0
locale/gitlab.pot
locale/gitlab.pot
+9
-0
spec/frontend/issuable_create/components/issuable_form_spec.js
...frontend/issuable_create/components/issuable_form_spec.js
+1
-0
No files found.
app/assets/javascripts/issuable_create/components/issuable_form.vue
View file @
cac4831e
...
@@ -53,7 +53,12 @@ export default {
...
@@ -53,7 +53,12 @@ export default {
<div
data-testid=
"issuable-title"
class=
"form-group row"
>
<div
data-testid=
"issuable-title"
class=
"form-group row"
>
<label
for=
"issuable-title"
class=
"col-form-label col-sm-2"
>
{{
__
(
'
Title
'
)
}}
</label>
<label
for=
"issuable-title"
class=
"col-form-label col-sm-2"
>
{{
__
(
'
Title
'
)
}}
</label>
<div
class=
"col-sm-10"
>
<div
class=
"col-sm-10"
>
<gl-form-input
id=
"issuable-title"
v-model=
"issuableTitle"
:placeholder=
"__('Title')"
/>
<gl-form-input
id=
"issuable-title"
v-model=
"issuableTitle"
:autofocus=
"true"
:placeholder=
"__('Title')"
/>
</div>
</div>
</div>
</div>
<div
data-testid=
"issuable-description"
class=
"form-group row"
>
<div
data-testid=
"issuable-description"
class=
"form-group row"
>
...
...
ee/app/assets/javascripts/pages/projects/quality/test_cases/new/index.js
0 → 100644
View file @
cac4831e
import
{
initTestCaseCreate
}
from
'
ee/test_case_create/test_case_create_bundle
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
initTestCaseCreate
({
mountPointSelector
:
'
#js-create-test-case
'
,
});
});
ee/app/assets/javascripts/test_case_create/components/test_case_create_root.vue
0 → 100644
View file @
cac4831e
<
script
>
import
{
GlButton
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
~/locale
'
;
import
createFlash
from
'
~/flash
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
IssuableCreate
from
'
~/issuable_create/components/issuable_create_root.vue
'
;
import
createTestCase
from
'
../queries/create_test_case.mutation.graphql
'
;
export
default
{
components
:
{
GlButton
,
IssuableCreate
,
},
inject
:
[
'
projectFullPath
'
,
'
projectTestCasesPath
'
,
'
descriptionPreviewPath
'
,
'
descriptionHelpPath
'
,
'
labelsFetchPath
'
,
'
labelsManagePath
'
,
],
data
()
{
return
{
createTestCaseRequestActive
:
false
,
};
},
methods
:
{
handleTestCaseSubmitClick
({
issuableTitle
,
issuableDescription
,
selectedLabels
})
{
this
.
createTestCaseRequestActive
=
true
;
return
this
.
$apollo
.
mutate
({
mutation
:
createTestCase
,
variables
:
{
createTestCaseInput
:
{
projectPath
:
this
.
projectFullPath
,
title
:
issuableTitle
,
description
:
issuableDescription
,
labelIds
:
selectedLabels
.
map
(
label
=>
label
.
id
),
},
},
})
.
then
(({
data
=
{}
})
=>
{
const
errors
=
data
.
createTestCase
?.
errors
;
if
(
errors
?.
length
)
{
throw
new
Error
(
`Error creating a test case. Error message:
${
errors
[
0
].
message
}
`
);
}
redirectTo
(
this
.
projectTestCasesPath
);
})
.
catch
(
error
=>
{
createFlash
({
message
:
__
(
'
Something went wrong while creating a test case.
'
),
captureError
:
true
,
error
,
});
})
.
finally
(()
=>
{
this
.
createTestCaseRequestActive
=
false
;
});
},
},
};
</
script
>
<
template
>
<issuable-create
:description-preview-path=
"descriptionPreviewPath"
:description-help-path=
"descriptionHelpPath"
:labels-fetch-path=
"labelsFetchPath"
:labels-manage-path=
"labelsManagePath"
>
<template
#title
>
<h3
class=
"page-title"
>
{{
__
(
'
New Test Case
'
)
}}
</h3>
</
template
>
<
template
#actions=
"issuableMeta"
>
<div
class=
"gl-flex-grow-1"
>
<gl-button
data-testid=
"submit-test-case"
category=
"primary"
variant=
"success"
:loading=
"createTestCaseRequestActive"
:disabled=
"!issuableMeta.issuableTitle.length"
@
click=
"handleTestCaseSubmitClick(issuableMeta)"
>
{{
__
(
'
Submit test case
'
)
}}
</gl-button
>
</div>
<gl-button
data-testid=
"cancel-test-case"
:disabled=
"createTestCaseRequestActive"
:href=
"projectTestCasesPath"
>
{{
__
(
'
Cancel
'
)
}}
</gl-button
>
</
template
>
</issuable-create>
</template>
ee/app/assets/javascripts/test_case_create/queries/create_test_case.mutation.graphql
0 → 100644
View file @
cac4831e
mutation
createTestCase
(
$createTestCaseInput
:
CreateTestCaseInput
!)
{
createTestCase
(
input
:
$createTestCaseInput
)
{
clientMutationId
errors
}
}
ee/app/assets/javascripts/test_case_create/test_case_create_bundle.js
0 → 100644
View file @
cac4831e
import
Vue
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
TestCaseCreateApp
from
'
./components/test_case_create_root.vue
'
;
Vue
.
use
(
VueApollo
);
export
function
initTestCaseCreate
({
mountPointSelector
})
{
const
mountPointEl
=
document
.
querySelector
(
mountPointSelector
);
if
(
!
mountPointEl
)
{
return
null
;
}
const
apolloProvider
=
new
VueApollo
({
defaultClient
:
createDefaultClient
(),
});
return
new
Vue
({
el
:
mountPointEl
,
apolloProvider
,
provide
:
{
...
mountPointEl
.
dataset
,
},
render
:
createElement
=>
createElement
(
TestCaseCreateApp
),
});
}
ee/app/views/projects/quality/test_cases/index.html.haml
View file @
cac4831e
-
breadcrumb_title
_
(
'Test Cases'
)
-
page_title
_
(
'Test Cases'
)
-
page_title
_
(
'Test Cases'
)
-
breadcrumb_title
_
(
"Test Cases"
)
-
@content_class
=
'project-test-cases'
ee/spec/features/projects/quality/test_case_create_spec.rb
0 → 100644
View file @
cac4831e
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Test Cases'
,
:js
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:label1
)
{
create
(
:label
,
project:
project
,
title:
'bug'
)
}
let_it_be
(
:label2
)
{
create
(
:label
,
project:
project
,
title:
'enhancement'
)
}
let_it_be
(
:label3
)
{
create
(
:label
,
project:
project
,
title:
'documentation'
)
}
before
do
project
.
add_developer
(
user
)
stub_licensed_features
(
quality_management:
true
)
sign_in
(
user
)
end
context
'test case create form'
do
before
do
visit
new_project_quality_test_case_path
(
project
)
wait_for_requests
end
it
'shows page title, title, description and label input fields'
do
page
.
within
(
'.issuable-create-container'
)
do
expect
(
page
.
find
(
'.page-title'
)).
to
have_content
(
'New Test Case'
)
end
page
.
within
(
'.issuable-create-container form'
)
do
form_fields
=
page
.
find_all
(
'.form-group.row'
)
expect
(
form_fields
[
0
].
find
(
'label'
)).
to
have_content
(
'Title'
)
expect
(
form_fields
[
0
]).
to
have_selector
(
'input#issuable-title'
)
expect
(
form_fields
[
1
].
find
(
'label'
)).
to
have_content
(
'Description'
)
expect
(
form_fields
[
1
]).
to
have_selector
(
'.js-vue-markdown-field'
)
expect
(
form_fields
[
2
].
find
(
'label'
)).
to
have_content
(
'Labels'
)
expect
(
form_fields
[
2
]).
to
have_selector
(
'.labels-select-wrapper'
)
end
end
it
'shows labels and footer actions within labels dropdown'
do
page
.
within
(
'.issuable-create-container form .labels-select-wrapper'
)
do
page
.
find
(
'.js-dropdown-button'
).
click
wait_for_requests
expect
(
page
.
find
(
'.js-labels-list .dropdown-content'
)).
to
have_selector
(
'li'
,
count:
3
)
expect
(
page
.
find
(
'.js-labels-list .dropdown-footer'
)).
to
have_selector
(
'li'
,
count:
2
)
end
end
it
'shows page actions'
do
page
.
within
(
'.issuable-create-container .footer-block'
)
do
expect
(
page
.
find
(
'button'
)).
to
have_content
(
'Submit test case'
)
expect
(
page
.
find
(
'a'
)).
to
have_content
(
'Cancel'
)
end
end
it
'creates a test case on saving form'
do
title
=
'Sample title'
description
=
'Sample _test case_ description.'
page
.
within
(
'.issuable-create-container form'
)
do
form_fields
=
page
.
find_all
(
'.form-group.row'
)
form_fields
[
0
].
find
(
'input#issuable-title'
).
native
.
send_keys
title
form_fields
[
1
].
find
(
'textarea#issuable-description'
).
native
.
send_keys
description
form_fields
[
2
].
find
(
'.js-dropdown-button'
).
click
wait_for_requests
form_fields
[
2
].
find_all
(
'.js-labels-list .dropdown-content li'
)[
0
].
click
end
click_button
'Submit test case'
wait_for_requests
expect
(
page
).
to
have_selector
(
'.content-wrapper .project-test-cases'
)
end
end
end
ee/spec/frontend/test_case_create/components/test_case_create_root_spec.js
0 → 100644
View file @
cac4831e
import
{
mount
}
from
'
@vue/test-utils
'
;
import
TestCaseCreateRoot
from
'
ee/test_case_create/components/test_case_create_root.vue
'
;
import
createTestCase
from
'
ee/test_case_create/queries/create_test_case.mutation.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
IssuableCreate
from
'
~/issuable_create/components/issuable_create_root.vue
'
;
jest
.
mock
(
'
~/flash
'
);
jest
.
mock
(
'
~/lib/utils/url_utility
'
);
const
mockProvide
=
{
projectFullPath
:
'
gitlab-org/gitlab-test
'
,
projectTestCasesPath
:
'
/gitlab-org/gitlab-test/-/quality/test_cases
'
,
descriptionPreviewPath
:
'
/gitlab-org/gitlab-test/preview_markdown
'
,
descriptionHelpPath
:
'
/help/user/markdown
'
,
labelsFetchPath
:
'
/gitlab-org/gitlab-test/-/labels.json
'
,
labelsManagePath
:
'
/gitlab-org/gitlab-shell/-/labels
'
,
};
const
createComponent
=
()
=>
mount
(
TestCaseCreateRoot
,
{
provide
:
mockProvide
,
mocks
:
{
$apollo
:
{
mutate
:
jest
.
fn
(),
},
},
});
describe
(
'
TestCaseCreateRoot
'
,
()
=>
{
let
wrapper
;
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
handleTestCaseSubmitClick
'
,
()
=>
{
const
issuableTitle
=
'
Sample title
'
;
const
issuableDescription
=
'
Sample _description_.
'
;
const
selectedLabels
=
[
{
id
:
1
,
set
:
true
,
color
:
'
#BADA55
'
,
text_color
:
'
#FFFFFF
'
,
title
:
'
Bug
'
,
},
];
const
mockCreateMutationResult
=
{
data
:
{
createTestCase
:
{
errors
:
[],
},
},
};
it
(
'
sets `createTestCaseRequestActive` prop to true
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockResolvedValue
(
mockCreateMutationResult
);
wrapper
.
vm
.
handleTestCaseSubmitClick
({
issuableTitle
,
issuableDescription
,
selectedLabels
,
});
expect
(
wrapper
.
vm
.
createTestCaseRequestActive
).
toBe
(
true
);
});
it
(
'
calls `$apollo.mutate` with `createTestCase` mutation and input variables containing projectPath, title, description and labelIds
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockResolvedValue
(
mockCreateMutationResult
);
wrapper
.
vm
.
handleTestCaseSubmitClick
({
issuableTitle
,
issuableDescription
,
selectedLabels
,
});
expect
(
wrapper
.
vm
.
$apollo
.
mutate
).
toHaveBeenCalledWith
(
expect
.
objectContaining
({
mutation
:
createTestCase
,
variables
:
{
createTestCaseInput
:
{
projectPath
:
'
gitlab-org/gitlab-test
'
,
title
:
issuableTitle
,
description
:
issuableDescription
,
labelIds
:
selectedLabels
.
map
(
label
=>
label
.
id
),
},
},
}),
);
});
it
(
'
calls `redirectTo` with projectTestCasesPath when mutation is successful
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockResolvedValue
(
mockCreateMutationResult
);
return
wrapper
.
vm
.
handleTestCaseSubmitClick
({
issuableTitle
,
issuableDescription
,
selectedLabels
,
})
.
then
(()
=>
{
expect
(
redirectTo
).
toHaveBeenCalledWith
(
mockProvide
.
projectTestCasesPath
);
})
.
finally
(()
=>
{
expect
(
wrapper
.
vm
.
createTestCaseRequestActive
).
toBe
(
false
);
});
});
it
(
'
calls `createFlash` with message and error captured when mutation fails
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockRejectedValue
({});
return
wrapper
.
vm
.
handleTestCaseSubmitClick
({
issuableTitle
,
issuableDescription
,
selectedLabels
,
})
.
then
(()
=>
{
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
'
Something went wrong while creating a test case.
'
,
captureError
:
true
,
error
:
expect
.
any
(
Object
),
});
})
.
finally
(()
=>
{
expect
(
wrapper
.
vm
.
createTestCaseRequestActive
).
toBe
(
false
);
});
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
renders issuable-create as a root component
'
,
()
=>
{
const
{
descriptionPreviewPath
,
descriptionHelpPath
,
labelsFetchPath
,
labelsManagePath
,
}
=
mockProvide
;
expect
(
wrapper
.
find
(
IssuableCreate
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
IssuableCreate
).
props
()).
toMatchObject
({
descriptionPreviewPath
,
descriptionHelpPath
,
labelsFetchPath
,
labelsManagePath
,
});
});
it
(
'
renders page title
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
h3
'
).
text
()).
toBe
(
'
New Test Case
'
);
});
it
(
'
renders page actions
'
,
()
=>
{
const
submitEl
=
wrapper
.
find
(
'
[data-testid="submit-test-case"]
'
);
const
cancelEl
=
wrapper
.
find
(
'
[data-testid="cancel-test-case"]
'
);
expect
(
submitEl
.
text
()).
toBe
(
'
Submit test case
'
);
expect
(
submitEl
.
props
()).
toMatchObject
({
loading
:
false
,
disabled
:
true
,
});
expect
(
cancelEl
.
text
()).
toBe
(
'
Cancel
'
);
expect
(
cancelEl
.
props
(
'
disabled
'
)).
toBe
(
false
);
expect
(
cancelEl
.
attributes
(
'
href
'
)).
toBe
(
mockProvide
.
projectTestCasesPath
);
});
it
(
'
submit button shows loading animation when `createTestCaseRequestActive` is true
'
,
async
()
=>
{
wrapper
.
setData
({
createTestCaseRequestActive
:
true
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
find
(
'
[data-testid="submit-test-case"]
'
).
props
(
'
loading
'
)).
toBe
(
true
);
});
it
(
'
cancel button is disabled when `createTestCaseRequestActive` is true
'
,
async
()
=>
{
wrapper
.
setData
({
createTestCaseRequestActive
:
true
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
find
(
'
[data-testid="cancel-test-case"]
'
).
props
(
'
disabled
'
)).
toBe
(
true
);
});
describe
(
'
events
'
,
()
=>
{
it
(
'
submit button click calls `handleTestCaseSubmitClick` method
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
handleTestCaseSubmitClick
'
).
mockImplementation
(
jest
.
fn
);
const
submitButton
=
wrapper
.
find
(
'
[data-testid="submit-test-case"]
'
);
submitButton
.
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
vm
.
handleTestCaseSubmitClick
).
toHaveBeenCalledWith
({
issuableTitle
:
''
,
issuableDescription
:
''
,
selectedLabels
:
[],
});
});
});
});
});
locale/gitlab.pot
View file @
cac4831e
...
@@ -16843,6 +16843,9 @@ msgstr ""
...
@@ -16843,6 +16843,9 @@ msgstr ""
msgid "New Snippet"
msgid "New Snippet"
msgstr ""
msgstr ""
msgid "New Test Case"
msgstr ""
msgid "New User"
msgid "New User"
msgstr ""
msgstr ""
...
@@ -23622,6 +23625,9 @@ msgstr ""
...
@@ -23622,6 +23625,9 @@ msgstr ""
msgid "Something went wrong while creating a requirement."
msgid "Something went wrong while creating a requirement."
msgstr ""
msgstr ""
msgid "Something went wrong while creating a test case."
msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
msgstr ""
...
@@ -24360,6 +24366,9 @@ msgstr ""
...
@@ -24360,6 +24366,9 @@ msgstr ""
msgid "Submit search"
msgid "Submit search"
msgstr ""
msgstr ""
msgid "Submit test case"
msgstr ""
msgid "Submit the current review."
msgid "Submit the current review."
msgstr ""
msgstr ""
...
...
spec/frontend/issuable_create/components/issuable_form_spec.js
View file @
cac4831e
...
@@ -65,6 +65,7 @@ describe('IssuableForm', () => {
...
@@ -65,6 +65,7 @@ describe('IssuableForm', () => {
expect
(
titleFieldEl
.
find
(
'
label
'
).
text
()).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
'
label
'
).
text
()).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
exists
()).
toBe
(
true
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
exists
()).
toBe
(
true
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
attributes
(
'
placeholder
'
)).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
attributes
(
'
placeholder
'
)).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
attributes
(
'
autofocus
'
)).
toBe
(
'
true
'
);
});
});
it
(
'
renders issuable description input field
'
,
()
=>
{
it
(
'
renders issuable description input field
'
,
()
=>
{
...
...
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