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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test": "vitest run"
"test": "vitest run --environment jsdom"
},
"dependencies": {
"solid-js": "^1.9.5"
Expand Down
20 changes: 4 additions & 16 deletions src/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ let viteLogo: string = importDefault "./assets/vite.svg"
let solidLogo: string = importDefault "./assets/solid.svg"


let Counter() : JSX.Element = import "Counter" "./components/Counter.fs"


[<JSX.Component>]
let App() =
let count, setCount = Solid.createSignal(0)
Expand Down Expand Up @@ -51,22 +54,7 @@ let App() =
]
]
Html.h1 "Vite + Solid + Feliz"
Html.div [
Attr.className "card"
Html.children [
Html.button [
Ev.onClick (fun _ -> setCount (count() + 1))
Html.children [
Html.text $"count is {count()}"
]
]
Html.div [
Html.text "Edit "
Html.code "src/App.fs"
Html.text " and save to test HMR"
]
]
]
Counter()
Html.p [
Attr.className "read-the-docs"
Html.children [
Expand Down
2 changes: 2 additions & 0 deletions src/App.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="./components/Counter.fs" />
<Compile Include="App.fs" />
<Compile Include="Testing.fs" />
<Compile Include="App.test.fs" />
<Compile Include="Index.fs" />
</ItemGroup>
Expand Down
107 changes: 1 addition & 106 deletions src/App.test.fs
Original file line number Diff line number Diff line change
@@ -1,112 +1,7 @@
namespace App

open Fable.Core.JsInterop
open Fable.Core
open Feliz.JSX.Solid

// https://vitest.dev/config/#environment
// https://docs.solidjs.com/guides/testing
// https://github.com/fable-compiler/Feliz.JSX
// https://fable.io/blog/2022/2022-10-18-fable-solid.html
// https://github.com/fable-compiler/Fable.Solid

// IMPORTANT! https://fable.io/docs/javascript/features.html

// as inspiration for types: https://github.com/Shmew/Fable.Jester/blob/master/src/Fable.Jester/Expect.fs

module Dom =
open Fable.Core.JsInterop
open Fable.Core

type IRenderResult =
abstract getByText: string -> obj
abstract getByRole: string -> obj

type DomEvent = {
click: obj -> unit
}

[<Import("render", from = "@solidjs/testing-library")>]
let render (fableComponent: obj) : IRenderResult = jsNative

[<Import("cleanup", from = "@solidjs/testing-library")>]
let cleanup(): unit = jsNative

[<Import("screen", from = "@solidjs/testing-library")>]
let screen: IRenderResult = jsNative

[<Import("fireEvent", from = "@solidjs/testing-library")>]
let fireEvent: DomEvent = jsNative

// for each Fable import try to match JS signature and try create
// correct types based on original typescript definitions but as F# types e.g. record types

module Vi =
type IMatcherResult =
abstract toBe: obj -> unit
abstract toEqual: obj -> unit
abstract toMatchObject: obj -> unit
abstract toHaveBeenCalled: unit -> unit
abstract toHaveBeenCalledWith: obj -> unit
abstract toHaveBeenCalledTimes: int -> unit
abstract toBeInTheDocument: unit -> unit
abstract toHaveTextContent: string -> unit
abstract toHaveClass: string -> unit
abstract toHaveStyle: string -> unit
abstract toHaveAttribute: string -> unit
abstract toHaveProperty: string -> unit
abstract toHaveValue: string -> unit
abstract toHaveFocus: unit -> unit
abstract toHaveFormValues: obj -> unit
abstract toHaveLength: int -> unit
abstract toBeDisabled: unit -> unit
abstract toBeEnabled: unit -> unit
abstract toBeVisible: unit -> unit
abstract toBeEmpty: unit -> unit
abstract toBeChecked: unit -> unit
abstract toBeSelected: unit -> unit
abstract toBeTruthy: unit -> unit
abstract toBeFalsy: unit -> unit
abstract toBeNull: unit -> unit
abstract toBeUndefined: unit -> unit
abstract toBeNaN: unit -> unit
abstract toBeGreaterThan: obj -> unit
abstract toBeLessThan: obj -> unit
abstract toBeGreaterThanOrEqual: obj -> unit
abstract toBeLessThanOrEqual: obj -> unit
abstract toBeCloseTo: obj -> unit

[<Import("expect", from = "vitest")>]
let expect(value: obj): IMatcherResult = jsNative

[<Import("toBeInTheDocument", from = "@testing-library/jest-dom/matchers")>]
let toBeInTheDocument: obj = jsNative

// Extension method for expect
[<Emit("$0.toBeInTheDocument()")>]
let inline expectToBeInTheDocument (value: obj): obj = jsNative

[<Import("beforeEach", from = "vitest")>]
let beforeEach(test: unit -> unit) = jsNative

[<Import("afterEach", from = "vitest")>]
let afterEach(test: unit -> unit) = jsNative

[<Import("beforeAll", from = "vitest")>]
let beforeAll(test: unit -> unit) = jsNative

[<Import("afterAll", from = "vitest")>]
let afterAll(test: unit -> unit) = jsNative

[<Import("it", from = "vitest")>]
let it(name: string, test: unit -> unit) = jsNative

[<Import("test", from = "vitest")>]
let test(name: string, test: unit -> unit) = jsNative

[<Import("describe", from = "vitest")>]
let describe(name: string, testSuite: unit -> unit) = jsNative

open Testing

module Test =

Expand Down
104 changes: 104 additions & 0 deletions src/Testing.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
namespace Testing

open Fable.Core

// https://vitest.dev/config/#environment
// https://docs.solidjs.com/guides/testing
// https://github.com/fable-compiler/Feliz.JSX
// https://fable.io/blog/2022/2022-10-18-fable-solid.html
// https://github.com/fable-compiler/Fable.Solid

// IMPORTANT! https://fable.io/docs/javascript/features.html

// as inspiration for types: https://github.com/Shmew/Fable.Jester/blob/master/src/Fable.Jester/Expect.fs

module Dom =

type IRenderResult =
abstract getByText: string -> obj
abstract getByRole: string -> obj

type DomEvent = {
click: obj -> unit
}

[<Import("render", from = "@solidjs/testing-library")>]
let render (fableComponent: obj) : IRenderResult = jsNative

[<Import("cleanup", from = "@solidjs/testing-library")>]
let cleanup(): unit = jsNative

[<Import("screen", from = "@solidjs/testing-library")>]
let screen: IRenderResult = jsNative

[<Import("fireEvent", from = "@solidjs/testing-library")>]
let fireEvent: DomEvent = jsNative

// for each Fable import try to match JS signature and try create
// correct types based on original typescript definitions but as F# types e.g. record types

module Vi =
type IMatcherResult =
abstract toBe: obj -> unit
abstract toEqual: obj -> unit
abstract toMatchObject: obj -> unit
abstract toHaveBeenCalled: unit -> unit
abstract toHaveBeenCalledWith: obj -> unit
abstract toHaveBeenCalledTimes: int -> unit
abstract toBeInTheDocument: unit -> unit
abstract toHaveTextContent: string -> unit
abstract toHaveClass: string -> unit
abstract toHaveStyle: string -> unit
abstract toHaveAttribute: string -> unit
abstract toHaveProperty: string -> unit
abstract toHaveValue: string -> unit
abstract toHaveFocus: unit -> unit
abstract toHaveFormValues: obj -> unit
abstract toHaveLength: int -> unit
abstract toBeDisabled: unit -> unit
abstract toBeEnabled: unit -> unit
abstract toBeVisible: unit -> unit
abstract toBeEmpty: unit -> unit
abstract toBeChecked: unit -> unit
abstract toBeSelected: unit -> unit
abstract toBeTruthy: unit -> unit
abstract toBeFalsy: unit -> unit
abstract toBeNull: unit -> unit
abstract toBeUndefined: unit -> unit
abstract toBeNaN: unit -> unit
abstract toBeGreaterThan: obj -> unit
abstract toBeLessThan: obj -> unit
abstract toBeGreaterThanOrEqual: obj -> unit
abstract toBeLessThanOrEqual: obj -> unit
abstract toBeCloseTo: obj -> unit

[<Import("expect", from = "vitest")>]
let expect(value: obj): IMatcherResult = jsNative

[<Import("toBeInTheDocument", from = "@testing-library/jest-dom/matchers")>]
let toBeInTheDocument: obj = jsNative

// Extension method for expect
[<Emit("$0.toBeInTheDocument()")>]
let inline expectToBeInTheDocument (value: obj): obj = jsNative

[<Import("beforeEach", from = "vitest")>]
let beforeEach(test: unit -> unit) = jsNative

[<Import("afterEach", from = "vitest")>]
let afterEach(test: unit -> unit) = jsNative

[<Import("beforeAll", from = "vitest")>]
let beforeAll(test: unit -> unit) = jsNative

[<Import("afterAll", from = "vitest")>]
let afterAll(test: unit -> unit) = jsNative

[<Import("it", from = "vitest")>]
let it(name: string, test: unit -> unit) = jsNative

[<Import("test", from = "vitest")>]
let test(name: string, test: unit -> unit) = jsNative

[<Import("describe", from = "vitest")>]
let describe(name: string, testSuite: unit -> unit) = jsNative
27 changes: 27 additions & 0 deletions src/components/Counter.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Componenents

open Feliz.JSX.Solid
open Fable.Core.JsInterop
open Fable.Core

[<JSX.Component>]
let Counter() =
let count, setCount = Solid.createSignal(0)

Html.div [
Attr.className "card"
Html.children [
Html.h2 "I am a counter from: Counter.fs"
Html.button [
Ev.onClick (fun _ -> setCount (count() + 1))
Html.children [
Html.text $"count is {count()}"
]
]
Html.div [
Html.text "Edit "
Html.code "src/components/Counter.fs"
Html.text " and save to test HMR"
]
]
]