Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions SlackNet.Tests/ChatUpdateMetadataTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#nullable enable
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using EasyAssertions;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using SlackNet.WebApi;

namespace SlackNet.Tests;

public class ChatUpdateMetadataTests
{
private RecordingHttp _http = null!;
private ISlackApiClient _sut = null!;

[SetUp]
public void SetUp()
{
var jsonSettings = Default.JsonSettings(Default.SlackTypeResolver(Default.AssembliesContainingSlackTypes));
_http = new RecordingHttp();
_sut = new SlackApiClient(_http, Default.UrlBuilder(jsonSettings), jsonSettings, "token");
}

[Test]
public async Task Update_WithoutMetadata_SendsNoMetadata()
{
await _sut.Chat.Update(new MessageUpdate { ChannelId = "C123", Ts = "1503435956.000247", Text = "edited" });

_http.Method.ShouldBe("chat.update");
_http.Body.ContainsKey("metadata").ShouldBe(false);
}

[Test]
public async Task Update_WithMetadataJson_SendsMetadata()
{
await _sut.Chat.Update(new MessageUpdate
{
ChannelId = "C123",
Ts = "1503435956.000247",
Text = "edited",
MetadataJson = new MessageMetadata { EventType = "task_created", EventPayload = JObject.Parse(@"{ ""id"": ""TK-42"" }") }
});

_http.Body["channel"]!.Value<string>().ShouldBe("C123");
_http.Body["text"]!.Value<string>().ShouldBe("edited");
JToken.DeepEquals(JObject.Parse(@"{ ""event_type"": ""task_created"", ""event_payload"": { ""id"": ""TK-42"" } }"), _http.Body["metadata"]).ShouldBe(true);
}

[Test]
public async Task Update_WithMetadataObject_SendsItAsMetadata()
{
await _sut.Chat.Update(new MessageUpdate { ChannelId = "C123", Ts = "1503435956.000247", MetadataObject = new TaskCreated { TaskId = "TK-42" } });

JToken.DeepEquals(JObject.Parse(@"{ ""event_type"": ""task_created"", ""event_payload"": { ""task_id"": ""TK-42"" } }"), _http.Body["metadata"]).ShouldBe(true);
}

[Test]
public async Task Update_WithMetadataJsonAndMetadataObject_SendsMetadataJson()
{
await _sut.Chat.Update(new MessageUpdate
{
ChannelId = "C123",
Ts = "1503435956.000247",
MetadataJson = new MessageMetadata { EventType = "from_json", EventPayload = new JObject() },
MetadataObject = new TaskCreated { TaskId = "TK-42" }
});

_http.Body["metadata"]!["event_type"]!.Value<string>().ShouldBe("from_json");
}

[SlackType("task_created")]
private class TaskCreated
{
public string TaskId { get; set; } = "";
}

private class RecordingHttp : IHttp
{
public string Method { get; private set; } = "";
public JObject Body { get; private set; } = new();

public async Task<T> Execute<T>(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default)
{
Method = requestMessage.RequestUri!.Segments[^1];
Body = JObject.Parse(await requestMessage.Content!.ReadAsStringAsync().ConfigureAwait(false));
return (T)(object)new WebApiResponse { Ok = true, Data = new JObject { ["ok"] = true } };
}
}
}
50 changes: 50 additions & 0 deletions SlackNet.Tests/MessageDeletedTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using EasyAssertions;
using Newtonsoft.Json;
using NUnit.Framework;
using SlackNet.Events;

namespace SlackNet.Tests;

public class MessageDeletedTests
{
private JsonSerializerSettings _sut;

[SetUp]
public void SetUp()
{
_sut = Default.JsonSettings(Default.SlackTypeResolver(Default.AssembliesContainingSlackTypes)).SerializerSettings;
}

[Test]
public void MessageDeleted_DeserializedWithPreviousMessage()
{
var result = Deserialize<Event>(@"{
""type"": ""message"",
""subtype"": ""message_deleted"",
""hidden"": true,
""channel"": ""C123ABC456"",
""ts"": ""1358878755.000001"",
""deleted_ts"": ""1358878749.000002"",
""event_ts"": ""1358878755.000001"",
""previous_message"": { ""type"": ""message"", ""user"": ""U123ABC456"", ""text"": ""Hello"", ""ts"": ""1358878749.000002"", ""thread_ts"": ""1358878700.000001"" }
}");

var deleted = result.ShouldBeA<MessageDeleted>().And;
deleted.DeletedTs.ShouldBe("1358878749.000002");
deleted.PreviousMessage.User.ShouldBe("U123ABC456");
deleted.PreviousMessage.Text.ShouldBe("Hello");
deleted.PreviousMessage.Ts.ShouldBe("1358878749.000002");
deleted.PreviousMessage.ThreadTs.ShouldBe("1358878700.000001");
deleted.ExtraProperties.ContainsKey("previous_message").ShouldBe(false);
}

[Test]
public void MessageDeleted_WithoutPreviousMessage_HasNone()
{
var result = Deserialize<Event>(@"{ ""type"": ""message"", ""subtype"": ""message_deleted"", ""hidden"": true, ""channel"": ""C123ABC456"", ""ts"": ""1358878755.000001"", ""deleted_ts"": ""1358878749.000002"" }");

result.ShouldBeA<MessageDeleted>().And.PreviousMessage.ShouldBeNull();
}

private T Deserialize<T>(string json) => JsonConvert.DeserializeObject<T>(json, _sut);
}
67 changes: 67 additions & 0 deletions SlackNet.Tests/MessageTeamTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using EasyAssertions;
using Newtonsoft.Json;
using NUnit.Framework;
using SlackNet.Events;

