Add tests for all but the content syntax parser module
This commit is contained in:
parent
f48b2070bc
commit
e657eb6513
17 changed files with 1072 additions and 127 deletions
2
.clippy.toml
Normal file
2
.clippy.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
allow-unwrap-in-tests = true
|
||||||
|
allow-expect-in-tests = true
|
||||||
224
.justfile
224
.justfile
|
|
@ -1,154 +1,176 @@
|
||||||
_default:
|
_default:
|
||||||
@just --list
|
@just --list
|
||||||
|
|
||||||
|
watch_cmd := "watchexec -qc -r -e rs,toml,html --color always -- "
|
||||||
|
cover_cmd := 'cargo llvm-cov --ignore-filename-regex "main\.rs|dev\.rs"'
|
||||||
|
just_cmd := 'just --unstable --timestamp --explain --command-color green'
|
||||||
|
|
||||||
# DEV
|
# DEV
|
||||||
|
|
||||||
|
# Start server
|
||||||
|
[group: 'develop']
|
||||||
|
run:
|
||||||
|
cargo run -- --hostname localhost --port 3003
|
||||||
|
|
||||||
|
alias r := run
|
||||||
|
|
||||||
# Build on changes
|
# Build on changes
|
||||||
[group('dev')]
|
[group: 'develop']
|
||||||
serve-watch:
|
run-watch:
|
||||||
watchexec -q -c -e rs,toml,html -r cargo run -- -p 3003 -h localhost
|
{{ watch_cmd }} {{ just_cmd }} run
|
||||||
|
|
||||||
alias sw := serve-watch
|
alias rw := run-watch
|
||||||
alias dev := serve-watch
|
alias dev := run-watch
|
||||||
alias d := serve-watch
|
alias d := run-watch
|
||||||
|
|
||||||
[group('dev')]
|
# Run all assessments on changes
|
||||||
serve-watch-interface:
|
[group: 'develop']
|
||||||
watchexec -qr -c -w . -w ../interface -e rs,toml,html cargo run \
|
verify-watch:
|
||||||
-- -h localhost -p 3001 -g ../interface/graph.toml
|
{{ watch_cmd }} {{ just_cmd }} verify
|
||||||
|
|
||||||
alias swi := serve-watch-interface
|
alias vw := verify-watch
|
||||||
alias dev-interface := serve-watch-interface
|
|
||||||
alias di := serve-watch-interface
|
|
||||||
|
|
||||||
# Run tests on changes
|
# Run tests on changes
|
||||||
[group('dev')]
|
[group: 'develop']
|
||||||
test-watch:
|
test-watch:
|
||||||
bacon --job test
|
{{ watch_cmd }} {{ just_cmd }} test
|
||||||
|
|
||||||
alias tw := test-watch
|
alias tw := test-watch
|
||||||
|
|
||||||
|
# Run tests with coverage reports on changes
|
||||||
|
[group: 'develop']
|
||||||
|
cover-watch:
|
||||||
|
{{ watch_cmd }} {{ just_cmd }} cover-report
|
||||||
|
|
||||||
|
alias ow := cover-watch
|
||||||
|
|
||||||
# Run cargo check on changes
|
# Run cargo check on changes
|
||||||
[group('dev')]
|
[group: 'develop']
|
||||||
check-watch:
|
check-watch:
|
||||||
bacon --job check
|
{{ watch_cmd }} {{ just_cmd }} check
|
||||||
|
|
||||||
alias cw := check-watch
|
alias cw := check-watch
|
||||||
|
|
||||||
# Format check on changes
|
|
||||||
[group('dev')]
|
|
||||||
format-watch:
|
|
||||||
bacon --job fmt-check
|
|
||||||
|
|
||||||
alias fw := format-watch
|
|
||||||
|
|
||||||
# Lint on changes
|
# Lint on changes
|
||||||
[group('dev')]
|
[group: 'develop']
|
||||||
lint-watch:
|
lint-watch:
|
||||||
bacon --job clippy
|
{{ watch_cmd }} {{ just_cmd }} lint
|
||||||
|
|
||||||
alias lw := lint-watch
|
alias lw := lint-watch
|
||||||
|
|
||||||
# Check before push
|
# Assess formatting on changes
|
||||||
[group('dev')]
|
[group: 'develop']
|
||||||
push: check
|
format-watch:
|
||||||
|
{{ watch_cmd }} {{ just_cmd }} format-assess
|
||||||
|
|
||||||
|
alias fw := format-watch
|
||||||
|
|
||||||
|
# Format all files
|
||||||
|
[group: 'develop']
|
||||||
|
format:
|
||||||
|
cargo fmt
|
||||||
|
|
||||||
|
alias f := format
|
||||||
|
|
||||||
|
# Verify before push
|
||||||
|
[group: 'develop']
|
||||||
|
push: verify
|
||||||
git push
|
git push
|
||||||
|
|
||||||
alias p := push
|
alias p := push
|
||||||
|
|
||||||
# RUN
|
# ANALYSIS
|
||||||
|
|
||||||
# Start server
|
# Run all analysis
|
||||||
[group('run')]
|
[group: 'assess']
|
||||||
serve:
|
verify: format-assess lint check test cover-assess
|
||||||
cargo run -- --hostname localhost --port 3003
|
|
||||||
|
|
||||||
alias s := serve
|
alias v := verify
|
||||||
|
|
||||||
|
# Assess coverage
|
||||||
|
[group: 'assess']
|
||||||
|
cover-assess:
|
||||||
|
{{ cover_cmd }} --fail-under-regions 90 report
|
||||||
|
|
||||||
|
# Assess formatting
|
||||||
|
[group: 'assess']
|
||||||
|
format-assess:
|
||||||
|
cargo fmt -- --check
|
||||||
|
|
||||||
|
alias fc := format-assess
|
||||||
|
|
||||||
|
# Lint with Clippy
|
||||||
|
[group: 'assess']
|
||||||
|
lint:
|
||||||
|
cargo clippy
|
||||||
|
|
||||||
|
alias l := lint
|
||||||
|
|
||||||
|
# Run cargo check
|
||||||
|
[group: 'assess']
|
||||||
|
check:
|
||||||
|
cargo check --workspace
|
||||||
|
|
||||||
|
alias c := check
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
[group: 'assess']
|
||||||
|
test:
|
||||||
|
cargo test -- --skip 'serial_tests::'
|
||||||
|
cargo test -- --test 'serial_tests::' --test-threads 1
|
||||||
|
|
||||||
|
alias t := test
|
||||||
|
|
||||||
|
# Run tests with coverage
|
||||||
|
[group: 'assess']
|
||||||
|
cover:
|
||||||
|
{{ cover_cmd }} --no-report -- --skip 'serial_tests::'
|
||||||
|
{{ cover_cmd }} --no-report -- --test 'serial_tests::' --test-threads 1
|
||||||
|
|
||||||
|
alias o := cover
|
||||||
|
|
||||||
|
## COVER
|
||||||
|
|
||||||
|
# Make coverage report
|
||||||
|
[group: 'cover']
|
||||||
|
cover-report: cover
|
||||||
|
{{ cover_cmd }} report --html
|
||||||
|
{{ cover_cmd }} report
|
||||||
|
|
||||||
|
alias or := cover-report
|
||||||
|
|
||||||
|
# Open coverage report
|
||||||
|
[group: 'cover']
|
||||||
|
cover-open: cover
|
||||||
|
{{ cover_cmd }} report --open
|
||||||
|
|
||||||
|
alias oo := cover-open
|
||||||
|
|
||||||
# BUILD
|
# BUILD
|
||||||
|
|
||||||
# Build project with Cargo
|
# Build project with Cargo
|
||||||
[group('build')]
|
[group: 'build']
|
||||||
build:
|
build:
|
||||||
cargo build
|
cargo build
|
||||||
|
|
||||||
alias b := build
|
alias b := build
|
||||||
|
|
||||||
# Cleanup build artifacts
|
# Cleanup build artifacts
|
||||||
[group('build')]
|
[group: 'build']
|
||||||
clean:
|
clean:
|
||||||
cargo clean
|
cargo clean
|
||||||
|
|
||||||
alias cl := clean
|
alias cl := clean
|
||||||
|
|
||||||
# Clean, build, run checks
|
# Clean, run assessments, release build
|
||||||
[group('build')]
|
[group: 'build']
|
||||||
full-build: clean build check
|
full-build: clean verify release-build
|
||||||
|
|
||||||
alias fb := full-build
|
alias fb := full-build
|
||||||
|
|
||||||
# Release build
|
# Release build
|
||||||
[group('build')]
|
[group: 'build']
|
||||||
release-build:
|
release-build: verify
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
alias rb := release-build
|
alias rb := release-build
|
||||||
|
|
||||||
# CHECKS
|
|
||||||
|
|
||||||
# Lint, check formatting and run tests
|
|
||||||
[group('checks')]
|
|
||||||
check: format-check lint cargo-check test
|
|
||||||
|
|
||||||
alias c := check
|
|
||||||
|
|
||||||
# Run cargo check
|
|
||||||
[group('checks')]
|
|
||||||
cargo-check:
|
|
||||||
cargo check --workspace
|
|
||||||
|
|
||||||
alias cc := cargo-check
|
|
||||||
|
|
||||||
# Lint with Clippy
|
|
||||||
[group('checks')]
|
|
||||||
lint:
|
|
||||||
cargo clippy
|
|
||||||
|
|
||||||
alias l := lint
|
|
||||||
|
|
||||||
# Check formatting without changing files
|
|
||||||
[group('checks')]
|
|
||||||
format-check:
|
|
||||||
cargo fmt -- --check
|
|
||||||
|
|
||||||
alias fc := format-check
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
[group('checks')]
|
|
||||||
test:
|
|
||||||
cargo test
|
|
||||||
|
|
||||||
alias t := test
|
|
||||||
|
|
||||||
# Run tests with coverage
|
|
||||||
[group('checks')]
|
|
||||||
cover:
|
|
||||||
cargo llvm-cov test
|
|
||||||
|
|
||||||
alias cv := cover
|
|
||||||
|
|
||||||
# Open test coverage report
|
|
||||||
[group('checks')]
|
|
||||||
cover-open:
|
|
||||||
cargo llvm-cov --open
|
|
||||||
|
|
||||||
alias cvo := cover-open
|
|
||||||
|
|
||||||
# FORMATTING
|
|
||||||
|
|
||||||
# Format all files
|
|
||||||
[group('checks')]
|
|
||||||
format:
|
|
||||||
cargo fmt
|
|
||||||
|
|
||||||
alias f := format
|
|
||||||
|
|
|
||||||
251
Cargo.lock
generated
251
Cargo.lock
generated
|
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.4"
|
version = "1.1.4"
|
||||||
|
|
@ -84,6 +90,12 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.10.0"
|
version = "2.10.0"
|
||||||
|
|
@ -185,6 +197,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
|
|
@ -246,6 +267,8 @@ dependencies = [
|
||||||
"tera",
|
"tera",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
"tower",
|
||||||
|
"ureq",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -260,6 +283,16 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
|
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
|
@ -552,6 +585,16 @@ version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
|
@ -772,6 +815,55 @@ version = "0.8.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom",
|
||||||
|
"libc",
|
||||||
|
"untrusted",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.23.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"rustls-webpki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pki-types"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.103.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.22"
|
version = "1.0.22"
|
||||||
|
|
@ -885,6 +977,12 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -917,6 +1015,12 @@ dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.111"
|
version = "2.0.111"
|
||||||
|
|
@ -1092,6 +1196,47 @@ version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq"
|
||||||
|
version = "3.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"flate2",
|
||||||
|
"log",
|
||||||
|
"percent-encoding",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"ureq-proto",
|
||||||
|
"utf-8",
|
||||||
|
"webpki-roots",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq-proto"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
|
@ -1159,6 +1304,15 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
|
|
@ -1227,13 +1381,22 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.60.2"
|
version = "0.60.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.53.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1245,6 +1408,22 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
|
"windows_aarch64_msvc 0.52.6",
|
||||||
|
"windows_i686_gnu 0.52.6",
|
||||||
|
"windows_i686_gnullvm 0.52.6",
|
||||||
|
"windows_i686_msvc 0.52.6",
|
||||||
|
"windows_x86_64_gnu 0.52.6",
|
||||||
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
|
"windows_x86_64_msvc 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.53.5"
|
version = "0.53.5"
|
||||||
|
|
@ -1252,58 +1431,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.53.1",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.53.1",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.53.1",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm 0.53.1",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.53.1",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.53.1",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.53.1",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc 0.53.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.53.1"
|
version = "0.53.1"
|
||||||
|
|
@ -1335,3 +1562,9 @@ dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||||
|
|
|
||||||
11
Cargo.toml
11
Cargo.toml
|
|
@ -11,6 +11,9 @@ documentation = "https://en.jutty.dev/node/Documentation"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version= "1.91.1"
|
rust-version= "1.91.1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
serial-tests = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.8.7"
|
axum = "0.8.7"
|
||||||
tokio = { version = "1.48.0", features = ["rt-multi-thread"] }
|
tokio = { version = "1.48.0", features = ["rt-multi-thread"] }
|
||||||
|
|
@ -19,9 +22,13 @@ serde_json = "1.0.145"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
toml = "0.9.8"
|
toml = "0.9.8"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
ureq = "3"
|
||||||
|
tower = { version = "0.5.2", features = ["util"] }
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
# levels: allow, expect, warn, force-warn, deny, forbid
|
# levels: allow, expect, warn, force-warn, deny, forbid
|
||||||
unsafe_code = { level = "forbid", priority = 99 }
|
unsafe_code = { level = "deny", priority = 99 }
|
||||||
unused = { level = "warn", priority = 10 }
|
unused = { level = "warn", priority = 10 }
|
||||||
let_underscore= { level = "warn", priority = 10 }
|
let_underscore= { level = "warn", priority = 10 }
|
||||||
nonstandard-style = "warn"
|
nonstandard-style = "warn"
|
||||||
|
|
@ -141,7 +148,6 @@ wildcard_imports = "warn"
|
||||||
zero_sized_map_values = "warn"
|
zero_sized_map_values = "warn"
|
||||||
|
|
||||||
# restrictive
|
# restrictive
|
||||||
allow_attributes = "forbid"
|
|
||||||
arithmetic_side_effects = "warn"
|
arithmetic_side_effects = "warn"
|
||||||
as_conversions = "warn"
|
as_conversions = "warn"
|
||||||
as_pointer_underscore = "warn"
|
as_pointer_underscore = "warn"
|
||||||
|
|
@ -155,7 +161,6 @@ expect_used = "warn"
|
||||||
filetype_is_file = "warn"
|
filetype_is_file = "warn"
|
||||||
float_cmp_const = "warn"
|
float_cmp_const = "warn"
|
||||||
fn_to_numeric_cast_any = "warn"
|
fn_to_numeric_cast_any = "warn"
|
||||||
get_unwrap = "warn"
|
|
||||||
if_then_some_else_none = "warn"
|
if_then_some_else_none = "warn"
|
||||||
indexing_slicing = "warn"
|
indexing_slicing = "warn"
|
||||||
infinite_loop = "warn"
|
infinite_loop = "warn"
|
||||||
|
|
|
||||||
39
src/dev.rs
39
src/dev.rs
|
|
@ -52,3 +52,42 @@ macro_rules! log {
|
||||||
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
fn run_in_debug_level(level: &str) {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {
|
||||||
|
std::env::set_var("DEBUG", level);
|
||||||
|
log!("Debug is set to {level}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn debug_var_set() {
|
||||||
|
for level in 0..9 {
|
||||||
|
run_in_debug_level(&level.to_string());
|
||||||
|
}
|
||||||
|
run_in_debug_level("");
|
||||||
|
run_in_debug_level("駄目!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trait_stripping() {
|
||||||
|
pub trait Loggable {
|
||||||
|
fn test(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Logger {}
|
||||||
|
|
||||||
|
impl Loggable for Logger {
|
||||||
|
fn test(&self) {
|
||||||
|
log!("This is inside a trait implementation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let logger = Logger {};
|
||||||
|
logger.test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
122
src/router.rs
122
src/router.rs
|
|
@ -54,3 +54,125 @@ pub fn new(graph: &Graph) -> Router {
|
||||||
|
|
||||||
router
|
router
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
syntax::serial::populate_graph,
|
||||||
|
types::{Config, Meta},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use axum::{
|
||||||
|
body::Body,
|
||||||
|
http::{Request, StatusCode},
|
||||||
|
response::Response,
|
||||||
|
};
|
||||||
|
use tower::ServiceExt as _;
|
||||||
|
|
||||||
|
async fn request(uri: &str, config: Option<&Config>) -> Response<Body> {
|
||||||
|
let default_graph = populate_graph();
|
||||||
|
let graph = Graph {
|
||||||
|
meta: Meta {
|
||||||
|
config: config
|
||||||
|
.map(|c| c.to_owned())
|
||||||
|
.unwrap_or(default_graph.meta.config),
|
||||||
|
..default_graph.meta
|
||||||
|
},
|
||||||
|
..default_graph
|
||||||
|
};
|
||||||
|
let router = new(&graph);
|
||||||
|
|
||||||
|
router
|
||||||
|
.oneshot(Request::builder().uri(uri).body(Body::empty()).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn smoke() {
|
||||||
|
let router = axum::Router::new();
|
||||||
|
let response = router
|
||||||
|
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn routes() {
|
||||||
|
let routes = [
|
||||||
|
"/",
|
||||||
|
"/about",
|
||||||
|
"/tree",
|
||||||
|
"/node/Syntax",
|
||||||
|
"/static/style.css",
|
||||||
|
"/static/favicon.svg",
|
||||||
|
"/graph/json",
|
||||||
|
"/graph/toml",
|
||||||
|
];
|
||||||
|
|
||||||
|
for route in routes {
|
||||||
|
let response = request(route, None).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn no_about_page() {
|
||||||
|
let config = Config {
|
||||||
|
about: false,
|
||||||
|
..populate_graph().meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = request("/about", Some(&config)).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn no_tree_page() {
|
||||||
|
let config = Config {
|
||||||
|
tree: false,
|
||||||
|
..populate_graph().meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = request("/tree", Some(&config)).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn no_toml_raw_graph() {
|
||||||
|
let config = Config {
|
||||||
|
raw_toml: false,
|
||||||
|
..populate_graph().meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = request("/graph/toml", Some(&config)).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn no_json_raw_graph() {
|
||||||
|
let config = Config {
|
||||||
|
raw_json: false,
|
||||||
|
..populate_graph().meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = request("/graph/json", Some(&config)).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn no_raw_graph() {
|
||||||
|
let config = Config {
|
||||||
|
raw: false,
|
||||||
|
..populate_graph().meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let toml_response = request("/graph/toml", Some(&config)).await;
|
||||||
|
assert_eq!(toml_response.status(), StatusCode::NOT_FOUND);
|
||||||
|
let json_response = request("/graph/json", Some(&config)).await;
|
||||||
|
assert_eq!(json_response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,3 +56,33 @@ pub async fn not_found() -> Response<Body> {
|
||||||
Some("The page you tried to access could not be found."),
|
Some("The page you tried to access could not be found."),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use axum::{
|
||||||
|
http::{StatusCode},
|
||||||
|
};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn not_found() {
|
||||||
|
let response = super::not_found().await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn internal_error() {
|
||||||
|
assert!(by_code(Some(201), None).status() == 201);
|
||||||
|
assert!(by_code(Some(304), None).status() == 304);
|
||||||
|
assert!(by_code(Some(418), None).status() == 418);
|
||||||
|
assert!(by_code(Some(505), None).status() == 505);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn custom_message() {
|
||||||
|
let pattern = "sibPtt0mvHPWS9HQ0YBQfGu8cUs954LZ";
|
||||||
|
let body = make_body(Some(501), Some(pattern));
|
||||||
|
assert!(body.contains(pattern));
|
||||||
|
assert!(!body.contains(&pattern.chars().rev().collect::<String>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,7 @@ pub async fn file(file_path: &str, content_type: &str) -> Response<Body> {
|
||||||
let header = header::CONTENT_TYPE;
|
let header = header::CONTENT_TYPE;
|
||||||
|
|
||||||
if let Ok(header_value) = HeaderValue::from_str(content_type) {
|
if let Ok(header_value) = HeaderValue::from_str(content_type) {
|
||||||
if let Some(h) = response.headers_mut().insert(header, header_value) {
|
response.headers_mut().append(header, header_value);
|
||||||
log!(
|
|
||||||
"Overwrote existing header {h:?} because a header for the same key existed"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log!("Failed to create content type header value from {content_type}");
|
log!("Failed to create content type header value from {content_type}");
|
||||||
}
|
}
|
||||||
|
|
@ -43,15 +39,70 @@ pub async fn serial(format: &Format) -> Response<Body> {
|
||||||
let body = serialize_graph(format, &graph);
|
let body = serialize_graph(format, &graph);
|
||||||
|
|
||||||
match *format {
|
match *format {
|
||||||
Format::Toml => handlers::raw::make_response(
|
Format::TOML => handlers::raw::make_response(
|
||||||
&body,
|
&body,
|
||||||
200,
|
200,
|
||||||
&[(header::CONTENT_TYPE, "text/plain")],
|
&[(header::CONTENT_TYPE, "text/plain")],
|
||||||
),
|
),
|
||||||
Format::Json => handlers::raw::make_response(
|
Format::JSON => handlers::raw::make_response(
|
||||||
&body,
|
&body,
|
||||||
200,
|
200,
|
||||||
&[(header::CONTENT_TYPE, "application/json")],
|
&[(header::CONTENT_TYPE, "application/json")],
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn serial_toml() {
|
||||||
|
let response = serial(&Format::TOML).await;
|
||||||
|
assert!(response.status() == 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn serial_toml_content_type() {
|
||||||
|
let response = serial(&Format::TOML).await;
|
||||||
|
assert!(
|
||||||
|
response.headers().get(header::CONTENT_TYPE).unwrap()
|
||||||
|
== "text/plain"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn serial_json_content_type() {
|
||||||
|
let response = serial(&Format::JSON).await;
|
||||||
|
assert!(
|
||||||
|
response.headers().get(header::CONTENT_TYPE).unwrap()
|
||||||
|
== "application/json"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn file_valid_header() {
|
||||||
|
let payload = "y1mgMhjeIMFsRNZ1tskP52DfWuvhvbRP";
|
||||||
|
let response = file("./static/graph.toml", payload).await;
|
||||||
|
assert_eq!(
|
||||||
|
response.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn file_invalid_header() {
|
||||||
|
let response = file("./static/graph.toml", "\n").await;
|
||||||
|
println!("{response:#?}");
|
||||||
|
assert!(response.headers().get(header::CONTENT_TYPE).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[should_panic(
|
||||||
|
expected = "Failed to read IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu \
|
||||||
|
contents: No such file or directory (os error 2)"
|
||||||
|
)]
|
||||||
|
async fn file_invalid_path() {
|
||||||
|
drop(file("IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu", "text/plain").await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,44 @@ pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
||||||
not_found,
|
not_found,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use axum::{
|
||||||
|
http::{HeaderName, StatusCode},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn syntax() {
|
||||||
|
let response = node(Path("Syntax".to_string())).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn syntax_content_type() {
|
||||||
|
let response = node(Path("Syntax".to_string())).await;
|
||||||
|
assert!(
|
||||||
|
response
|
||||||
|
.headers()
|
||||||
|
.get(HeaderName::from_static("content-type"),)
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
== "text/html"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn not_found() {
|
||||||
|
let response = node(Path("InexistentNode".to_string())).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn redirect() {
|
||||||
|
let response = node(Path("syntax".to_string())).await;
|
||||||
|
assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,38 @@ pub async fn search(Form(query): Form<Query>) -> Redirect {
|
||||||
pub struct Query {
|
pub struct Query {
|
||||||
node: String,
|
node: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use axum::{
|
||||||
|
http::{StatusCode},
|
||||||
|
};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn search_redirect() {
|
||||||
|
let query = Form(Query {
|
||||||
|
node: String::from("duZzBrgCzMhVY15wehxasezsGNatOKIq"),
|
||||||
|
});
|
||||||
|
let response = search(query).await;
|
||||||
|
assert!(response.status_code() == StatusCode::PERMANENT_REDIRECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn about_page_ok() {
|
||||||
|
let response = page("about.html").await;
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn tree_page_ok() {
|
||||||
|
let response = page("tree.html").await;
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn inexistent_page_error() {
|
||||||
|
let response = page("HBvcwqT8wLk6hxk1GdvNcEzJ6IiZ2Fod").await;
|
||||||
|
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,39 @@ pub(in crate::router::handlers) fn make_response(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log!("Failed to wrap header value {}", header.1);
|
log!("Failed to create header value from {}", header.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn repeated_header() {
|
||||||
|
let headers = [
|
||||||
|
(header::ACCEPT, "Not really"),
|
||||||
|
(header::ACCEPT, "This again?"),
|
||||||
|
];
|
||||||
|
let response = make_response("", 418, &headers);
|
||||||
|
assert!(response.headers().get_all(header::ACCEPT).iter().count() == 1);
|
||||||
|
assert_eq!(
|
||||||
|
response
|
||||||
|
.headers()
|
||||||
|
.get(header::ACCEPT)
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
"This again?",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_header() {
|
||||||
|
let response = make_response("", 418, &[(header::MAX_FORWARDS, "\n")]);
|
||||||
|
assert!(response.headers().get(header::MAX_FORWARDS).is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,9 @@ pub(in crate::router::handlers) fn render(
|
||||||
error_message: Option<String>,
|
error_message: Option<String>,
|
||||||
) -> (String, u16) {
|
) -> (String, u16) {
|
||||||
// TODO just return an Option/String> here
|
// TODO just return an Option/String> here
|
||||||
let tera = match tera::Tera::new(concat!(
|
let tera = match tera::Tera::new("./templates/**/*") {
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
|
||||||
"/templates/**/*"
|
|
||||||
)) {
|
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let early_error_message = format!("{e:#?}");
|
|
||||||
log!("{}", early_error_message);
|
|
||||||
return (emergency_wrap(&e), 500);
|
return (emergency_wrap(&e), 500);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -73,7 +68,8 @@ pub(in crate::router::handlers) fn render(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emergency_wrap(message: &tera::Error) -> String {
|
fn emergency_wrap(error: &tera::Error) -> String {
|
||||||
|
log!("{error:#?}");
|
||||||
format!(
|
format!(
|
||||||
r#"<!DOCTYPE html>
|
r#"<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
@ -93,7 +89,7 @@ fn emergency_wrap(message: &tera::Error) -> String {
|
||||||
<h2><strong>Early Pre-Templating Error</strong></h2>
|
<h2><strong>Early Pre-Templating Error</strong></h2>
|
||||||
<p>This normally indicates a malformed template.</p>
|
<p>This normally indicates a malformed template.</p>
|
||||||
<pre>
|
<pre>
|
||||||
{message}
|
{error:#?}
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
If you haven't modified templates, plese consider
|
If you haven't modified templates, plese consider
|
||||||
|
|
@ -104,3 +100,104 @@ fn emergency_wrap(message: &tera::Error) -> String {
|
||||||
"#
|
"#
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn by_filename_forced_error() {
|
||||||
|
let response =
|
||||||
|
by_filename("index.html", &tera::Context::new(), 418, None, true);
|
||||||
|
assert_eq!(response.status(), 418);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn by_filename_index() {
|
||||||
|
let response =
|
||||||
|
by_filename("index.html", &tera::Context::new(), 418, None, false);
|
||||||
|
assert_eq!(response.status(), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn by_filename_file_not_found() {
|
||||||
|
let response = by_filename(
|
||||||
|
"bwbl3BnWsluIgbO2NV9t3vtihwcjuF6t",
|
||||||
|
&tera::Context::new(),
|
||||||
|
418,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
assert_eq!(response.status(), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn by_filename_empty() {
|
||||||
|
let response = by_filename("", &tera::Context::new(), 418, None, false);
|
||||||
|
assert_eq!(response.status(), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_with_context() {
|
||||||
|
let payload = "dBgIw8DnNHxJojiXzu445qUC4UpxwZCy";
|
||||||
|
let mut context = tera::Context::new();
|
||||||
|
let node = crate::types::Node::new(Some(payload.to_string()));
|
||||||
|
let graph = crate::syntax::serial::populate_graph();
|
||||||
|
context.insert("node", &node);
|
||||||
|
context.insert("text", &crate::syntax::content::parse(&node.text));
|
||||||
|
context.insert("incoming", &graph.incoming.get(&node.id));
|
||||||
|
context.insert("config", &graph.meta.config.parse_text());
|
||||||
|
let (body, status) = render("node.html", &context, None);
|
||||||
|
assert_eq!(status, 200);
|
||||||
|
assert!(body.matches(payload).count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_custom_error_message() {
|
||||||
|
let payload = "dBgIw8DnNHxJojiXzu445qUC4UpxwZCy";
|
||||||
|
let (body, status) = render(
|
||||||
|
"ObH9jYUl4wMhUNcXnuqwVVzHoqx4ufyN",
|
||||||
|
&tera::Context::new(),
|
||||||
|
Some(payload.to_string()),
|
||||||
|
);
|
||||||
|
assert_eq!(status, 500);
|
||||||
|
assert!(body.matches(payload).count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_empty() {
|
||||||
|
let (body, status) = render(
|
||||||
|
"R8D1pxwHZDxcH5SMjR7rZEnIzmpkiHkH",
|
||||||
|
&tera::Context::new(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
assert_eq!(status, 500);
|
||||||
|
assert!(body.matches("Template render failed").count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_not_found() {
|
||||||
|
let payload = "OL6kb9qHe7Iwr7wFIRKUTeFhF34BRsQo";
|
||||||
|
let (body, status) = render(payload, &tera::Context::new(), None);
|
||||||
|
|
||||||
|
assert!(body.matches("TemplateNotFound").count() > 0);
|
||||||
|
assert!(body.matches(payload).count() > 0);
|
||||||
|
assert_eq!(status, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_bad_context() {
|
||||||
|
let (body, status) = render("node.html", &tera::Context::new(), None);
|
||||||
|
assert!(body.matches("Template render failed.").count() > 0);
|
||||||
|
assert_eq!(status, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn emergency_wrap_custom_message() {
|
||||||
|
let payload = "JLaTtsnd2IFukIOvqFNymeuiaS6nMaUc";
|
||||||
|
let error = tera::Error::msg(payload);
|
||||||
|
let html = emergency_wrap(&error);
|
||||||
|
assert!(html.matches(payload).count() == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub struct Arguments {
|
pub struct Arguments {
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
|
@ -57,3 +57,58 @@ fn parse(defaults: &Arguments, args: &[String]) -> Arguments {
|
||||||
}
|
}
|
||||||
out_args
|
out_args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn address() {
|
||||||
|
let args = Arguments {
|
||||||
|
hostname: String::from("localhost"),
|
||||||
|
port: 3007,
|
||||||
|
graph_path: PathBuf::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(args.make_address(), "localhost:3007");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hostname() {
|
||||||
|
let defaults = Arguments::new();
|
||||||
|
|
||||||
|
let payload = String::from("olUCu7vWcUAsumv2xpj2Z55EDheWLTEu");
|
||||||
|
let args =
|
||||||
|
parse(&defaults, &[String::from("-h"), String::from(&payload)]);
|
||||||
|
assert_eq!(args.hostname, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn port() {
|
||||||
|
let defaults = Arguments::new();
|
||||||
|
|
||||||
|
let payload = 3901;
|
||||||
|
let args = parse(&defaults, &[String::from("-p"), payload.to_string()]);
|
||||||
|
assert_eq!(args.port, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn graph_path() {
|
||||||
|
let defaults = Arguments::new();
|
||||||
|
|
||||||
|
let payload = PathBuf::from("/tmp/");
|
||||||
|
let args = parse(
|
||||||
|
&defaults,
|
||||||
|
&[String::from("-g"), payload.to_str().unwrap().to_string()],
|
||||||
|
);
|
||||||
|
assert_eq!(args.graph_path, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty() {
|
||||||
|
let defaults = Arguments::new();
|
||||||
|
|
||||||
|
let args = parse(&defaults, &[]);
|
||||||
|
assert_eq!(defaults, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,11 +128,97 @@ pub fn deserialize_graph(in_format: &Format, serial: &str) -> Graph {
|
||||||
match *in_format {
|
match *in_format {
|
||||||
Format::TOML => match toml::from_str(serial) {
|
Format::TOML => match toml::from_str(serial) {
|
||||||
Ok(g) => g,
|
Ok(g) => g,
|
||||||
Err(error) => Graph::new(Some(error.to_string())),
|
Err(error) => Graph::new(Some(&error.to_string())),
|
||||||
},
|
},
|
||||||
Format::JSON => match serde_json::from_str(serial) {
|
Format::JSON => match serde_json::from_str(serial) {
|
||||||
Ok(g) => g,
|
Ok(g) => g,
|
||||||
Err(error) => Graph::new(Some(error.to_string())),
|
Err(error) => Graph::new(Some(&error.to_string())),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn good_json() {
|
||||||
|
let json = r#"
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"JSON": {
|
||||||
|
"text": "",
|
||||||
|
"title": "JSON",
|
||||||
|
"links": [],
|
||||||
|
"id": "JSON",
|
||||||
|
"hidden": false,
|
||||||
|
"connections": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root_node": "JSON"
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let graph = deserialize_graph(&Format::JSON, json);
|
||||||
|
assert!(graph.meta.messages.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bad_json() {
|
||||||
|
let graph = deserialize_graph(&Format::JSON, ":::");
|
||||||
|
let message = graph.meta.messages.first().unwrap();
|
||||||
|
assert!(message.contains("expected value at line 1 column 1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn detached_node() {
|
||||||
|
let node = Node {
|
||||||
|
id: String::from("SomeNode"),
|
||||||
|
text: String::new(),
|
||||||
|
title: String::new(),
|
||||||
|
links: vec![String::new()],
|
||||||
|
hidden: false,
|
||||||
|
connections: Some(vec![Edge {
|
||||||
|
anchor: String::from("SomeAnchor"),
|
||||||
|
from: String::new(),
|
||||||
|
to: String::new(),
|
||||||
|
detached: false,
|
||||||
|
}]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut map: HashMap<String, Node> = HashMap::new();
|
||||||
|
map.insert(String::from("SomeNode"), node);
|
||||||
|
|
||||||
|
let modulated_map = modulate_nodes(&map);
|
||||||
|
let modulated_node = modulated_map.get("SomeNode").unwrap().clone();
|
||||||
|
let modulated_connections = modulated_node.connections.unwrap();
|
||||||
|
let modulated_connection = modulated_connections.first().unwrap();
|
||||||
|
assert!(modulated_connection.anchor == "SomeAnchor");
|
||||||
|
assert!(modulated_connection.detached);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod serial_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bad_graph_path() {
|
||||||
|
println!("T");
|
||||||
|
let original_working_directory = std::env::current_dir().unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
std::env::set_current_dir(std::path::Path::new(
|
||||||
|
"tests/mocks/no_graph"
|
||||||
|
))
|
||||||
|
.is_ok()
|
||||||
|
);
|
||||||
|
|
||||||
|
let graph = populate_graph();
|
||||||
|
let message = graph.meta.messages.first().unwrap();
|
||||||
|
assert!(message.contains("TOML parse error"));
|
||||||
|
assert!(message.contains("No such file or directory"));
|
||||||
|
|
||||||
|
assert!(std::env::set_current_dir(original_working_directory).is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
81
src/types.rs
81
src/types.rs
|
|
@ -198,3 +198,84 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::syntax::serial::populate_graph;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_graph() {
|
||||||
|
let graph = Graph::new(Some("ISryQFd9peG6eYz9CFRQFWeD1GnPo0oj"));
|
||||||
|
assert!(graph.nodes.is_empty());
|
||||||
|
assert!(graph.incoming.is_empty());
|
||||||
|
assert_eq!(
|
||||||
|
graph.meta.messages.first().unwrap(),
|
||||||
|
"ISryQFd9peG6eYz9CFRQFWeD1GnPo0oj"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_node_message() {
|
||||||
|
let node = Node::new(None);
|
||||||
|
assert_eq!(node.text, "Node is empty, missing or wasn't found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_footer_text() {
|
||||||
|
let default_graph = populate_graph();
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
footer_text: String::new(),
|
||||||
|
..default_graph.meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_config = config.parse_text();
|
||||||
|
|
||||||
|
println!("{:?}", parsed_config.footer_text);
|
||||||
|
assert!(parsed_config.footer_text.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_footer_text() {
|
||||||
|
let payload = "0kqBrdS8NPrU4xVxh2xW0hUzAw926JCQ";
|
||||||
|
let default_graph = populate_graph();
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
footer_text: format!("`{payload}`"),
|
||||||
|
..default_graph.meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_config = config.parse_text();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
parsed_config
|
||||||
|
.footer_text
|
||||||
|
.matches(format!("<code>{payload}</code>").as_str())
|
||||||
|
.count()
|
||||||
|
== 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_about_text() {
|
||||||
|
let payload = "ZqPFl84JlzSS0QUo61RwTUPONIE78Lmw";
|
||||||
|
let default_graph = populate_graph();
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
about_text: format!("`{payload}`"),
|
||||||
|
..default_graph.meta.config
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_config = config.parse_text();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
parsed_config
|
||||||
|
.about_text
|
||||||
|
.matches(format!("<code>{payload}</code>").as_str())
|
||||||
|
.count()
|
||||||
|
== 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
3
tests/mocks/bad_graph/static/graph.toml
Normal file
3
tests/mocks/bad_graph/static/graph.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[meta]
|
||||||
|
config = {
|
||||||
|
'
|
||||||
13
tests/mocks/good_json/graph.json
Normal file
13
tests/mocks/good_json/graph.json
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"JSON": {
|
||||||
|
"text": "",
|
||||||
|
"title": "JSON",
|
||||||
|
"links": [],
|
||||||
|
"id": "JSON",
|
||||||
|
"hidden": false,
|
||||||
|
"connections": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root_node": "JSON"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue