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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies
run: npm i

- name: Run tests
run: npm run test
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Vite Feliz Solid ⚡️

![CI](https://github.com/jkone27/vite-feliz-solid/actions/workflows/ci.yml/badge.svg)

![vite feliz solid in action](image.png)

A template for writing your next [Solid-js](https://solidjs.com) app in [F#](https://dotnet.microsoft.com/en-us/languages/fsharp) with seamless [vite](https://vite.dev/guide/) integration.
Expand All @@ -17,11 +19,16 @@ Write your F# app using [Feliz.JSX.Solid](https://github.com/fable-compiler/Feli

```bash
> npm i
> npm run test
> npm run dev
```

Or use [bun](https://bun.sh/) it's blazing fast!

## How does this all work? 🐉

Thanks to the awesome [vite-plugin-fable](https://fable.io/vite-plugin-fable/), check it out and contribute or join [F# discord](https://discord.com/channels/196693847965696000/196695876054286336).
Thanks to the awesome [vite-plugin-fable](https://fable.io/vite-plugin-fable/), check it out and contribute or join [F# discord](https://discord.com/channels/196693847965696000/196695876054286336).

### Trick for vitest in solidjs

had to be aware of this [server inline trick](https://github.com/vitest-dev/vitest/discussions/6537) in [vitest.config.ts](./vitest.config.ts)
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"test": "vitest"
},
"dependencies": {
"solid-js": "^1.9.5"
},
"devDependencies": {
"@solidjs/testing-library": "^0.8.10",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/user-event": "^14.6.1",
"jsdom": "^26.0.0",
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add deps

"vite": "^6.2.0",
"vite-plugin-fable": "^0.0.36",
"vite-plugin-solid": "^2.11.2",
Expand Down
3 changes: 2 additions & 1 deletion src/App.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="App.fs" />
<Compile Include="App.test.fs" />
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add test file

<Compile Include="Index.fs" />
</ItemGroup>

Expand Down
132 changes: 132 additions & 0 deletions src/App.test.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
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

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dom (TestingLibrary) fable bindings

// 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
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vi (vitest) fable bindings



module Test =

Vi.describe("render app and increment count", fun () ->

Vi.afterAll(fun () ->
Dom.cleanup()
)

let element = Dom.render(App())

Vi.test("should render initial count", fun () ->
let countElement = element.getByText("count is 0")
Vi.expect(countElement).toBeInTheDocument()
)

Vi.test("should increment count on button click", fun () ->
let buttonElement = element.getByRole("button" )
Dom.fireEvent.click(buttonElement)
let updatedButtonElement = element.getByText("count is 1")
Vi.expect(updatedButtonElement).toBeInTheDocument()
)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actual test

)
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js"
"jsxImportSource": "solid-js",
"types": ["vite/client", "@testing-library/jest-dom"]
}
}
2 changes: 1 addition & 1 deletion vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export default defineConfig({
include: ["**/*.{test,spec}.{js,jsx,ts,tsx,fs}"],
exclude: [...configDefaults.exclude, "dist", ".idea", ".git", ".cache"],
environment: "jsdom",
setupFiles: "../vitest.ts",
transform: {
"^.+\\.fs$": "vite-plugin-fable",
},
conditions: ["development", "browser"]
},
});
15 changes: 15 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import solid from "vite-plugin-solid"
import { defineConfig } from "vitest/config"
import existingConfig from "./vite.config"

const createTestConfig = { ...existingConfig, resolve: {
conditions: ["development", "browser"],
test: {
server: {
deps: { inline: true }
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requitred for this to work in vscode ext

}
}
}
};

export default defineConfig(createTestConfig)
11 changes: 0 additions & 11 deletions vitest.ts

This file was deleted.