fx

The atago project wrote these specs on its own initiative and runs them in its own CI, to exercise atago against a real program. They are not fx’s official test suite, and the fx project is not affiliated with atago.

Summary #

4 suites · 50 scenarios

Contents #

fx (side effects on disk) #

A JSON viewer sounds like a read-only program, and mostly it is — which is exactly why the places where fx writes deserve an exhaustive delta rather than a per-file check.

Two of them exist. save rewrites the file fx was given, in place, and refuses to do so when there is no file or when the path is a symlink. And before any reducer runs, fx loads .fxrc.js from the working directory and from the user’s home, so a stray file in either place changes what a reducer means. changes: states the whole picture in one assertion — what was written and, just as importantly, that nothing else was — and sandbox_home puts the home directory inside the workdir so a write there would show up in the same delta.

Source: test/e2e/thirdparty/fx/changes.atago.yaml

Scenario: save rewrites the file it was given and touches nothing else #

only when fx --version succeeds

Given #

  • Fixture file config.json is created.
  • Fixture file untouched.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture config.json:

{"b":2,"a":1}

Fixture untouched.json:

{"keep":true}

When #

fx config.json sortKeys save

Then #

  • exit code is 0
  • the step changed exactly created nothing, modified config.json, deleted nothing
  • file config.json equals exact bytes

Scenario: running the same normalization twice changes nothing the second time #

only when fx --version succeeds

Given #

  • Fixture file config.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture config.json:

{"b":2,"a":1}

When #

fx config.json sortKeys save
fx config.json sortKeys save

Then #

  • after fx config.json sortKeys save:
    • exit code is 0
    • the step changed exactly modified config.json
  • after fx config.json sortKeys save:
    • exit code is 0
    • the step changed exactly created nothing, modified nothing, deleted nothing

Scenario: a reducer that only reads leaves the workdir alone #

only when fx --version succeeds

Given #

  • Fixture file config.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture config.json:

{"a":1}

When #

fx config.json .a

Then #

  • exit code is 0
  • stdout equals an exact value
  • the step changed exactly created nothing, modified nothing, deleted nothing

Scenario: save without a file argument fails and writes nothing #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"a":1}

When #

fx save

Then #

  • exit code is 1
  • stderr contains specify a file as the first argument
  • the step changed exactly created nothing, modified nothing, deleted nothing

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file real.json is created.
  • Fixture file link.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture real.json:

{"b":2,"a":1}

When #

fx link.json sortKeys save

Then #

  • exit code is 1
  • stderr contains cannot save to a symbolic link
  • the step changed exactly created nothing, modified nothing, deleted nothing
  • file real.json equals exact bytes

Scenario: a .fxrc.js in the working directory adds a function reducers can call #

only when fx --version succeeds

Given #

  • Fixture file .fxrc.js is created.
  • Fixture file data.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture .fxrc.js:

function double(x) {
  return x * 2
}

Fixture data.json:

{"n":21}

When #

fx data.json .n double

Then #

  • exit code is 0
  • stdout equals an exact value
  • the step changed exactly created nothing, modified nothing, deleted nothing

Scenario: a .fxrc.js in the home directory is loaded too, and fx writes nothing there #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file .atago-home/.fxrc.js is created.
  • Fixture file data.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture .atago-home/.fxrc.js:

function shout(x) {
  return String(x).toUpperCase()
}

Fixture data.json:

{"word":"atago"}

When #

fx data.json .word shout

Then #

  • exit code is 0
  • stdout equals an exact value
  • the step changed exactly created nothing, modified nothing, deleted nothing

fx (input formats, strictness, round trips) #

fx accepts more than JSON, and how it decides what it is holding is a contract of its own: --yaml and --toml switch parsers explicitly, but a file argument ending in .yaml, .yml or .toml switches them implicitly, and the two flags are mutually exclusive with each other and with --raw.

Strictness is the other half. By default fx reads JSON the way a human writes it — comments and trailing commas included — and --strict turns exactly those tolerances back into errors. The round-trip scenarios use fx twice in a pipeline so the assertion is about a relationship (encode then decode returns the original bytes) rather than about one recorded output.

