Skip to content

Commit 4f75db6

Browse files
authoredAug 1, 2022
Merge pull request #77 from 5am-code/dev
v0.8.0 🍉 - Bugfixes, Pagination and General Improvements
2 parents 21e07d4 + 1963906 commit 4f75db6

13 files changed

+802
-20
lines changed
 

‎src/Endpoints/Database.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace FiveamCode\LaravelNotionApi\Endpoints;
44

5+
use FiveamCode\LaravelNotionApi\Entities\Collections\EntityCollection;
56
use FiveamCode\LaravelNotionApi\Entities\Collections\PageCollection;
67
use FiveamCode\LaravelNotionApi\Notion;
78
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
@@ -66,7 +67,7 @@ public function query(): PageCollection
6667
} // TODO Compound filters!
6768

6869
if ($this->startCursor !== null) {
69-
$postData['start_cursor'] = $this->startCursor;
70+
$postData['start_cursor'] = $this->startCursor->__toString();
7071
}
7172

7273
if ($this->pageSize !== null) {
@@ -104,4 +105,15 @@ public function sortBy(Collection $sorts): Database
104105

105106
return $this;
106107
}
108+
109+
/**
110+
* @param EntityCollection $entityCollection
111+
* @return $this
112+
*/
113+
public function offsetByResponse(EntityCollection $entityCollection): Database
114+
{
115+
$this->offset($entityCollection->nextCursor());
116+
117+
return $this;
118+
}
107119
}

‎src/Entities/Collections/EntityCollection.php

+51
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use FiveamCode\LaravelNotionApi\Entities\Page;
88
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
99
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
10+
use FiveamCode\LaravelNotionApi\Query\StartCursor;
1011
use Illuminate\Support\Arr;
1112
use Illuminate\Support\Collection;
1213

@@ -25,6 +26,16 @@ class EntityCollection
2526
*/
2627
protected array $rawResults = [];
2728

29+
/**
30+
* @var bool
31+
*/
32+
protected bool $hasMore = false;
33+
34+
/**
35+
* @var string
36+
*/
37+
protected ?string $nextCursor = null;
38+
2839
/**
2940
* @var Collection
3041
*/
@@ -96,13 +107,24 @@ protected function collectChildren(): void
96107
protected function fillFromRaw()
97108
{
98109
$this->fillResult();
110+
$this->fillCursorInformation();
99111
}
100112

101113
protected function fillResult()
102114
{
103115
$this->rawResults = $this->responseData['results'];
104116
}
105117

118+
protected function fillCursorInformation()
119+
{
120+
if (Arr::exists($this->responseData, 'has_more')) {
121+
$this->hasMore = $this->responseData['has_more'];
122+
}
123+
if (Arr::exists($this->responseData, 'next_cursor')) {
124+
$this->nextCursor = $this->responseData['next_cursor'];
125+
}
126+
}
127+
106128
/**
107129
* @return array
108130
*/
@@ -111,6 +133,14 @@ public function getRawResponse(): array
111133
return $this->responseData;
112134
}
113135

136+
/**
137+
* @return string
138+
*/
139+
public function getRawNextCursor(): ?string
140+
{
141+
return $this->nextCursor;
142+
}
143+
114144
/**
115145
* @return Collection
116146
*/
@@ -128,4 +158,25 @@ public function asJson(): string
128158
return $item->toArray();
129159
});
130160
}
161+
162+
/**
163+
* @return bool
164+
*/
165+
public function hasMoreEntries(): bool
166+
{
167+
return $this->hasMore;
168+
}
169+
170+
/**
171+
* @return StartCursor
172+
*/
173+
public function nextCursor(): ?StartCursor
174+
{
175+
$rawNextCursor = $this->getRawNextCursor();
176+
if ($rawNextCursor === null) {
177+
return null;
178+
}
179+
180+
return new StartCursor($rawNextCursor);
181+
}
131182
}

‎src/Entities/Page.php

+13
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,19 @@ public function setDate(string $propertyTitle, DateTime $start, ?DateTime $end =
344344
return $this;
345345
}
346346

