Skip to content

Commit 279f65a

Browse files
Merge pull request #170 from notion-dotnet/bfix/165-create-page-fails
Fix: Create page fails 🐛
2 parents 12bc6ab + 225cd7d commit 279f65a

File tree

18 files changed

+262
-79
lines changed

18 files changed

+262
-79
lines changed

.github/workflows/ci-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ jobs:
3434
run: dotnet build --no-restore
3535

3636
- name: Test
37-
run: dotnet test --no-build --verbosity normal
37+
run: dotnet test --filter "FullyQualifiedName~Notion.UnitTests" --no-build --verbosity normal

.github/workflows/publish-code.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
run: dotnet build --no-restore -c Release
2828

2929
- name: Test
30-
run: dotnet test -c Release --no-build --verbosity normal
30+
run: dotnet test -c Release --filter "FullyQualifiedName~Notion.UnitTests" --no-build --verbosity normal
3131

3232
- name: Pack solution [Release]
3333
run: |

.github/workflows/test-publish-code.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
run: dotnet build --no-restore -c Release
3131

3232
- name: Test
33-
run: dotnet test -c Release --no-build --verbosity normal
33+
run: dotnet test --filter "FullyQualifiedName~Notion.UnitTests" -c Release --no-build --verbosity normal
3434

3535
- name: Pack solution [Release]
3636
run: |

Notion.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1616
.editorconfig = .editorconfig
1717
EndProjectSection
1818
EndProject
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notion.IntegrationTests", "Test\Notion.IntegrationTests\Notion.IntegrationTests.csproj", "{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}"
20+
EndProject
1921
Global
2022
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2123
Debug|Any CPU = Debug|Any CPU
@@ -50,13 +52,26 @@ Global
5052
{B3AE07EA-49CC-4A86-A2D4-04E1FF00AB04}.Release|x64.Build.0 = Release|Any CPU
5153
{B3AE07EA-49CC-4A86-A2D4-04E1FF00AB04}.Release|x86.ActiveCfg = Release|Any CPU
5254
{B3AE07EA-49CC-4A86-A2D4-04E1FF00AB04}.Release|x86.Build.0 = Release|Any CPU
55+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|Any CPU.Build.0 = Debug|Any CPU
57+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|x64.ActiveCfg = Debug|Any CPU
58+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|x64.Build.0 = Debug|Any CPU
59+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|x86.ActiveCfg = Debug|Any CPU
60+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Debug|x86.Build.0 = Debug|Any CPU
61+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|Any CPU.ActiveCfg = Release|Any CPU
62+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|Any CPU.Build.0 = Release|Any CPU
63+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|x64.ActiveCfg = Release|Any CPU
64+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|x64.Build.0 = Release|Any CPU
65+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|x86.ActiveCfg = Release|Any CPU
66+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451}.Release|x86.Build.0 = Release|Any CPU
5367
EndGlobalSection
5468
GlobalSection(SolutionProperties) = preSolution
5569
HideSolutionNode = FALSE
5670
EndGlobalSection
5771
GlobalSection(NestedProjects) = preSolution
5872
{BF5F85F3-901C-40B0-8357-A1919F89AE2E} = {4A92506A-3CF1-4E86-B9FD-D5F109655D87}
5973
{B3AE07EA-49CC-4A86-A2D4-04E1FF00AB04} = {F474CF12-E2AC-4388-B764-BAE891D307B8}
74+
{E0E2D7D5-E2AD-4587-AE88-BA5812A90451} = {F474CF12-E2AC-4388-B764-BAE891D307B8}
6075
EndGlobalSection
6176
GlobalSection(ExtensibilityGlobals) = postSolution
6277
SolutionGuid = {3C5C8AC9-88CA-4079-BC0B-C1A81248B0B1}

