Skip to content

Commit 37bdcdc

Browse files
Merge pull request #494 from notion-dotnet/480-add-support-to-retrieve-a-file-upload
Add support for Retrieve a file upload API
2 parents e23801b + f43d570 commit 37bdcdc

File tree

8 files changed

+157
-1
lines changed

8 files changed

+157
-1
lines changed

Src/Notion.Client/Api/ApiEndpoints.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ public static class FileUploadsApiUrls
146146
public static string Send(string fileUploadId) => $"/v1/file_uploads/{fileUploadId}/send";
147147
public static string Complete(string fileUploadId) => $"/v1/file_uploads/{fileUploadId}/complete";
148148
public static string List => "/v1/file_uploads";
149+
public static string Retrieve(IRetrieveFileUploadPathParameters pathParameters) => $"/v1/file_uploads/{pathParameters.FileUploadId}";
149150
}
150151
}
151152
}

Src/Notion.Client/Api/FileUploads/IFileUploadsClient.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,16 @@ Task<ListFileUploadsResponse> ListAsync(
5151
ListFileUploadsRequest request,
5252
CancellationToken cancellationToken = default
5353
);
54+
55+
/// <summary>
56+
/// Retrieve a specific File Upload by its ID.
57+
/// </summary>
58+
/// <param name="request"></param>
59+
/// <param name="cancellationToken"></param>
60+
/// <returns></returns>
61+
Task<RetrieveFileUploadResponse> RetrieveAsync(
62+
RetrieveFileUploadRequest request,
63+
CancellationToken cancellationToken = default
64+
);
5465
}
5566
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Notion.Client
6+
{
7+
public sealed partial class FileUploadsClient
8+
{
9+
public async Task<RetrieveFileUploadResponse> RetrieveAsync(
10+
RetrieveFileUploadRequest request,
11+
CancellationToken cancellationToken = default)
12+
{
13+
IRetrieveFileUploadPathParameters pathParameters = request;
14+
15+
if (pathParameters == null || string.IsNullOrEmpty(pathParameters.FileUploadId))
16+
{
17+
throw new ArgumentNullException(nameof(pathParameters.FileUploadId), "FileUploadId cannot be null or empty.");
18+
}
19+
20+
var endpoint = ApiEndpoints.FileUploadsApiUrls.Retrieve(pathParameters);
21+
22+
return await _restClient.GetAsync<RetrieveFileUploadResponse>(
23+
endpoint,
24+
cancellationToken: cancellationToken
25+
);
26+
}
27+
}
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Notion.Client
2+
{
3+
public interface IRetrieveFileUploadPathParameters
4+
{
5+
/// <summary>
6+
/// The ID of the File Upload to retrieve.
7+
/// </summary>
8+
string FileUploadId { get; set; }
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Notion.Client
2+
{
3+
public class RetrieveFileUploadRequest : IRetrieveFileUploadPathParameters
4+
{
5+
public string FileUploadId { get; set; }
6+
}
7+
}
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 class RetrieveFileUploadResponse : FileObjectResponse
4+
{
5+
}
6+
}

Test/Notion.IntegrationTests/FileUploadsClientTests.cs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,41 @@ public async Task ListAsync()
139139
Assert.NotNull(response.Results);
140140
Assert.True(response.Results.Count <= 5);
141141
}
142+
143+
[Fact]
144+
public async Task RetrieveAsync()
145+
{
146+
// Arrange
147+
var createRequest = new CreateFileUploadRequest
148+
{
149+
Mode = FileUploadMode.ExternalUrl,
150+
ExternalUrl = "https://unsplash.com/photos/hOhlYhAiizc/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNzYwMTkxNzc3fA&force=true",
151+
FileName = "sample-image.jpg",
152+
};
153+
154+
var createResponse = await Client.FileUploads.CreateAsync(createRequest);
155+
156+
Assert.NotNull(createResponse);
157+
Assert.NotNull(createResponse.Id);
158+
Assert.Equal("sample-image.jpg", createResponse.FileName);
159+
Assert.Equal("image/jpeg", createResponse.ContentType);
160+
Assert.Equal("pending", createResponse.Status);
161+
162+
// Act
163+
var retrieveRequest = new RetrieveFileUploadRequest
164+
{
165+
FileUploadId = createResponse.Id
166+
};
167+
168+
var retrieveResponse = await Client.FileUploads.RetrieveAsync(retrieveRequest);
169+
170+
// Assert
171+
Assert.NotNull(retrieveResponse);
172+
Assert.Equal(createResponse.Id, retrieveResponse.Id);
173+
Assert.Equal("sample-image.jpg", retrieveResponse.FileName);
174+
Assert.Equal("image/jpeg", retrieveResponse.ContentType);
175+
// The status might have changed from "pending" to "uploaded" depending on Notion's processing time
176+
Assert.Contains(retrieveResponse.Status, new[] { "pending", "uploaded" });
177+
}
142178
}
143-
}
179+
}

Test/Notion.UnitTests/FileUploadsClientTests.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,61 @@ public async Task ListAsync_CallsRestClientGetAsync_WithCorrectParameters()
219219
}
220220

221221
#endregion ListAsync Tests
222+
223+
#region RetrieveAsync Tests
224+
225+
// Add tests for RetrieveAsync method
226+
[Fact]
227+
public async Task RetrieveAsync_ThrowsArgumentNullException_WhenFileUploadIdIsNullOrEmpty()
228+
{
229+
// Arrange
230+
var request = new RetrieveFileUploadRequest
231+
{
232+
FileUploadId = null
233+
};
234+
235+
// Act & Assert
236+
var exception = await Assert.ThrowsAsync<ArgumentNullException>(() => _fileUploadClient.RetrieveAsync(request));
237+
Assert.Equal("FileUploadId", exception.ParamName);
238+
Assert.Equal("FileUploadId cannot be null or empty. (Parameter 'FileUploadId')", exception.Message);
239+
}
240+
241+
[Fact]
242+
public async Task RetrieveAsync_CallsRestClientGetAsync_WithCorrectParameters()
243+
{
244+
// Arrange
245+
var fileUploadId = Guid.NewGuid().ToString();
246+
var request = new RetrieveFileUploadRequest
247+
{
248+
FileUploadId = fileUploadId
249+
};
250+
251+
var expectedResponse = new RetrieveFileUploadResponse
252+
{
253+
Id = fileUploadId,
254+
FileName = "testfile.txt",
255+
Status = "completed"
256+
};
257+
258+
_restClientMock
259+
.Setup(client => client.GetAsync<RetrieveFileUploadResponse>(
260+
It.Is<string>(url => url == ApiEndpoints.FileUploadsApiUrls.Retrieve(request)),
261+
It.IsAny<IDictionary<string, string>>(),
262+
null,
263+
null,
264+
It.IsAny<CancellationToken>()
265+
))
266+
.ReturnsAsync(expectedResponse);
267+
268+
// Act
269+
var response = await _fileUploadClient.RetrieveAsync(request);
270+
271+
// Assert
272+
Assert.Equal(expectedResponse.Id, response.Id);
273+
Assert.Equal(expectedResponse.FileName, response.FileName);
274+
Assert.Equal(expectedResponse.Status, response.Status);
275+
_restClientMock.VerifyAll();
276+
}
277+
278+
#endregion RetrieveAsync Tests
222279
}

0 commit comments

Comments
 (0)