347+
/**
348+
* @param $propertyTitle
349+
* @param $start
350+
* @param $end
351+
* @return Page
352+
*/
353+
public function setDateTime(string $propertyTitle, DateTime $start, ?DateTime $end = null): Page
354+
{
355+
$this->set($propertyTitle, Date::valueWithTime($start, $end));
356+
357+
return $this;
358+
}
359+
347360
/**
348361
* @param $propertyTitle
349362
* @param $relationIds

‎src/Entities/Properties/Date.php

+65-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use FiveamCode\LaravelNotionApi\Entities\Contracts\Modifiable;
77
use FiveamCode\LaravelNotionApi\Entities\PropertyItems\RichDate;
88
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
9+
use Illuminate\Support\Arr;
910

1011
/**
1112
* Class Date.
@@ -26,6 +27,39 @@ public static function value(?DateTime $start, ?DateTime $end = null): Date
2627
$dateProperty = new Date();
2728
$dateProperty->content = $richDate;
2829

30+
if ($richDate->isRange()) {
31+
$dateProperty->rawContent = [
32+
'date' => [
33+
'start' => $start->format('Y-m-d'),
34+
'end' => $end->format('Y-m-d'),
35+
],
36+
];
37+
} else {
38+
$dateProperty->rawContent = [
39+
'date' => [
40+
'start' => $start->format('Y-m-d'),
41+
],
42+
];
43+
}
44+
45+
return $dateProperty;
46+
}
47+
48+
/**
49+
* @param $start
50+
* @param $end
51+
* @return Date
52+
*/
53+
public static function valueWithTime(?DateTime $start, ?DateTime $end = null): Date
54+
{
55+
$richDate = new RichDate();
56+
$richDate->setStart($start);
57+
$richDate->setEnd($end);
58+
$richDate->setHasTime(true);
59+
60+
$dateProperty = new Date();
61+
$dateProperty->content = $richDate;
62+
2963
if ($richDate->isRange()) {
3064
$dateProperty->rawContent = [
3165
'date' => [
@@ -57,19 +91,26 @@ protected function fillDate(): void
5791
{
5892
$richDate = new RichDate();
5993

60-
if (isset($this->rawContent['start'])) {
94+
if (Arr::exists($this->rawContent, 'start')) {
6195
$startAsIsoString = $this->rawContent['start'];
6296
$richDate->setStart(new DateTime($startAsIsoString));
97+
$richDate->setHasTime($this->isIsoTimeString($startAsIsoString));
6398
}
6499

65-
if (isset($this->rawContent['end'])) {
100+
if (Arr::exists($this->rawContent, 'end')) {
66101
$endAsIsoString = $this->rawContent['end'];
67102
$richDate->setEnd(new DateTime($endAsIsoString));
68103
}
69104

70105
$this->content = $richDate;
71106
}
72107

108+
// function for checking if ISO datetime string includes time or not
109+
private function isIsoTimeString(string $isoTimeDateString): bool
110+
{
111+
return strpos($isoTimeDateString, 'T') !== false;
112+
}
113+
73114
/**
74115
* @return RichDate
75116
*/
@@ -91,14 +132,34 @@ public function isRange(): bool
91132
*/
92133
public function getStart(): DateTime
93134
{
135+
if ($this->getContent() === null) {
136+
throw new HandlingException('Invalid content: The content of the Date Property is null.');
137+
}
138+
94139
return $this->getContent()->getStart();
95140
}
96141

97142
/**
98-
* @return DateTime
143+
* @return ?DateTime
99144
*/
100-
public function getEnd(): DateTime
145+
public function getEnd(): ?DateTime
101146
{
147+
if ($this->getContent() === null) {
148+
return null;
149+
}
150+
102151
return $this->getContent()->getEnd();
103152
}
153+
154+
/**
155+
* @return bool
156+
*/
157+
public function hasTime(): bool
158+
{
159+
if ($this->getContent() === null) {
160+
return false;
161+
}
162+
163+
return $this->getContent()->hasTime();
164+
}
104165
}

‎src/Entities/Properties/Rollup.php

+13-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected function fillFromRaw(): void
3737
break;
3838
default:
3939
throw new HandlingException("Unexpected rollupType {$this->rollupType}");
40-
}
40+
}
4141
}
4242
}
4343

@@ -89,12 +89,21 @@ private function setRollupContentArray()
8989
// TODO
9090
$rollupPropertyItem['id'] = 'undefined';
9191

92-
$this->content->add(
93-
Property::fromResponse('', $rollupPropertyItem)
94-
);
92+
if ($this->isRollupPropertyContentSet($rollupPropertyItem)) {
93+
$this->content->add(
94+
Property::fromResponse('', $rollupPropertyItem)
95+
);
96+
}
9597
}
9698
}
9799

