Files
octokit.net/Octokit.Tests/SimpleJsonSerializerTests.cs
notauserx 891015c39f update models with updated permission enum (#2633)
* update models with updated permission enum

* add suppress message attribute

* update integration tests

* refactor: new and legacy update teams endpint

* refactor: add new delete team endpoint

* use TeamPermission on NewTeam

* use updated delete on team context dispose

* add permission enum for team response object

* refactor: remove legacy suffix from method names

* introduce permissions object on Team

* refactor: rename enum to TeamRepositoryPermission

* fix formatting

* change Permission to string to match api specs

* add TeamRepository

* add CheckTeamPermission endpoint support

* fix convention tests

* update comments on TeamRepository props

* add two new endpoints in TeamsClient

* refactor: rename ApiUrl for TeamPermission

* fix test

* implement methods for new endpoints

* add the integration tests

* fix spelling

* update comments

* refactor: rename method name

* fix: add end tag for remarks

* refactor: remove unused method param

* fix docstring comment

* the unit tests are in finally

* add docs for teams api

* split CheckTeamPermissions into two methods

* Update ObservableTeamsClientTests.cs based on review

Co-authored-by: Keegan Campbell <me@kfcampbell.com>

* add cref to legacy update and delete endpoints

* remove editorconfig file

* Update Octokit.Tests/Clients/TeamsClientTests.cs

Co-authored-by: Keegan Campbell <me@kfcampbell.com>

* remove unused line

* rename variable based on review

* rename prop to match constructor param

* add comment to explain TeamPermission enum values on update

Co-authored-by: notauserx <notauserx@users.noreply.github.com>
Co-authored-by: Keegan Campbell <me@kfcampbell.com>
2023-01-20 10:48:00 -08:00

535 lines
22 KiB
C#

using Octokit.Helpers;
using Octokit.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
namespace Octokit.Tests
{
public class SimpleJsonSerializerTests
{
public class TheSerializeMethod
{
[Fact]
public void UsesRubyCasing()
{
var item = new Sample { Id = 42, FirstName = "Phil", IsSomething = true, Private = true };
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"id\":42,\"first_name\":\"Phil\",\"is_something\":true,\"private\":true}", json);
}
[Fact]
public void OmitsPropertiesWithNullValue()
{
var item = new
{
Object = (object)null,
NullableInt = (int?)null,
NullableBool = (bool?)null
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{}", json);
}
[Fact]
public void DoesNotOmitsNullablePropertiesWithAValue()
{
var item = new
{
Object = new { Id = 42 },
NullableInt = (int?)1066,
NullableBool = (bool?)true
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"object\":{\"id\":42},\"nullable_int\":1066,\"nullable_bool\":true}", json);
}
[Fact]
public void HandlesMixingNullAndNotNullData()
{
var item = new
{
Int = 42,
Bool = true,
NullableInt = (int?)null,
NullableBool = (bool?)null
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"int\":42,\"bool\":true}", json);
}
[Fact]
public void HandleUnicodeCharacters()
{
const string backspace = "\b";
const string tab = "\t";
var sb = new StringBuilder();
sb.Append("My name has Unicode characters");
Enumerable.Range(0, 19).Select(e => System.Convert.ToChar(e))
.Aggregate(sb, (a, b) => a.Append(b));
sb.Append(backspace).Append(tab);
var data = sb.ToString();
var json = new SimpleJsonSerializer().Serialize(data);
var lastTabCharacter = json
.Reverse()
.Skip(1)
.Take(2)
.Reverse()
.Aggregate(new StringBuilder(), (a, b) => a.Append(b));
var deserializeData = new SimpleJsonSerializer().Deserialize<string>(json);
Assert.Equal("\\t", lastTabCharacter.ToString());
Assert.Equal(data, deserializeData);
}
[Fact]
public void HandlesBase64EncodedStrings()
{
var item = new SomeObject
{
Name = "Ferris Bueller",
Content = "Day off",
Description = "stuff"
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"name\":\"RmVycmlzIEJ1ZWxsZXI=\",\"description\":\"stuff\",\"content\":\"RGF5IG9mZg==\"}", json);
}
[Fact]
public void HandlesEnum()
{
var item = new ObjectWithEnumProperty
{
Name = "Ferris Bueller",
SomeEnum = SomeEnum.Unicode,
SomeEnumNullable = SomeEnum.Unicode,
StringEnum = SomeEnum.SomethingElse,
StringEnumNullable = SomeEnum.SomethingElse
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"name\":\"Ferris Bueller\",\"some_enum\":\"unicode\",\"some_enum_nullable\":\"unicode\",\"string_enum\":\"something else\",\"string_enum_nullable\":\"something else\"}", json);
}
[Fact]
public void HandlesEnumDefaults()
{
var item = new ObjectWithEnumProperty
{
Name = "Ferris Bueller",
SomeEnum = SomeEnum.PlusOne,
StringEnum = SomeEnum.PlusOne
};
var json = new SimpleJsonSerializer().Serialize(item);
Assert.Equal("{\"name\":\"Ferris Bueller\",\"some_enum\":\"+1\",\"string_enum\":\"+1\"}", json);
}
}
public class TheDeserializeMethod
{
[Fact]
public void DeserializesEventInfosWithUnderscoresInName()
{
const string json = "{\"event\":\"head_ref_deleted\"}";
new SimpleJsonSerializer().Deserialize<EventInfo>(json);
}
public class MessageSingle
{
public string Message { get; private set; }
}
[Fact]
public void DeserializesStringsWithHyphensAndUnderscoresIntoString()
{
const string json = @"{""message"":""-my-test-string_with_underscores_""}";
var response = new SimpleJsonSerializer().Deserialize<MessageSingle>(json);
Assert.Equal("-my-test-string_with_underscores_", response.Message);
}
public class MessageList
{
public IReadOnlyList<string> Message { get; private set; }
}
[Fact]
public void DeserializesStringsWithHyphensAndUnderscoresIntoStringList()
{
const string json = @"{""message"":""-my-test-string_with_underscores_""}";
var response = new SimpleJsonSerializer().Deserialize<MessageList>(json);
Assert.Equal("-my-test-string_with_underscores_", response.Message[0]);
}
[Fact]
public void UnderstandsRubyCasing()
{
const string json = "{\"id\":42,\"first_name\":\"Phil\",\"is_something\":true,\"private\":true}";
var sample = new SimpleJsonSerializer().Deserialize<Sample>(json);
Assert.Equal(42, sample.Id);
Assert.Equal("Phil", sample.FirstName);
Assert.True(sample.IsSomething);
Assert.True(sample.Private);
}
[Fact]
public void DeserializesPublicReadonlyAutoProperties()
{
const string json = "{\"content\":\"hello\"}";
var someObject = new SimpleJsonSerializer().Deserialize<ReadOnlyAutoProperties>(json);
Assert.Equal("hello", someObject.Content);
}
public class ReadOnlyAutoProperties
{
public string Content { get; private set; }
}
[Fact]
public void DeserializesProtectedProperties()
{
const string json = "{\"content\":\"hello\"}";
var someObject = new SimpleJsonSerializer().Deserialize<AnotherObject>(json);
Assert.Equal("*hello*", someObject.Content);
}
public class AnotherObject
{
[Parameter(Key = "content")]
protected string EncodedContent { get; set; }
public string Content { get { return "*" + EncodedContent + "*"; } }
}
[Fact]
public void HandlesBase64EncodedStrings()
{
const string json = "{\"name\":\"RmVycmlzIEJ1ZWxsZXI=\",\"description\":\"stuff\",\"content\":\"RGF5IG9mZg==\"}";
var item = new SimpleJsonSerializer().Deserialize<SomeObject>(json);
Assert.Equal("Ferris Bueller", item.Name);
Assert.Equal("Day off", item.Content);
Assert.Equal("stuff", item.Description);
}
[Fact]
public void CanDeserializeOrganization()
{
const string json = "{" +
"\"login\": \"mono\"," +
"\"id\": 53395," +
"\"avatar_url\": \"https://avatars.githubusercontent.com/u/53395?\"," +
"\"gravatar_id\": \"f275a99c0b4e6044d3e81daf445f8174\"," +
"\"url\": \"https://api.github.com/users/mono\"," +
"\"html_url\": \"https://github.com/mono\"," +
"\"followers_url\": \"https://api.github.com/users/mono/followers\"," +
"\"following_url\": \"https://api.github.com/users/mono/following{/other_user}\"," +
"\"gists_url\": \"https://api.github.com/users/mono/gists{/gist_id}\"," +
"\"starred_url\": \"https://api.github.com/users/mono/starred{/owner}{/repo}\"," +
"\"subscriptions_url\": \"https://api.github.com/users/mono/subscriptions\"," +
"\"organizations_url\": \"https://api.github.com/users/mono/orgs\"," +
"\"repos_url\": \"https://api.github.com/users/mono/repos\"," +
"\"events_url\": \"https://api.github.com/users/mono/events{/privacy}\"," +
"\"received_events_url\": \"https://api.github.com/users/mono/received_events\"," +
"\"type\": \"Organization\"," +
"\"site_admin\": false," +
"\"name\": \"Mono Project\"," +
"\"company\": null," +
"\"blog\": \"http://mono-project.com\"," +
"\"location\": \"Boston, MA\"," +
"\"email\": \"mono@xamarin.com\"," +
"\"hireable\": null," +
"\"bio\": null," +
"\"public_repos\": 161," +
"\"public_gists\": 0," +
"\"followers\": 0," +
"\"following\": 0," +
"\"created_at\": \"2009-02-10T17:53:17Z\"," +
"\"updated_at\": 1404691976" +
"}";
var result = new SimpleJsonSerializer().Deserialize<User>(json);
Assert.Equal("Mono Project", result.Name);
Assert.Null(result.Hireable);
Assert.Equal(new DateTimeOffset(2009, 02, 10, 17, 53, 17, TimeSpan.Zero), result.CreatedAt);
Assert.Equal(new DateTimeOffset(2014, 07, 07, 00, 12, 56, TimeSpan.Zero), result.UpdatedAt);
}
[Fact]
public void DeserializesInheritedProperties()
{
const string json = "{\"sha\":\"commit-sha\",\"url\":\"commit-url\",\"message\":\"commit-message\"}";
var result = new SimpleJsonSerializer().Deserialize<Commit>(json);
Assert.Equal("commit-sha", result.Sha);
Assert.Equal("commit-url", result.Url);
Assert.Equal("commit-message", result.Message);
}
[Fact]
public void RespectsParameterKeyName()
{
const string json = "{\"_links\":\"blah\"}";
var result = new SimpleJsonSerializer().Deserialize<Sample>(json);
Assert.Equal("blah", result.Links);
}
[Fact]
public void DefaultsMissingParameters()
{
const string json = @"{""private"":true}";
var sample = new SimpleJsonSerializer().Deserialize<Sample>(json);
Assert.Equal(0, sample.Id);
Assert.Null(sample.FirstName);
Assert.False(sample.IsSomething);
Assert.True(sample.Private);
}
[Fact]
public void DeserializesEnums()
{
const string json1 = @"{""some_enum"":""+1""}";
const string json2 = @"{""some_enum"":""utf-8""}";
const string json3 = @"{""some_enum"":""something else""}";
const string json4 = @"{""some_enum"":""another_example""}";
const string json5 = @"{""some_enum"":""unicode""}";
var sample1 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json1);
var sample2 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json2);
var sample3 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json3);
var sample4 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json4);
var sample5 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json5);
Assert.Equal(SomeEnum.PlusOne, sample1.SomeEnum);
Assert.Equal(SomeEnum.Utf8, sample2.SomeEnum);
Assert.Equal(SomeEnum.SomethingElse, sample3.SomeEnum);
Assert.Equal(SomeEnum.AnotherExample, sample4.SomeEnum);
Assert.Equal(SomeEnum.Unicode, sample5.SomeEnum);
}
[Fact]
public void DeserializesNullableEnums()
{
const string json1 = @"{""some_enum_nullable"":""+1""}";
const string json2 = @"{""some_enum_nullable"":""utf-8""}";
const string json3 = @"{""some_enum_nullable"":""something else""}";
const string json4 = @"{""some_enum_nullable"":""another_example""}";
const string json5 = @"{""some_enum_nullable"":""unicode""}";
const string json6 = @"{""some_enum_nullable"":null}";
var sample1 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json1);
var sample2 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json2);
var sample3 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json3);
var sample4 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json4);
var sample5 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json5);
var sample6 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json6);
Assert.Equal(SomeEnum.PlusOne, sample1.SomeEnumNullable);
Assert.Equal(SomeEnum.Utf8, sample2.SomeEnumNullable);
Assert.Equal(SomeEnum.SomethingElse, sample3.SomeEnumNullable);
Assert.Equal(SomeEnum.AnotherExample, sample4.SomeEnumNullable);
Assert.Equal(SomeEnum.Unicode, sample5.SomeEnumNullable);
Assert.False(sample6.SomeEnumNullable.HasValue);
}
[Fact]
public void DeserializesStringEnums()
{
const string json1 = @"{""string_enum"":""+1""}";
const string json2 = @"{""string_enum"":""utf-8""}";
const string json3 = @"{""string_enum"":""something else""}";
const string json4 = @"{""string_enum"":""another_example""}";
const string json5 = @"{""string_enum"":""unicode""}";
var sample1 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json1);
var sample2 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json2);
var sample3 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json3);
var sample4 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json4);
var sample5 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json5);
Assert.Equal(SomeEnum.PlusOne, sample1.StringEnum);
Assert.Equal(SomeEnum.Utf8, sample2.StringEnum);
Assert.Equal(SomeEnum.SomethingElse, sample3.StringEnum);
Assert.Equal(SomeEnum.AnotherExample, sample4.StringEnum);
Assert.Equal(SomeEnum.Unicode, sample5.StringEnum);
}
[Fact]
public void DeserializesNullableStringEnums()
{
const string json1 = @"{""string_enum_nullable"":""+1""}";
const string json2 = @"{""string_enum_nullable"":""utf-8""}";
const string json3 = @"{""string_enum_nullable"":""something else""}";
const string json4 = @"{""string_enum_nullable"":""another_example""}";
const string json5 = @"{""string_enum_nullable"":""unicode""}";
const string json6 = @"{""string_enum_nullable"":null}";
var sample1 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json1);
var sample2 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json2);
var sample3 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json3);
var sample4 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json4);
var sample5 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json5);
var sample6 = new SimpleJsonSerializer().Deserialize<ObjectWithEnumProperty>(json6);
Assert.Equal(SomeEnum.PlusOne, sample1.StringEnumNullable);
Assert.Equal(SomeEnum.Utf8, sample2.StringEnumNullable);
Assert.Equal(SomeEnum.SomethingElse, sample3.StringEnumNullable);
Assert.Equal(SomeEnum.AnotherExample, sample4.StringEnumNullable);
Assert.Equal(SomeEnum.Unicode, sample5.StringEnumNullable);
Assert.False(sample6.StringEnumNullable.HasValue);
}
[Fact]
public void ShouldDeserializeMultipleEnumValues()
{
var strings = new[]
{
"locked",
"unlocked",
"head_ref_deleted",
"head_ref_restored"
};
foreach (var value in strings)
{
var enumValue = SimpleJsonSerializer.DeserializeEnum(value, typeof(EventInfoState));
// Test passes if no exception thrown
}
}
// this test is the root cause of https://github.com/octokit/octokit.net/issues/2052
// as the API is returning a null value where the enum is expecting
// something like a string
//
// this should be removed once we can confirm the GitHub API is no
// longer returning a null for the parent Team's permission value,
// making the test redundant
[Fact]
public void ShouldDeserializeParentTeamWithNullPermission()
{
var teamJson = @"{
""id"": 1,
""node_id"": ""MDQ6VGVhbTE="",
""url"": ""https://api.github.com/teams/1"",
""html_url"": ""https://api.github.com/teams/justice-league"",
""name"": ""Justice League"",
""slug"": ""justice-league"",
""description"": ""A great team."",
""privacy"": ""closed"",
""permission"": ""admin"",
""members_url"": ""https://api.github.com/teams/1/members{/member}"",
""repositories_url"": ""https://api.github.com/teams/1/repos"",
""parent"": {
""id"": 1,
""node_id"": ""MDQ6LFJSbTE="",
""url"": ""https://api.github.com/teams/2"",
""html_url"": ""https://api.github.com/teams/super-friends"",
""name"": ""Super Friends"",
""slug"": ""super-friends"",
""description"": ""Also a great team."",
""privacy"": ""closed"",
""permission"": null,
""members_url"": ""https://api.github.com/teams/2/members{/member}"",
""repositories_url"": ""https://api.github.com/teams/2/repos"",
}
}
}";
var result = new SimpleJsonSerializer().Deserialize<Team>(teamJson);
// original value works as expected
Assert.Equal("admin", result.Permission);
// parent permission is marked as null and cannot be parsed
Assert.Null(result.Parent.Permission);
}
}
public class Sample
{
public int Id { get; set; }
public string FirstName { get; set; }
public bool IsSomething { get; set; }
public bool Private { get; set; }
[Parameter(Key = "_links")]
public string Links { get; set; }
}
public class SomeObject
{
[SerializeAsBase64]
public string Name { get; set; }
[SerializeAsBase64]
public string Content;
public string Description { get; set; }
}
}
public class ObjectWithEnumProperty
{
public string Name { get; set; }
public SomeEnum SomeEnum { get; set; }
public SomeEnum? SomeEnumNullable { get; set; }
public StringEnum<SomeEnum> StringEnum { get; set; }
public StringEnum<SomeEnum>? StringEnumNullable { get; set; }
}
public enum SomeEnum
{
[Parameter(Value = "+1")]
PlusOne,
[Parameter(Value = "utf-8")]
Utf8,
[Parameter(Value = "something else")]
SomethingElse,
[Parameter(Value = "another_example")]
AnotherExample,
[Parameter(Value = "unicode")]
Unicode
}
}