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
9 changes: 8 additions & 1 deletion .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
---
version: v1.0.0
version: v1.1.0
changelog:
- date: 2025-10-29
version: v1.1.0
changes:
- type: feature
text: "Added the option of performing reversible soft deletion on Channel and User entities."
- type: feature
text: "Added a MutedUsersManager class that allows for muting specific user IDs on client side."
- date: 2025-10-02
version: v1.0.0
changes:
Expand Down
32 changes: 30 additions & 2 deletions c-sharp-chat/PubnubChatApi/PubNubChatApi.Tests/ChannelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public async Task TestUpdateChannel()
}

[Test]
public async Task TestDeleteChannel()
public async Task TestHardDeleteChannel()
{
var channel = TestUtils.AssertOperation(await chat.CreatePublicConversation());

Expand All @@ -75,14 +75,42 @@ public async Task TestDeleteChannel()
var channelExists = await chat.GetChannel(channel.Id);
Assert.False(channelExists.Error, "Couldn't fetch created channel from chat");

await channel.Delete();
await channel.Delete(false);

await Task.Delay(3000);

var channelAfterDelete = await chat.GetChannel(channel.Id);
Assert.True(channelAfterDelete.Error, "Fetched the supposedly-deleted channel from chat");
}

[Test]
public async Task TestSoftDeleteAndRestoreChannel()
{
var channel = TestUtils.AssertOperation(await chat.CreatePublicConversation());

await Task.Delay(3000);

var channelExists = await chat.GetChannel(channel.Id);
Assert.False(channelExists.Error, "Couldn't fetch created channel from chat");

await channel.Delete(true);

await Task.Delay(3000);

var channelAfterDelete = await chat.GetChannel(channel.Id);
Assert.False(channelAfterDelete.Error, "Channel should still exist after soft-delete");
Assert.True(channelAfterDelete.Result.IsDeleted, "Channel should be marked as soft-deleted");

await channelAfterDelete.Result.Restore();
Assert.False(channelAfterDelete.Result.IsDeleted, "Channel should be restored");

await Task.Delay(3000);

var channelAfterRestore = await chat.GetChannel(channel.Id);
Assert.False(channelAfterRestore.Error, "Channel should still exist after restore");
Assert.False(channelAfterRestore.Result.IsDeleted, "Channel fetched from server again should be marked as not-deleted after restore");
}

[Test]
public async Task TestLeaveChannel()
{
Expand Down
21 changes: 15 additions & 6 deletions c-sharp-chat/PubnubChatApi/PubNubChatApi.Tests/ChatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public async Task TestCreateDirectConversation()
directConversation.InviteesMemberships.First().UserId == convoUser.Id);

//Cleanup
await directConversation.CreatedChannel.Delete();
await directConversation.CreatedChannel.Delete(false);
}

[Test]
Expand All @@ -126,7 +126,7 @@ public async Task TestCreateGroupConversation()
x.UserId == convoUser1.Id && x.ChannelId == id));

//Cleanup
await groupConversation.CreatedChannel.Delete();
await groupConversation.CreatedChannel.Delete(false);
}

[Test]
Expand Down Expand Up @@ -172,11 +172,20 @@ public async Task TestEmitEvent()
[Test]
public async Task TestGetUnreadMessagesCounts()
{
await channel.SendText("wololo");
var testChannel = TestUtils.AssertOperation(await chat.CreatePublicConversation());
await testChannel.Join();
await testChannel.SendText("wololo");
await testChannel.SendText("wololo1");
await testChannel.SendText("wololo2");
await testChannel.SendText("wololo3");

await Task.Delay(3000);
await Task.Delay(6000);

var unreads =
TestUtils.AssertOperation(await chat.GetUnreadMessagesCounts(filter:$"channel.id LIKE \"{testChannel.Id}\""));
Assert.True(unreads.Any(x => x.ChannelId == testChannel.Id && x.Count == 4));

Assert.True(TestUtils.AssertOperation(await chat.GetUnreadMessagesCounts(limit: 50)).Any(x => x.ChannelId == channel.Id && x.Count > 0));
await testChannel.Delete(false);
}

[Test]
Expand All @@ -200,7 +209,7 @@ public async Task TestMarkAllMessagesAsRead()
var counts = TestUtils.AssertOperation(await chat.GetUnreadMessagesCounts());

markTestChannel.Leave();
await markTestChannel.Delete();
await markTestChannel.Delete(false);

Assert.False(counts.Any(x => x.ChannelId == markTestChannel.Id && x.Count > 0));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;

namespace PubNubChatApi.Tests;