100+
private function isRollupPropertyContentSet($rollupPropertyItem): bool
101+
{
102+
return Arr::exists($rollupPropertyItem, 'type')
103+
&& Arr::exists($rollupPropertyItem, $rollupPropertyItem['type'])
104+
&& ! is_null($rollupPropertyItem[$rollupPropertyItem['type']]);
105+
}
106+
98107
private function setRollupContentDate()
99108
{
100109
$this->content = new RichDate();

‎src/Entities/PropertyItems/RichDate.php

+15-4
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@
1111
*/
1212
class RichDate extends Entity
1313
{
14-
/**
15-
* @var string
16-
*/
1714
protected DateTime $start;
1815
protected ?DateTime $end = null;
16+
protected bool $hasTime = false;
1917

2018
/**
2119
* @param array $responseData
@@ -63,13 +61,21 @@ public function getStart(): ?DateTime
6361
}
6462

6563
/**
66-
* @return DateTime
64+
* @return ?DateTime
6765
*/
6866
public function getEnd(): ?DateTime
6967
{
7068
return $this->end;
7169
}
7270

71+
/**
72+
* @return bool
73+
*/
74+
public function hasTime(): bool
75+
{
76+
return $this->hasTime;
77+
}
78+
7379
public function setStart($start): void
7480
{
7581
$this->start = $start;
@@ -79,4 +85,9 @@ public function setEnd($end): void
7985
{
8086
$this->end = $end;
8187
}
88+
89+
public function setHasTime($hasTime): void
90+
{
91+
$this->hasTime = $hasTime;
92+
}
8293
}

‎src/Query/StartCursor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function __construct(string $cursor)
2222
$this->cursor = $cursor;
2323
}
2424

25-
public function __toString()
25+
public function __toString(): string
2626
{
2727
return $this->cursor;
2828
}

‎tests/EndpointDatabaseTest.php

+87
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
99
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
1010
use FiveamCode\LaravelNotionApi\Query\Sorting;
11+
use FiveamCode\LaravelNotionApi\Query\StartCursor;
1112
use Illuminate\Support\Collection;
1213
use Illuminate\Support\Facades\Http;
1314
use Notion;
@@ -157,4 +158,90 @@ public function it_throws_a_notion_exception_bad_request()
157158

158159
Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')->query();
159160
}
161+
162+
/** @test */
163+
public function it_queries_a_database_with_and_without_offset_and_processes_result()
164+
{
165+
// success /v1/databases/DATABASE_DOES_EXIST/query
166+
Http::fake([
167+
'https://api.notion.com/v1/databases/8284f3ff77e24d4a939d19459e4d6bdc/query*' => Http::sequence()
168+
->push(
169+
json_decode(file_get_contents('tests/stubs/endpoints/databases/response_query_offset_start_200.json'), true),
170+
200,
171+
['Headers']
172+
)
173+
->push(
174+
json_decode(file_get_contents('tests/stubs/endpoints/databases/response_query_offset_end_200.json'), true),
175+
200,
176+
['Headers']
177+
),
178+
]);
179+
180+
$result = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')
181+
->query();
182+
183+
//check instance and offset
184+
$this->assertInstanceOf(PageCollection::class, $result);
185+
$this->assertEquals(true, $result->hasMoreEntries());
186+
$this->assertInstanceOf(StartCursor::class, $result->nextCursor());
187+
$this->assertEquals('1500b7c7-329f-4854-8912-4c6972a8743e', $result->nextCursor());
188+
$this->assertEquals('1500b7c7-329f-4854-8912-4c6972a8743e', $result->getRawNextCursor());
189+
190+
$resultCollection = $result->asCollection();
191+
192+
$this->assertIsIterable($resultCollection);
193+
$this->assertContainsOnly(Page::class, $resultCollection);
194+
195+
// check page object
196+
$page = $resultCollection->first();
197+
$this->assertEquals('Betty Holberton', $page->getTitle());
198+
199+
$resultWithOffset = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')
200+
->offsetByResponse($result)
201+
->query();
202+
203+
// check instance and offset
204+
$this->assertInstanceOf(PageCollection::class, $resultWithOffset);
205+
$this->assertEquals(false, $resultWithOffset->hasMoreEntries());
206+
$this->assertEquals(null, $resultWithOffset->nextCursor());
207+
$this->assertEquals(null, $resultWithOffset->getRawNextCursor());
208+
209+
$resultWithOffsetCollection = $resultWithOffset->asCollection();
210+
211+
$this->assertIsIterable($resultWithOffsetCollection);
212+
$this->assertContainsOnly(Page::class, $resultWithOffsetCollection);
213+
214+
// check page object
215+
$page = $resultWithOffsetCollection->first();
216+
$this->assertEquals('Betty Holberton', $page->getTitle());
217+
}
218+
219+
/**
220+
* @test
221+
* ! edge-case
222+
*/
223+
public function it_queries_a_database_with_a_rollup_property_with_empty_selects()
224+
{
225+
// success /v1/databases/DATABASE_DOES_EXIST/query
226+
Http::fake([
227+
'https://api.notion.com/v1/databases/11971214ce574df7a58389c1deda61d7/query*' => Http::response(
228+
json_decode(file_get_contents('tests/stubs/endpoints/databases/response_query_rollup_empty_select_200.json'), true),
229+
200,
230+
['Headers']
231+
),
232+
]);
233+
234+
$result = Notion::database('11971214ce574df7a58389c1deda61d7')->query();
235+
236+
$this->assertInstanceOf(PageCollection::class, $result);
237+
238+
$resultCollection = $result->asCollection();
239+
240+
$this->assertIsIterable($resultCollection);
241+
$this->assertContainsOnly(Page::class, $resultCollection);
242+
243+
// check page object
244+
$page = $resultCollection->first();
245+
$this->assertEquals(0, $page->getProperty('Rollup')->getContent()->count());
246+
}
160247
}

