Skip to content

Commit

Permalink
Add E2E tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vKito committed Mar 3, 2023
1 parent 1f92b83 commit cee289a
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 2 deletions.
28 changes: 28 additions & 0 deletions App.Test/App.Test.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>

<ItemGroup>
<Compile Include="Check.fs" />
<Compile Include="ScrutinyStateMachine.fs" />
<Compile Include="Main.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Update="FSharp.Core" Version="7.0.0" />
<PackageReference Include="DEdge.Diffract" Version="0.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Microsoft.Playwright" Version="1.31.1" />
<PackageReference Include="Scrutiny" Version="2.0.0" />
<PackageReference Include="Unquote" Version="6.1.0" />
<PackageReference Include="xunit.core" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
39 changes: 39 additions & 0 deletions App.Test/Check.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[<Microsoft.FSharp.Core.AutoOpen>]
module App.Test.Check

open System
open Microsoft.FSharp.Quotations.Patterns
open Swensen.Unquote

let testWithReason expression reason =
try
Assertions.test expression
with e ->
let diff =
match expression with
| Call(_, methodInfo, [ a; b ]) when methodInfo.Name = "op_Equality" ->
let a = a.Eval()
let b = b.Eval()

let diffMethod =
typeof<DEdge.Diffract.Differ>
.GetMethod(nameof DEdge.Diffract.Differ.Diff)
.MakeGenericMethod [| a.GetType() |]

let diff: DEdge.Diffract.Diff option =
downcast diffMethod.Invoke(null, [| b; a; null |])

let diffString = DEdge.Diffract.Differ.ToString diff
$"\nDiff =\n{diffString}"
| _ -> String.Empty

raise (
Exception(
reason
+ diff
+ "\n----------------------------\nUnquote Message:\n"
+ e.Message
)
)

let test expression = testWithReason expression String.Empty
97 changes: 97 additions & 0 deletions App.Test/Main.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
module App.Test.Main

open System
open Microsoft.Playwright
open Scrutiny
open Xunit
open Xunit.Abstractions

// https://blog.ploeh.dk/2014/03/21/composed-assertions-with-unquote/

type PlaywrightTests(outputHelper: ITestOutputHelper) =
do
Microsoft.Playwright.Program.Main([| "install" |])
|> ignore

let logger msg = outputHelper.WriteLine(msg)
let playwright = Playwright.CreateAsync().GetAwaiter().GetResult()

[<Fact>]
member this.``Loads home page``() = task {
let launchOptions = BrowserTypeLaunchOptions()
launchOptions.Headless <- false

let! browser = playwright.Firefox.LaunchAsync(launchOptions)
let! context = browser.NewContextAsync(BrowserNewContextOptions(IgnoreHTTPSErrors = true))

let! page = context.NewPageAsync()

let! _ = page.GotoAsync("http://localhost:5173/SubtleConduit/")

let header = page.GetByRole(AriaRole.Heading)
let! text = header.First.InnerTextAsync()

test <@ text = "conduit" @>

do!
page
.GetByTestId("feedItems")
.Locator("li")
.Nth(0)
.WaitForAsync()

let! postCount =
page
.GetByTestId("feedItems")
.Locator("li")
.CountAsync()

test <@ postCount > 1 @>

do!
page
.GetByTestId("tags")
.Locator("li")
.Nth(0)
.WaitForAsync()

let! tagCount =
page
.GetByTestId("tags")
.Locator("li")
.CountAsync()

test <@ tagCount > 1 @>
}

[<Fact>]
member this.``Run Scrutiny Test``() = task {
let isHeadless = Environment.GetEnvironmentVariable("CI") = "true"

let launchOptions = BrowserTypeLaunchOptions()
launchOptions.Headless <- isHeadless
//launchOptions.SlowMo <- 500f

let! browser = playwright.Firefox.LaunchAsync(launchOptions)
let! context = browser.NewContextAsync(BrowserNewContextOptions(IgnoreHTTPSErrors = true))

let! page = context.NewPageAsync()

let! _ = page.GotoAsync("http://localhost:5173/SubtleConduit/")

let config =
{ ScrutinyConfig.Default with
Seed = 553931187
MapOnly = false
ComprehensiveActions = true
ComprehensiveStates = true
}

let! result = scrutinize config (GlobalState(page, logger)) ScrutinyStateMachine.home
// Assert.True(result.Steps |> Seq.length >= 5)
// Assert.Equal(5, result.Graph.Length)
test <@ 1 = 2 @>
}

