Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more tests #17

Merged
merged 1 commit into from
Jun 14, 2024
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Tests
module BaseTests

open System
open System.Net.Http
Expand All @@ -8,10 +8,10 @@ open VahterBanBot.Tests.ContainerTestBase
open Xunit
open Xunit.Extensions.AssemblyFixture

type Tests(containers: VahterTestContainers) =
type BaseTests(fixture: VahterTestContainers) =
[<Fact>]
let ``Random path returns OK`` () = task {
let! resp = containers.Http.GetAsync("/" + Guid.NewGuid().ToString())
let! resp = fixture.Http.GetAsync("/" + Guid.NewGuid().ToString())
let! body = resp.Content.ReadAsStringAsync()
Assert.Equal(System.Net.HttpStatusCode.OK, resp.StatusCode)
Assert.Equal("OK", body)
Expand All @@ -21,14 +21,14 @@ type Tests(containers: VahterTestContainers) =
let ``Not possible to interact with the bot without authorization`` () = task {
let http = new HttpClient()
let content = new StringContent("""{"update_id":123}""", Encoding.UTF8, "application/json")
let uri = containers.Uri.ToString() + "bot"
let uri = fixture.Uri.ToString() + "bot"
let! resp = http.PostAsync(uri, content)
Assert.Equal(System.Net.HttpStatusCode.Unauthorized, resp.StatusCode)
}

[<Fact>]
let ``Should be possible to interact with the bot`` () = task {
let! resp = Update(Id = 123) |> containers.SendMessage
let! resp = Update(Id = 123) |> fixture.SendMessage
let! body = resp.Content.ReadAsStringAsync()
Assert.Equal(System.Net.HttpStatusCode.OK, resp.StatusCode)
Assert.Equal("null", body)
Expand Down
27 changes: 26 additions & 1 deletion src/VahterBanBot.Tests/ContainerTestBase.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@ open DotNet.Testcontainers.Builders
open DotNet.Testcontainers.Configurations
open DotNet.Testcontainers.Containers
open Newtonsoft.Json
open Npgsql
open Telegram.Bot.Types
open Testcontainers.PostgreSql
open VahterBanBot.Tests.TgMessageUtils
open Xunit
open Dapper

type VahterTestContainers() =
let solutionDir = CommonDirectoryPath.GetSolutionDirectory()
let dbAlias = "vahter-db"
let internalConnectionString = $"Server={dbAlias};Database=vahter_bot_ban;Port=5432;User Id=vahter_bot_ban_service;Password=vahter_bot_ban_service;Include Error Detail=true;Minimum Pool Size=1;Maximum Pool Size=20;Max Auto Prepare=100;Auto Prepare Min Usages=1;Trust Server Certificate=true;"
let pgImage = "postgres:15.6" // same as in Azure

// will be filled in IAsyncLifetime.InitializeAsync
let mutable uri: Uri = null
let mutable httpClient: HttpClient = null
let mutable publicConnectionString: string = null

// base image for the app, we'll build exactly how we build it in Azure
let image =
Expand Down Expand Up @@ -76,7 +81,7 @@ type VahterTestContainers() =
.WithEnvironment("SHOULD_DELETE_CHANNEL_MESSAGES", "true")
.WithEnvironment("IGNORE_SIDE_EFFECTS", "false")
.WithEnvironment("USE_POLLING", "false")
.WithEnvironment("DATABASE_URL", $"Server={dbAlias};Database=vahter_bot_ban;Port=5432;User Id=vahter_bot_ban_service;Password=vahter_bot_ban_service;Include Error Detail=true;Minimum Pool Size=1;Maximum Pool Size=20;Max Auto Prepare=100;Auto Prepare Min Usages=1;Trust Server Certificate=true;")
.WithEnvironment("DATABASE_URL", internalConnectionString)
.DependsOn(flywayContainer)
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(80))
.Build()
Expand All @@ -90,6 +95,7 @@ type VahterTestContainers() =
// wait for both to finish
do! imageTask
do! dbTask
publicConnectionString <- $"Server=127.0.0.1;Database=vahter_bot_ban;Port={dbContainer.GetMappedPublicPort(5432)};User Id=vahter_bot_ban_service;Password=vahter_bot_ban_service;Include Error Detail=true;Minimum Pool Size=1;Maximum Pool Size=20;Max Auto Prepare=100;Auto Prepare Min Usages=1;Trust Server Certificate=true;"

// initialize DB with the schema, database and a DB user
let script = File.ReadAllText(CommonDirectoryPath.GetSolutionDirectory().DirectoryPath + "/init.sql")
Expand Down Expand Up @@ -135,3 +141,22 @@ type VahterTestContainers() =
let! resp = httpClient.PostAsync("/bot", content)
return resp
}

