📄 test/JsonLdRecipeParser.Tests/Json/JsonLdSerializerContextTests/DeserializeShould.cs
using System;
using System.Text.Json;
using JsonLdRecipeParser.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;

namespace JsonLdRecipeParser.Tests.Json.JsonLdSerializerContextTests;

[TestClass]
public class DeserializeShould
{
    const string googleExample = """
        {
            "@context": "https://schema.org/",
            "@type": "Recipe",
            "name": "Non-Alcoholic Piña Colada",
            "image": [
                "https://example.com/photos/1x1/photo.jpg",
                "https://example.com/photos/4x3/photo.jpg",
                "https://example.com/photos/16x9/photo.jpg"
            ],
            "author": {
                "@type": "Person",
                "name": "Mary Stone"
            },
            "datePublished": "2018-03-10",
            "description": "This non-alcoholic pina colada is everyone's favorite!",
            "recipeCuisine": "American",
            "prepTime": "PT1M",
            "cookTime": "PT2M",
            "totalTime": "PT3M",
            "keywords": "non-alcoholic",
            "recipeYield": "4 servings",
            "recipeCategory": "Drink",
            "nutrition": {
                "@type": "NutritionInformation",
                "calories": "120 calories"
            },
            "aggregateRating": {
                "@type": "AggregateRating",
                "ratingValue": "5",
                "ratingCount": "18"
            },
            "recipeIngredient": [
                "400ml of pineapple juice",
                "100ml cream of coconut",
                "ice"
            ],
            "recipeInstructions": [
                {
                    "@type": "HowToStep",
                    "name": "Blend",
                    "text": "Blend 400ml of pineapple juice and 100ml cream of coconut until smooth.",
                    "url": "https://example.com/non-alcoholic-pina-colada#step1",
                    "image": "https://example.com/photos/non-alcoholic-pina-colada/step1.jpg"
                },
                {
                    "@type": "HowToStep",
                    "name": "Fill",
                    "text": "Fill a glass with ice.",
                    "url": "https://example.com/non-alcoholic-pina-colada#step2",
                    "image": "https://example.com/photos/non-alcoholic-pina-colada/step2.jpg"
                },
                {
                    "@type": "HowToStep",
                    "name": "Pour",
                    "text": "Pour the pineapple juice and coconut mixture over ice.",
                    "url": "https://example.com/non-alcoholic-pina-colada#step3",
                    "image": "https://example.com/photos/non-alcoholic-pina-colada/step3.jpg"
                }
            ],
            "video": {
                "@type": "VideoObject",
                "name": "How to Make a Non-Alcoholic Piña Colada",
                "description": "This is how you make a non-alcoholic piña colada.",
                "thumbnailUrl": [
                    "https://example.com/photos/1x1/photo.jpg",
                    "https://example.com/photos/4x3/photo.jpg",
                    "https://example.com/photos/16x9/photo.jpg"
                ],
                "contentUrl": "https://www.example.com/video123.mp4",
                "embedUrl": "https://www.example.com/videoplayer?video=123",
                "uploadDate": "2018-02-05T08:00:00+08:00",
                "duration": "PT1M33S",
                "interactionStatistic": {
                    "@type": "InteractionCounter",
                    "interactionType": {
                        "@type": "WatchAction"
                    },
                    "userInteractionCount": 2347
                },
                "expires": "2019-02-05T08:00:00+08:00"
            }
        }
        """;

    [TestMethod]
    public void DeserializeAnEmptyArray()
    {
        // Arrange
        var json = "[]";

        // Act
        var result = JsonSerializer.Deserialize(json, JsonLdSerializerContext.Default.JsonLd);

        // Assert
        result.ShouldNotBeNull();
        var things = result.Value.ShouldBeOfType<Thing[]>();
        things.ShouldBeEmpty();
    }

    [TestMethod]
    public void DeserializeJsonLdFromGoogleExample()
    {
        // Act
        var result = JsonSerializer.Deserialize(googleExample, JsonLdSerializerContext.Default.JsonLd);

        // Assert
        result.ShouldNotBeNull();
        var recipe = result.Value.ShouldBeOfType<JsonLdRecipeParser.Json.Recipe>();
        recipe.ShouldBeEquivalentTo(
            new JsonLdRecipeParser.Json.Recipe
            {
                Name = "Non-Alcoholic Piña Colada",
                Description = "This non-alcoholic pina colada is everyone's favorite!",
                Author = new Authors
                {
                    Value = new JsonLdRecipeParser.Json.Author { Value = new Person { Name = "Mary Stone" } },
                },
                PrepTime = TimeSpan.FromMinutes(1),
                TotalTime = TimeSpan.FromMinutes(3),
                CookTime = TimeSpan.FromMinutes(2),
                Nutrition = new NutritionInformation { Calories = new Quantity { Value = "120 calories" } },
                RecipeCategory = new RecipeCategories { Value = "Drink" },
                RecipeCuisine = new RecipeCuisines { Value = "American" },
                RecipeIngredient =
                [
                    new RecipeIngredient { Value = "400ml of pineapple juice" },
                    new RecipeIngredient { Value = "100ml cream of coconut" },
                    new RecipeIngredient { Value = "ice" },
                ],
                RecipeInstructions =
                [
                    new RecipeInstruction
                    {
                        Value = new HowToStep
                        {
                            Name = "Blend",
                            Text = "Blend 400ml of pineapple juice and 100ml cream of coconut until smooth.",
                        },
                    },
                    new RecipeInstruction
                    {
                        Value = new HowToStep { Name = "Fill", Text = "Fill a glass with ice." },
                    },
                    new RecipeInstruction
                    {
                        Value = new HowToStep
                        {
                            Name = "Pour",
                            Text = "Pour the pineapple juice and coconut mixture over ice.",
                        },
                    },
                ],
                RecipeYield = new Quantity { Value = "4 servings" },
            }
        );
    }

    [TestMethod]
    public void DeserializeJsonLdFromGoogleExampleInArray()
    {
        // Arrange
        const string json = $"[{googleExample}]";

        // Act
        var result = JsonSerializer.Deserialize(json, JsonLdSerializerContext.Default.JsonLd);

        // Assert
        result.ShouldNotBeNull();
        var things = result.Value.ShouldBeOfType<Thing[]>();
        things.Length.ShouldBe(1);
        things[0].ShouldBeOfType<JsonLdRecipeParser.Json.Recipe>();
    }
}