squint 2025-05-01

hey squinters anyone used playwright with squint? my current issue is that playwright is giving me errors if i try this

(require '["@playwright/test" :refer [test expect]])

(test "has title"
      (^:async fn [{:keys [page]}]
       (js-await (page.goto ""))
       (js-await (-> (expect page)
                     (.toHaveTitle #"/MyTest/")))))
Playwright complains that the first argument of the generated function has to be destructured. So squint generates this
test("has title", (async function (p__3) {....
but playwright wants that
test("has title", (async function ({ page }) {
Any way to get this working with squint or do i have to fiddle that somehow :D

you can use ^:js to use js destructuring

❤️ 1

is there a way to create a macro for this piece of code something like (deftest name body)

i'm currently trying to get that somehow but i'm to dumb for macros i'm not that advanced yet 😄

can anyone explain what i'm doing wrong 😞

(defmacro deftest [name bound & body]
  `(test ~name
         (^:async fn [^:js {:keys [page]}]
          (let [~bound page]
            ~@body))))
test is a function that is defined in a node library

✅ 1

man now i get it why you should use macroexpand-1 😄 ok wrote my second real use macro thanx again @borkdude and i promise to not over use this stuff

🙌 1
🚀 2

SyntaxError: /home/metti/code/staryou/node/e2e-tests/tests/ex.spec.mjs: Unexpected reserved word 'await'. (11:1)

   9 | clojure.core.test(squint_core.str("2. has title"), (function ({macros_SLASH_page}) {
  10 | const _STAR_page_STAR_1 = macros.page;
> 11 | (await _STAR_page_STAR_1.goto(""));
     |  ^
  12 | return (await expect(_STAR_page_STAR_1).toHaveTitle(/StarYou/));
  13 | ;;;
  14 | }));

   at ex.spec.mjs:11

   9 | clojure.core.test(squint_core.str("2. has title"), (function ({macros_SLASH_page}) {
  10 | const _STAR_page_STAR_1 = macros.page;
> 11 | (await _STAR_page_STAR_1.goto(""));
     | ^
  12 | return (await expect(_STAR_page_STAR_1).toHaveTitle(/StarYou/));
  13 | ;;;
  14 | }));

Error: No tests found

and the funny part is why is it using clojure.core.test 😄

test is a clojure.core function

you probably want to do something like this:

(defmacro deftest [name bound & body]
  `(~'test ~name
    ((with-meta 'fn {:async true}) [~(with-meta '{:keys [page]} {:js true})]
     (let [~bound ~'page]
       ~@body))))
I think I might just switch to non-syntax-quote since you're basically fighting against auto-resolving here

Whats the wit-meta doing?

I guess i have to learn more about macros :/

when you want to generate a symbol that has metadata from a macro you have to do it that way

I just found the doc in the reader section interesting didn't know that. And non-syntax-quote means somthing like that (list test ~name ...) ?

Usually you want to use list* so the varargs flattened into the list

(list* 'test .... body)

Ah ok so i dont have to use ~@body right

Ok this was great thank you so much @borkdude

yay i did it but still not really a clue 😄 but it works that way

(defmacro deftest [name binding & body]
  (list 'test name
        (list 'fn [(with-meta '{:keys [page]} {:js true})]
              (let [binding 'page]
                (list 'Promise.all (into [] body))))))

nice, perhaps you forgot the async metadata on fn though?

the let expression also needs to be quoted

it would probably help if you just wrote this as a function and inspected the output yourself in a REPL

you can also print the metadata like this:

(binding [*print-meta* true] (pr-str expression))

combined with:

(def expression (macroexpand-1 '(deftest ....)))
you may get what's failing

here is a newer version

(defmacro deftest [name binding & body]
  (list 'test name
        (list (with-meta 'fn {:async true}) [(with-meta '{:keys [page]} {:js true})]
              (let [binding 'page]
                body
                nil))))
is there a more elegant way to skip the return?

you mean nrepl with squint and do a macroexpand-1 right

skip the return? what I mean is that you're not generating a let expression

you can do this in a normal Clojure REPL, squint's REPL doesn't support this probably

babashka / nbb do

do you use clj-kondo?

here you can see that the binding argument of the macro isn't used:

which may already give you a clue

so something like that right

(defmacro deftest [name binding & body]
  (list 'test name
        (list (with-meta 'fn {:async true}) [(with-meta '{:keys [page]} {:js true})]
              (list 'let (vector binding 'page)
                    (list* 'do body)))))
no 😄

now you compare this version with the syntax-quote and decide which one is worse :)

so thats how a playwright test would look now

(deftest "2. has title" page
  (js-await (.goto page ""))
  (js-await (-> page
                expect
                (.toHaveTitle #"Hello World"))))

👍 1

(test "3. has title"
      (^:async fn [^:js {:keys [page]}]
       (js-await (.goto page ""))
       (js-await (-> page
                     expect
                     (.toHaveTitle #"StarYou")))))