summaryrefslogtreecommitdiff
path: root/src/SMAPI.Tests/WikiClient/ChangeDescriptorTests.cs
blob: 8e7e1fb88ae729e8e352584f2e7edab2355615eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System.Collections.Generic;
using NUnit.Framework;
using StardewModdingAPI;
using StardewModdingAPI.Toolkit.Framework.Clients.Wiki;

namespace SMAPI.Tests.WikiClient
{
    /// <summary>Unit tests for <see cref="ChangeDescriptor"/>.</summary>
    [TestFixture]
    internal class ChangeDescriptorTests
    {
        /*********
        ** Unit tests
        *********/
        /****
        ** Constructor
        ****/
        [Test(Description = "Assert that Parse sets the expected values for valid and invalid descriptors.")]
        public void Parse_SetsExpectedValues_Raw()
        {
            // arrange
            string rawDescriptor = "-Nexus:2400,    -B, XX → YY, Nexus:451,+A, XXX → YYY, invalidA →, → invalidB";
            string[] expectedAdd = { "Nexus:451", "A" };
            string[] expectedRemove = { "Nexus:2400", "B" };
            IDictionary<string, string> expectedReplace = new Dictionary<string, string>
            {
                ["XX"] = "YY",
                ["XXX"] = "YYY"
            };
            string[] expectedErrors = {
                "Failed parsing ' invalidA →': can't map to a blank value. Use the '-value' format to remove a value.",
                "Failed parsing ' → invalidB': can't map from a blank old value. Use the '+value' format to add a value."
            };

            // act
            ChangeDescriptor parsed = ChangeDescriptor.Parse(rawDescriptor, out string[] errors);

            // assert
            Assert.That(parsed.Add, Is.EquivalentTo(expectedAdd), $"{nameof(parsed.Add)} doesn't match the expected value.");
            Assert.That(parsed.Remove, Is.EquivalentTo(expectedRemove), $"{nameof(parsed.Replace)} doesn't match the expected value.");
            Assert.That(parsed.Replace, Is.EquivalentTo(expectedReplace), $"{nameof(parsed.Replace)} doesn't match the expected value.");
            Assert.That(errors, Is.EquivalentTo(expectedErrors), $"{nameof(errors)} doesn't match the expected value.");
        }

        [Test(Description = "Assert that Parse sets the expected values for descriptors when a format callback is specified.")]
        public void Parse_SetsExpectedValues_Formatted()
        {
            // arrange
            string rawDescriptor = "-1.0.1,    -2.0-beta, 1.00 → 1.0, 1.0.0,+2.0-beta.15, 2.0 → 2.0-beta, invalidA →, → invalidB";
            string[] expectedAdd = { "1.0.0", "2.0.0-beta.15" };
            string[] expectedRemove = { "1.0.1", "2.0.0-beta" };
            IDictionary<string, string> expectedReplace = new Dictionary<string, string>
            {
                ["1.00"] = "1.0.0",
                ["2.0.0"] = "2.0.0-beta"
            };
            string[] expectedErrors = {
                "Failed parsing ' invalidA →': can't map to a blank value. Use the '-value' format to remove a value.",
                "Failed parsing ' → invalidB': can't map from a blank old value. Use the '+value' format to add a value."
            };

            // act
            ChangeDescriptor parsed = ChangeDescriptor.Parse(
                rawDescriptor,
                out string[] errors,
                formatValue: raw => SemanticVersion.TryParse(raw, out ISemanticVersion? version)
                    ? version.ToString()
                    : raw
            );

            // assert
            Assert.That(parsed.Add, Is.EquivalentTo(expectedAdd), $"{nameof(parsed.Add)} doesn't match the expected value.");
            Assert.That(parsed.Remove, Is.EquivalentTo(expectedRemove), $"{nameof(parsed.Replace)} doesn't match the expected value.");
            Assert.That(parsed.Replace, Is.EquivalentTo(expectedReplace), $"{nameof(parsed.Replace)} doesn't match the expected value.");
            Assert.That(errors, Is.EquivalentTo(expectedErrors), $"{nameof(errors)} doesn't match the expected value.");
        }