interface IDisposable with
member this.Dispose() = playwright.Dispose()
62 changes: 62 additions & 0 deletions App.Test/ScrutinyStateMachine.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace App.Test

open Microsoft.Playwright
open Scrutiny

type GlobalState(page: IPage, logger: string -> unit) =
member val Logger = logger
member val Page = page

member x.GetInputValueAsync(selector: string) = task {
let! element = x.Page.QuerySelectorAsync(selector)
let! value = element.EvaluateAsync("e => e.value")
return value.ToString()
}


module rec ScrutinyStateMachine =
let home =
fun (gs: GlobalState) -> page {
name "Home"

onEnter (fun _ -> task {
let header = gs.Page.GetByRole(AriaRole.Heading)
let! text = header.First.InnerTextAsync()

test <@ text = "conduit" @>

do!
gs
.Page
.GetByTestId("feedItems")
.Locator("li")
.Nth(0)
.WaitForAsync()

let! postCount =
gs
.Page
.GetByTestId("feedItems")
.Locator("li")
.CountAsync()

test <@ postCount > 1 @>

do!
gs
.Page
.GetByTestId("tags")
.Locator("li")
.Nth(0)
.WaitForAsync()

let! tagCount =
gs
.Page
.GetByTestId("tags")
.Locator("li")
.CountAsync()

test <@ tagCount > 1 @>
})
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ An attempt at building a [RealWorld](https://github.com/gothinkster/realworld) a

## View the live demo here

<a href="https://cubeofshame.codeberg.page/SubtleConduit/" target="_blank">https://cubeofshame.codeberg.page/SubtleConduit/</a>
<a href="https://cubeofshame.codeberg.page/SubtleConduit/" target="_blank">https://cubeofshame.codeberg.page/SubtleConduit/ </a>

---

Expand Down Expand Up @@ -46,4 +46,4 @@ To build for prod:
* [ ] Error handling within the application itself
* [ ] Commenting system
* [ ] Icons for header menu items when logged in
* [ ] Routing (URL) is all sorts of janky
* [ ] Routing (URL) is all sorts of janky
17 changes: 17 additions & 0 deletions SubtleConduit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3476A04E-BDC
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "App", "src\App\App.fsproj", "{5B5D02DC-736D-4AFD-92DC-9EB7941269DC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EC0CC3D2-1CA3-4253-9993-8CE368FA1831}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "App.Test", "App.Test\App.Test.fsproj", "{10CF5879-3FF1-4392-A7D9-354977FF4376}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -32,8 +36,21 @@ Global
{5B5D02DC-736D-4AFD-92DC-9EB7941269DC}.Release|x64.Build.0 = Release|Any CPU
{5B5D02DC-736D-4AFD-92DC-9EB7941269DC}.Release|x86.ActiveCfg = Release|Any CPU
{5B5D02DC-736D-4AFD-92DC-9EB7941269DC}.Release|x86.Build.0 = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|x64.ActiveCfg = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|x64.Build.0 = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|x86.ActiveCfg = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Debug|x86.Build.0 = Debug|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|Any CPU.Build.0 = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|x64.ActiveCfg = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|x64.Build.0 = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|x86.ActiveCfg = Release|Any CPU
{10CF5879-3FF1-4392-A7D9-354977FF4376}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5B5D02DC-736D-4AFD-92DC-9EB7941269DC} = {3476A04E-BDC6-4DC0-8D86-C2AFECA621B0}
{10CF5879-3FF1-4392-A7D9-354977FF4376} = {EC0CC3D2-1CA3-4253-9993-8CE368FA1831}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions src/App/Components/Feed/FeedItems.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ let FeedItems dispatch articles favoriteArticle setArticleFilter =

let view =
Html.ul [
Attr.testId "feedItems"
Bind.el (
articles,
function
Expand Down
1 change: 1 addition & 0 deletions src/App/Components/Tags/Tags.fs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let Tags (articleFilter: ArticleApi.ArticleFilter option) (setArticleFilter: Art
]
Html.div [
Html.ul [
Attr.testId "tags"
Bind.el (
tags,
(function
Expand Down

0 comments on commit cee289a

Please sign in to comment.