‎tests/EndpointPagesTest.php

+52-6
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ public function it_returns_page_entity_with_filled_properties()
6969
// check properties
7070
$this->assertSame('Notion Is Awesome', $pageResult->getTitle());
7171
$this->assertSame('page', $pageResult->getObjectType());
72-
$this->assertCount(7, $pageResult->getRawProperties());
73-
$this->assertCount(7, $pageResult->getProperties());
74-
$this->assertCount(7, $pageResult->getPropertyKeys());
72+
$this->assertCount(9, $pageResult->getRawProperties());
73+
$this->assertCount(9, $pageResult->getProperties());
74+
$this->assertCount(9, $pageResult->getPropertyKeys());
75+
76+
// check date and datetime properties
77+
$this->assertTrue($pageResult->getProperty('DateWithTime')->hasTime());
78+
$this->assertFalse($pageResult->getProperty('DateWithoutTime')->hasTime());
7579

7680
$this->assertInstanceOf(Carbon::class, $pageResult->getCreatedTime());
7781
$this->assertInstanceOf(Carbon::class, $pageResult->getLastEditedTime());
@@ -106,9 +110,11 @@ public function it_assembles_properties_for_a_new_page()
106110
$checkboxKey = 'CheckboxProperty';
107111
$checkboxValue = true;
108112
$dateRangeKey = 'DateRangeProperty';
113+
$dateTimeRangeKey = 'DateTimeRangeProperty';
109114
$dateRangeStartValue = Carbon::now()->toDateTime();
110115
$dateRangeEndValue = Carbon::tomorrow()->toDateTime();
111116
$dateKey = 'DateProperty';
117+
$dateTimeKey = 'DateTimeProperty';
112118
$dateValue = Carbon::yesterday()->toDateTime();
113119
$emailKey = 'EmailProperty';
114120
$emailValue = 'notion-is-awesome@example.org';
@@ -135,7 +141,9 @@ public function it_assembles_properties_for_a_new_page()
135141
$page->setTitle('Name', $pageTitle);
136142
$page->setCheckbox($checkboxKey, $checkboxValue);
137143
$page->setDate($dateRangeKey, $dateRangeStartValue, $dateRangeEndValue);
144+
$page->setDateTime($dateTimeRangeKey, $dateRangeStartValue, $dateRangeEndValue);
138145
$page->setDate($dateKey, $dateValue);
146+
$page->setDateTime($dateTimeKey, $dateValue);
139147
$page->setEmail($emailKey, $emailValue);
140148
$page->setMultiSelect($multiSelectKey, $multiSelectValues);
141149
$page->setNumber($numberKey, $numberValue);
@@ -175,27 +183,65 @@ public function it_assembles_properties_for_a_new_page()
175183
$this->assertTrue($dateRangeProp->isRange());
176184
$this->assertEquals($dateRangeStartValue, $dateRangeProp->getStart());
177185
$this->assertEquals($dateRangeEndValue, $dateRangeProp->getEnd());
186+
$this->assertFalse($dateRangeProp->hasTime());
178187
$this->assertJson($dateRangeProp->asText());
179188
$this->assertStringContainsString($dateRangeStartValue->format('Y-m-d H:i:s'), $dateRangeProp->asText());
180189
$this->assertStringContainsString($dateRangeEndValue->format('Y-m-d H:i:s'), $dateRangeProp->asText());
181190
$dateRangeContent = $dateRangeProp->getRawContent();
182191
$this->assertArrayHasKey('date', $dateRangeContent);
183192
$this->assertCount(2, $dateRangeContent['date']);
184193
$this->assertArrayHasKey('start', $dateRangeContent['date']);
185-
$this->assertEquals($dateRangeStartValue->format('c'), $dateRangeContent['date']['start']);
194+
$this->assertEquals($dateRangeStartValue->format('Y-m-d'), $dateRangeContent['date']['start']);
186195
$this->assertArrayHasKey('end', $dateRangeContent['date']);
187-
$this->assertEquals($dateRangeEndValue->format('c'), $dateRangeContent['date']['end']);
196+
$this->assertEquals($dateRangeEndValue->format('Y-m-d'), $dateRangeContent['date']['end']);
197+
198+
// date range (with time)
199+
$this->assertTrue(
200+
$this->assertContainsInstanceOf(Date::class, $properties)
201+
);
202+
$dateTimeRangeProp = $page->getProperty($dateTimeRangeKey);
203+
$this->assertInstanceOf(RichDate::class, $dateTimeRangeProp->getContent());
204+
$dateTimeRangeContent = $dateTimeRangeProp->getContent();
205+
$this->assertTrue($dateTimeRangeProp->isRange());
206+
$this->assertEquals($dateRangeStartValue, $dateTimeRangeProp->getStart());
207+
$this->assertEquals($dateRangeEndValue, $dateTimeRangeProp->getEnd());
208+
$this->assertTrue($dateTimeRangeProp->hasTime());
209+
$this->assertJson($dateTimeRangeProp->asText());
210+
$this->assertStringContainsString($dateRangeStartValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText());
211+
$this->assertStringContainsString($dateRangeEndValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText());
212+
$dateTimeRangeContent = $dateTimeRangeProp->getRawContent();
213+
$this->assertArrayHasKey('date', $dateTimeRangeContent);
214+
$this->assertCount(2, $dateTimeRangeContent['date']);
215+
$this->assertArrayHasKey('start', $dateTimeRangeContent['date']);
216+
$this->assertEquals($dateRangeStartValue->format('c'), $dateTimeRangeContent['date']['start']);
217+
$this->assertArrayHasKey('end', $dateTimeRangeContent['date']);
218+
$this->assertEquals($dateRangeEndValue->format('c'), $dateTimeRangeContent['date']['end']);
188219