        [Test(Description = "Assert that Apply returns the expected value for the given descriptor.")]

        // null input
        [TestCase(null, "", ExpectedResult = null)]
        [TestCase(null, "+Nexus:2400", ExpectedResult = "Nexus:2400")]
        [TestCase(null, "-Nexus:2400", ExpectedResult = null)]

        // blank input
        [TestCase("", null, ExpectedResult = "")]
        [TestCase("", "", ExpectedResult = "")]

        // add value
        [TestCase("", "+Nexus:2400", ExpectedResult = "Nexus:2400")]
        [TestCase("Nexus:2400", "+Nexus:2400", ExpectedResult = "Nexus:2400")]
        [TestCase("Nexus:2400", "Nexus:2400", ExpectedResult = "Nexus:2400")]
        [TestCase("Nexus:2400", "+Nexus:2401", ExpectedResult = "Nexus:2400, Nexus:2401")]
        [TestCase("Nexus:2400", "Nexus:2401", ExpectedResult = "Nexus:2400, Nexus:2401")]

        // remove value
        [TestCase("", "-Nexus:2400", ExpectedResult = "")]
        [TestCase("Nexus:2400", "-Nexus:2400", ExpectedResult = "")]
        [TestCase("Nexus:2400", "-Nexus:2401", ExpectedResult = "Nexus:2400")]

        // replace value
        [TestCase("", "Nexus:2400 → Nexus:2401", ExpectedResult = "")]
        [TestCase("Nexus:2400", "Nexus:2400 → Nexus:2401", ExpectedResult = "Nexus:2401")]
        [TestCase("Nexus:1", "Nexus: 2400 → Nexus: 2401", ExpectedResult = "Nexus:1")]

        // complex strings
        [TestCase("", "+Nexus:A, Nexus:B, -Chucklefish:14, Nexus:2400 → Nexus:2401, Nexus:A→Nexus:B", ExpectedResult = "Nexus:A, Nexus:B")]
        [TestCase("Nexus:2400", "+Nexus:A, Nexus:B, -Chucklefish:14, Nexus:2400 → Nexus:2401, Nexus:A→Nexus:B", ExpectedResult = "Nexus:2401, Nexus:A, Nexus:B")]
        [TestCase("Nexus:2400, Nexus:2401, Nexus:B,Chucklefish:14", "+Nexus:A, Nexus:B, -Chucklefish:14, Nexus:2400 → Nexus:2401, Nexus:A→Nexus:B", ExpectedResult = "Nexus:2401, Nexus:2401, Nexus:B, Nexus:A")]
        public string Apply_Raw(string input, string? descriptor)
        {
            ChangeDescriptor parsed = ChangeDescriptor.Parse(descriptor, out string[] errors);

            Assert.IsEmpty(errors, "Parsing the descriptor failed.");

            return parsed.ApplyToCopy(input);
        }

        [Test(Description = "Assert that ToString returns the expected normalized descriptors.")]
        [TestCase(null, ExpectedResult = "")]
        [TestCase("", ExpectedResult = "")]
        [TestCase("+   Nexus:2400", ExpectedResult = "+Nexus:2400")]
        [TestCase("  Nexus:2400  ", ExpectedResult = "+Nexus:2400")]
        [TestCase("-Nexus:2400", ExpectedResult = "-Nexus:2400")]
        [TestCase("  Nexus:2400   →Nexus:2401  ", ExpectedResult = "Nexus:2400 → Nexus:2401")]
        [TestCase("+Nexus:A, Nexus:B, -Chucklefish:14, Nexus:2400 → Nexus:2401, Nexus:A→Nexus:B", ExpectedResult = "+Nexus:A, +Nexus:B, -Chucklefish:14, Nexus:2400 → Nexus:2401, Nexus:A → Nexus:B")]
        public string ToString(string? descriptor)
        {
            var parsed = ChangeDescriptor.Parse(descriptor, out string[] errors);

            Assert.IsEmpty(errors, "Parsing the descriptor failed.");

            return parsed.ToString();
        }
    }
}