Welcome 👋
Neo.form.field.Currency is Neo's number field for money: type 12.345 and it keeps 12.35; store a 5 and it shows 5.00. Two small methods do all of that work, and no test pins them yet. Your spec becomes the record of what the field promises.
This is a good first issue for Hacktoberfest 2026. It needs Node.js and a clone of this repository: no Docker, no AI setup, no framework internals beyond one file.
[!IMPORTANT]
Reserved for first-time Neo.mjs contributors. The maintainer team will not claim, edit, or implement this issue through 2026-10-31. Comment here to claim it, and ask anything on this issue.
Set up once: follow Set up the engine from a clone, including npm run bundle-browser-deps: without it the unit suite selects zero tests.
Where things live
- Source:
src/form/field/Currency.mjs: inputValueAdjustor(value) turns typed text into a number, inputValueRenderer(value) turns a number into the text you see.
- New test file:
test/playwright/unit/form/field/Currency.spec.mjs
- Pattern to copy:
test/playwright/unit/form/field/EmailValidate.spec.mjs (the setup() call and imports at the top)
- Tip: the currency field, like every number field, needs one main-thread stub while your tests run. Install it in
test.beforeAll, only if it is missing, and remove it in test.afterAll, exactly as test/playwright/unit/apps/colors/ViewportController.spec.mjs does in its test.beforeAll: const main = Neo.ns('Neo.main', true); if (!main.DomEvents) { main.DomEvents = {registerDisabledInputChars() {}, unregisterDisabledInputChars() {}}; /* delete it again in afterAll */ }. Do not put it at the top of the file: another spec imports the real DomEvents, and npm run test-unit then stops with Namespace collision in unitTestMode for Neo.main.DomEvents.
What to cover
inputValueAdjustor(value):
| Input |
Returns today |
'' |
null |
'12' |
12 |
'12.345' |
12.35 |
'-5.5' |
-5.5 |
'1e3' |
1000 |
3.5 (already a number) |
3.5, unchanged |
'1.005' |
1: the binary float for 1.005 sits just below it, so toFixed(2) gives '1.00' |
'abc' |
NaN |
inputValueRenderer(value):
| Input |
Returns today |
null |
null |
5 |
'5.00' |
1.5 |
'1.50' |
0.125 |
'0.13' |
The field also sets maxValue: 1000000 and stepSize: 0.01.
Done when
Out of scope
Changing the field's behaviour, currency symbols or locales, and the base Number field.
While you wait for review
You just pinned one small piece of a multi-threaded application engine: in Neo.mjs your app's code runs inside a web worker, and the main thread only paints. Two things worth ten minutes:
- See the part nobody expects. Run
npm run build-themes -- -n -e dev -t all and npm run server-start, open apps/workstation/, and drag a tab out of the browser window. It becomes its own OS window, still running, with the same component instances and the same worker. Benefits: Introduction explains why that is possible.
- Your coding agent can go much further here. The skills this repository's AI maintainers work with are published on npm as
neo-agent-skills, and they need no Knowledge Base and no Memory Core. With Claude or GPT beside you, the help wanted issues are within reach after this one.
Maintainer notes
Curated under #18985 (Hacktoberfest 2026). Found work: no unit or component spec names this module on dev (2026-09-23), and every value above was computed by running the two methods' logic, not read off the source.
Live latest-open sweep: the latest 20 open issues at 2026-09-23T14:24Z; no equivalent, and title searches return closed history only. A2A: no claim on this scope. Memory Core: no prior decision on this module.
Origin Session ID: 3be453e4-8b04-4865-be62-4cff34f4e0c6
Welcome 👋
Neo.form.field.Currencyis Neo's number field for money: type12.345and it keeps12.35; store a5and it shows5.00. Two small methods do all of that work, and no test pins them yet. Your spec becomes the record of what the field promises.This is a good first issue for Hacktoberfest 2026. It needs Node.js and a clone of this repository: no Docker, no AI setup, no framework internals beyond one file.
Set up once: follow Set up the engine from a clone, including
npm run bundle-browser-deps: without it the unit suite selects zero tests.Where things live
src/form/field/Currency.mjs:inputValueAdjustor(value)turns typed text into a number,inputValueRenderer(value)turns a number into the text you see.test/playwright/unit/form/field/Currency.spec.mjstest/playwright/unit/form/field/EmailValidate.spec.mjs(thesetup()call and imports at the top)test.beforeAll, only if it is missing, and remove it intest.afterAll, exactly astest/playwright/unit/apps/colors/ViewportController.spec.mjsdoes in itstest.beforeAll:const main = Neo.ns('Neo.main', true); if (!main.DomEvents) { main.DomEvents = {registerDisabledInputChars() {}, unregisterDisabledInputChars() {}}; /* delete it again in afterAll */ }. Do not put it at the top of the file: another spec imports the realDomEvents, andnpm run test-unitthen stops withNamespace collision in unitTestMode for Neo.main.DomEvents.What to cover
inputValueAdjustor(value):''null'12'12'12.345'12.35'-5.5'-5.5'1e3'10003.5(already a number)3.5, unchanged'1.005'1: the binary float for 1.005 sits just below it, sotoFixed(2)gives'1.00''abc'NaNinputValueRenderer(value):nullnull5'5.00'1.5'1.50'0.125'0.13'The field also sets
maxValue: 1000000andstepSize: 0.01.Done when
test/playwright/unit/form/field/Currency.spec.mjsexists, following the pattern file's setup.test(...)per table row, plus one for the two config values.'abc'givingNaNrather thannull, say), write it on this issue before changingsrc/: that is a behaviour change for its own PR.npm run test-unit -- test/playwright/unit/form/field/Currency.spec.mjspasses.npm run test-unitpasses.Out of scope
Changing the field's behaviour, currency symbols or locales, and the base
Numberfield.While you wait for review
You just pinned one small piece of a multi-threaded application engine: in Neo.mjs your app's code runs inside a web worker, and the main thread only paints. Two things worth ten minutes:
npm run build-themes -- -n -e dev -t allandnpm run server-start, openapps/workstation/, and drag a tab out of the browser window. It becomes its own OS window, still running, with the same component instances and the same worker. Benefits: Introduction explains why that is possible.neo-agent-skills, and they need no Knowledge Base and no Memory Core. With Claude or GPT beside you, thehelp wantedissues are within reach after this one.Maintainer notes
Curated under #18985 (Hacktoberfest 2026). Found work: no unit or component spec names this module on
dev(2026-09-23), and every value above was computed by running the two methods' logic, not read off the source. Live latest-open sweep: the latest 20 open issues at 2026-09-23T14:24Z; no equivalent, and title searches return closed history only. A2A: no claim on this scope. Memory Core: no prior decision on this module.Origin Session ID: 3be453e4-8b04-4865-be62-4cff34f4e0c6