| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import { NodeFileSystem } from "@effect/platform-node"
- import { describe, expect } from "bun:test"
- import { Effect, Layer } from "effect"
- import { provideTmpdirInstance } from "../fixture/fixture"
- import { testEffect } from "../lib/effect"
- import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
- import { Format } from "../../src/format"
- import * as Formatter from "../../src/format/formatter"
- const it = testEffect(Layer.mergeAll(Format.defaultLayer, CrossSpawnSpawner.defaultLayer, NodeFileSystem.layer))
- describe("Format", () => {
- it.live("status() returns built-in formatters when no config overrides", () =>
- provideTmpdirInstance(() =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- const statuses = yield* fmt.status()
- expect(Array.isArray(statuses)).toBe(true)
- expect(statuses.length).toBeGreaterThan(0)
- for (const item of statuses) {
- expect(typeof item.name).toBe("string")
- expect(Array.isArray(item.extensions)).toBe(true)
- expect(typeof item.enabled).toBe("boolean")
- }
- const gofmt = statuses.find((item) => item.name === "gofmt")
- expect(gofmt).toBeDefined()
- expect(gofmt!.extensions).toContain(".go")
- }),
- ),
- ),
- )
- it.live("status() returns empty list when formatter is disabled", () =>
- provideTmpdirInstance(
- () =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- expect(yield* fmt.status()).toEqual([])
- }),
- ),
- { config: { formatter: false } },
- ),
- )
- it.live("status() excludes formatters marked as disabled in config", () =>
- provideTmpdirInstance(
- () =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- const statuses = yield* fmt.status()
- const gofmt = statuses.find((item) => item.name === "gofmt")
- expect(gofmt).toBeUndefined()
- }),
- ),
- {
- config: {
- formatter: {
- gofmt: { disabled: true },
- },
- },
- },
- ),
- )
- it.live("status() excludes uv when ruff is disabled", () =>
- provideTmpdirInstance(
- () =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- const statuses = yield* fmt.status()
- expect(statuses.find((item) => item.name === "ruff")).toBeUndefined()
- expect(statuses.find((item) => item.name === "uv")).toBeUndefined()
- }),
- ),
- {
- config: {
- formatter: {
- ruff: { disabled: true },
- },
- },
- },
- ),
- )
- it.live("status() excludes ruff when uv is disabled", () =>
- provideTmpdirInstance(
- () =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- const statuses = yield* fmt.status()
- expect(statuses.find((item) => item.name === "ruff")).toBeUndefined()
- expect(statuses.find((item) => item.name === "uv")).toBeUndefined()
- }),
- ),
- {
- config: {
- formatter: {
- uv: { disabled: true },
- },
- },
- },
- ),
- )
- it.live("service initializes without error", () => provideTmpdirInstance(() => Format.Service.use(() => Effect.void)))
- it.live("status() initializes formatter state per directory", () =>
- Effect.gen(function* () {
- const a = yield* provideTmpdirInstance(() => Format.Service.use((fmt) => fmt.status()), {
- config: { formatter: false },
- })
- const b = yield* provideTmpdirInstance(() => Format.Service.use((fmt) => fmt.status()))
- expect(a).toEqual([])
- expect(b.length).toBeGreaterThan(0)
- }),
- )
- it.live("runs enabled checks for matching formatters in parallel", () =>
- provideTmpdirInstance((path) =>
- Effect.gen(function* () {
- const file = `${path}/test.parallel`
- yield* Effect.promise(() => Bun.write(file, "x"))
- const one = {
- extensions: Formatter.gofmt.extensions,
- enabled: Formatter.gofmt.enabled,
- }
- const two = {
- extensions: Formatter.mix.extensions,
- enabled: Formatter.mix.enabled,
- }
- let active = 0
- let max = 0
- yield* Effect.acquireUseRelease(
- Effect.sync(() => {
- Formatter.gofmt.extensions = [".parallel"]
- Formatter.mix.extensions = [".parallel"]
- Formatter.gofmt.enabled = async () => {
- active++
- max = Math.max(max, active)
- await Bun.sleep(20)
- active--
- return ["sh", "-c", "true"]
- }
- Formatter.mix.enabled = async () => {
- active++
- max = Math.max(max, active)
- await Bun.sleep(20)
- active--
- return ["sh", "-c", "true"]
- }
- }),
- () =>
- Format.Service.use((fmt) =>
- Effect.gen(function* () {
- yield* fmt.init()
- yield* fmt.file(file)
- }),
- ),
- () =>
- Effect.sync(() => {
- Formatter.gofmt.extensions = one.extensions
- Formatter.gofmt.enabled = one.enabled
- Formatter.mix.extensions = two.extensions
- Formatter.mix.enabled = two.enabled
- }),
- )
- expect(max).toBe(2)
- }),
- ),
- )
- it.live("runs matching formatters sequentially for the same file", () =>
- provideTmpdirInstance(
- (path) =>
- Effect.gen(function* () {
- const file = `${path}/test.seq`
- yield* Effect.promise(() => Bun.write(file, "x"))
- yield* Format.Service.use((fmt) =>
- Effect.gen(function* () {
- yield* fmt.init()
- yield* fmt.file(file)
- }),
- )
- expect(yield* Effect.promise(() => Bun.file(file).text())).toBe("xAB")
- }),
- {
- config: {
- formatter: {
- first: {
- command: ["sh", "-c", 'sleep 0.05; v=$(cat "$1"); printf \'%sA\' "$v" > "$1"', "sh", "$FILE"],
- extensions: [".seq"],
- },
- second: {
- command: ["sh", "-c", 'v=$(cat "$1"); printf \'%sB\' "$v" > "$1"', "sh", "$FILE"],
- extensions: [".seq"],
- },
- },
- },
- },
- ),
- )
- })
|