189220
// date
190221
$dateProp = $page->getProperty($dateKey);
191222
$this->assertInstanceOf(RichDate::class, $dateProp->getContent());
192223
$this->assertFalse($dateProp->isRange());
193224
$this->assertEquals($dateValue, $dateProp->getStart());
225+
$this->assertNull($dateProp->getEnd());
226+
$this->assertFalse($dateProp->hasTime());
194227
$dateContent = $dateProp->getRawContent();
195228
$this->assertArrayHasKey('date', $dateContent);
196229
$this->assertCount(1, $dateContent['date']);
197230
$this->assertArrayHasKey('start', $dateContent['date']);
198-
$this->assertEquals($dateValue->format('c'), $dateContent['date']['start']);
231+
$this->assertEquals($dateValue->format('Y-m-d'), $dateContent['date']['start']);
232+
233+
// date (with time)
234+
$dateTimeProp = $page->getProperty($dateTimeKey);
235+
$this->assertInstanceOf(RichDate::class, $dateTimeProp->getContent());
236+
$this->assertFalse($dateTimeProp->isRange());
237+
$this->assertEquals($dateValue, $dateTimeProp->getStart());
238+
$this->assertNull($dateTimeProp->getEnd());
239+
$this->assertTrue($dateTimeProp->hasTime());
240+
$dateTimeContent = $dateTimeProp->getRawContent();
241+
$this->assertArrayHasKey('date', $dateTimeContent);
242+
$this->assertCount(1, $dateTimeContent['date']);
243+
$this->assertArrayHasKey('start', $dateTimeContent['date']);
244+
$this->assertEquals($dateValue->format('c'), $dateTimeContent['date']['start']);
199245