public class ClientSideMuteTests
{
private Chat chat1;
private User user1;

private Chat chat2;
private User user2;

private Channel channel1;
private Channel channel2;

[SetUp]
public async Task Setup()
{
chat1 = TestUtils.AssertOperation(await Chat.CreateInstance(new PubnubChatConfig(),
new PNConfiguration(new UserId("client_side_mute_test_user_1"))
{
PublishKey = PubnubTestsParameters.PublishKey,
SubscribeKey = PubnubTestsParameters.SubscribeKey
}));
chat2 = TestUtils.AssertOperation(await Chat.CreateInstance(new PubnubChatConfig(),
new PNConfiguration(new UserId("client_side_mute_test_user_2"))
{
PublishKey = PubnubTestsParameters.PublishKey,
SubscribeKey = PubnubTestsParameters.SubscribeKey
}));
user1 = TestUtils.AssertOperation(await chat1.GetCurrentUser());
user2 = TestUtils.AssertOperation(await chat2.GetCurrentUser());
channel1 = TestUtils.AssertOperation(await chat1.CreatePublicConversation("mute_tests_channel"));
await Task.Delay(3000);
channel2 = TestUtils.AssertOperation(await chat2.GetChannel("mute_tests_channel"));
}

[TearDown]
public async Task CleanUp()
{
await channel1.Leave();
await channel2.Leave();
await user1.DeleteUser(false);
chat1.Destroy();
await user2.DeleteUser(false);
chat2.Destroy();
await channel1.Delete(false);
await channel2.Delete(false);
await Task.Delay(4000);
}

[Test]
public async Task TestMuteInMessages()
{
var messageReset = new ManualResetEvent(false);
channel1.OnMessageReceived += message =>
{
messageReset.Set();
};
await channel1.Join();

await Task.Delay(3000);

await channel2.SendText("This message should not be muted.");
var received = messageReset.WaitOne(10000);
Assert.True(received, "Didn't receive message from not-yet-muted user.");

messageReset = new ManualResetEvent(false);
await chat1.MutedUsersManager.MuteUser(user2.Id);
await channel2.SendText("This message should be muted.");
received = messageReset.WaitOne(10000);
Assert.False(received, "Received message from muted user.");

messageReset = new ManualResetEvent(false);
await chat1.MutedUsersManager.UnMuteUser(user2.Id);
await channel2.SendText("This message shouldn't be muted now.");
received = messageReset.WaitOne(10000);
Assert.True(received, "Didn't receive message from un-muted user.");
}

[Test]
public async Task TestMuteInMessageHistory()
{
await channel2.SendText("One");
await channel2.SendText("Two");
await channel2.SendText("Three");

await Task.Delay(6000);

var history = TestUtils.AssertOperation(await channel1.GetMessageHistory("99999999999999999", "00000000000000000", 3));
Assert.True(history.Count == 3, "Didn't get message history for non-muted user");

await chat1.MutedUsersManager.MuteUser(user2.Id);

history = TestUtils.AssertOperation(await channel1.GetMessageHistory("99999999999999999", "00000000000000000", 3));
Assert.True(history.Count == 0, "Got message history for muted user");

await chat1.MutedUsersManager.UnMuteUser(user2.Id);

history = TestUtils.AssertOperation(await channel1.GetMessageHistory("99999999999999999", "00000000000000000", 3));
Assert.True(history.Count == 3, "Didn't get message history for un-muted user");
}

[Test]
public async Task TestMuteInEvents()
{
var eventReset = new ManualResetEvent(false);
channel1.OnCustomEvent += chatEvent =>
{
if (chatEvent.Type != PubnubChatEventType.Custom)
{
return;
}
eventReset.Set();
};
channel1.SetListeningForCustomEvents(true);

await Task.Delay(3000);

await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"not-muted\"}");
var received = eventReset.WaitOne(10000);
Assert.True(received, "Didn't receive event from not-yet-muted user.");

eventReset = new ManualResetEvent(false);
await chat1.MutedUsersManager.MuteUser(user2.Id);
await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"muted\"}");
received = eventReset.WaitOne(10000);
Assert.False(received, "Received event from muted user.");

eventReset = new ManualResetEvent(false);
await chat1.MutedUsersManager.UnMuteUser(user2.Id);
await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"un-muted\"}");
received = eventReset.WaitOne(10000);
Assert.True(received, "Didn't receive event from un-muted user.");
}

[Test]
public async Task TestMuteInEventsHistory()
{
await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"one\"}");
await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"two\"}");
await chat2.EmitEvent(PubnubChatEventType.Custom, channel2.Id, "{\"test\":\"three\"}");

var history = TestUtils.AssertOperation(await chat1.GetEventsHistory(channel1.Id,"99999999999999999", "00000000000000000", 3));
Assert.True(history.Events.Count == 3, "Didn't get events history for non-muted user");

await chat1.MutedUsersManager.MuteUser(user2.Id);

history = TestUtils.AssertOperation(await chat1.GetEventsHistory(channel1.Id,"99999999999999999", "00000000000000000", 3));
Assert.True(history.Events.Count == 0, "Got events history for muted user");

await chat1.MutedUsersManager.UnMuteUser(user2.Id);