Source: test/e2e/thirdparty/fx/formats.atago.yaml

Scenario: –yaml parses YAML into the JSON model #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

service:
  name: api
  port: 8080

When #

fx --yaml .service.port

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: –toml parses TOML into the JSON model #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

[package]
name = "atago"
version = "1.2.3"

When #

fx --toml .package.name

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: a .yaml file argument switches parsers with no flag at all #

only when fx --version succeeds

Given #

  • Fixture file config.yaml is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture config.yaml:

service:
  name: api
  replicas: 3

When #

fx config.yaml .service.replicas

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: a .toml file argument does the same #

only when fx --version succeeds

Given #

  • Fixture file config.toml is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture config.toml:

[package]
name = "atago"

When #

fx config.toml .package.name

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: extension detection ignores case #

only when fx --version succeeds

Given #

  • Fixture file CONFIG.YAML is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture CONFIG.YAML:

service:
  name: api

When #

fx CONFIG.YAML .service.name

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: an unknown extension stays on the JSON parser #

only when fx --version succeeds

Given #

  • Fixture file payload.txt is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture payload.txt:

{"a":1}

When #

fx payload.txt .a

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: –raw treats each input line as a string #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

hello
hi

When #

fx -r len

Then #

  • exit code is 0
  • stdout line 1 equals an exact value
  • stdout line 2 equals an exact value

Scenario: -s collects a stream of documents into one array #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"n":1}
{"n":2}
{"n":3}

When #

fx -s len

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: -rs combines raw lines into an array of strings #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

alpha
beta

When #

fx -rs .

Then #

  • exit code is 0
  • stdout equals an exact value

Expected output #

expected stdout:

[
  "alpha",
  "beta"
]

Scenario: the default parser accepts comments and a trailing comma #

only when fx --version succeeds

Given #

  • Fixture file loose.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture loose.json:

{
  // the service this config belongs to
  "name": "api",
  "port": 8080,
}

When #

fx loose.json .port

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: –strict rejects a comment #

only when fx --version succeeds

Given #

  • Fixture file loose.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture loose.json:

{
  // the service this config belongs to
  "name": "api"
}

When #

fx --strict loose.json .name

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains Comments are not allowed in strict mode

Scenario: –strict rejects a trailing comma #

only when fx --version succeeds

Given #

  • Fixture file trailing.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture trailing.json:

{
  "name": "api",
}

When #

fx --strict trailing.json .name

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains Trailing comma is not allowed in strict mode

Scenario: –raw and –yaml together are refused #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

a: 1

When #

fx --yaml --raw .

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains can't use --yaml/--toml and --raw flags together

Scenario: –yaml and –toml together are refused #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

a: 1

When #

fx --yaml --toml .

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains can't use both --yaml and --toml flags together

Scenario: base64 encoding round-trips through a second fx #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file secret.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture secret.json:

{"token":"s3cr3t value"}

When #

fx secret.json .token toBase64 | fx -r fromBase64

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: a document survives a JSON to YAML to JSON round trip byte for byte #

only when fx --version succeeds

Given #

  • Fixture file source.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture source.json:

{"name":"atago","nums":[1,2,3],"nested":{"leaf":true}}

When #

fx source.json .
fx source.json YAML.stringify
fx round_trip.yaml .

Then #

  • after fx source.json .:
    • exit code is 0
  • after fx source.json YAML.stringify:
    • exit code is 0
  • after fx round_trip.yaml .:
    • exit code is 0
    • file after.txt is byte-identical to before.txt

Generated artifacts #

  • before.txt
  • round_trip.yaml
  • after.txt

Scenario: –no-inline expands the containers the default output packs onto one line #

only when fx --version succeeds

Given #

  • Fixture file doc.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture doc.json:

{"nums":[1,2],"nested":{"leaf":1}}

When #

fx doc.json .
fx --no-inline doc.json .

Then #

  • after fx doc.json .:
    • exit code is 0
    • stdout contains "nums": [ 1, 2 ]
  • after fx --no-inline doc.json .:
    • exit code is 0
    • stdout equals an exact value