member _.AdminUsers = [
Tg.user(id = 34, username = "vahter_1")
Tg.user(id = 69, username = "vahter_2")
]

member _.LogChat = Tg.chat(id = -123, username = "logs")
member _.ChatsToMonitor = [
Tg.chat(id = -666, username = "pro.hell")
Tg.chat(id = -42, username = "dotnetru")
]

member _.MessageExist(msg: Message) = task {
use conn = new NpgsqlConnection(publicConnectionString)
//language=postgresql
let sql = "SELECT COUNT(*) FROM message WHERE chat_id = @chatId AND message_id = @messageId"
let! count = conn.QuerySingleAsync<int>(sql, {| chatId = msg.Chat.Id; messageId = msg.MessageId |})
return count = 1
}
46 changes: 46 additions & 0 deletions src/VahterBanBot.Tests/PingTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module PingTests

open System.Net
open VahterBanBot.Tests.ContainerTestBase
open VahterBanBot.Tests.TgMessageUtils
open Xunit
open Xunit.Extensions.AssemblyFixture

type PingTests(fixture: VahterTestContainers) =
[<Fact>]
let ``Message got recorded`` () = task {
// chat from the allowed list
let msg = Tg.quickMsg(chat = fixture.ChatsToMonitor[0])

// assert that the message is not in the db
let! msgExist = fixture.MessageExist msg.Message
Assert.False msgExist

// send the message to the bot
let! resp = fixture.SendMessage msg
Assert.Equal(HttpStatusCode.OK, resp.StatusCode)

// assert that the message is in the db
let! msgExist = fixture.MessageExist msg.Message
Assert.True msgExist
}

[<Fact>]
let ``Message not recorded if chat is not on the list`` () = task {
// some random chat
let msg = Tg.quickMsg(chat = Tg.chat())

// assert that the message is not in the db
let! msgExist = fixture.MessageExist msg.Message
Assert.False msgExist

// send the message to the bot
let! resp = fixture.SendMessage msg
Assert.Equal(HttpStatusCode.OK, resp.StatusCode)

// assert that the message is still not in the db
let! msgExist = fixture.MessageExist msg.Message
Assert.False msgExist
}

interface IAssemblyFixture<VahterTestContainers>
30 changes: 30 additions & 0 deletions src/VahterBanBot.Tests/TgMessageUtils.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module VahterBanBot.Tests.TgMessageUtils

open System
open Telegram.Bot.Types

type Tg() =
static let rnd = Random.Shared
static member user (?id: int64, ?username: string, ?firstName: string) =
User(
Id = (id |> Option.defaultValue (rnd.NextInt64())),
Username = (username |> Option.defaultValue null),
FirstName = (firstName |> Option.defaultWith (fun () -> Guid.NewGuid().ToString()))
)
static member chat (?id: int64, ?username: string) =
Chat(
Id = (id |> Option.defaultValue (rnd.NextInt64())),
Username = (username |> Option.defaultValue null)
)
static member quickMsg (?text: string, ?chat: Chat, ?from: User, ?date: DateTime) =
Update(
Id = rnd.Next(),
Message =
Message(
MessageId = rnd.Next(),
Text = (text |> Option.defaultValue (Guid.NewGuid().ToString())),
Chat = (chat |> Option.defaultValue (Tg.chat())),
From = (from |> Option.defaultValue (Tg.user())),
Date = (date |> Option.defaultValue DateTime.UtcNow)
)
)
4 changes: 3 additions & 1 deletion src/VahterBanBot.Tests/VahterBanBot.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="TgMessageUtils.fs" />
<Compile Include="ContainerTestBase.fs" />
<Compile Include="Tests.fs"/>
<Compile Include="BaseTests.fs" />
<Compile Include="PingTests.fs" />
<Compile Include="Program.fs"/>
</ItemGroup>

Expand Down
8 changes: 6 additions & 2 deletions src/VahterBanBot/Bot.fs
Original file line number Diff line number Diff line change
Expand Up @@ -406,14 +406,18 @@
(botClient: ITelegramBotClient)
(botConfig: BotConfiguration)
(logger: ILogger)
(message: Message) = task {

Check warning on line 409 in src/VahterBanBot/Bot.fs

View workflow job for this annotation

GitHub Actions / build

This state machine is not statically compilable. A resumable code invocation at '(451,8--451,43)' could not be reduced. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning.

use banOnReplyActivity = botActivity.StartActivity("onUpdate")

// early return if if we can't process it
// early return if we can't process it
if isNull message || isNull message.From then
logger.LogWarning "Received update without message"
else

// early return if we don't monitor this chat
if not (botConfig.ChatsToMonitor.ContainsValue message.Chat.Id) then
()
else

%banOnReplyActivity
.SetTag("chatId", message.Chat.Id)
Expand Down
Loading