history = TestUtils.AssertOperation(await chat1.GetEventsHistory(channel1.Id,"99999999999999999", "00000000000000000", 3));
Assert.True(history.Events.Count == 3, "Didn't get events history for un-muted user");
}

[Test]
public async Task TestMuteListSyncing()
{
var userId = Guid.NewGuid().ToString();
var chatWithSync = TestUtils.AssertOperation(await Chat.CreateInstance(new PubnubChatConfig(syncMutedUsers:true),
new PNConfiguration(new UserId(userId))
{
PublishKey = PubnubTestsParameters.PublishKey,
SubscribeKey = PubnubTestsParameters.SubscribeKey
}));
TestUtils.AssertOperation(await chatWithSync.MutedUsersManager.MuteUser(user1.Id));

chatWithSync.Destroy();

await Task.Delay(3000);
var chatWithSyncSecondInstance = TestUtils.AssertOperation(await Chat.CreateInstance(new PubnubChatConfig(syncMutedUsers:true),
new PNConfiguration(new UserId(userId))
{
PublishKey = PubnubTestsParameters.PublishKey,
SubscribeKey = PubnubTestsParameters.SubscribeKey
}));
await Task.Delay(5000);
Assert.True(chatWithSyncSecondInstance.MutedUsersManager.MutedUsers.Contains(user1.Id), "Second instance of chat didn't have synced mute list");

chatWithSyncSecondInstance.Destroy();
await chatWithSyncSecondInstance.DeleteUser(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public async Task TestDeleteMessage()
var manualReceivedEvent = new ManualResetEvent(false);
channel.OnMessageReceived += async message =>
{
message.Delete(true);
await message.Delete(true);

await Task.Delay(2000);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public static class PubnubTestsParameters
private static readonly string EnvSubscribeKey = Environment.GetEnvironmentVariable("PN_SUB_KEY");
private static readonly string EnvSecretKey = Environment.GetEnvironmentVariable("PN_SEC_KEY");

public static readonly string PublishKey = string.IsNullOrEmpty(EnvPublishKey) ? "pub-c-79c582a2-d7a4-4ee7-9f28-7a6f1b7fa11c" : EnvPublishKey;
public static readonly string SubscribeKey = string.IsNullOrEmpty(EnvSubscribeKey) ? "sub-c-ca0af928-f4f9-474c-b56e-d6be81bf8ed0" : EnvSubscribeKey;
public static readonly string PublishKey = string.IsNullOrEmpty(EnvPublishKey) ? "demo-36" : EnvPublishKey;
public static readonly string SubscribeKey = string.IsNullOrEmpty(EnvSubscribeKey) ? "demo-36" : EnvSubscribeKey;
public static readonly string SecretKey = string.IsNullOrEmpty(EnvSecretKey) ? "demo-36" : EnvSecretKey;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public async Task CleanUp()
{
channel.Leave();
await Task.Delay(3000);
await channel.Delete();
await channel.Delete(false);
chat.Destroy();
await Task.Delay(3000);
}
Expand Down
34 changes: 31 additions & 3 deletions c-sharp-chat/PubnubChatApi/PubNubChatApi.Tests/UserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ await testUser.Update(new ChatUserData()
Assert.True(updated);

//Cleanup
await testUser.DeleteUser();
await testUser.DeleteUser(false);
}

[Test]
public async Task TestUserDelete()
public async Task TestHardUserDelete()
{
var someUser = TestUtils.AssertOperation(await chat.CreateUser(Guid.NewGuid().ToString()));

TestUtils.AssertOperation(await chat.GetUser(someUser.Id));

await someUser.DeleteUser();
await someUser.DeleteUser(false);

await Task.Delay(3000);

Expand All @@ -109,6 +109,34 @@ public async Task TestUserDelete()
Assert.Fail("Got the freshly deleted user");
}
}

[Test]
public async Task TestSoftDeleteAndRestoreUser()
{
var testUser = TestUtils.AssertOperation(await chat.CreateUser(Guid.NewGuid().ToString()));

await Task.Delay(3000);

var userExists = await chat.GetUser(testUser.Id);
Assert.False(userExists.Error, "Couldn't fetch created user from chat");

await testUser.DeleteUser(true);

await Task.Delay(3000);

var userAfterDelete = await chat.GetUser(testUser.Id);
Assert.False(userAfterDelete.Error, "User should still exist after soft-delete");
Assert.True(userAfterDelete.Result.IsDeleted, "user should be marked as soft-deleted");

await userAfterDelete.Result.Restore();
Assert.False(userAfterDelete.Result.IsDeleted, "User should be restored");

await Task.Delay(3000);

var userAfterRestore = await chat.GetUser(testUser.Id);
Assert.False(userAfterRestore.Error, "User should still exist after restore");
Assert.False(userAfterRestore.Result.IsDeleted, "User fetched from server again should be marked as not-deleted after restore");
}

[Test]
public async Task TestUserWherePresent()
Expand Down
Loading