Expected output #

expected stdout:

{
  "nums": [
    1,
    2
  ],
  "nested": {
    "leaf": 1
  }
}

Scenario: malformed YAML fails with a diagnostic that points at the line #

only when fx --version succeeds

Given #

  • Fixture file broken.yaml is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture broken.yaml:

service:
 name: api
  port: 8080

When #

fx broken.yaml .

Then #

  • exit code is 1
  • stdout contains mapping value is not allowed
  • stderr is empty

Scenario: malformed TOML fails without writing to stdout #

only when fx --version succeeds

Given #

  • Fixture file broken.toml is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture broken.toml:

a = 

When #

fx broken.toml .

Then #

  • exit code is not 0
  • stdout is empty

fx (third-party CLI, JSON reducer contract) #

fx is two programs wearing one name. Hand it a reducer and it behaves like a filter — JSON in, a value out, an exit code for the shell. Hand it nothing and it opens a full-screen viewer instead. This file pins the filter half; the viewer lives in tui.atago.yaml and the parser flags in formats.atago.yaml.

The filter contract is worth pinning precisely because it is not the one a jq user expects. A reducer is JavaScript, not a query language, so an absent key is undefined rather than an error: fx reports it on stderr and still exits 0, while dereferencing THROUGH that undefined is a hard exit 1. Strings print unquoted, exit() lets the reducer choose the process’s exit code, and the identity path hands back the original number literals instead of what a float64 round trip would leave.

Source: test/e2e/thirdparty/fx/fx.atago.yaml

Scenario: version prints a semantic version #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

When #

fx --version

Then #

  • exit code is 0
  • stdout matches /^[0-9]+\.[0-9]+\.[0-9]+/
  • stderr is empty

Scenario: the identity reducer pretty-prints the document and keeps key order #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"b":2,"a":1}

When #

fx .

Then #

  • exit code is 0
  • stdout equals an exact value
  • stderr is empty

Expected output #

expected stdout:

{
  "b": 2,
  "a": 1
}

Scenario: a dotted path selects a nested value and prints strings unquoted #

only when fx --version succeeds

Given #

  • Fixture file user.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture user.json:

{"profile":{"name":"alice","admin":true}}

When #

fx user.json .profile.name

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: reducers compose left to right #

only when fx --version succeeds

Given #

  • Fixture file items.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture items.json:

{"items":["a","b","c"]}

When #

fx items.json .items len

Then #

  • exit code is 0
  • stdout equals an exact value

Scenario: an arrow function transforms the document #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"nums":[1,2,3]}

When #

fx '.nums.map(n => n * 2)'

Then #

  • exit code is 0
  • stdout equals an exact value

Expected output #

expected stdout:

[
  2,
  4,
  6
]

Scenario: a missing key reports undefined on stderr and still exits 0 #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"a":1}

When #

fx .nope

Then #

  • exit code is 0
  • stdout is empty
  • stderr equals an exact value

Scenario: dereferencing through a missing key is a hard error #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"a":1}

When #

fx .a.b.c

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains TypeError

Scenario: exit() hands the reducer’s own code to the shell #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{}

stdin for fx:

{}

When #

fx 'exit(3)'
fx 'exit(0)'

Then #

  • after fx 'exit(3)':
    • exit code is 3
  • after fx 'exit(0)':
    • exit code is 0

Scenario: invalid JSON fails loudly and keeps stdout clean #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"bad"

When #

fx .

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains Expected colon after object key

Scenario: a missing input file fails before anything is printed #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

When #

fx no-such.json .

Then #

  • exit code is 1
  • stdout is empty
  • stderr contains no-such.json

Scenario: empty input succeeds with no output at all #

only when fx --version succeeds

Given #

  • Fixture file empty.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

(read from file empty.json)

When #

fx .

Then #

  • exit code is 0
  • stdout is empty
  • stderr is empty

Scenario: each document in a stream produces its own result #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"n":1}
{"n":2}

When #

fx .n

Then #

  • exit code is 0
  • stdout line 1 equals an exact value
  • stdout line 2 equals an exact value

