ProjectLighthouse/ProjectLighthouse.Tests.GameApiTests/Unit/Controllers/MessageControllerTests.cs
sudokoko aea66b4a74
Implement in-game and website notifications (#932)
* Implement notifications logic, basic calls, and admin command

* Remove unnecessary code

* Add ability to stack notifications and return manually created XML

* Remove test that is no longer needed and is causing failures

* Apply suggestions from code review

* Merge notifications with existing announcements page

* Order notifications by descending ID instead of ascending ID

* Move notification send task to moderation options under user

Also restyles the buttons to line up next to each other like in the slot pages.

* Style/position fixes with granted slots/notification partials

* Fix incorrect form POST route

* Prevent notification text area from breaking out of container

* Actually use builder result for notification text

* Minor restructuring of the notifications page

* Add notifications for team picks, publish issues, and moderation

* Mark notifications as dismissed instead of deleting them

* Add XMLdoc to SendNotification method

* Fix incorrect URL in announcements webhook

* Remove unnecessary inline style from granted slots partial

* Apply suggestions from code review

* Apply first batch of suggestions from code review

* Apply second batch of suggestions from code review

* Change notification icon depending on if user has unread notifications

* Show unread notification icon if there is an announcement posted

* Remove "potential" wording from definitive fixes in error docs

* Remove "Error code:" from publish notifications

* Send notification if user tries to unlock a mod-locked level

* Change notification timestamp format to include date

* Add clarification to level mod-lock notification message

* Change team pick notifications to moderation notifications

Apparently the MMPick type doesn't show a visual notification.

* Apply suggestions from code review

* Add obsolete to notification types that display nothing in-game

* Remove unused imports and remove icon switch case in favor of bell icon

* Last minute fixes

* Send notification upon earth wipe and clarify moderation case notifications

* Add check for empty/too long notification text
2023-10-29 20:27:41 +00:00

281 lines
No EOL
10 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Mail;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Mail;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class MessageControllerTests
{
[Fact]
public void Eula_ShouldReturnLicense_WhenConfigEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\n";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public void Eula_ShouldReturnLicenseAndConfigString_WhenConfigNotEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "unit test eula text";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\nunit test eula text";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public async Task Announcement_WithVariables_ShouldBeResolved()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "you are now logged in as %user (id: %id)";
const string expected = "you are now logged in as unittest (id: 1)";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Announcement_WithEmptyString_ShouldBeEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "";
const string expected = "";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Filter_ShouldNotCensor_WhenCensorDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
const string expectedBody = "unit test message";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
[Fact]
public async Task Filter_ShouldCensor_WhenCensorEnabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message bruh";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"bruh",
};
const string expectedBody = "unit test message ****";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
private static Mock<IMailService> getMailServiceMock()
{
Mock<IMailService> mailMock = new();
mailMock.Setup(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true));
return mailMock;
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = false;
CensorConfiguration.Instance.FilteredWordList = new List<string>();
const string expected = "/setemail unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, filteredMessage);
}
[Fact]
public async Task Filter_ShouldSendEmail_WhenMailEnabled_AndEmailNotTaken()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
const string expectedEmail = "unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
Assert.Equal(expectedEmail, dbMock.Users.First().EmailAddress);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailTaken()
{
List<UserEntity> users = new()
{
MockHelper.GetUnitTestUser(),
new UserEntity
{
UserId = 2,
EmailAddress = "unittest@unittest.com",
EmailAddressVerified = false,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(users);
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailAlreadyVerified()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity>
{
unitTestUser,
});
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailFormatInvalid()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity>
{
unitTestUser,
});
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittestinvalidemail@@@";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
}