using Microsoft.AspNetCore.Http; using PrivaPub.Api.Mastodon.Auth; using PrivaPub.Api.Mastodon.Infrastructure; using System.Text; namespace PrivaPub.Tests.Api { public class MastodonParamsTests { static async Task Read(string query = "", string contentType = default, string body = default) { var context = new DefaultHttpContext(); context.Request.QueryString = new QueryString(query); if (body != default) { context.Request.ContentType = contentType; var bytes = Encoding.UTF8.GetBytes(body); context.Request.Body = new MemoryStream(bytes); context.Request.ContentLength = bytes.Length; } return await MastodonParams.Read(context.Request, TestContext.Current.CancellationToken); } [Fact] public async Task Absent_values_are_null_not_false_or_zero() { var parameters = await Read(); Assert.Null(parameters.Bool("sensitive")); Assert.Null(parameters.Int("limit")); Assert.Null(parameters.Get("status")); Assert.Empty(parameters.List("media_ids")); } [Fact] public async Task Reads_rails_style_arrays_from_the_query() { var parameters = await Read("?id[]=1&id[]=2&limit=5&local=true"); Assert.Equal(new[] { "1", "2" }, parameters.List("id")); Assert.Equal(5, parameters.Int("limit")); Assert.True(parameters.Bool("local")); } [Fact] public async Task Reads_forms_and_nested_keys() { var parameters = await Read(contentType: "application/x-www-form-urlencoded", body: "status=hi&media_ids[]=a&media_ids[]=b&poll[options][]=x&poll[options][]=y&sensitive=0"); Assert.Equal("hi", parameters.Get("status")); Assert.Equal(new[] { "a", "b" }, parameters.List("media_ids")); Assert.Equal(new[] { "x", "y" }, parameters.List("poll[options]")); Assert.False(parameters.Bool("sensitive")); } [Fact] public async Task Reads_json_bodies_the_same_way() { var parameters = await Read(contentType: "application/json", body: """{"status":"hi","media_ids":["a","b"],"poll":{"options":["x","y"],"expires_in":300},"sensitive":true,"source":{"privacy":"unlisted"}}"""); Assert.Equal(new[] { "a", "b" }, parameters.List("media_ids")); Assert.Equal(new[] { "x", "y" }, parameters.List("poll[options]")); Assert.Equal(300, parameters.Int("poll[expires_in]")); Assert.True(parameters.Bool("sensitive")); Assert.Equal("unlisted", parameters.Get("source[privacy]")); } [Theory] [InlineData(new[] { "read" }, "read:statuses", true)] [InlineData(new[] { "read:statuses" }, "read:statuses", true)] [InlineData(new[] { "read:accounts" }, "read:statuses", false)] [InlineData(new[] { "write" }, "read:statuses", false)] [InlineData(new[] { "follow" }, "write:follows", true)] [InlineData(new[] { "follow" }, "write:statuses", false)] public void Scopes_grant_like_mastodons(string[] granted, string required, bool expected) => Assert.Equal(expected, MastodonScopes.Grants(granted, required)); } }