Scenario: filter drops documents from a stream instead of emitting them #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"n":1}
{"n":2}
{"n":3}

When #

fx 'filter(x => x.n > 2)'

Then #

  • exit code is 0
  • stdout equals an exact value

Expected output #

expected stdout:

{
  "n": 3
}

Scenario: the identity path keeps number literals JavaScript would rewrite #

only when fx --version succeeds

Given #

  • Fixture file numbers.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture numbers.json:

{"exact":1.0,"big":10000000000000000001}

When #

fx numbers.json .
fx numbers.json 'x => x'

Then #

  • after fx numbers.json .:
    • exit code is 0
    • stdout contains "exact": 1.0, "big": 10000000000000000001
  • after fx numbers.json 'x => x':
    • exit code is 0
    • stdout contains "exact": 1, "big": 10000000000000000001
    • stdout does not contain "exact": 1.0

Scenario: piped output carries no terminal escapes #

only when fx --version succeeds

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

stdin for fx:

{"a":"text","b":42,"c":null}

When #

fx .

Then #

  • exit code is 0
  • stdout does not match /\x1b\[/

Scenario: a directory given as input fails without writing to stdout #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file subdir/keep.txt is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture subdir/keep.txt:

placeholder

When #

fx subdir .

Then #

  • exit code is not 0
  • stdout is empty

fx (interactive viewer, pty testbed) #

Given a file and no reducer, fx stops being a filter and becomes a full-screen JSON viewer: a foldable tree, a regexp search, and a cursor whose position is reported as a JSON path in the status bar.

What makes it an unusual TUI to test is where it draws. fx paints the whole interface on stderr and keeps stdout for the one value the user asks it to print, so fx data.json > picked.txt is a real workflow: the UI still appears on the terminal and the file receives only the selected node. The scenarios below drive the viewer inside a pseudo-terminal and assert both sides of that split — the rendered screen, and what the pipeline behind it received.

The waits are expect_screen, not expect: fx negotiates with the terminal before its first paint, so the interesting condition is a rendered frame rather than a byte on the wire.

Source: test/e2e/thirdparty/fx/tui.atago.yaml

Scenario: the viewer renders the document and quits cleanly on q #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"],"nested":{"deep":{"leaf":42}}}

When #

# interactive (pty): fx viewer.json

Then #

  • exit code is 0

Scenario: esc leaves the viewer with a success code #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago"}

When #

# interactive (pty): fx viewer.json

Then #

  • exit code is 0

Scenario: the interface goes to stderr, so a redirected stdout stays empty #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"]}

When #

# interactive (pty): fx viewer.json > picked.txt

Then #

  • exit code is 0
  • file picked.txt equals exact bytes

Scenario: P prints the value under the cursor to stdout #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"]}

When #

# interactive (pty): fx viewer.json > picked.txt

Then #

  • exit code is 0
  • file picked.txt equals exact bytes

Scenario: collapse-all folds the containers and expand-all brings them back #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"],"nested":{"deep":{"leaf":42}}}

When #

# interactive (pty): fx viewer.json

Then #

  • exit code is 0

Scenario: search moves the cursor to the match and the status bar shows its path #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"],"nested":{"deep":{"leaf":42}}}

When #

# interactive (pty): fx viewer.json

Then #

  • exit code is 0

Scenario: the rendered frame shows the tree and the status bar together #

only when fx --version succeeds · skipped on Windows

Given #

  • Fixture file viewer.json is created.
  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

Inputs #

Fixture viewer.json:

{"name":"atago","tags":["cli","e2e"],"nested":{"deep":{"leaf":42}}}

When #

# interactive (pty): fx viewer.json

Then #

  • rendered screen line 1 contains {
  • rendered screen contains "leaf": 42
  • rendered screen contains viewer.json

Scenario: with a terminal and no file, fx prints its usage instead of opening the viewer #

only when fx --version succeeds · skipped on Windows

Given #

  • The command runs with an isolated home under ${workdir}/.atago-home (HOME/XDG or APPDATA redirected).

When #

# interactive (pty): fx

Then #

  • exit code is 0
  • stdout contains https://fx.wtf