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
c3196212
Commit
c3196212
authored
Dec 04, 2020
by
Sean Arnold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add GraphQL mutation for adding oncall rotation
- Add oncall rotation type + enums - Add mutation - Update docs
parent
0675d91b
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1595 additions
and
48 deletions
+1595
-48
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+246
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+732
-48
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+43
-0
ee/app/graphql/ee/types/mutation_type.rb
ee/app/graphql/ee/types/mutation_type.rb
+1
-0
ee/app/graphql/mutations/incident_management/oncall_rotation/base.rb
...hql/mutations/incident_management/oncall_rotation/base.rb
+25
-0
ee/app/graphql/mutations/incident_management/oncall_rotation/create.rb
...l/mutations/incident_management/oncall_rotation/create.rb
+110
-0
ee/app/graphql/types/incident_management/oncall_rotation_date_input_type.rb
...es/incident_management/oncall_rotation_date_input_type.rb
+32
-0
ee/app/graphql/types/incident_management/oncall_rotation_length_input_type.rb
.../incident_management/oncall_rotation_length_input_type.rb
+20
-0
ee/app/graphql/types/incident_management/oncall_rotation_length_unit_enum.rb
...s/incident_management/oncall_rotation_length_unit_enum.rb
+14
-0
ee/app/graphql/types/incident_management/oncall_rotation_type.rb
...graphql/types/incident_management/oncall_rotation_type.rb
+46
-0
ee/app/graphql/types/incident_management/oncall_user_input_type.rb
...aphql/types/incident_management/oncall_user_input_type.rb
+24
-0
ee/app/graphql/types/incident_management/oncall_user_type.rb
ee/app/graphql/types/incident_management/oncall_user_type.rb
+24
-0
ee/spec/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
...ations/incident_management/oncall_rotation/create_spec.rb
+126
-0
ee/spec/graphql/types/incident_management/oncall_rotation_type_spec.rb
...ql/types/incident_management/oncall_rotation_type_spec.rb
+22
-0
ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
...ations/incident_management/oncall_rotation/create_spec.rb
+130
-0
No files found.
doc/api/graphql/reference/gitlab_schema.graphql
View file @
c3196212
...
...
@@ -10870,6 +10870,66 @@ An ISO 8601-encoded date
"""
scalar
ISO8601Date
"""
Describes an incident management on-call rotation
"""
type
IncidentManagementOncallRotation
{
"""
ID
of
the
on
-
call
rotation
"""
id
:
IncidentManagementOncallRotationID
!
"""
Time
zone
of
the
on
-
call
schedule
"""
length
:
Int
"""
Unit
of
the
on
-
call
rotation
length
"""
lengthUnit
:
OncallRotationUnitEnum
"""
Name
of
the
on
-
call
rotation
"""
name
:
String
!
"""
Participants
of
the
on
-
call
rotation
"""
participants
(
"""
Returns
the
elements
in
the
list
that
come
after
the
specified
cursor
.
"""
after
:
String
"""
Returns
the
elements
in
the
list
that
come
before
the
specified
cursor
.
"""
before
:
String
"""
Returns
the
first
_n_
elements
from
the
list
.
"""
first
:
Int
"""
Returns
the
last
_n_
elements
from
the
list
.
"""
last
:
Int
):
OncallUserTypeConnection
"""
Start
date
of
the
on
-
call
rotation
"""
startsAt
:
Time
}
"""
Identifier of IncidentManagement::OncallRotation
"""
scalar
IncidentManagementOncallRotationID
"""
Describes an incident management on-call schedule
"""
...
...
@@ -14794,6 +14854,7 @@ type Mutation {
"""
mergeRequestUpdate
(
input
:
MergeRequestUpdateInput
!):
MergeRequestUpdatePayload
namespaceIncreaseStorageTemporarily
(
input
:
NamespaceIncreaseStorageTemporarilyInput
!):
NamespaceIncreaseStorageTemporarilyPayload
oncallRotationCreate
(
input
:
OncallRotationCreateInput
!):
OncallRotationCreatePayload
oncallScheduleCreate
(
input
:
OncallScheduleCreateInput
!):
OncallScheduleCreatePayload
oncallScheduleDestroy
(
input
:
OncallScheduleDestroyInput
!):
OncallScheduleDestroyPayload
oncallScheduleUpdate
(
input
:
OncallScheduleUpdateInput
!):
OncallScheduleUpdatePayload
...
...
@@ -15404,6 +15465,116 @@ Identifier of Noteable
"""
scalar
NoteableID
"""
Autogenerated input type of OncallRotationCreate
"""
input
OncallRotationCreateInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
name
of
the
on
-
call
rotation
"""
name
:
String
!
"""
The
usernames
of
users
participating
in
the
on
-
call
rotation
"""
participants
:
[
OncallUserInputType
!]!
"""
The
project
to
create
the
on
-
call
schedule
in
"""
projectPath
:
ID
!
"""
The
rotation
length
of
the
on
-
call
rotation
"""
rotationLength
:
OncallRotationLengthInputType
!
"""
The
iid
of
the
on
-
call
schedule
to
create
the
on
-
call
rotation
in
"""
scheduleIid
:
String
!
"""
The
start
date
and
time
of
the
on
-
call
rotation
"""
startsAt
:
OncallRotationDateInputType
!
}
"""
Autogenerated return type of OncallRotationCreate
"""
type
OncallRotationCreatePayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
"""
The
on
-
call
rotation
"""
oncallRotation
:
IncidentManagementOncallRotation
}
"""
Date input type for on-call rotation
"""
input
OncallRotationDateInputType
{
"""
The
date
component
of
the
date
in
YYYY
-
MM
-
DD
format
"""
date
:
String
!
"""
The
time
component
of
the
date
in
24
hr
HH
:
MM
format
"""
time
:
String
!
}
"""
The rotation length of the on-call rotation
"""
input
OncallRotationLengthInputType
{
"""
The
rotation
length
of
the
on
-
call
rotation
"""
length
:
Int
!
"""
The
unit
of
the
rotation
length
of
the
on
-
call
rotation
"""
unit
:
OncallRotationUnitEnum
!
}
"""
Rotation length unit of an on-call rotation
"""
enum
OncallRotationUnitEnum
{
"""
One
Days
"""
DAYS
"""
One
Hours
"""
HOURS
"""
One
Weeks
"""
WEEKS
}
"""
Autogenerated input type of OncallScheduleCreate
"""
...
...
@@ -15549,6 +15720,81 @@ type OncallScheduleUpdatePayload {
oncallSchedule
:
IncidentManagementOncallSchedule
}
"""
The rotation user and color palette
"""
input
OncallUserInputType
{
"""
The
color
palette
to
assign
to
the
on
-
call
user
,
for
example
:
"
blue
".
"""
colorPalette
:
String
"""
The
color
weight
to
assign
to
for
the
on
-
call
user
,
for
example
"500".
Max
4
chars
.
For
easy
identification
of
the
user
.
"""
colorWeight
:
String
"""
The
username
of
the
user
to
participate
in
the
on
-
call
rotation
.
i
.
e
user_one
"""
username
:
String
!
}
"""
The rotation user and color palette
"""
type
OncallUserType
{
"""
The
color
palette
to
assign
to
the
on
-
call
user
.
For
example
"
blue
".
"""
colorPalette
:
String
"""
The
color
weight
to
assign
to
for
the
on
-
call
user
,
for
example
"500".
Max
4
chars
.
For
easy
identification
of
the
user
.
"""
colorWeight
:
String
"""
The
user
who
is
participating
"""
user
:
User
!
}
"""
The connection type for OncallUserType.
"""
type
OncallUserTypeConnection
{
"""
A
list
of
edges
.
"""
edges
:
[
OncallUserTypeEdge
]
"""
A
list
of
nodes
.
"""
nodes
:
[
OncallUserType
]
"""
Information
to
aid
in
pagination
.
"""
pageInfo
:
PageInfo
!
}
"""
An edge in a connection.
"""
type
OncallUserTypeEdge
{
"""
A
cursor
for
use
in
pagination
.
"""
cursor
:
String
!
"""
The
item
at
the
end
of
the
edge
.
"""
node
:
OncallUserType
}
"""
Represents a package
"""
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
c3196212
...
...
@@ -29915,6 +29915,160 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "IncidentManagementOncallRotation",
"description": "Describes an incident management on-call rotation",
"fields": [
{
"name": "id",
"description": "ID of the on-call rotation",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "IncidentManagementOncallRotationID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "length",
"description": "Time zone of the on-call schedule",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "lengthUnit",
"description": "Unit of the on-call rotation length",
"args": [
],
"type": {
"kind": "ENUM",
"name": "OncallRotationUnitEnum",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Name of the on-call rotation",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "participants",
"description": "Participants of the on-call rotation",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "OncallUserTypeConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "startsAt",
"description": "Start date of the on-call rotation",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "IncidentManagementOncallRotationID",
"description": "Identifier of IncidentManagement::OncallRotation",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "IncidentManagementOncallSchedule",
...
...
@@ -43081,6 +43235,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallRotationCreate",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "OncallRotationCreateInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "OncallRotationCreatePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallScheduleCreate",
"description": null,
...
...
@@ -45935,8 +46116,8 @@
},
{
"kind": "INPUT_OBJECT",
"name": "Oncall
Schedule
CreateInput",
"description": "Autogenerated input type of Oncall
Schedule
Create",
"name": "Oncall
Rotation
CreateInput",
"description": "Autogenerated input type of Oncall
Rotation
Create",
"fields": null,
"inputFields": [
{
...
...
@@ -45953,9 +46134,23 @@
},
"defaultValue": null
},
{
"name": "scheduleIid",
"description": "The iid of the on-call schedule to create the on-call rotation in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "The name of the on-call
schedule
",
"description": "The name of the on-call
rotation
",
"type": {
"kind": "NON_NULL",
"name": null,
...
...
@@ -45968,29 +46163,55 @@
"defaultValue": null
},
{
"name": "
description
",
"description": "The
description of the on-call schedule
",
"name": "
startsAt
",
"description": "The
start date and time of the on-call rotation
",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "OncallRotationDateInputType",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "
timezone
",
"description": "The
timezone of the on-call schedule
",
"name": "
rotationLength
",
"description": "The
rotation length of the on-call rotation
",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "
SCALAR
",
"name": "
String
",
"kind": "
INPUT_OBJECT
",
"name": "
OncallRotationLengthInputType
",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "participants",
"description": "The usernames of users participating in the on-call rotation",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "OncallUserInputType",
"ofType": null
}
}
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
...
...
@@ -46008,8 +46229,8 @@
},
{
"kind": "OBJECT",
"name": "Oncall
Schedule
CreatePayload",
"description": "Autogenerated return type of Oncall
Schedule
Create",
"name": "Oncall
Rotation
CreatePayload",
"description": "Autogenerated return type of Oncall
Rotation
Create",
"fields": [
{
"name": "clientMutationId",
...
...
@@ -46052,14 +46273,14 @@
"deprecationReason": null
},
{
"name": "oncall
Schedule
",
"description": "The on-call
schedule
",
"name": "oncall
Rotation
",
"description": "The on-call
rotation
",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "IncidentManagementOncall
Schedule
",
"name": "IncidentManagementOncall
Rotation
",
"ofType": null
},
"isDeprecated": false,
...
...
@@ -46075,27 +46296,27 @@
},
{
"kind": "INPUT_OBJECT",
"name": "Oncall
ScheduleDestroyInput
",
"description": "
Autogenerated input type of OncallScheduleDestroy
",
"name": "Oncall
RotationDateInputType
",
"description": "
Date input type for on-call rotation
",
"fields": null,
"inputFields": [
{
"name": "
projectPath
",
"description": "The
project to remove the on-call schedule from
",
"name": "
date
",
"description": "The
date component of the date in YYYY-MM-DD format
",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "
ID
",
"name": "
String
",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "
iid
",
"description": "The
on-call schedule internal ID to remove
",
"name": "
time
",
"description": "The
time component of the date in 24hr HH:MM format
",
"type": {
"kind": "NON_NULL",
"name": null,
...
...
@@ -46106,16 +46327,6 @@
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
...
...
@@ -46123,22 +46334,279 @@
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallScheduleDestroyPayload",
"description": "Autogenerated return type of OncallScheduleDestroy",
"fields": [
"kind": "INPUT_OBJECT",
"name": "OncallRotationLengthInputType",
"description": "The rotation length of the on-call rotation",
"fields": null,
"inputFields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"name": "length",
"description": "The rotation length of the on-call rotation",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "unit",
"description": "The unit of the rotation length of the on-call rotation",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "OncallRotationUnitEnum",
"ofType": null
}
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "OncallRotationUnitEnum",
"description": "Rotation length unit of an on-call rotation",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "HOURS",
"description": "One Hours",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DAYS",
"description": "One Days",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "WEEKS",
"description": "One Weeks",
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "OncallScheduleCreateInput",
"description": "Autogenerated input type of OncallScheduleCreate",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project to create the on-call schedule in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "The name of the on-call schedule",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "description",
"description": "The description of the on-call schedule",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "timezone",
"description": "The timezone of the on-call schedule",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallScheduleCreatePayload",
"description": "Autogenerated return type of OncallScheduleCreate",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallSchedule",
"description": "The on-call schedule",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "IncidentManagementOncallSchedule",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "OncallScheduleDestroyInput",
"description": "Autogenerated input type of OncallScheduleDestroy",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project to remove the on-call schedule from",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "iid",
"description": "The on-call schedule internal ID to remove",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallScheduleDestroyPayload",
"description": "Autogenerated return type of OncallScheduleDestroy",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
...
...
@@ -46335,6 +46803,222 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "OncallUserInputType",
"description": "The rotation user and color palette",
"fields": null,
"inputFields": [
{
"name": "username",
"description": "The username of the user to participate in the on-call rotation. i.e user_one",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "colorPalette",
"description": "The color palette to assign to the on-call user, for example: \"blue\".",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "colorWeight",
"description": "The color weight to assign to for the on-call user, for example \"500\". Max 4 chars. For easy identification of the user.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallUserType",
"description": "The rotation user and color palette",
"fields": [
{
"name": "colorPalette",
"description": "The color palette to assign to the on-call user. For example \"blue\".",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "colorWeight",
"description": "The color weight to assign to for the on-call user, for example \"500\". Max 4 chars. For easy identification of the user.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "user",
"description": "The user who is participating",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "User",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallUserTypeConnection",
"description": "The connection type for OncallUserType.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "OncallUserTypeEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "OncallUserType",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallUserTypeEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "OncallUserType",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Package",
doc/api/graphql/reference/index.md
View file @
c3196212
...
...
@@ -1712,6 +1712,19 @@ Autogenerated return type of HttpIntegrationUpdate.
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`integration`
| AlertManagementHttpIntegration | The HTTP integration |
### IncidentManagementOncallRotation
Describes an incident management on-call rotation.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`id`
| IncidentManagementOncallRotationID! | ID of the on-call rotation |
|
`length`
| Int | Time zone of the on-call schedule |
|
`lengthUnit`
| OncallRotationUnitEnum | Unit of the on-call rotation length |
|
`name`
| String! | Name of the on-call rotation |
|
`participants`
| OncallUserTypeConnection | Participants of the on-call rotation |
|
`startsAt`
| Time | Start date of the on-call rotation |
### IncidentManagementOncallSchedule
Describes an incident management on-call schedule.
...
...
@@ -2377,6 +2390,16 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
|
`repositionNote`
| Boolean! | Indicates the user can perform
`reposition_note`
on this resource |
|
`resolveNote`
| Boolean! | Indicates the user can perform
`resolve_note`
on this resource |
### OncallRotationCreatePayload
Autogenerated return type of OncallRotationCreate.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`oncallRotation`
| IncidentManagementOncallRotation | The on-call rotation |
### OncallScheduleCreatePayload
Autogenerated return type of OncallScheduleCreate.
...
...
@@ -2407,6 +2430,16 @@ Autogenerated return type of OncallScheduleUpdate.
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`oncallSchedule`
| IncidentManagementOncallSchedule | The on-call schedule |
### OncallUserType
The rotation user and color palette.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`colorPalette`
| String | The color palette to assign to the on-call user. For example "blue". |
|
`colorWeight`
| String | The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user. |
|
`user`
| User! | The user who is participating |
### Package
Represents a package.
...
...
@@ -4574,6 +4607,16 @@ Values for sorting projects.
|
`SIMILARITY`
| Most similar to the search query |
|
`STORAGE`
| Sort by storage size |
### OncallRotationUnitEnum
Rotation length unit of an on-call rotation.
| Value | Description |
| ----- | ----------- |
|
`DAYS`
| One Days |
|
`HOURS`
| One Hours |
|
`WEEKS`
| One Weeks |
### PackageTypeEnum
| Value | Description |
...
...
ee/app/graphql/ee/types/mutation_type.rb
View file @
c3196212
...
...
@@ -55,6 +55,7 @@ module EE
mount_mutation
::
Mutations
::
IncidentManagement
::
OncallSchedule
::
Create
mount_mutation
::
Mutations
::
IncidentManagement
::
OncallSchedule
::
Update
mount_mutation
::
Mutations
::
IncidentManagement
::
OncallSchedule
::
Destroy
mount_mutation
::
Mutations
::
IncidentManagement
::
OncallRotation
::
Create
prepend
(
Types
::
DeprecatedMutations
)
end
...
...
ee/app/graphql/mutations/incident_management/oncall_rotation/base.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Mutations
module
IncidentManagement
module
OncallRotation
class
Base
<
BaseMutation
field
:oncall_rotation
,
::
Types
::
IncidentManagement
::
OncallRotationType
,
null:
true
,
description:
'The on-call rotation'
authorize
:admin_incident_management_oncall_schedule
private
def
response
(
result
,
errors
=
nil
)
{
oncall_rotation:
result
.
payload
[
:oncall_rotation
],
errors:
errors
.
presence
||
result
.
errors
}
end
end
end
end
end
ee/app/graphql/mutations/incident_management/oncall_rotation/create.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Mutations
module
IncidentManagement
module
OncallRotation
class
Create
<
Base
include
ResolvesProject
graphql_name
'OncallRotationCreate'
argument
:project_path
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'The project to create the on-call schedule in'
argument
:schedule_iid
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'The iid of the on-call schedule to create the on-call rotation in'
,
as: :iid
argument
:name
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'The name of the on-call rotation'
argument
:starts_at
,
Types
::
IncidentManagement
::
OncallRotationDateInputType
,
required:
true
,
description:
'The start date and time of the on-call rotation'
argument
:rotation_length
,
Types
::
IncidentManagement
::
OncallRotationLengthInputType
,
required:
true
,
description:
'The rotation length of the on-call rotation'
argument
:participants
,
[
Types
::
IncidentManagement
::
OncallUserInputType
],
required:
true
,
description:
'The usernames of users participating in the on-call rotation'
MAXIMUM_PARTICIPANTS
=
100
def
resolve
(
iid
:,
project_path
:,
participants
:,
**
args
)
project
=
authorized_find!
(
full_path:
project_path
)
schedule
=
::
IncidentManagement
::
OncallSchedulesFinder
.
new
(
current_user
,
project
,
iids:
iid
)
.
execute
.
first
raise_schedule_not_found
unless
schedule
result
=
::
IncidentManagement
::
OncallRotations
::
CreateService
.
new
(
schedule
,
project
,
current_user
,
prepare_params
(
schedule
,
participants
,
args
)
).
execute
errors
=
result
.
error?
?
[
result
.
message
]
:
[]
response
(
result
,
errors
)
end
private
def
prepare_params
(
schedule
,
participants
,
args
)
rotation_length
=
args
[
:rotation_length
][
:length
]
rotation_length_unit
=
args
[
:rotation_length
][
:unit
]
starts_at
=
parse_start_time
(
schedule
,
args
)
args
.
slice
(
:name
).
merge
(
length:
rotation_length
,
length_unit:
rotation_length_unit
,
starts_at:
starts_at
,
participants:
find_participants
(
participants
)
)
end
def
parse_start_time
(
schedule
,
args
)
args
[
:starts_at
].
asctime
.
in_time_zone
(
schedule
.
timezone
)
end
def
find_object
(
full_path
:)
resolve_project
(
full_path:
full_path
)
end
def
find_participants
(
user_array
)
raise_too_many_users_error
if
user_array
.
size
>
MAXIMUM_PARTICIPANTS
usernames
=
user_array
.
map
{
|
h
|
h
[
:username
]
}
matched_users
=
UsersFinder
.
new
(
current_user
,
username:
usernames
).
execute
.
order_by
(
:username
)
raise_user_not_found
if
matched_users
.
size
!=
user_array
.
size
user_array
=
user_array
.
sort_by!
{
|
h
|
h
[
:username
]
}
user_array
.
map
.
with_index
{
|
param
,
i
|
param
.
to_h
.
merge
(
user:
matched_users
[
i
])
}
end
def
raise_schedule_not_found
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'The schedule could not be found'
end
def
raise_too_many_users_error
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
"A maximum of
#{
MAXIMUM_PARTICIPANTS
}
participants can be added"
end
def
raise_user_not_found
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'A username that was provided could not be matched to a user'
end
end
end
end
end
ee/app/graphql/types/incident_management/oncall_rotation_date_input_type.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
# rubocop: disable Graphql/AuthorizeTypes
class
OncallRotationDateInputType
<
BaseInputObject
graphql_name
'OncallRotationDateInputType'
description
'Date input type for on-call rotation'
argument
:date
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'The date component of the date in YYYY-MM-DD format'
argument
:time
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'The time component of the date in 24hr HH:MM format'
DATE_FORMAT
=
%r[
\d
{4}-[0123]
\d
-
\d
{2}]
.
freeze
TIME_FORMAT
=
%r[[012]
\d
:
\d
{2}]
.
freeze
def
prepare
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'Date given is invalid'
unless
DATE_FORMAT
.
match
(
date
)
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'Time given is invalid'
unless
TIME_FORMAT
.
match
(
time
)
Time
.
parse
(
"
#{
date
}
#{
time
}
"
)
rescue
ArgumentError
,
TypeError
raise
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'Date & time is invalid'
end
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
ee/app/graphql/types/incident_management/oncall_rotation_length_input_type.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
# rubocop: disable Graphql/AuthorizeTypes
class
OncallRotationLengthInputType
<
BaseInputObject
graphql_name
'OncallRotationLengthInputType'
description
'The rotation length of the on-call rotation'
argument
:length
,
GraphQL
::
INT_TYPE
,
required:
true
,
description:
'The rotation length of the on-call rotation'
argument
:unit
,
Types
::
IncidentManagement
::
OncallRotationLengthUnitEnum
,
required:
true
,
description:
'The unit of the rotation length of the on-call rotation'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
ee/app/graphql/types/incident_management/oncall_rotation_length_unit_enum.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
class
OncallRotationLengthUnitEnum
<
BaseEnum
graphql_name
'OncallRotationUnitEnum'
description
'Rotation length unit of an on-call rotation'
::
IncidentManagement
::
OncallRotation
.
length_units
.
keys
.
each
do
|
unit
|
value
unit
.
upcase
,
value:
unit
,
description:
"One
#{
unit
.
titleize
}
"
end
end
end
end
ee/app/graphql/types/incident_management/oncall_rotation_type.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
class
OncallRotationType
<
BaseObject
graphql_name
'IncidentManagementOncallRotation'
description
'Describes an incident management on-call rotation'
authorize
:read_incident_management_oncall_schedule
field
:id
,
Types
::
GlobalIDType
[
::
IncidentManagement
::
OncallRotation
],
null:
false
,
description:
'ID of the on-call rotation'
field
:name
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
'Name of the on-call rotation'
field
:starts_at
,
Types
::
TimeType
,
null:
true
,
description:
'Start date of the on-call rotation'
field
:length
,
GraphQL
::
INT_TYPE
,
null:
true
,
description:
'Time zone of the on-call schedule'
field
:length_unit
,
Types
::
IncidentManagement
::
OncallRotationLengthUnitEnum
,
null:
true
,
description:
'Unit of the on-call rotation length'
field
:participants
,
::
Types
::
IncidentManagement
::
OncallUserType
.
connection_type
,
null:
true
,
description:
'Participants of the on-call rotation'
def
participants
object
.
oncall_participants
end
end
end
end
ee/app/graphql/types/incident_management/oncall_user_input_type.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
# rubocop: disable Graphql/AuthorizeTypes
class
OncallUserInputType
<
BaseInputObject
graphql_name
'OncallUserInputType'
description
'The rotation user and color palette'
argument
:username
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'The username of the user to participate in the on-call rotation. i.e user_one'
argument
:color_palette
,
GraphQL
::
STRING_TYPE
,
required:
false
,
description:
'The color palette to assign to the on-call user, for example: "blue".'
argument
:color_weight
,
GraphQL
::
STRING_TYPE
,
required:
false
,
description:
'The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
ee/app/graphql/types/incident_management/oncall_user_type.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
module
Types
module
IncidentManagement
# rubocop: disable Graphql/AuthorizeTypes
class
OncallUserType
<
BaseObject
graphql_name
'OncallUserType'
description
'The rotation user and color palette'
field
:user
,
Types
::
UserType
,
null:
false
,
description:
'The user who is participating'
field
:color_palette
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
'The color palette to assign to the on-call user. For example "blue".'
field
:color_weight
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
'The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
ee/spec/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
IncidentManagement
::
OncallRotation
::
Create
do
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let
(
:args
)
do
{
project_path:
project
.
full_path
,
name:
'On-call rotation'
,
schedule_iid:
schedule
.
iid
,
starts_at:
"2020-01-10 09:00"
.
in_time_zone
(
schedule
.
timezone
),
rotation_length:
{
length:
1
,
unit:
::
IncidentManagement
::
OncallRotation
.
rotation_length_units
[
:days
]
},
participants:
[
{
username:
current_user
.
username
,
color_weight:
"500"
,
color_palette:
"black"
}
]
}
end
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:admin_incident_management_oncall_schedule
)
}
describe
'#resolve'
do
subject
(
:resolve
)
{
mutation_for
(
project
,
current_user
).
resolve
(
iid:
schedule
.
iid
,
project_path:
project
.
full_path
,
participants:
args
[
:participants
],
**
args
)
}
context
'user has access to project'
do
before
do
stub_licensed_features
(
oncall_schedules:
true
)
project
.
add_maintainer
(
current_user
)
end
context
'when OncallRotation::CreateService responds with success'
do
it
'returns the on-call rotation with no errors'
do
expect
(
resolve
).
to
match
(
oncall_rotation:
::
IncidentManagement
::
OncallRotation
.
last!
,
errors:
be_empty
)
end
end
context
'when OncallRotations::CreateService responds with an error'
do
before
do
allow_any_instance_of
(
::
IncidentManagement
::
OncallRotations
::
CreateService
)
.
to
receive
(
:execute
)
.
and_return
(
ServiceResponse
.
error
(
payload:
{
oncall_rotation:
nil
},
message:
'An on-call rotation already exists'
))
end
it
'returns errors'
do
expect
(
resolve
).
to
eq
(
oncall_rotation:
nil
,
errors:
[
'An on-call rotation already exists'
]
)
end
end
describe
'error cases'
do
context
'user cannot be found'
do
before
do
args
.
merge!
(
participants:
[
username:
'unknown'
])
end
it
'raises an error'
do
expect
{
resolve
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'A username that was provided could not be matched to a user'
)
end
end
context
'user does not have access to the project'
do
before
do
other_user
=
create
(
:user
)
args
.
merge!
(
participants:
[
{
username:
other_user
.
username
,
color_weight:
"500"
,
color_palette:
"black"
}
]
)
end
it
'raises an error'
do
expect
{
resolve
}.
to
raise_error
(
ActiveRecord
::
RecordInvalid
,
/participant does not have access to the project/
)
end
end
context
'schedule does not exist'
do
let
(
:schedule
)
{
double
(
iid:
non_existing_record_iid
,
timezone:
'UTC'
)
}
it
'raises an error'
do
expect
{
resolve
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
'The schedule could not be found'
)
end
end
context
'too many users'
do
before
do
stub_const
(
'Mutations::IncidentManagement::OncallRotation::Create::MAXIMUM_PARTICIPANTS'
,
0
)
end
it
'raises an error'
do
expect
{
resolve
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ArgumentError
,
"A maximum of
#{
described_class
::
MAXIMUM_PARTICIPANTS
}
participants can be added"
)
end
end
end
end
context
'when resource is not accessible to the user'
do
it
'raises an error'
do
expect
{
resolve
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
end
end
private
def
mutation_for
(
project
,
user
)
described_class
.
new
(
object:
project
,
context:
{
current_user:
user
},
field:
nil
)
end
end
ee/spec/graphql/types/incident_management/oncall_rotation_type_spec.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
GitlabSchema
.
types
[
'IncidentManagementOncallRotation'
]
do
specify
{
expect
(
described_class
.
graphql_name
).
to
eq
(
'IncidentManagementOncallRotation'
)
}
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:read_incident_management_oncall_schedule
)
}
it
'exposes the expected fields'
do
expected_fields
=
%i[
id
name
starts_at
rotation_length
rotation_length_unit
participants
]
expect
(
described_class
).
to
have_graphql_fields
(
*
expected_fields
)
end
end
ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
0 → 100644
View file @
c3196212
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Creating a new on-call schedule'
do
include
GraphqlHelpers
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let
(
:args
)
do
{
project_path:
project
.
full_path
,
name:
'On-call rotation'
,
schedule_iid:
schedule
.
iid
.
to_s
,
starts_at:
{
date:
"2020-09-19"
,
time:
"09:00"
},
rotation_length:
{
length:
1
,
unit:
'DAYS'
},
participants:
[
{
username:
current_user
.
username
,
colorWeight:
"500"
,
colorPalette:
"black"
}
]
}
end
let
(
:mutation
)
do
graphql_mutation
(
:oncall_rotation_create
,
args
)
do
<<~
QL
clientMutationId
errors
oncallRotation {
id
name
startsAt
length
lengthUnit
participants {
nodes {
user {
id
username
}
}
}
}
QL
end
end
let
(
:mutation_response
)
{
graphql_mutation_response
(
:oncall_rotation_create
)
}
before
do
stub_licensed_features
(
oncall_schedules:
true
)
project
.
add_maintainer
(
current_user
)
end
it
'creates a new on-call rotation'
,
:aggregate_failures
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
new_oncall_rotation
=
::
IncidentManagement
::
OncallRotation
.
last!
oncall_rotation_response
=
mutation_response
[
'oncallRotation'
]
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
expect
(
oncall_rotation_response
.
slice
(
*
%w[id name length lengthUnit]
)).
to
eq
(
'id'
=>
global_id_of
(
new_oncall_rotation
),
'name'
=>
args
[
:name
],
'length'
=>
1
,
'lengthUnit'
=>
'DAYS'
)
start_time
=
"
#{
args
[
:starts_at
][
:date
]
}
#{
args
[
:starts_at
][
:time
]
}
"
.
in_time_zone
(
schedule
.
timezone
)
expect
(
Time
.
parse
(
oncall_rotation_response
[
'startsAt'
])).
to
eq
(
start_time
)
expect
(
oncall_rotation_response
.
dig
(
'participants'
,
'nodes'
)).
to
contain_exactly
(
{
'user'
=>
{
'id'
=>
global_id_of
(
current_user
),
'username'
=>
current_user
.
username
}
}
)
end
%i[project_path schedule_iid name starts_at rotation_length participants]
.
each
do
|
argument
|
context
"without required argument
#{
argument
}
"
do
before
do
args
.
delete
(
argument
)
end
it_behaves_like
'an invalid argument to the mutation'
,
argument_name:
argument
end
end
context
'time is invalid'
do
before
do
args
[
:starts_at
][
:time
]
=
'999:999'
end
it
'returns the on-call rotation with errors'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
graphql_errors
).
not_to
be_empty
error
=
graphql_errors
.
first
.
dig
(
'extensions'
,
'problems'
,
0
,
'explanation'
)
expect
(
error
).
to
match
(
'Time given is invalid'
)
end
end
context
'date is invalid'
do
before
do
args
[
:starts_at
][
:date
]
=
'incorrect date'
end
it
'returns the on-call rotation with errors'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
graphql_errors
).
not_to
be_empty
error
=
graphql_errors
.
first
.
dig
(
'extensions'
,
'problems'
,
0
,
'explanation'
)
expect
(
error
).
to
match
(
'Date given is invalid'
)
end
end
end
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