Chores: weekly points and rewards are for child accounts only
build-container / build (push) Successful in 5m0s

- The weekly board, reward tiers and the board's This week card only include children
- Rewards can be for all children or chosen children, not adults
- Tests and README updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-26 15:33:28 -04:00
1 parent 15ddc68cf0
commit e88b9dedf0
5 files changed
+15 -10

No files matched your search

+3
View File
@@ -3,6 +3,7 @@ const http = require('http'), assert = require('assert'), fs = require('fs'), os
process.env.DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'nehub-chores-'));
const users = require('../users'), chores = require('../chores');
const P = { a: users.create({ name: 'Ann', role: 'admin', handle: 'YQ' }), b: users.create({ name: 'Bob', role: 'user', tabs: ['chores'], handle: 'Yg' }), c: users.create({ name: 'Cy', role: 'user', tabs: ['chores'], handle: 'Yw' }), d: users.create({ name: 'Di', role: 'user', tabs: ['music'], handle: 'ZA' }) };
users.update(P.b.id, { kid: { on: true } }); users.update(P.c.id, { kid: { on: true } }); // (points and rewards are for child accounts)
const hub = http.createServer((req, res) => users.runAs(P[req.headers['x-user'] || 'a'], () => chores.handle(req, res))).listen(0, async () => {
const B = 'http://127.0.0.1:' + hub.address().port + '/api/chores', call = (p, o = {}, who) => fetch(B + p, { ...o, headers: { ...(o.headers || {}), ...(who ? { 'x-user': who } : {}) } }), post = (p, b, who) => call(p, { method: 'POST', body: JSON.stringify(b) }, who), j = r => r.json();
const today = chores.ymd(new Date()), board = async (who, date = today) => (await j(await call('/?date=' + date, {}, who))).board;
@@ -36,6 +37,8 @@ const hub = http.createServer((req, res) => users.runAs(P[req.headers['x-user']
assert.equal((await post('/claim', { chore: sweep.id, date: today }, 'c')).status, 409, 'someone else cannot take it too'); assert.equal((await post('/done', { chore: sweep.id, date: today }, 'c')).status, 403, 'or tick it off');
assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'c')).status, 403, 'or put it back'); assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'b')).status, 200); assert.equal((await board('b')).find(x => x.title === 'Sweep').claimable, true, 'put back in the pool');
await post('/claim', { chore: sweep.id, date: today }, 'c'); assert.equal((await post('/done', { chore: sweep.id, date: today }, 'c')).status, 200); sw = (await board('b')).find(x => x.title === 'Sweep'); assert.ok(sw.done && sw.user === P.c.id, 'done by the one who took it'); assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'c')).status, 200); assert.equal((await post('/claim', { chore: dishes.id, date: today }, 'b')).status, 400, 'only pool chores');
// points are for children only: an adult who does a chore is not on the weekly board
assert.ok(!(await j(await call('/week?date=' + today, {}, 'a'))).people.some(x => x.name === 'Ann'), 'the admin is not in the weekly goals'); assert.equal((await post('/reward', { title: 'x', points: 3, for: [P.a.id] })).status, 400, 'rewards cannot be for an adult');
// weekly goals: tiers, a Monday-to-Sunday week, what each person did, handing a reward over
assert.equal((await post('/reward', { title: 'Pick the movie', points: 5 }, 'b')).status, 403, 'only an admin sets rewards'); assert.equal((await post('/reward', { title: '', points: 5 })).status, 400); assert.equal((await post('/reward', { title: 'x', points: 0 })).status, 400);
const r5 = await j(await post('/reward', { title: 'Pick the movie', points: 5 })), r50 = await j(await post('/reward', { title: 'A trip', points: 50 })); let wk = await j(await call('/week?date=' + today, {}, 'a')); assert.equal(wk.from, chores.addDays(wk.from, 0)); assert.equal(new Date(wk.from + 'T12:00:00Z').getUTCDay(), 1, 'a week starts on Monday'); assert.equal(wk.tiers.length, 2);