Skip to content

Commit

Permalink
more tests (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
Szer authored Jun 14, 2024
1 parent b10af81 commit 5cfecd6
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 9 deletions.
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 @@ -407,13 +407,17 @@ let onUpdate
(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 / deploy

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

0 comments on commit 5cfecd6

Please sign in to comment.