Skip to content

Commit

Permalink
JS tests
Browse files Browse the repository at this point in the history
  • Loading branch information
blopker committed Nov 7, 2024
1 parent a3a73f3 commit 876582d
Show file tree
Hide file tree
Showing 11 changed files with 2,191 additions and 79 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ build-prod:
docker build -t totem-prod -f compose/production/django/Dockerfile .

test:
npm run test:ci
docker compose -f local.yml run --rm django coverage run -m pytest -n auto

tasks:
Expand Down
36 changes: 36 additions & 0 deletions assets/js/components/circles.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { test, expect } from "vitest"
import { render } from "@solidjs/testing-library"
import userEvent from "@testing-library/user-event"
import { MobileEvent } from "./circles"

const user = userEvent.setup()

test("increments value", async () => {
const result = render(() => (
<MobileEvent
event={{
space: {
title: "Test Space",
slug: "test-space",
date_created: "2023-01-01T00:00:00.000Z",
date_modified: "2023-01-01T00:00:00.000Z",
author: {
name: "Test User",
profile_avatar_type: "TD",
},
subtitle: "Test Subtitle",
},
url: "https://totem.org",
start: "2023-01-01T00:00:00.000Z",
slug: "test-event",
date_created: "2023-01-01T00:00:00.000Z",
date_modified: "2023-01-01T00:00:00.000Z",
title: "Test Event",
}}
/>
))
const html = result.container.innerHTML
expect(html).toContain("Test Space")
expect(html).toContain("Test Event")
expect(html).not.toContain("Invalid")
})
2 changes: 1 addition & 1 deletion assets/js/components/circles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ function Event(props: { event: EventListSchema }) {
)
}

function MobileEvent(props: { event: EventListSchema }) {
export function MobileEvent(props: { event: EventListSchema }) {
const start = () => {
const s = props.event.start
if (s) return timestampToTimeString(s)
Expand Down
6 changes: 3 additions & 3 deletions assets/js/components/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createSignal } from "solid-js"
import { useTippy } from "solid-tippy"
import { Content } from "tippy.js"
import { useTippy } from "@/libs/tippy"
import type { Content } from "tippy.js"
import "tippy.js/dist/tippy.css"
import "tippy.js/themes/light.css"

Expand All @@ -23,7 +23,7 @@ export function useTotemTip({ content }: { content: Content }) {
}

const Tooltip = (props: TooltipProps) => {
const setAnchor = () => useTotemTip({ content: props.text! })
const setAnchor = () => useTotemTip({ content: props.text ?? "" })
return (
// eslint-disable-next-line solid/no-innerhtml
<div class={props.class} ref={setAnchor()} innerHTML={props.children} />
Expand Down
188 changes: 188 additions & 0 deletions assets/js/libs/tippy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// from https://github.com/lxsmnsyc/solid-tippy
import {
createComputed,
createEffect,
createSignal,
onCleanup,
untrack,
} from "solid-js"
import makeTippy, { type Instance, type Props } from "tippy.js"
import makeHeadlessTippy from "tippy.js/headless"

export interface TippyOptions {
disabled?: boolean
hidden?: boolean
props?: Partial<Props>
}

export function tippy<T extends Element>(
target: T,
opts: () => TippyOptions | undefined
): void {
createEffect(() => {
const options = opts()
const instance = makeTippy(
target,
untrack(() => options?.props)
)

createComputed(() => {
if (options?.disabled) {
instance.disable()
} else {
instance.enable()
}
})

createComputed(() => {
if (options?.hidden) {
instance.hide()
} else {
instance.show()
}
})

createComputed(() => {
instance.setProps({
...(options?.props ?? {}),
})
})

onCleanup(() => {
instance.destroy()
})
})
}

export function tippyHeadless<T extends Element>(
target: T,
opts: () => TippyOptions | undefined
): void {
createEffect(() => {
const options = opts()
const instance = makeHeadlessTippy(
target,
untrack(() => options?.props)
)

createComputed(() => {
if (options?.disabled) {
instance.disable()
} else {
instance.enable()
}
})

createComputed(() => {
if (options?.hidden) {
instance.hide()
} else {
instance.show()
}
})

createComputed(() => {
instance.setProps({
...(options?.props ?? {}),
})
})

onCleanup(() => {
instance.destroy()
})
})
}

export function useTippy<T extends Element>(
target: () => T | undefined | null,
options?: TippyOptions
): () => Instance | undefined {
const [current, setCurrent] = createSignal<Instance>()

createEffect(() => {
const currentTarget = target()
if (currentTarget) {
const instance = makeTippy(
currentTarget,
untrack(() => options?.props)
)

setCurrent(instance)

createComputed(() => {
if (options?.disabled) {
instance.disable()
} else {
instance.enable()
}
})

createComputed(() => {
if (options?.hidden) {
instance.hide()
} else {
instance.show()
}
})

createComputed(() => {
instance.setProps({
...(options?.props ?? {}),
})
})

onCleanup(() => {
instance.destroy()
})
}
})

return () => current()
}

export function useTippyHeadless<T extends Element>(
target: () => T | undefined | null,
options?: TippyOptions
): () => Instance | undefined {
const [current, setCurrent] = createSignal<Instance>()

createEffect(() => {
const currentTarget = target()
if (currentTarget) {
const instance = makeHeadlessTippy(
currentTarget,
untrack(() => options?.props)
)

setCurrent(instance)

createComputed(() => {
if (options?.disabled) {
instance.disable()
} else {
instance.enable()
}
})

createComputed(() => {
if (options?.hidden) {
instance.hide()
} else {
instance.show()
}
})

createComputed(() => {
instance.setProps({
...(options?.props ?? {}),
})
})

onCleanup(() => {
instance.destroy()
})
}
})

return () => current()
}
10 changes: 5 additions & 5 deletions build.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/usr/bin/env node
import * as esbuild from "esbuild"
import { solidPlugin } from "esbuild-plugin-solid"
import fs from "fs"
import process from "process"
import fs from "node:fs"
import process from "node:process"

var arg = process.argv[2]
const arg = process.argv[2]

var options = {
const options = {
entryPoints: ["assets/js/app.js", "assets/js/social.ts"],
bundle: true,
minify: true,
Expand All @@ -32,7 +32,7 @@ if (arg === "watch") {
options.sourcemap = "inline"
options.minify = false
options.define["process.env.NODE_ENV"] = '"development"'
let ctx = await esbuild.context(options)
const ctx = await esbuild.context(options)
await ctx.watch()
} else {
const result = await esbuild.build(options)
Expand Down
Loading

0 comments on commit 876582d

Please sign in to comment.