Skip to content

Commit

Permalink
Merge pull request #190 from learntocloud/adding-tests
Browse files Browse the repository at this point in the history
update to use new partiton key
  • Loading branch information
madebygps authored Feb 25, 2024
2 parents b8d5a16 + 9942d09 commit 45913cb
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 59 deletions.
74 changes: 23 additions & 51 deletions src/DictionaryFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ public DictionaryFunctions(ILoggerFactory loggerFactory, DefinitionsRepository d
_definitionOfTheDayRepository = definitionOfTheDayRepository;
}

[OpenApiOperation(operationId: "GetAllDefinitions", tags: new[] { "Definitions" }, Summary = "Retrieve All Definitions", Description = "Retrieves a paginated list of all definitions. Supports pagination through continuation tokens.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "List of Definitions", Description = "Returns a paginated list of definitions along with a continuation token for further pages.")]
[Function("GetAllDefinitions")]
public async Task<HttpResponseData> GetAllDefinitions(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req, string? continuationToken = null, int? pageSize = 10)
Expand All @@ -46,14 +43,10 @@ public async Task<HttpResponseData> GetAllDefinitions(
}

[Function("GetDefinitionById")]
[OpenApiOperation(operationId: "GetDefinitionById", tags: new[] { "Definitions" }, Summary = "Get definition by ID", Description = "This operation returns a definition by its ID.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "id", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The ID of the definition.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns the definition.")]
public async Task<HttpResponseData> GetDefinitionById(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string id)
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string id, string word)
{
var definition = await _definitionsRepository.GetDefinitionByIdAsync(id);
var definition = await _definitionsRepository.GetDefinitionByIdAsync(id, word);
if (definition == null)
{
_logger.LogInformation($"No definition found for ID: {id}");
Expand All @@ -64,10 +57,6 @@ public async Task<HttpResponseData> GetDefinitionById(
}

[Function("GetDefinitionByWord")]
[OpenApiOperation(operationId: "GetDefinitionByWord", tags: new[] { "Definitions" }, Summary = "Get definition by word", Description = "This operation returns a definition by its word.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "word", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The word of the definition.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns the definition.")]
public async Task<HttpResponseData> GetDefinitionByWord(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string word)
{
Expand All @@ -82,12 +71,6 @@ public async Task<HttpResponseData> GetDefinitionByWord(
}

[Function("GetDefinitionsByTag")]
[OpenApiOperation(operationId: "GetDefinitionsByTag", tags: new[] { "Definitions" }, Summary = "Get definitions by tag", Description = "This operation returns definitions associated with a specific tag.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "tag", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The tag to get the definitions for.")]
[OpenApiParameter(name: "continuationToken", In = ParameterLocation.Query, Required = false, Type = typeof(string), Description = "The continuation token to get the next page of definitions.")]
[OpenApiParameter(name: "pageSize", In = ParameterLocation.Query, Required = false, Type = typeof(int), Description = "The number of definitions to return per page.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Dictionary<string, Definition>), Summary = "Successful response", Description = "This returns a list of definitions associated with the tag.")]
public async Task<HttpResponseData> GetDefinitionsByTagAsync(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string tag, string? continuationToken = null, int? pageSize = 10)
{
Expand All @@ -107,12 +90,6 @@ public async Task<HttpResponseData> GetDefinitionsByTagAsync(
}

[Function("GetDefinitionsBySearch")]
[OpenApiOperation(operationId: "GetDefinitionsBySearch", tags: new[] { "Definitions" }, Summary = "Get definitions by search term", Description = "This operation returns definitions matching a search term.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "searchTerm", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The search term to get the definitions for.")]
[OpenApiParameter(name: "continuationToken", In = ParameterLocation.Query, Required = false, Type = typeof(string), Description = "The continuation token to get the next page of definitions.")]
[OpenApiParameter(name: "pageSize", In = ParameterLocation.Query, Required = false, Type = typeof(int), Description = "The number of definitions to return per page.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Dictionary<string, Definition>), Summary = "Successful response", Description = "This returns a list of definitions matching the search term.")]
public async Task<HttpResponseData> GetDefinitionsBySearch(
[HttpTrigger(AuthorizationLevel.Function, "get")]
HttpRequestData req, string searchTerm, string? continuationToken = null, int? pageSize = 10)
Expand All @@ -132,12 +109,24 @@ public async Task<HttpResponseData> GetDefinitionsBySearch(
return CreateJsonResponse(req, HttpStatusCode.OK, result);
}

[Function("DeleteDefinition")]
public async Task<HttpResponseData> DeleteDefinition(
[HttpTrigger(AuthorizationLevel.Admin, "delete")] HttpRequestData req, string word)
{

var existingDefinition = await _definitionsRepository.GetDefinitionByWordAsync(word);
if (existingDefinition == null)
{
_logger.LogInformation($"DeleteDefinition: Definition with word {word} not found.");
return CreateJsonResponse(req, HttpStatusCode.NotFound, new { Error = $"Definition with word {word} not found." });
}
await _definitionsRepository.DeleteDefinitionAsync(existingDefinition);
_logger.LogInformation($"Definition with {word} deleted successfully.");
return req.CreateResponse(HttpStatusCode.NoContent);
}


[Function("GetRandomDefinition")]
[OpenApiOperation(operationId: "GetRandomDefinition", tags: new[] { "Definitions" }, Summary = "Get a random definition", Description = "This operation returns a random definition.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns a random definition.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.InternalServerError, Summary = "Internal Server Error", Description = "When an error occurs while processing the request.")]
public async Task<HttpResponseData> GetRandomDefinition(
[HttpTrigger(AuthorizationLevel.Admin, "get")] HttpRequestData req)
{
Expand All @@ -152,12 +141,6 @@ public async Task<HttpResponseData> GetRandomDefinition(
}

[Function("CreateDefinition")]
[OpenApiOperation(operationId: "CreateDefinition", tags: new[] { "Definitions" }, Summary = "Create a new definition", Description = "This operation creates a new definition.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiRequestBody("application/json", typeof(Definition), Required = true, Description = "The new definition to create.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.Created, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns the created definition.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Summary = "Bad Request", Description = "When the request body is null, empty or invalid.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.Conflict, Summary = "Conflict", Description = "When a definition with the same word already exists.")]
public async Task<HttpResponseData> CreateDefinition(
[HttpTrigger(AuthorizationLevel.Admin, "post")] HttpRequestData req)
{
Expand Down Expand Up @@ -185,22 +168,14 @@ public async Task<HttpResponseData> CreateDefinition(
}

[Function("UpdateDefinition")]
[OpenApiOperation(operationId: "UpdateDefinition", tags: new[] { "Definitions" }, Summary = "Update an existing definition", Description = "This operation updates an existing definition.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "definition_id", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The ID of the definition to update.")]
[OpenApiRequestBody("application/json", typeof(Definition), Required = true, Description = "The updated definition.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns the updated definition.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.NotFound, Summary = "Definition not found", Description = "When no definition is found with the provided ID.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Summary = "Bad Request", Description = "When the request body is null, empty or invalid.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.InternalServerError, Summary = "Internal Server Error", Description = "When an error occurs while processing the request.")]
public async Task<HttpResponseData> UpdateDefinition(
[HttpTrigger(AuthorizationLevel.Admin, "put", Route = "UpdateDefinition/{definition_id}")] HttpRequestData req, string definition_id)
[HttpTrigger(AuthorizationLevel.Admin, "put", Route = "UpdateDefinition")] HttpRequestData req, string word)
{
var existingDefinition = await _definitionsRepository.GetDefinitionByIdAsync(definition_id);
var existingDefinition = await _definitionsRepository.GetDefinitionByWordAsync(word);
if (existingDefinition == null)
{
_logger.LogInformation($"UpdateDefinition: Definition with id {definition_id} not found.");
var errorContent = new { Error = $"Definition with id {definition_id} not found." };
_logger.LogInformation($"UpdateDefinition: Definition with word {word} not found.");
var errorContent = new { Error = $"Definition with word {word} not found." };
return CreateJsonResponse(req, HttpStatusCode.NotFound, errorContent);
}
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Expand All @@ -218,14 +193,11 @@ public async Task<HttpResponseData> UpdateDefinition(
return CreateJsonResponse(req, HttpStatusCode.BadRequest, errorContent);
}
await _definitionsRepository.UpdateDefinition(data);
_logger.LogInformation($"Definition with id {definition_id} updated successfully.");
_logger.LogInformation($"Definition with word {word} updated successfully.");
return CreateJsonResponse(req, HttpStatusCode.OK, data);
}

[Function("GetDefinitionOfTheDay")]
[OpenApiOperation(operationId: "GetDefinitionOfTheDay", tags: new[] { "Definitions" }, Summary = "Get definition of the day", Description = "This operation returns the definition of the day.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Definition), Summary = "Successful response", Description = "This returns the definition of the day.")]
public async Task<HttpResponseData> GetDefinitionOfTheDay(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req)
{
Expand Down
12 changes: 6 additions & 6 deletions src/Repositories/DefinitionsRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public DefinitionsRepository(CosmosClient client, IConfiguration configuration)

return await QueryWithPagingAsync<Definition>(query, pageSize, continuationToken);
}
public async Task<Definition?> GetDefinitionByIdAsync(string id)
public async Task<Definition?> GetDefinitionByIdAsync(string id, string word)
{
var response = await _definitionsCollection.ReadItemAsync<Definition>(id, new PartitionKey(id));
var response = await _definitionsCollection.ReadItemAsync<Definition>(id, new PartitionKey(word));
return response.Resource;
}
public async Task<Definition?> GetDefinitionByWordAsync(string word)
Expand All @@ -52,18 +52,18 @@ public DefinitionsRepository(CosmosClient client, IConfiguration configuration)
pageSize = pageSize.HasValue && pageSize.Value <= MaxPageSize ? pageSize.Value : MaxPageSize;
return await QueryWithPagingAsync<Definition>(query, pageSize, continuationToken);
}
public async Task DeleteDefinitionAsync(string definitionId)
public async Task DeleteDefinitionAsync(Definition definition)
{
await _definitionsCollection.DeleteItemAsync<Definition>(definitionId, new PartitionKey(definitionId));
await _definitionsCollection.DeleteItemAsync<Definition>(definition.Id, new PartitionKey(definition.Word));
}
public async Task AddDefinitionAsync(Definition definition)
{
definition.Id = Guid.NewGuid().ToString("N");
await _definitionsCollection.CreateItemAsync(definition, new PartitionKey(definition.Id));
await _definitionsCollection.CreateItemAsync(definition, new PartitionKey(definition.Word));
}
public async Task UpdateDefinition(Definition existingDefinition)
{
await _definitionsCollection.ReplaceItemAsync(existingDefinition, existingDefinition.Id, new PartitionKey(existingDefinition.Id));
await _definitionsCollection.ReplaceItemAsync(existingDefinition, existingDefinition.Id, new PartitionKey(existingDefinition.Word));
}

private async Task<(List<T>, string?)> QueryWithPagingAsync<T>(string query, int? pageSize, string? continuationToken)
Expand Down
4 changes: 2 additions & 2 deletions src/Repositories/DefintionOfTheDayRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public async Task UpdateDefinitionOfTheDay(Definition newDefinition)
}
if (currentDefinition != null)
{
await _definitionOfTheDayCollection.DeleteItemAsync<Definition>(currentDefinition.Id, new PartitionKey(currentDefinition.Id));
await _definitionOfTheDayCollection.DeleteItemAsync<Definition>(currentDefinition.Id, new PartitionKey(currentDefinition.Word));
}
await _definitionOfTheDayCollection.UpsertItemAsync(newDefinition, new PartitionKey(newDefinition.Id));
await _definitionOfTheDayCollection.UpsertItemAsync(newDefinition, new PartitionKey(newDefinition.Word));
}


Expand Down

0 comments on commit 45913cb

Please sign in to comment.