Src/Notion.Client/Api/Databases/RequestParams/DatabasesCreateParameters/ParentPageInput.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Notion.Client
44
{
5-
public class ParentPageInput
5+
public class ParentPageInput : IPageParentInput
66
{
77
[JsonProperty("page_id")]
88
public string PageId { get; set; }

Src/Notion.Client/Api/Pages/IPagesClient.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@ namespace Notion.Client
55
{
66
public interface IPagesClient
77
{
8-
Task<Page> CreateAsync(NewPage page);
8+
/// <summary>
9+
/// Creates a new page in the specified database or as a child of an existing page.
10+
///
11+
/// If the parent is a database, the <see href="https://developers.notion.com/reference-link/page#property-value-object">property values</see> of the new page in the properties parameter must conform to the parent <see href="https://developers.notion.com/reference-link/database">database</see>'s property schema.
12+
///
13+
/// If the parent is a page, the only valid property is <strong>title</strong>.
14+
/// </summary>
15+
/// <param name="pagesCreateParameters">Create page parameters</param>
16+
/// <returns>Created page.</returns>
17+
Task<Page> CreateAsync(PagesCreateParameters pagesCreateParameters);
18+
919
Task<Page> RetrieveAsync(string pageId);
1020

1121
Task<Page> UpdatePropertiesAsync(

Src/Notion.Client/Api/Pages/PagesClient.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,35 @@ public PagesClient(IRestClient client)
1414
_client = client;
1515
}
1616

17-
public async Task<Page> CreateAsync(NewPage page)
17+
/// <summary>
18+
/// Creates a new page in the specified database or as a child of an existing page.
19+
///
20+
/// If the parent is a database, the <see href="https://developers.notion.com/reference-link/page#property-value-object">property values</see> of the new page in the properties parameter must conform to the parent <see href="https://developers.notion.com/reference-link/database">database</see>'s property schema.
21+
///
22+
/// If the parent is a page, the only valid property is <strong>title</strong>.
23+
/// </summary>
24+
/// <param name="pagesCreateParameters">Create page parameters</param>
25+
/// <returns>Created page.</returns>
26+
public async Task<Page> CreateAsync(PagesCreateParameters pagesCreateParameters)
1827
{
19-
if (page == null)
28+
if (pagesCreateParameters is null)
2029
{
21-
throw new ArgumentNullException(nameof(page));
30+
throw new ArgumentNullException(nameof(pagesCreateParameters));
2231
}
2332

24-
if (page.Parent == null)
33+
var bodyParameters = (IPagesCreateBodyParameters)pagesCreateParameters;
34+
35+
if (bodyParameters.Parent == null)
2536
{
26-
throw new ArgumentNullException(nameof(page.Parent), "Parent is required!");
37+
throw new ArgumentNullException(nameof(bodyParameters.Parent), "Parent is required!");
2738
}
2839

29-
if (page.Properties == null)
40+
if (bodyParameters.Properties == null)
3041
{
31-
throw new ArgumentNullException(nameof(page.Properties), "Properties are required!");
42+
throw new ArgumentNullException(nameof(bodyParameters.Properties), "Properties are required!");
3243
}
3344

34-
return await _client.PostAsync<Page>(PagesApiUrls.Create(), page);
45+
return await _client.PostAsync<Page>(PagesApiUrls.Create(), bodyParameters);
3546
}
3647

3748
public async Task<Page> RetrieveAsync(string pageId)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Notion.Client
4+
{
5+
public class DatabaseParentInput : IPageParentInput
6+
{
7+
[JsonProperty("database_id")]
8+
public string DatabaseId { get; set; }
9+
}
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Notion.Client
2+
{
3+
public interface IPageParentInput
4+
{
5+
}
6+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Collections.Generic;
2+
using Newtonsoft.Json;
3+
4+
namespace Notion.Client
5+
{
6+
public interface IPagesCreateBodyParameters
7+
{
8+
[JsonProperty("parent")]
9+
IPageParentInput Parent { get; set; }
10+
11+
[JsonProperty("properties")]
12+
IDictionary<string, PropertyValue> Properties { get; set; }
13+
14+
[JsonProperty("children")]
15+
IList<Block> Children { get; set; }
16+
17+
[JsonProperty("icon")]
18+
IPageIcon Icon { get; set; }
19+
20+
[JsonProperty("cover")]
21+
FileObject Cover { get; set; }
22+
}
23+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Notion.Client
2+
{
3+
public interface IPagesCreateQueryParameters
4+
{
5+
}
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace Notion.Client
4+
{
5+
public class PagesCreateParameters : IPagesCreateBodyParameters, IPagesCreateQueryParameters
6+
{
7+
public IPageParentInput Parent { get; set; }
8+
public IDictionary<string, PropertyValue> Properties { get; set; }
9+
public IList<Block> Children { get; set; }
10+
public IPageIcon Icon { get; set; }
11+
public FileObject Cover { get; set; }
12+
}
13+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Collections.Generic;
2+
3+
namespace Notion.Client
4+
{
5+
public class PagesCreateParametersBuilder
6+
{
7+
private IPageParentInput parent;
8+
private Dictionary<string, PropertyValue> properties = new Dictionary<string, PropertyValue>();
9+
private IList<Block> children = new List<Block>();
10+
private IPageIcon icon;
11+
private FileObject cover;
12+
13+
private PagesCreateParametersBuilder()
14+
{
15+
}
16+
17+
public static PagesCreateParametersBuilder Create(IPageParentInput parent)
18+
{
19+
return new PagesCreateParametersBuilder
20+
{
21+
parent = parent
22+
};
23+
}
24+
25+
public PagesCreateParametersBuilder AddProperty(string nameOrId, PropertyValue value)
26+
{
27+
properties[nameOrId] = value;
28+
return this;
29+
}
30+
31+
public PagesCreateParametersBuilder AddPageContent(Block block)
32+
{
33+
children.Add(block);
34+
return this;
35+
}
36+
37+
public PagesCreateParameters Build()
38+
{
39+
return new PagesCreateParameters
40+
{
41+
Parent = parent,
42+
Properties = properties,
43+
Children = children,
44+
Icon = icon,
45+
Cover = cover
46+
};
47+
}
48+
}
49+
}

Src/Notion.Client/Models/Page/NewPage.cs

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using FluentAssertions;
6+
using Notion.Client;
7+
using Xunit;
8+
9+
namespace Notion.IntegrationTests
10+
{
11+
public class IPageClientTests
12+
{
13+
[Fact]
14+
public async Task CreateAsync_CreatesANewPage()
15+
{
16+
var options = new ClientOptions
17+
{
18+
AuthToken = Environment.GetEnvironmentVariable("NOTION_AUTH_TOKEN")
19+
};
20+
21+
IPagesClient _client = new PagesClient(new RestClient(options));
22+
23+
PagesCreateParameters pagesCreateParameters = PagesCreateParametersBuilder.Create(new DatabaseParentInput
24+
{
25+
DatabaseId = "f86f2262-0751-40f2-8f63-e3f7a3c39fcb"
26+
})
27+
.AddProperty("Name", new TitlePropertyValue
28+
{
29+
Title = new List<RichTextBase>
30+
{
31+
new RichTextText
32+
{
33+
Text = new Text
34+
{
35+
Content = "Test Page Title"
36+
}
37+
}
38+
}
39+
})
40+
.Build();
41+
42+
var page = await _client.CreateAsync(pagesCreateParameters);
43+
44+
page.Should().NotBeNull();
45+
page.Parent.Should().BeOfType<DatabaseParent>().Which
46+
.DatabaseId.Should().Be("f86f2262-0751-40f2-8f63-e3f7a3c39fcb");
47+
48+
page.Properties.Should().ContainKey("Name");
49+
page.Properties["Name"].Should().BeOfType<TitlePropertyValue>().Which
50+
.Title.First().PlainText.Should().Be("Test Page Title");
51+
52+
await _client.UpdateAsync(page.Id, new PagesUpdateParameters
53+
{
54+
Archived = true
55+
});
56+
}
57+
}
58+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\..\Src\Notion.Client\Notion.Client.csproj" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="FluentAssertions" Version="5.10.3" />
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
17+
<PackageReference Include="xunit" Version="2.4.1" />
18+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
<PrivateAssets>all</PrivateAssets>
21+
</PackageReference>
22+
<PackageReference Include="coverlet.collector" Version="3.0.2">
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
<PrivateAssets>all</PrivateAssets>
25+
</PackageReference>
26+
</ItemGroup>
27+
28+
</Project>

0 commit comments

Comments
 (0)