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
ae385098
Commit
ae385098
authored
May 17, 2021
by
Coung Ngo
Committed by
Olena Horal-Koretska
May 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add due_date and multiple assignees to issues page refactor
parent
43a97e56
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
181 additions
and
82 deletions
+181
-82
app/assets/javascripts/issues_list/components/issues_list_app.vue
...ts/javascripts/issues_list/components/issues_list_app.vue
+14
-5
app/assets/javascripts/issues_list/constants.js
app/assets/javascripts/issues_list/constants.js
+38
-18
app/assets/javascripts/issues_list/index.js
app/assets/javascripts/issues_list/index.js
+2
-0
app/assets/javascripts/issues_list/utils.js
app/assets/javascripts/issues_list/utils.js
+13
-17
app/assets/javascripts/lib/utils/number_utils.js
app/assets/javascripts/lib/utils/number_utils.js
+10
-0
ee/app/helpers/ee/issues_helper.rb
ee/app/helpers/ee/issues_helper.rb
+2
-1
ee/spec/helpers/ee/issues_helper_spec.rb
ee/spec/helpers/ee/issues_helper_spec.rb
+6
-3
spec/frontend/issues_list/components/issues_list_app_spec.js
spec/frontend/issues_list/components/issues_list_app_spec.js
+12
-0
spec/frontend/issues_list/mock_data.js
spec/frontend/issues_list/mock_data.js
+36
-28
spec/frontend/issues_list/utils_spec.js
spec/frontend/issues_list/utils_spec.js
+22
-10
spec/frontend/lib/utils/number_utility_spec.js
spec/frontend/lib/utils/number_utility_spec.js
+26
-0
No files found.
app/assets/javascripts/issues_list/components/issues_list_app.vue
View file @
ae385098
...
...
@@ -16,22 +16,25 @@ import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
import
IssuableList
from
'
~/issuable_list/components/issuable_list_root.vue
'
;
import
{
IssuableListTabs
,
IssuableStates
}
from
'
~/issuable_list/constants
'
;
import
{
API_PARAM
,
apiSortParams
,
CREATED_DESC
,
i18n
,
MAX_LIST_SIZE
,
PAGE_SIZE
,
PARAM_DUE_DATE
,
PARAM_PAGE
,
PARAM_SORT
,
PARAM_STATE
,
RELATIVE_POSITION_DESC
,
UPDATED_DESC
,
URL_PARAM
,
urlSortParams
,
}
from
'
~/issues_list/constants
'
;
import
{
convertTo
Api
Params
,
convertToParams
,
convertToSearchQuery
,
convertToUrlParams
,
getDueDateValue
,
getFilterTokens
,
getSortKey
,
getSortOptions
,
...
...
@@ -113,6 +116,9 @@ export default {
hasIssueWeightsFeature
:
{
default
:
false
,
},
hasMultipleIssueAssigneesFeature
:
{
default
:
false
,
},
initialEmail
:
{
default
:
''
,
},
...
...
@@ -155,6 +161,7 @@ export default {
const
defaultSortKey
=
state
===
IssuableStates
.
Closed
?
UPDATED_DESC
:
CREATED_DESC
;
return
{
dueDateFilter
:
getDueDateValue
(
getParameterByName
(
PARAM_DUE_DATE
)),
exportCsvPathWithQuery
:
this
.
getExportCsvPathWithQuery
(),
filterTokens
:
getFilterTokens
(
window
.
location
.
search
),
isLoading
:
false
,
...
...
@@ -177,10 +184,10 @@ export default {
return
this
.
state
===
IssuableStates
.
Opened
;
},
apiFilterParams
()
{
return
convertTo
ApiParams
(
this
.
filterTokens
);
return
convertTo
Params
(
this
.
filterTokens
,
API_PARAM
);
},
urlFilterParams
()
{
return
convertTo
UrlParams
(
this
.
filterTokens
);
return
convertTo
Params
(
this
.
filterTokens
,
URL_PARAM
);
},
searchQuery
()
{
return
convertToSearchQuery
(
this
.
filterTokens
)
||
undefined
;
...
...
@@ -203,7 +210,7 @@ export default {
icon
:
'
user
'
,
token
:
AuthorToken
,
dataType
:
'
user
'
,
unique
:
tru
e
,
unique
:
!
this
.
hasMultipleIssueAssigneesFeatur
e
,
defaultAuthors
:
DEFAULT_NONE_ANY
,
fetchAuthors
:
this
.
fetchUsers
,
},
...
...
@@ -298,6 +305,7 @@ export default {
},
urlParams
()
{
return
{
due_date
:
this
.
dueDateFilter
,
page
:
this
.
page
,
search
:
this
.
searchQuery
,
state
:
this
.
state
,
...
...
@@ -366,6 +374,7 @@ export default {
return
axios
.
get
(
this
.
endpoint
,
{
params
:
{
due_date
:
this
.
dueDateFilter
,
page
:
this
.
page
,
per_page
:
PAGE_SIZE
,
search
:
this
.
searchQuery
,
...
...
app/assets/javascripts/issues_list/constants.js
View file @
ae385098
...
...
@@ -100,10 +100,26 @@ export const i18n = {
export
const
JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY
=
'
jira-import-success-alert-hide-map
'
;
export
const
PARAM_DUE_DATE
=
'
due_date
'
;
export
const
PARAM_PAGE
=
'
page
'
;
export
const
PARAM_SORT
=
'
sort
'
;
export
const
PARAM_STATE
=
'
state
'
;
export
const
DUE_DATE_NONE
=
'
0
'
;
export
const
DUE_DATE_ANY
=
''
;
export
const
DUE_DATE_OVERDUE
=
'
overdue
'
;
export
const
DUE_DATE_WEEK
=
'
week
'
;
export
const
DUE_DATE_MONTH
=
'
month
'
;
export
const
DUE_DATE_NEXT_MONTH_AND_PREVIOUS_TWO_WEEKS
=
'
next_month_and_previous_two_weeks
'
;
export
const
DUE_DATE_VALUES
=
[
DUE_DATE_NONE
,
DUE_DATE_ANY
,
DUE_DATE_OVERDUE
,
DUE_DATE_WEEK
,
DUE_DATE_MONTH
,
DUE_DATE_NEXT_MONTH_AND_PREVIOUS_TWO_WEEKS
,
];
export
const
BLOCKING_ISSUES_DESC
=
'
BLOCKING_ISSUES_DESC
'
;
export
const
CREATED_ASC
=
'
CREATED_ASC
'
;
export
const
CREATED_DESC
=
'
CREATED_DESC
'
;
...
...
@@ -258,13 +274,16 @@ export const urlSortParams = {
export
const
MAX_LIST_SIZE
=
10
;
export
const
API_PARAM
=
'
apiParam
'
;
export
const
URL_PARAM
=
'
urlParam
'
;
export
const
NORMAL_FILTER
=
'
normalFilter
'
;
export
const
SPECIAL_FILTER
=
'
specialFilter
'
;
export
const
ALTERNATIVE_FILTER
=
'
alternativeFilter
'
;
export
const
SPECIAL_FILTER_VALUES
=
[
FILTER_NONE
,
FILTER_ANY
,
FILTER_CURRENT
];
export
const
filters
=
{
author_username
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
author_username
'
,
},
...
...
@@ -272,7 +291,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[author_username]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
author_username
'
,
},
...
...
@@ -282,7 +301,7 @@ export const filters = {
},
},
assignee_username
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
assignee_username
'
,
[
SPECIAL_FILTER
]:
'
assignee_id
'
,
...
...
@@ -291,10 +310,11 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[assignee_username]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
assignee_username[]
'
,
[
SPECIAL_FILTER
]:
'
assignee_id
'
,
[
ALTERNATIVE_FILTER
]:
'
assignee_username
'
,
},
[
OPERATOR_IS_NOT
]:
{
[
NORMAL_FILTER
]:
'
not[assignee_username][]
'
,
...
...
@@ -302,7 +322,7 @@ export const filters = {
},
},
milestone
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
milestone
'
,
},
...
...
@@ -310,7 +330,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[milestone]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
milestone_title
'
,
},
...
...
@@ -320,7 +340,7 @@ export const filters = {
},
},
labels
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
labels
'
,
},
...
...
@@ -328,7 +348,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[labels]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
label_name[]
'
,
},
...
...
@@ -338,13 +358,13 @@ export const filters = {
},
},
my_reaction_emoji
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
my_reaction_emoji
'
,
[
SPECIAL_FILTER
]:
'
my_reaction_emoji
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
my_reaction_emoji
'
,
[
SPECIAL_FILTER
]:
'
my_reaction_emoji
'
,
...
...
@@ -352,19 +372,19 @@ export const filters = {
},
},
confidential
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
confidential
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
confidential
'
,
},
},
},
iteration
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
iteration_title
'
,
[
SPECIAL_FILTER
]:
'
iteration_id
'
,
...
...
@@ -373,7 +393,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[iteration_title]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
iteration_title
'
,
[
SPECIAL_FILTER
]:
'
iteration_id
'
,
...
...
@@ -384,7 +404,7 @@ export const filters = {
},
},
epic_id
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
epic_id
'
,
[
SPECIAL_FILTER
]:
'
epic_id
'
,
...
...
@@ -393,7 +413,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[epic_id]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
epic_id
'
,
[
SPECIAL_FILTER
]:
'
epic_id
'
,
...
...
@@ -404,7 +424,7 @@ export const filters = {
},
},
weight
:
{
apiParam
:
{
[
API_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
weight
'
,
[
SPECIAL_FILTER
]:
'
weight
'
,
...
...
@@ -413,7 +433,7 @@ export const filters = {
[
NORMAL_FILTER
]:
'
not[weight]
'
,
},
},
urlParam
:
{
[
URL_PARAM
]
:
{
[
OPERATOR_IS
]:
{
[
NORMAL_FILTER
]:
'
weight
'
,
[
SPECIAL_FILTER
]:
'
weight
'
,
...
...
app/assets/javascripts/issues_list/index.js
View file @
ae385098
...
...
@@ -90,6 +90,7 @@ export function mountIssuesListApp() {
hasIssuableHealthStatusFeature
,
hasIssues
,
hasIssueWeightsFeature
,
hasMultipleIssueAssigneesFeature
,
importCsvIssuesPath
,
initialEmail
,
isSignedIn
,
...
...
@@ -127,6 +128,7 @@ export function mountIssuesListApp() {
hasIssuableHealthStatusFeature
:
parseBoolean
(
hasIssuableHealthStatusFeature
),
hasIssues
:
parseBoolean
(
hasIssues
),
hasIssueWeightsFeature
:
parseBoolean
(
hasIssueWeightsFeature
),
hasMultipleIssueAssigneesFeature
:
parseBoolean
(
hasMultipleIssueAssigneesFeature
),
isSignedIn
:
parseBoolean
(
isSignedIn
),
issuesPath
,
jiraIntegrationPath
,
...
...
app/assets/javascripts/issues_list/utils.js
View file @
ae385098
...
...
@@ -4,6 +4,7 @@ import {
CREATED_DESC
,
DUE_DATE_ASC
,
DUE_DATE_DESC
,
DUE_DATE_VALUES
,
filters
,
LABEL_PRIORITY_DESC
,
MILESTONE_DUE_ASC
,
...
...
@@ -21,12 +22,15 @@ import {
WEIGHT_ASC
,
WEIGHT_DESC
,
}
from
'
~/issues_list/constants
'
;
import
{
isPositiveInteger
}
from
'
~/lib/utils/number_utils
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
FILTERED_SEARCH_TERM
}
from
'
~/vue_shared/components/filtered_search_bar/constants
'
;
export
const
getSortKey
=
(
sort
)
=>
Object
.
keys
(
urlSortParams
).
find
((
key
)
=>
urlSortParams
[
key
].
sort
===
sort
);
export
const
getDueDateValue
=
(
value
)
=>
(
DUE_DATE_VALUES
.
includes
(
value
)
?
value
:
undefined
);
export
const
getSortOptions
=
(
hasIssueWeightsFeature
,
hasBlockedIssuesFeature
)
=>
{
const
sortOptions
=
[
{
...
...
@@ -167,28 +171,20 @@ export const getFilterTokens = (locationSearch) => {
return
filterTokens
.
concat
(
searchTokens
);
};
const
getFilterType
=
(
data
)
=>
SPECIAL_FILTER_VALUES
.
includes
(
data
)
?
SPECIAL_FILTER
:
NORMAL_FILTER
;
export
const
convertToApiParams
=
(
filterTokens
)
=>
filterTokens
.
filter
((
token
)
=>
token
.
type
!==
FILTERED_SEARCH_TERM
)
.
reduce
((
acc
,
token
)
=>
{
const
filterType
=
getFilterType
(
token
.
value
.
data
);
const
apiParam
=
filters
[
token
.
type
].
apiParam
[
token
.
value
.
operator
][
filterType
];
return
Object
.
assign
(
acc
,
{
[
apiParam
]:
acc
[
apiParam
]
?
`
${
acc
[
apiParam
]}
,
${
token
.
value
.
data
}
`
:
token
.
value
.
data
,
});
},
{});
const
getFilterType
=
(
data
,
tokenType
=
''
)
=>
SPECIAL_FILTER_VALUES
.
includes
(
data
)
||
(
tokenType
===
'
assignee_username
'
&&
isPositiveInteger
(
data
))
?
SPECIAL_FILTER
:
NORMAL_FILTER
;
export
const
convertTo
UrlParams
=
(
filterTokens
)
=>
export
const
convertTo
Params
=
(
filterTokens
,
paramType
)
=>
filterTokens
.
filter
((
token
)
=>
token
.
type
!==
FILTERED_SEARCH_TERM
)
.
reduce
((
acc
,
token
)
=>
{
const
filterType
=
getFilterType
(
token
.
value
.
data
);
const
urlParam
=
filters
[
token
.
type
].
urlParam
[
token
.
value
.
operator
]?.[
filterType
];
const
filterType
=
getFilterType
(
token
.
value
.
data
,
token
.
type
);
const
param
=
filters
[
token
.
type
][
paramType
]
[
token
.
value
.
operator
]?.[
filterType
];
return
Object
.
assign
(
acc
,
{
[
urlParam
]:
acc
[
urlParam
]
?
acc
[
urlParam
].
concat
(
token
.
value
.
data
)
:
[
token
.
value
.
data
]
,
[
param
]:
acc
[
param
]
?
[
acc
[
param
],
token
.
value
.
data
].
flat
()
:
token
.
value
.
data
,
});
},
{});
...
...
app/assets/javascripts/lib/utils/number_utils.js
View file @
ae385098
...
...
@@ -171,3 +171,13 @@ export const formattedChangeInPercent = (firstY, lastY, { nonFiniteResult = '-'
export
const
isNumeric
=
(
value
)
=>
{
return
!
Number
.
isNaN
(
parseInt
(
value
,
10
));
};
const
numberRegex
=
/^
[
0-9
]
+$/
;
/**
* Checks whether the value is a positive number or 0, or a string with equivalent value
*
* @param value
* @return {boolean}
*/
export
const
isPositiveInteger
=
(
value
)
=>
numberRegex
.
test
(
value
);
ee/app/helpers/ee/issues_helper.rb
View file @
ae385098
...
...
@@ -47,7 +47,8 @@ module EE
data
=
super
.
merge!
(
has_blocked_issues_feature:
project
.
feature_available?
(
:blocked_issues
).
to_s
,
has_issuable_health_status_feature:
project
.
feature_available?
(
:issuable_health_status
).
to_s
,
has_issue_weights_feature:
project
.
feature_available?
(
:issue_weights
).
to_s
has_issue_weights_feature:
project
.
feature_available?
(
:issue_weights
).
to_s
,
has_multiple_issue_assignees_feature:
project
.
feature_available?
(
:multiple_issue_assignees
).
to_s
)
if
project
.
feature_available?
(
:epics
)
&&
project
.
group
...
...
ee/spec/helpers/ee/issues_helper_spec.rb
View file @
ae385098
...
...
@@ -137,7 +137,7 @@ RSpec.describe EE::IssuesHelper do
context
'when features are enabled'
do
before
do
stub_licensed_features
(
epics:
true
,
iterations:
true
,
issue_weights:
true
,
issuable_health_status:
true
,
blocked_issues:
true
)
stub_licensed_features
(
epics:
true
,
iterations:
true
,
issue_weights:
true
,
issuable_health_status:
true
,
blocked_issues:
true
,
multiple_issue_assignees:
true
)
end
it
'returns data with licensed features enabled'
do
...
...
@@ -145,6 +145,7 @@ RSpec.describe EE::IssuesHelper do
has_blocked_issues_feature:
'true'
,
has_issuable_health_status_feature:
'true'
,
has_issue_weights_feature:
'true'
,
has_multiple_issue_assignees_feature:
'true'
,
group_epics_path:
group_epics_path
(
project
.
group
,
format: :json
),
project_iterations_path:
api_v4_projects_iterations_path
(
id:
project
.
id
)
}
...
...
@@ -163,17 +164,19 @@ RSpec.describe EE::IssuesHelper do
context
'when features are disabled'
do
before
do
stub_licensed_features
(
epics:
false
,
iterations:
false
,
issue_weights:
false
,
issuable_health_status:
false
,
blocked_issues:
false
)
stub_licensed_features
(
epics:
false
,
iterations:
false
,
issue_weights:
false
,
issuable_health_status:
false
,
blocked_issues:
false
,
multiple_issue_assignees:
false
)
end
it
'returns data with licensed features disabled'
do
expected
=
{
has_blocked_issues_feature:
'false'
,
has_issuable_health_status_feature:
'false'
,
has_issue_weights_feature:
'false'
has_issue_weights_feature:
'false'
,
has_multiple_issue_assignees_feature:
'false'
}
result
=
helper
.
issues_list_data
(
project
,
current_user
,
finder
)
expect
(
result
).
to
include
(
expected
)
expect
(
result
).
not_to
include
(
:group_epics_path
)
expect
(
result
).
not_to
include
(
:project_iterations_path
)
...
...
spec/frontend/issues_list/components/issues_list_app_spec.js
View file @
ae385098
...
...
@@ -13,8 +13,10 @@ import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
import
{
apiSortParams
,
CREATED_DESC
,
DUE_DATE_OVERDUE
,
PAGE_SIZE
,
PAGE_SIZE_MANUAL
,
PARAM_DUE_DATE
,
RELATIVE_POSITION_DESC
,
urlSortParams
,
}
from
'
~/issues_list/constants
'
;
...
...
@@ -217,6 +219,16 @@ describe('IssuesListApp component', () => {
});
describe
(
'
initial url params
'
,
()
=>
{
describe
(
'
due_date
'
,
()
=>
{
it
(
'
is set from the url params
'
,
()
=>
{
global
.
jsdom
.
reconfigure
({
url
:
`
${
TEST_HOST
}
?
${
PARAM_DUE_DATE
}
=
${
DUE_DATE_OVERDUE
}
`
});
wrapper
=
mountComponent
();
expect
(
findIssuableList
().
props
(
'
urlParams
'
)).
toMatchObject
({
due_date
:
DUE_DATE_OVERDUE
});
});
});
describe
(
'
page
'
,
()
=>
{
it
(
'
is set from the url params
'
,
()
=>
{
const
page
=
5
;
...
...
spec/frontend/issues_list/mock_data.js
View file @
ae385098
...
...
@@ -8,7 +8,9 @@ export const locationSearch = [
'
author_username=homer
'
,
'
not[author_username]=marge
'
,
'
assignee_username[]=bart
'
,
'
not[assignee_username][]=lisa
'
,
'
assignee_username[]=lisa
'
,
'
not[assignee_username][]=patty
'
,
'
not[assignee_username][]=selma
'
,
'
milestone_title=season+4
'
,
'
not[milestone_title]=season+20
'
,
'
label_name[]=cartoon
'
,
...
...
@@ -26,7 +28,8 @@ export const locationSearch = [
].
join
(
'
&
'
);
export
const
locationSearchWithSpecialValues
=
[
'
assignee_id=None
'
,
'
assignee_id=123
'
,
'
assignee_username=bart
'
,
'
my_reaction_emoji=None
'
,
'
iteration_id=Current
'
,
'
epic_id=None
'
,
...
...
@@ -37,7 +40,9 @@ export const filteredTokens = [
{
type
:
'
author_username
'
,
value
:
{
data
:
'
homer
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
author_username
'
,
value
:
{
data
:
'
marge
'
,
operator
:
OPERATOR_IS_NOT
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
bart
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
lisa
'
,
operator
:
OPERATOR_IS_NOT
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
lisa
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
patty
'
,
operator
:
OPERATOR_IS_NOT
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
selma
'
,
operator
:
OPERATOR_IS_NOT
}
},
{
type
:
'
milestone
'
,
value
:
{
data
:
'
season 4
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
milestone
'
,
value
:
{
data
:
'
season 20
'
,
operator
:
OPERATOR_IS_NOT
}
},
{
type
:
'
labels
'
,
value
:
{
data
:
'
cartoon
'
,
operator
:
OPERATOR_IS
}
},
...
...
@@ -57,7 +62,8 @@ export const filteredTokens = [
];
export
const
filteredTokensWithSpecialValues
=
[
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
None
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
123
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
assignee_username
'
,
value
:
{
data
:
'
bart
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
my_reaction_emoji
'
,
value
:
{
data
:
'
None
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
iteration
'
,
value
:
{
data
:
'
Current
'
,
operator
:
OPERATOR_IS
}
},
{
type
:
'
epic_id
'
,
value
:
{
data
:
'
None
'
,
operator
:
OPERATOR_IS
}
},
...
...
@@ -67,12 +73,12 @@ export const filteredTokensWithSpecialValues = [
export
const
apiParams
=
{
author_username
:
'
homer
'
,
'
not[author_username]
'
:
'
marge
'
,
assignee_username
:
'
bart
'
,
'
not[assignee_username]
'
:
'
lisa
'
,
assignee_username
:
[
'
bart
'
,
'
lisa
'
]
,
'
not[assignee_username]
'
:
[
'
patty
'
,
'
selma
'
]
,
milestone
:
'
season 4
'
,
'
not[milestone]
'
:
'
season 20
'
,
labels
:
'
cartoon,tv
'
,
'
not[labels]
'
:
'
live action,drama
'
,
labels
:
[
'
cartoon
'
,
'
tv
'
]
,
'
not[labels]
'
:
[
'
live action
'
,
'
drama
'
]
,
my_reaction_emoji
:
'
thumbsup
'
,
confidential
:
'
no
'
,
iteration_title
:
'
season: #4
'
,
...
...
@@ -84,7 +90,8 @@ export const apiParams = {
};
export
const
apiParamsWithSpecialValues
=
{
assignee_id
:
'
None
'
,
assignee_id
:
'
123
'
,
assignee_username
:
'
bart
'
,
my_reaction_emoji
:
'
None
'
,
iteration_id
:
'
Current
'
,
epic_id
:
'
None
'
,
...
...
@@ -92,28 +99,29 @@ export const apiParamsWithSpecialValues = {
};
export
const
urlParams
=
{
author_username
:
[
'
homer
'
]
,
'
not[author_username]
'
:
[
'
marge
'
]
,
'
assignee_username[]
'
:
[
'
bart
'
],
'
not[assignee_username][]
'
:
[
'
lis
a
'
],
milestone_title
:
[
'
season 4
'
]
,
'
not[milestone_title]
'
:
[
'
season 20
'
]
,
author_username
:
'
homer
'
,
'
not[author_username]
'
:
'
marge
'
,
'
assignee_username[]
'
:
[
'
bart
'
,
'
lisa
'
],
'
not[assignee_username][]
'
:
[
'
patty
'
,
'
selm
a
'
],
milestone_title
:
'
season 4
'
,
'
not[milestone_title]
'
:
'
season 20
'
,
'
label_name[]
'
:
[
'
cartoon
'
,
'
tv
'
],
'
not[label_name][]
'
:
[
'
live action
'
,
'
drama
'
],
my_reaction_emoji
:
[
'
thumbsup
'
]
,
confidential
:
[
'
no
'
]
,
iteration_title
:
[
'
season: #4
'
]
,
'
not[iteration_title]
'
:
[
'
season: #20
'
]
,
epic_id
:
[
'
12
'
]
,
'
not[epic_id]
'
:
[
'
34
'
]
,
weight
:
[
'
1
'
]
,
'
not[weight]
'
:
[
'
3
'
]
,
my_reaction_emoji
:
'
thumbsup
'
,
confidential
:
'
no
'
,
iteration_title
:
'
season: #4
'
,
'
not[iteration_title]
'
:
'
season: #20
'
,
epic_id
:
'
12
'
,
'
not[epic_id]
'
:
'
34
'
,
weight
:
'
1
'
,
'
not[weight]
'
:
'
3
'
,
};
export
const
urlParamsWithSpecialValues
=
{
assignee_id
:
[
'
None
'
],
my_reaction_emoji
:
[
'
None
'
],
iteration_id
:
[
'
Current
'
],
epic_id
:
[
'
None
'
],
weight
:
[
'
None
'
],
assignee_id
:
'
123
'
,
'
assignee_username[]
'
:
'
bart
'
,
my_reaction_emoji
:
'
None
'
,
iteration_id
:
'
Current
'
,
epic_id
:
'
None
'
,
weight
:
'
None
'
,
};
spec/frontend/issues_list/utils_spec.js
View file @
ae385098
...
...
@@ -8,11 +8,11 @@ import {
urlParams
,
urlParamsWithSpecialValues
,
}
from
'
jest/issues_list/mock_data
'
;
import
{
urlSortParams
}
from
'
~/issues_list/constants
'
;
import
{
API_PARAM
,
DUE_DATE_VALUES
,
URL_PARAM
,
urlSortParams
}
from
'
~/issues_list/constants
'
;
import
{
convertTo
Api
Params
,
convertToParams
,
convertToSearchQuery
,
convertToUrlParams
,
getDueDateValue
,
getFilterTokens
,
getSortKey
,
getSortOptions
,
...
...
@@ -25,6 +25,16 @@ describe('getSortKey', () => {
});
});
describe
(
'
getDueDateValue
'
,
()
=>
{
it
.
each
(
DUE_DATE_VALUES
)(
'
returns the argument when it is `%s`
'
,
(
value
)
=>
{
expect
(
getDueDateValue
(
value
)).
toBe
(
value
);
});
it
(
'
returns undefined when the argument is invalid
'
,
()
=>
{
expect
(
getDueDateValue
(
'
invalid value
'
)).
toBeUndefined
();
});
});
describe
(
'
getSortOptions
'
,
()
=>
{
describe
.
each
`
hasIssueWeightsFeature | hasBlockedIssuesFeature | length | containsWeight | containsBlocking
...
...
@@ -70,23 +80,25 @@ describe('getFilterTokens', () => {
});
});
describe
(
'
convertTo
Api
Params
'
,
()
=>
{
describe
(
'
convertToParams
'
,
()
=>
{
it
(
'
returns api params given filtered tokens
'
,
()
=>
{
expect
(
convertTo
ApiParams
(
filteredTokens
)).
toEqual
(
apiParams
);
expect
(
convertTo
Params
(
filteredTokens
,
API_PARAM
)).
toEqual
(
apiParams
);
});
it
(
'
returns api params given filtered tokens with special values
'
,
()
=>
{
expect
(
convertToApiParams
(
filteredTokensWithSpecialValues
)).
toEqual
(
apiParamsWithSpecialValues
);
expect
(
convertToParams
(
filteredTokensWithSpecialValues
,
API_PARAM
)).
toEqual
(
apiParamsWithSpecialValues
,
);
});
});
describe
(
'
convertToUrlParams
'
,
()
=>
{
it
(
'
returns url params given filtered tokens
'
,
()
=>
{
expect
(
convertTo
UrlParams
(
filteredTokens
)).
toEqual
(
urlParams
);
expect
(
convertTo
Params
(
filteredTokens
,
URL_PARAM
)).
toEqual
(
urlParams
);
});
it
(
'
returns url params given filtered tokens with special values
'
,
()
=>
{
expect
(
convertToUrlParams
(
filteredTokensWithSpecialValues
)).
toEqual
(
urlParamsWithSpecialValues
);
expect
(
convertToParams
(
filteredTokensWithSpecialValues
,
URL_PARAM
)).
toEqual
(
urlParamsWithSpecialValues
,
);
});
});
...
...
spec/frontend/lib/utils/number_utility_spec.js
View file @
ae385098
...
...
@@ -10,6 +10,7 @@ import {
changeInPercent
,
formattedChangeInPercent
,
isNumeric
,
isPositiveInteger
,
}
from
'
~/lib/utils/number_utils
'
;
describe
(
'
Number Utils
'
,
()
=>
{
...
...
@@ -184,4 +185,29 @@ describe('Number Utils', () => {
expect
(
isNumeric
(
value
)).
toBe
(
outcome
);
});
});
describe
.
each
`
value | outcome
${
0
}
|
${
true
}
${
'
0
'
}
|
${
true
}
${
12345
}
|
${
true
}
${
'
12345
'
}
|
${
true
}
${
-
1
}
|
${
false
}
${
'
-1
'
}
|
${
false
}
${
1.01
}
|
${
false
}
${
'
1.01
'
}
|
${
false
}
${
'
abcd
'
}
|
${
false
}
${
'
100abcd
'
}
|
${
false
}
${
'
abcd100
'
}
|
${
false
}
${
''
}
|
${
false
}
${
false
}
|
${
false
}
${
true
}
|
${
false
}
${
undefined
}
|
${
false
}
${
null
}
|
${
false
}
${
Infinity
}
|
${
false
}
`
(
'
isPositiveInteger
'
,
({
value
,
outcome
})
=>
{
it
(
`when called with
${
typeof
value
}
${
value
}
it returns
${
outcome
}
`
,
()
=>
{
expect
(
isPositiveInteger
(
value
)).
toBe
(
outcome
);
});
});
});
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