Files
start-os/sdk/package/lib/test/output.test.ts
Aiden McClelland f2142f0bb3 add documentation for ai agents (#3115)
* add documentation for ai agents

* docs: consolidate CLAUDE.md and CONTRIBUTING.md, add style guidelines

- Refactor CLAUDE.md to reference CONTRIBUTING.md for build/test/format info
- Expand CONTRIBUTING.md with comprehensive build targets, env vars, and testing
- Add code style guidelines section with conventional commits
- Standardize SDK prettier config to use single quotes (matching web)
- Add project-level Claude Code settings to disable co-author attribution

* style(sdk): apply prettier with single quotes

Run prettier across sdk/base and sdk/package to apply the
standardized quote style (single quotes matching web).

* docs: add USER.md for per-developer TODO filtering

- Add agents/USER.md to .gitignore (contains user identifier)
- Document session startup flow in CLAUDE.md:
  - Create USER.md if missing, prompting for identifier
  - Filter TODOs by @username tags
  - Offer relevant TODOs on session start

* docs: add i18n documentation task to agent TODOs

* docs: document i18n ID patterns in core/

Add agents/i18n-patterns.md covering rust-i18n setup, translation file
format, t!() macro usage, key naming conventions, and locale selection.
Remove completed TODO item and add reference in CLAUDE.md.

* chore: clarify that all builds work on any OS with Docker
2026-02-06 00:10:16 +01:00

149 lines
4.6 KiB
TypeScript

import { inputSpecSpec, InputSpecSpec } from './output'
import * as _I from '../index'
import { camelCase } from '../../scripts/oldSpecToBuilder'
import { deepMerge } from '../../../base/lib/util'
export type IfEquals<T, U, Y = unknown, N = never> =
(<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N
export function testOutput<A, B>(): (c: IfEquals<A, B>) => null {
return () => null
}
/// Testing the types of the input spec
testOutput<InputSpecSpec['rpc']['enable'], boolean>()(null)
testOutput<InputSpecSpec['rpc']['username'], string>()(null)
testOutput<InputSpecSpec['rpc']['username'], string>()(null)
testOutput<InputSpecSpec['rpc']['advanced']['auth'], string[]>()(null)
testOutput<
InputSpecSpec['rpc']['advanced']['serialversion'],
'segwit' | 'non-segwit'
>()(null)
testOutput<InputSpecSpec['rpc']['advanced']['servertimeout'], number>()(null)
testOutput<
InputSpecSpec['advanced']['peers']['addnode'][0]['hostname'],
string | null
>()(null)
testOutput<
InputSpecSpec['testListUnion'][0]['union']['value']['name'],
string
>()(null)
testOutput<InputSpecSpec['testListUnion'][0]['union']['selection'], 'lnd'>()(
null,
)
testOutput<InputSpecSpec['mediasources'], Array<'filebrowser' | 'nextcloud'>>()(
null,
)
// @ts-expect-error Because enable should be a boolean
testOutput<InputSpecSpec['rpc']['enable'], string>()(null)
// prettier-ignore
// @ts-expect-error Expect that the string is the one above
testOutput<InputSpecSpec["testListUnion"][0]['selection']['selection'], "selection">()(null);
/// Here we test the output of the matchInputSpecSpec function
describe('Inputs', () => {
const validInput: InputSpecSpec = {
mediasources: ['filebrowser'],
testListUnion: [
{
union: { selection: 'lnd', value: { name: 'string' } },
},
],
rpc: {
enable: true,
bio: 'This is a bio',
username: 'test',
password: 'test',
advanced: {
auth: ['test'],
serialversion: 'segwit',
servertimeout: 6,
threads: 3,
workqueue: 9,
},
},
'zmq-enabled': false,
txindex: false,
wallet: { enable: false, avoidpartialspends: false, discardfee: 0.0001 },
advanced: {
mempool: {
maxmempool: 1,
persistmempool: true,
mempoolexpiry: 23,
mempoolfullrbf: true,
},
peers: {
listen: true,
onlyconnect: true,
onlyonion: true,
addnode: [
{
hostname: 'test',
port: 1,
},
],
},
dbcache: 5,
pruning: {
selection: 'disabled',
value: { disabled: {} },
},
blockfilters: {
blockfilterindex: false,
peerblockfilters: false,
},
bloomfilters: { peerbloomfilters: false },
},
}
test('test valid input', async () => {
const { validator } = await inputSpecSpec.build({} as any)
const output = validator.unsafeCast(validInput)
expect(output).toEqual(validInput)
})
test('test no longer care about the conversion of min/max and validating', async () => {
const { validator } = await inputSpecSpec.build({} as any)
validator.unsafeCast(
deepMerge({}, validInput, { rpc: { advanced: { threads: 0 } } }),
)
})
test('test errors should throw for number in string', async () => {
const { validator } = await inputSpecSpec.build({} as any)
expect(() =>
validator.unsafeCast(deepMerge({}, validInput, { rpc: { enable: 2 } })),
).toThrowError()
})
test('Test that we set serialversion to something not segwit or non-segwit', async () => {
const { validator } = await inputSpecSpec.build({} as any)
expect(() =>
validator.unsafeCast(
deepMerge({}, validInput, {
rpc: { advanced: { serialversion: 'testing' } },
}),
),
).toThrowError()
})
})
describe('camelCase', () => {
test("'EquipmentClass name'", () => {
expect(camelCase('EquipmentClass name')).toEqual('equipmentClassName')
})
test("'Equipment className'", () => {
expect(camelCase('Equipment className')).toEqual('equipmentClassName')
})
test("'equipment class name'", () => {
expect(camelCase('equipment class name')).toEqual('equipmentClassName')
})
test("'Equipment Class Name'", () => {
expect(camelCase('Equipment Class Name')).toEqual('equipmentClassName')
})
test("'hyphen-name-format'", () => {
expect(camelCase('hyphen-name-format')).toEqual('hyphenNameFormat')
})
test("'underscore_name_format'", () => {
expect(camelCase('underscore_name_format')).toEqual('underscoreNameFormat')
})
})