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
Hide 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 {
<div
data-testid=
"issuable-title"
class=
"form-group row"
>
<label
for=
"issuable-title"
class=
"col-form-label col-sm-2"
>
{{
__
(
'
Title
'
)
}}
</label>
<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
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'
)
-
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 ""
msgid "New Snippet"
msgstr ""
msgid "New Test Case"
msgstr ""
msgid "New User"
msgstr ""
...
...
@@ -23622,6 +23625,9 @@ msgstr ""
msgid "Something went wrong while creating a requirement."
msgstr ""
msgid "Something went wrong while creating a test case."
msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
...
...
@@ -24360,6 +24366,9 @@ msgstr ""
msgid "Submit search"
msgstr ""
msgid "Submit test case"
msgstr ""
msgid "Submit the current review."
msgstr ""
...
...
spec/frontend/issuable_create/components/issuable_form_spec.js
View file @
cac4831e
...
...
@@ -65,6 +65,7 @@ describe('IssuableForm', () => {
expect
(
titleFieldEl
.
find
(
'
label
'
).
text
()).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
exists
()).
toBe
(
true
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
attributes
(
'
placeholder
'
)).
toBe
(
'
Title
'
);
expect
(
titleFieldEl
.
find
(
GlFormInput
).
attributes
(
'
autofocus
'
)).
toBe
(
'
true
'
);
});
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