200246
// email
201247
$this->assertTrue($this->assertContainsInstanceOf(Email::class, $properties));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
{
2+
"object": "list",
3+
"results": [
4+
{
5+
"object": "page",
6+
"id": "1500b7c7-329f-4854-8912-4c6972a8743e",
7+
"created_time": "2021-05-24T11:03:00.000Z",
8+
"last_edited_time": "2021-05-24T11:13:00.000Z",
9+
"parent": {
10+
"type": "database_id",
11+
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
12+
},
13+
"archived": false,
14+
"properties": {
15+
"Birth year": {
16+
"id": "_f<<",
17+
"type": "rich_text",
18+
"rich_text": [
19+
{
20+
"type": "text",
21+
"text": {
22+
"content": "1917",
23+
"link": null
24+
},
25+
"annotations": {
26+
"bold": false,
27+
"italic": false,
28+
"strikethrough": false,
29+
"underline": false,
30+
"code": false,
31+
"color": "default"
32+
},
33+
"plain_text": "1917",
34+
"href": null
35+
}
36+
]
37+
},
38+
"Known for": {
39+
"id": "aUmo",
40+
"type": "multi_select",
41+
"multi_select": [
42+
{
43+
"id": "f55ee1a3-e67f-4793-ba3f-5dac02938a5f",
44+
"name": "ENIAC",
45+
"color": "purple"
46+
},
47+
{
48+
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
49+
"name": "UNIVAC",
50+
"color": "default"
51+
},
52+
{
53+
"id": "55c46053-f87e-40e9-8070-6c398939fed6",
54+
"name": "Breakpoints",
55+
"color": "red"
56+
}
57+
]
58+
},
59+
"Name": {
60+
"id": "title",
61+
"type": "title",
62+
"title": [
63+
{
64+
"type": "text",
65+
"text": {
66+
"content": "Betty Holberton",
67+
"link": null
68+
},
69+
"annotations": {
70+
"bold": false,
71+
"italic": false,
72+
"strikethrough": false,
73+
"underline": false,
74+
"code": false,
75+
"color": "default"
76+
},
77+
"plain_text": "Betty Holberton",
78+
"href": null
79+
}
80+
]
81+
}
82+
}
83+
},
84+
{
85+
"object": "page",
86+
"id": "ab2a7a85-08a1-4dfc-be89-0e30aeffc0f6",
87+
"created_time": "2021-05-24T11:03:02.464Z",
88+
"last_edited_time": "2021-05-24T11:12:00.000Z",
89+
"parent": {
90+
"type": "database_id",
91+
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
92+
},
93+
"archived": false,
94+
"properties": {
95+
"Birth year": {
96+
"id": "_f<<",
97+
"type": "rich_text",
98+
"rich_text": [
99+
{
100+
"type": "text",
101+
"text": {
102+
"content": "1906",
103+
"link": null
104+
},
105+
"annotations": {
106+
"bold": false,
107+
"italic": false,
108+
"strikethrough": false,
109+
"underline": false,
110+
"code": false,
111+
"color": "default"
112+
},
113+
"plain_text": "1906",
114+
"href": null
115+
}
116+
]
117+
},
118+
"Known for": {
119+
"id": "aUmo",
120+
"type": "multi_select",
121+
"multi_select": [
122+
{
123+
"id": "1ada9715-0139-4c1c-b1af-9d8d2fe80ea2",
124+
"name": "COBOL",
125+
"color": "orange"
126+
},
127+
{
128+
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
129+
"name": "UNIVAC",
130+
"color": "default"
131+
}
132+
]
133+
},
134+
"Name": {
135+
"id": "title",
136+
"type": "title",
137+
"title": [
138+
{
139+
"type": "text",
140+
"text": {
141+
"content": "Grace Hopper",
142+
"link": null
143+
},
144+
"annotations": {
145+
"bold": false,
146+
"italic": false,
147+
"strikethrough": false,
148+
"underline": false,
149+
"code": false,
150+
"color": "default"
151+
},
152+
"plain_text": "Grace Hopper",
153+
"href": null
154+
}
155+
]
156+
}
157+
}
158+
}
159+
],
160+
"next_cursor": null,
161+
"has_more": false
162+
}
163+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
{
2+
"object": "list",
3+
"results": [
4+
{
5+
"object": "page",
6+
"id": "1500b7c7-329f-4854-8912-4c6972a8743e",
7+
"created_time": "2021-05-24T11:03:00.000Z",
8+
"last_edited_time": "2021-05-24T11:13:00.000Z",
9+
"parent": {
10+
"type": "database_id",
11+
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
12+
},
13+
"archived": false,
14+
"properties": {
15+
"Birth year": {
16+
"id": "_f<<",
17+
"type": "rich_text",
18+
"rich_text": [
19+
{
20+
"type": "text",
21+
"text": {
22+
"content": "1917",
23+
"link": null
24+
},
25+
"annotations": {
26+
"bold": false,
27+
"italic": false,
28+
"strikethrough": false,
29+
"underline": false,
30+
"code": false,
31+
"color": "default"
32+
},
33+
"plain_text": "1917",
34+
"href": null
35+
}
36+
]
37+
},
38+
"Known for": {
39+
"id": "aUmo",
40+
"type": "multi_select",
41+
"multi_select": [
42+
{
43+
"id": "f55ee1a3-e67f-4793-ba3f-5dac02938a5f",
44+
"name": "ENIAC",
45+
"color": "purple"
46+
},
47+
{
48+
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
49+
"name": "UNIVAC",
50+
"color": "default"
51+
},
52+
{
53+
"id": "55c46053-f87e-40e9-8070-6c398939fed6",
54+
"name": "Breakpoints",
55+
"color": "red"
56+
}
57+
]
58+
},
59+
"Name": {
60+
"id": "title",
61+
"type": "title",
62+
"title": [
63+
{
64+
"type": "text",
65+
"text": {
66+
"content": "Betty Holberton",
67+
"link": null
68+
},
69+
"annotations": {
70+
"bold": false,
71+
"italic": false,
72+
"strikethrough": false,
73+
"underline": false,
74+
"code": false,
75+
"color": "default"
76+
},
77+
"plain_text": "Betty Holberton",
78+
"href": null
79+
}
80+
]
81+
}
82+
}
83+
},
84+
{
85+
"object": "page",
86+
"id": "ab2a7a85-08a1-4dfc-be89-0e30aeffc0f6",
87+
"created_time": "2021-05-24T11:03:02.464Z",
88+
"last_edited_time": "2021-05-24T11:12:00.000Z",
89+
"parent": {
90+
"type": "database_id",
91+
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
92+
},
93+
"archived": false,
94+
"properties": {
95+
"Birth year": {
96+
"id": "_f<<",
97+
"type": "rich_text",
98+
"rich_text": [
99+
{
100+
"type": "text",
101+
"text": {
102+
"content": "1906",
103+
"link": null
104+
},
105+
"annotations": {
106+
"bold": false,
107+
"italic": false,
108+
"strikethrough": false,
109+
"underline": false,
110+
"code": false,
111+
"color": "default"
112+
},
113+
"plain_text": "1906",
114+
"href": null
115+
}
116+
]
117+
},
118+
"Known for": {
119+
"id": "aUmo",
120+
"type": "multi_select",
121+
"multi_select": [
122+
{
123+
"id": "1ada9715-0139-4c1c-b1af-9d8d2fe80ea2",
124+
"name": "COBOL",
125+
"color": "orange"
126+
},
127+
{
128+
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
129+
"name": "UNIVAC",
130+
"color": "default"
131+
}
132+
]
133+
},
134+
"Name": {
135+
"id": "title",
136+
"type": "title",
137+
"title": [
138+
{
139+
"type": "text",
140+
"text": {
141+
"content": "Grace Hopper",
142+
"link": null
143+
},
144+
"annotations": {
145+
"bold": false,
146+
"italic": false,
147+
"strikethrough": false,
148+
"underline": false,
149+
"code": false,
150+
"color": "default"
151+
},
152+
"plain_text": "Grace Hopper",
153+
"href": null
154+
}
155+
]
156+
}
157+
}
158+
}
159+
],
160+
"next_cursor": "1500b7c7-329f-4854-8912-4c6972a8743e",
161+
"has_more": true
162+
}
163+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
{
2+
"object": "list",
3+
"results": [
4+
{
5+
"object": "page",
6+
"id": "1321e6b6-0771-48bb-9814-6501c2ec3c32",
7+
"created_time": "2022-07-09T10:29:00.000Z",
8+
"last_edited_time": "2022-07-09T10:45:00.000Z",
9+
"created_by": {
10+
"object": "user",
11+
"id": "04536682-601a-4531-a18f-4fa89fdf14a8"
12+
},
13+
"last_edited_by": {
14+
"object": "user",
15+
"id": "04531682-603a-4531-a18f-1fa89fdfb4a8"
16+
},
17+
"cover": null,
18+
"icon": null,
19+
"parent": {
20+
"type": "database_id",
21+
"database_id": "15971224-ce57-4df1-a583-89c1deca63d7"
22+
},
23+
"archived": false,
24+
"properties": {
25+
"Test Rollup Problem": {
26+
"id": "G|zT",
27+
"type": "relation",
28+
"relation": [
29+
{
30+
"id": "dcad104b-222c-4d63-b83e-852f22612f4a"
31+
},
32+
{
33+
"id": "3611ce31-ae52-45dc-bc5a-10626ca19ab5"
34+
}
35+
]
36+
},
37+
"Rollup": {
38+
"id": "JCh`",
39+
"type": "rollup",
40+
"rollup": {
41+
"type": "array",
42+
"array": [
43+
{
44+
"type": "select",
45+
"select": null
46+
}
47+
],
48+
"function": "show_original"
49+
}
50+
},
51+
"Name": {
52+
"id": "title",
53+
"type": "title",
54+
"title": []
55+
}
56+
},
57+
"url": "https:\/\/www.notion.so\/132de616077648bb98146501c2ec3c32"
58+
},
59+
{
60+
"object": "page",
61+
"id": "43dd6b90-6bde-48ea-9f06-79fee96de99c",
62+
"created_time": "2022-07-09T10:29:00.000Z",
63+
"last_edited_time": "2022-07-09T10:29:00.000Z",
64+
"created_by": {
65+
"object": "user",
66+
"id": "04d36682-603a-4531-a18f-4fa19fdfb4a8"
67+
},
68+
"last_edited_by": {
69+
"object": "user",
70+
"id": "04d36682-603a-4531-a18f-4fa891dfb4a8"
71+
},
72+
"cover": null,
73+
"icon": null,
74+
"parent": {
75+
"type": "database_id",
76+
"database_id": "1d9712d4-ce57-4df7-a583-89c1dedac3d7"
77+
},
78+
"archived": false,
79+
"properties": {
80+
"Test Rollup Problem": {
81+
"id": "G|zT",
82+
"type": "relation",
83+
"relation": []
84+
},
85+
"Rollup": {
86+
"id": "JCh`",
87+
"type": "rollup",
88+
"rollup": {
89+
"type": "array",
90+
"array": [],
91+
"function": "show_original"
92+
}
93+
},
94+
"Name": {
95+
"id": "title",
96+
"type": "title",
97+
"title": []
98+
}
99+
},
100+
"url": "https:\/\/www.notion.so\/430d6b9d6b9e48ea9f067cfee96de9d9"
101+
},
102+
{
103+
"object": "page",
104+
"id": "788c67fe-84d2-4cf8-aab6-6cd6448d98b2",
105+
"created_time": "2022-07-09T10:29:00.000Z",
106+
"last_edited_time": "2022-07-09T10:29:00.000Z",
107+
"created_by": {
108+
"object": "user",
109+
"id": "04536682-613a-4531-a18f-4fd89fdfb4a8"
110+
},
111+
"last_edited_by": {
112+
"object": "user",
113+
"id": "04436622-603a-4531-a18f-4fa89fdfb4a8"
114+
},
115+
"cover": null,
116+
"icon": null,
117+
"parent": {
118+
"type": "database_id",
119+
"database_id": "15972224-ce57-4df7-a583-89c1de1a63dd"
120+
},
121+
"archived": false,
122+
"properties": {
123+
"Test Rollup Problem": {
124+
"id": "G|zT",
125+
"type": "relation",
126+
"relation": []
127+
},
128+
"Rollup": {
129+
"id": "JCh`",
130+
"type": "rollup",
131+
"rollup": {
132+
"type": "array",
133+
"array": [],
134+
"function": "show_original"
135+
}
136+
},
137+
"Name": {
138+
"id": "title",
139+
"type": "title",
140+
"title": []
141+
}
142+
},
143+
"url": "https:\/\/www.notion.so\/788c67de84d24cf8dab660d64c8998b2"
144+
}
145+
],
146+
"next_cursor": null,
147+
"has_more": false
148+
}

‎tests/stubs/endpoints/pages/response_specific_200.json

+18
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@
4040
}
4141
]
4242
},
43+
"DateWithTime":{
44+
"id": ">d{D",
45+
"type": "date",
46+
"date": {
47+
"start": "2021-05-14T00:00:00.000+00:00",
48+
"end": "2021-06-14T00:00:00.000+00:00",
49+
"time_zone": null
50+
}
51+
},
52+
"DateWithoutTime":{
53+
"id": ">c{d",
54+
"type": "date",
55+
"date": {
56+
"start": "2021-05-14",
57+
"end": "2021-06-14",
58+
"time_zone": null
59+
}
60+
},
4361
"SelectColumn": {
4462
"id": "nKff",
4563
"type": "select",

0 commit comments

Comments
 (0)
Please sign in to comment.