namespace SlackNet.Tests;

public class MessageTeamTests
{
private JsonSerializerSettings _sut;

[SetUp]
public void SetUp()
{
_sut = Default.JsonSettings(Default.SlackTypeResolver(Default.AssembliesContainingSlackTypes)).SerializerSettings;
}

[Test]
public void MessageEvent_FromSharedChannel_HasUserTeamAndSourceTeam()
{
var result = Deserialize<Event>(@"{ ""type"": ""message"", ""user"": ""U123ABC456"", ""text"": ""Hello"", ""ts"": ""1355517523.000005"", ""team"": ""T111"", ""user_team"": ""T222"", ""source_team"": ""T333"" }");

var message = result.ShouldBeA<MessageEvent>().And;
message.Team.ShouldBe("T111");
message.UserTeam.ShouldBe("T222");
message.SourceTeam.ShouldBe("T333");
message.ExtraProperties.ShouldBeEmpty();
}

[Test]
public void MessageEvent_FromUnsharedChannel_HasNoUserTeamOrSourceTeam()
{
var result = Deserialize<Event>(@"{ ""type"": ""message"", ""user"": ""U123ABC456"", ""text"": ""Hello"", ""ts"": ""1355517523.000005"", ""team"": ""T111"" }");

var message = result.ShouldBeA<MessageEvent>().And;
message.UserTeam.ShouldBeNull();
message.SourceTeam.ShouldBeNull();
}

[Test]
public void MessageChanged_MessagesHaveUserTeamAndSourceTeam()
{
var result = Deserialize<Event>(@"{
""type"": ""message"",
""subtype"": ""message_changed"",
""channel"": ""C123ABC456"",
""message"": { ""type"": ""message"", ""user"": ""U123ABC456"", ""text"": ""Hello again"", ""ts"": ""1355517523.000005"", ""user_team"": ""T222"", ""source_team"": ""T333"" },
""previous_message"": { ""type"": ""message"", ""user"": ""U123ABC456"", ""text"": ""Hello"", ""ts"": ""1355517523.000005"", ""user_team"": ""T222"", ""source_team"": ""T333"" }
}");

var changed = result.ShouldBeA<MessageChanged>().And;
changed.Message.UserTeam.ShouldBe("T222");
changed.PreviousMessage.SourceTeam.ShouldBe("T333");
}

[Test]
public void AppMention_FromSharedChannel_HasUserTeamAndSourceTeam()
{
var result = Deserialize<Event>(@"{ ""type"": ""app_mention"", ""user"": ""U123ABC456"", ""text"": ""<@U0LAN0Z89> hi"", ""ts"": ""1355517523.000005"", ""user_team"": ""T222"", ""source_team"": ""T333"" }");

var mention = result.ShouldBeA<AppMention>().And;
mention.UserTeam.ShouldBe("T222");
mention.SourceTeam.ShouldBe("T333");
}

private T Deserialize<T>(string json) => JsonConvert.DeserializeObject<T>(json, _sut);
}
4 changes: 4 additions & 0 deletions SlackNet/Events/Messages/MessageDeleted.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ public class MessageDeleted : MessageEvent
public string DeletedTs { get; set; }
[JsonIgnore]
public DateTime DeleteTimestamp => DeletedTs.ToDateTime().GetValueOrDefault();
/// <summary>
/// The message that was deleted.
/// </summary>
public MessageEvent PreviousMessage { get; set; }
}
8 changes: 8 additions & 0 deletions SlackNet/Events/Messages/MessageEventBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ public abstract class MessageEventBase : Event
public string Text { get; set; }
public string Ts { get; set; }
public string Team { get; set; }
/// <summary>
/// The workspace of the user who sent the message. Only sent when the message comes from a channel that is shared between workspaces.
/// </summary>
public string UserTeam { get; set; }
/// <summary>
/// The workspace the message was sent from. Only sent when the message comes from a channel that is shared between workspaces.
/// </summary>
public string SourceTeam { get; set; }
public bool DisplayAsBot { get; set; }
[JsonIgnore]
public DateTime Timestamp => Ts.ToDateTime().GetValueOrDefault();
Expand Down
3 changes: 2 additions & 1 deletion SlackNet/WebApi/ChatApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ public Task<MessageUpdateResponse> Update(MessageUpdate messageUpdate, Cancellat
{ "parse", messageUpdate.Parse },
{ "link_names", messageUpdate.LinkNames },
{ "as_user", messageUpdate.AsUser },
{ "file_ids", messageUpdate.FileIds }
{ "file_ids", messageUpdate.FileIds },
{ "metadata", messageUpdate.MetadataJson ?? MessageMetadata.FromObject(messageUpdate.MetadataObject, jsonSettings) }
},
cancellationToken);

Expand Down
10 changes: 10 additions & 0 deletions SlackNet/WebApi/Responses/MessageUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,14 @@ public class MessageUpdate
/// Array of new file ids that will be sent with this message.
/// </summary>
public IList<string> FileIds { get; set; }
/// <summary>
/// A custom event attached to the message. Leave as null to leave the existing metadata alone.
/// </summary>
/// <remarks>Will take precedence over <see cref="MetadataObject"/>.</remarks>
public MessageMetadata MetadataJson { get; set; }
/// <summary>
/// A custom event attached to the message. Leave as null to leave the existing metadata alone.
/// </summary>
/// <remarks>The specified object will be automatically converted to a <see cref="MessageMetadata"/> using the standard Slack JSON conventions.</remarks>
public object MetadataObject { get; set; }
}
Loading