Skip to content

Commit 7c83e69

Browse files
authored
Merge pull request #8221 from nextcloud/tests/rest-api-integration
test: cover the documented REST API with integration tests
2 parents 2e7b5b8 + 8e170a5 commit 7c83e69

10 files changed

Lines changed: 1205 additions & 1 deletion

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
96706
1+
198420

tests/integration/config/behat.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ default:
1414
baseUrl: http://localhost:8080/
1515
- RequestContext
1616
- BoardContext
17+
- DeckApiContext
1718
- CommentContext
1819
- AttachmentContext
1920
- SearchContext
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
Feature: REST API - Attachments
2+
Basic coverage of the attachment endpoints documented at
3+
https://deck.readthedocs.io/en/stable/API/#attachments
4+
5+
Background:
6+
Given user "admin" exists
7+
And user "user0" exists
8+
And user "user1" exists
9+
And acting as user "user0"
10+
And sending "POST" to the API endpoint "/boards" with body:
11+
| title | Attachment board |
12+
| color | ff0000 |
13+
And the response value "id" is stored as "boardId"
14+
And sending "POST" to the API endpoint "/boards/<boardId>/stacks" with body:
15+
| title | ToDo |
16+
| order | 1 |
17+
And the response value "id" is stored as "stackId"
18+
And sending "POST" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards" with body:
19+
| title | Card with attachments |
20+
| type | plain |
21+
| order | 999 |
22+
And the response value "id" is stored as "cardId"
23+
24+
Scenario: POST /boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments - Upload an attachment
25+
When uploading the file "test.txt" with content "Example content" as attachment type "deck_file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
26+
Then the response should have a status code "200"
27+
And the response value "cardId" should be "<cardId>"
28+
And the response value "type" should be "deck_file"
29+
And the response value "data" should be "test.txt"
30+
And the response value "createdBy" should be "user0"
31+
And the response value "deletedAt" should be "0"
32+
And the response value "extendedData.filesize" should be "15"
33+
34+
Scenario: GET /boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments - Get a list of attachments
35+
Given uploading the file "test.txt" with content "Example content" as attachment type "deck_file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
36+
And the response should have a status code "200"
37+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
38+
Then the response should have a status code "200"
39+
And the response should be a list of objects
40+
And the response list should contain 1 entry
41+
And the response list should contain an entry with "data" set to "test.txt"
42+
And the response value "0.extendedData.info.filename" should be "test"
43+
And the response value "0.extendedData.info.extension" should be "txt"
44+
45+
Scenario: GET /boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId} - Get the attachment file
46+
Given uploading the file "test.txt" with content "Example content" as attachment type "deck_file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
47+
And the response value "id" is stored as "attachmentId"
48+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments/<attachmentId>"
49+
Then the response should have a status code "200"
50+
And the response body should be "Example content"
51+
52+
Scenario: DELETE /boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId} - Delete and restore an attachment
53+
Given uploading the file "test.txt" with content "Example content" as attachment type "deck_file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
54+
And the response value "id" is stored as "attachmentId"
55+
When sending "DELETE" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments/<attachmentId>"
56+
Then the response should have a status code "200"
57+
And the response value "deletedAt" should not be "0"
58+
# Attachments are deleted in two steps, so they stay listed with a deletion
59+
# timestamp until they are either restored or removed for good
60+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
61+
Then the response list should contain 1 entry
62+
And the response value "0.deletedAt" should not be "0"
63+
When sending "PUT" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments/<attachmentId>/restore"
64+
Then the response should have a status code "200"
65+
And the response value "deletedAt" should be "0"
66+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
67+
Then the response list should contain 1 entry
68+
And the response value "0.deletedAt" should be "0"
69+
70+
Scenario: Attachments stored in the files app are only returned by API version 1.1
71+
Given using the Deck API version "1.1"
72+
When uploading the file "in-files.txt" with content "Example content" as attachment type "file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
73+
Then the response should have a status code "200"
74+
And the response value "type" should be "file"
75+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
76+
Then the response should have a status code "200"
77+
And the response list should contain 1 entry
78+
And the response list should contain an entry with "type" set to "file"
79+
# API version 1.0 predates the files app integration and only knows deck_file attachments
80+
Given using the Deck API version "1.0"
81+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
82+
Then the response should have a status code "200"
83+
And the response list should contain 0 entries
84+
85+
Scenario: Attachments of a board of another user are not accessible
86+
Given uploading the file "test.txt" with content "Example content" as attachment type "deck_file" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
87+
And the response value "id" is stored as "attachmentId"
88+
And acting as user "user1"
89+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments"
90+
Then the response should have a status code "403"
91+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments/<attachmentId>"
92+
Then the response should have a status code "403"
93+
When sending "DELETE" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards/<cardId>/attachments/<attachmentId>"
94+
Then the response should have a status code "403"
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Feature: REST API - Authentication
2+
The API is meant to be consumed by external integrations rather than by a
3+
browser, so it has to stay reachable with basic auth and without a CSRF
4+
token, see https://deck.readthedocs.io/en/stable/API/#prerequisites
5+
6+
Background:
7+
Given user "admin" exists
8+
And user "user0" exists
9+
And user "user1" exists
10+
And acting as user "user0"
11+
And sending "POST" to the API endpoint "/boards" with body:
12+
| title | Integration board |
13+
| color | ff0000 |
14+
And the response value "id" is stored as "boardId"
15+
16+
Scenario: Unauthenticated requests are rejected
17+
When sending "GET" to the API endpoint "/boards" without authentication
18+
Then the response should have a status code "401"
19+
When sending "GET" to the API endpoint "/boards/<boardId>" without authentication
20+
Then the response should have a status code "401"
21+
22+
# The password is the one the shared behat provisioning steps assign to new users
23+
Scenario: A client can use the API with basic auth and without a CSRF token
24+
When sending "GET" to the API endpoint "/boards" as "user0" with password "123456"
25+
Then the response should have a status code "200"
26+
And the response list should contain an entry with "title" set to "Integration board"
27+
When sending "GET" to the API endpoint "/boards/<boardId>" as "user0" with password "123456"
28+
Then the response should have a status code "200"
29+
And the response value "title" should be "Integration board"
30+
31+
Scenario: Basic auth is bound to the authenticated user
32+
When sending "GET" to the API endpoint "/boards/<boardId>" as "user1" with password "123456"
33+
Then the response should have a status code "403"
34+
And the response value "message" should be "Permission denied"
35+
When sending "GET" to the API endpoint "/boards" as "user1" with password "123456"
36+
Then the response should have a status code "200"
37+
And the response list should not contain an entry with "title" set to "Integration board"
38+
39+
Scenario: A client can write through the API with basic auth
40+
When sending "POST" to the API endpoint "/boards/<boardId>/stacks" as "user0" with password "123456" and body:
41+
| title | Stack from a client |
42+
| order | 1 |
43+
Then the response should have a status code "200"
44+
And the response value "title" should be "Stack from a client"
45+
When sending "GET" to the API endpoint "/boards/<boardId>/stacks"
46+
Then the response should have a status code "200"
47+
And the response list should contain an entry with "title" set to "Stack from a client"
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
Feature: REST API - Boards
2+
Basic coverage of the board endpoints documented at
3+
https://deck.readthedocs.io/en/stable/API/#boards
4+
5+
Background:
6+
Given user "admin" exists
7+
And user "user0" exists
8+
And user "user1" exists
9+
And acting as user "user0"
10+
11+
Scenario: POST /boards - Create a new board
12+
When sending "POST" to the API endpoint "/boards" with body:
13+
| title | Board title |
14+
| color | ff0000 |
15+
Then the response should have a status code "200"
16+
And the response value "title" should be "Board title"
17+
And the response value "color" should be "ff0000"
18+
And the response value "archived" should be "false"
19+
And the response value "deletedAt" should be "0"
20+
And the response value "owner.uid" should be "user0"
21+
And the response value "permissions.PERMISSION_READ" should be "true"
22+
And the response value "permissions.PERMISSION_EDIT" should be "true"
23+
And the response value "permissions.PERMISSION_MANAGE" should be "true"
24+
And the response value "permissions.PERMISSION_SHARE" should be "true"
25+
And the response value "acl" should be empty
26+
And the response value "labels" should have 4 entries
27+
28+
Scenario: POST /boards - Fail to create a board with invalid parameters
29+
When sending "POST" to the API endpoint "/boards" with body:
30+
| title | This is a very long name that exceeds the maximum length of a deck board which is limited to 100 characters |
31+
| color | ff0000 |
32+
Then the response should have a status code "400"
33+
And the response value "status" should be "400"
34+
When sending "POST" to the API endpoint "/boards" with body:
35+
| title | Board title |
36+
| color | |
37+
Then the response should have a status code "400"
38+
And the response value "status" should be "400"
39+
40+
Scenario: GET /boards - Get a list of boards
41+
Given sending "POST" to the API endpoint "/boards" with body:
42+
| title | Listed board |
43+
| color | 00ff00 |
44+
And the response should have a status code "200"
45+
When sending "GET" to the API endpoint "/boards"
46+
Then the response should have a status code "200"
47+
And the response should be a list of objects
48+
And the response list should contain an entry with "title" set to "Listed board"
49+
And the response should have the header "ETag"
50+
51+
Scenario: GET /boards - Get a list of boards with details
52+
Given sending "POST" to the API endpoint "/boards" with body:
53+
| title | Detailed board |
54+
| color | 00ff00 |
55+
And the response value "id" is stored as "boardId"
56+
When sending "GET" to the API endpoint "/boards?details=true"
57+
Then the response should have a status code "200"
58+
And the response list should contain an entry with "id" set to "<boardId>"
59+
60+
Scenario: GET /boards - Limit the board list with If-Modified-Since
61+
Given sending "POST" to the API endpoint "/boards" with body:
62+
| title | Unmodified board |
63+
| color | 00ff00 |
64+
When sending "GET" to the API endpoint "/boards" with the header "If-Modified-Since" set to "Sun, 03 Aug 2036 10:34:12 GMT"
65+
Then the response should have a status code "200"
66+
And the response list should contain 0 entries
67+
68+
Scenario: GET /boards/{boardId} - Get board details
69+
Given sending "POST" to the API endpoint "/boards" with body:
70+
| title | Board details |
71+
| color | 0000ff |
72+
And the response value "id" is stored as "boardId"
73+
When sending "GET" to the API endpoint "/boards/<boardId>"
74+
Then the response should have a status code "200"
75+
And the response value "id" should be "<boardId>"
76+
And the response value "title" should be "Board details"
77+
And the response value "color" should be "0000ff"
78+
And the response should have the header "ETag"
79+
80+
Scenario: GET /boards/{boardId} - Unchanged boards are answered with 304 Not Modified
81+
Given sending "POST" to the API endpoint "/boards" with body:
82+
| title | Etag board |
83+
| color | 0000ff |
84+
And the response value "id" is stored as "boardId"
85+
And sending "GET" to the API endpoint "/boards/<boardId>"
86+
And the response header "ETag" is stored as "boardEtag"
87+
When sending "GET" to the API endpoint "/boards/<boardId>" with the header "If-None-Match" set to "<boardEtag>"
88+
Then the response should have a status code "304"
89+
90+
Scenario: PUT /boards/{boardId} - Update board details
91+
Given sending "POST" to the API endpoint "/boards" with body:
92+
| title | Board to update |
93+
| color | ff0000 |
94+
And the response value "id" is stored as "boardId"
95+
When sending "PUT" to the API endpoint "/boards/<boardId>" with body:
96+
| title | Updated board |
97+
| color | 00ff00 |
98+
| archived | true |
99+
Then the response should have a status code "200"
100+
And the response value "title" should be "Updated board"
101+
And the response value "color" should be "00ff00"
102+
And the response value "archived" should be "true"
103+
When sending "GET" to the API endpoint "/boards/<boardId>"
104+
Then the response value "title" should be "Updated board"
105+
And the response value "archived" should be "true"
106+
107+
Scenario: DELETE /boards/{boardId} - Delete a board and restore it again
108+
Given sending "POST" to the API endpoint "/boards" with body:
109+
| title | Board to delete |
110+
| color | ff0000 |
111+
And the response value "id" is stored as "boardId"
112+
When sending "DELETE" to the API endpoint "/boards/<boardId>"
113+
Then the response should have a status code "200"
114+
# Boards are deleted in two steps, so they stay listed with a deletion timestamp
115+
# until they are either restored or removed for good by the cleanup job
116+
And the response value "deletedAt" should not be "0"
117+
When sending "POST" to the API endpoint "/boards/<boardId>/undo_delete"
118+
Then the response should have a status code "200"
119+
And the response value "deletedAt" should be "0"
120+
When sending "GET" to the API endpoint "/boards/<boardId>"
121+
Then the response should have a status code "200"
122+
And the response value "title" should be "Board to delete"
123+
And the response value "deletedAt" should be "0"
124+
125+
Scenario: POST /boards/{boardId}/acl - Add, update and delete an acl rule
126+
Given sending "POST" to the API endpoint "/boards" with body:
127+
| title | Shared board |
128+
| color | ff0000 |
129+
And the response value "id" is stored as "boardId"
130+
When sending "POST" to the API endpoint "/boards/<boardId>/acl" with body:
131+
| type | 0 |
132+
| participant | user1 |
133+
| permissionEdit | true |
134+
| permissionShare | false |
135+
| permissionManage | false |
136+
Then the response should have a status code "200"
137+
And the response value "participant.uid" should be "user1"
138+
And the response value "type" should be "0"
139+
And the response value "boardId" should be "<boardId>"
140+
And the response value "permissionEdit" should be "true"
141+
And the response value "permissionShare" should be "false"
142+
And the response value "permissionManage" should be "false"
143+
And the response value "owner" should be "false"
144+
And the response value "id" is stored as "aclId"
145+
146+
When sending "PUT" to the API endpoint "/boards/<boardId>/acl/<aclId>" with body:
147+
| permissionEdit | false |
148+
| permissionShare | true |
149+
| permissionManage | true |
150+
Then the response should have a status code "200"
151+
And the response value "permissionEdit" should be "false"
152+
And the response value "permissionShare" should be "true"
153+
And the response value "permissionManage" should be "true"
154+
155+
Given acting as user "user1"
156+
When sending "GET" to the API endpoint "/boards"
157+
Then the response list should contain an entry with "title" set to "Shared board"
158+
159+
Given acting as user "user0"
160+
When sending "DELETE" to the API endpoint "/boards/<boardId>/acl/<aclId>"
161+
Then the response should have a status code "200"
162+
Given acting as user "user1"
163+
When sending "GET" to the API endpoint "/boards"
164+
Then the response list should not contain an entry with "title" set to "Shared board"
165+
166+
Scenario: POST /boards/{boardId}/clone - Clone a board
167+
Given sending "POST" to the API endpoint "/boards" with body:
168+
| title | Board to clone |
169+
| color | ff0000 |
170+
And the response value "id" is stored as "boardId"
171+
And sending "POST" to the API endpoint "/boards/<boardId>/stacks" with body:
172+
| title | ToDo |
173+
| order | 1 |
174+
And the response value "id" is stored as "stackId"
175+
And sending "POST" to the API endpoint "/boards/<boardId>/stacks/<stackId>/cards" with body:
176+
| title | Card to clone |
177+
| type | plain |
178+
| order | 999 |
179+
When sending "POST" to the API endpoint "/boards/<boardId>/clone" with body:
180+
| withCards | true |
181+
Then the response should have a status code "200"
182+
And the response value "title" should be "Board to clone (copy)"
183+
And the response value "id" should not be "<boardId>"
184+
And the response value "id" is stored as "clonedBoardId"
185+
When sending "GET" to the API endpoint "/boards/<clonedBoardId>/stacks"
186+
Then the response should have a status code "200"
187+
And the response list should contain 1 entry
188+
And the response value "0.title" should be "ToDo"
189+
And the response value "0.cards" should have 1 entry
190+
And the response value "0.cards.0.title" should be "Card to clone"
191+
192+
Scenario: Boards of other users are not accessible
193+
Given sending "POST" to the API endpoint "/boards" with body:
194+
| title | Private board |
195+
| color | ff0000 |
196+
And the response value "id" is stored as "boardId"
197+
Given acting as user "user1"
198+
When sending "GET" to the API endpoint "/boards/<boardId>"
199+
Then the response should have a status code "403"
200+
And the response value "status" should be "403"
201+
And the response value "message" should be "Permission denied"
202+
When sending "PUT" to the API endpoint "/boards/<boardId>" with body:
203+
| title | Hijacked board |
204+
| color | 00ff00 |
205+
| archived | false |
206+
Then the response should have a status code "403"
207+
When sending "DELETE" to the API endpoint "/boards/<boardId>"
208+
Then the response should have a status code "403"

0 commit comments

Comments
 (0)