v3.13.4: Cards editor counter field: explicit heading, placeholder, validation
The keyset table's column is headed "Counter (hex)" with the placeholder 0000000001, and cardsAdd refuses a save whose counter is not 1-10 hex digits (empty included; whitespace stripped) - the same rule the store enforces. The store keeps its import-compatible empty -> 1 default for API/import callers. Docs: repo AGENTS (v3.13.4 note). sw cache simple-v374. Tests: 667 Python + 797 frontend green.
This commit is contained in:
@@ -337,7 +337,7 @@ test('the release field is collected, cleared and restored', () => {
|
||||
test('saving a preset posts the form with the pre-settled TAR table', async () => {
|
||||
const els = setup();
|
||||
els['cards-name'].value = 'New card';
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB' });
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' });
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
// the role fields are pre-settled by the markup; the test's fake elements
|
||||
// start empty - the defaults fill in
|
||||
@@ -347,7 +347,7 @@ test('saving a preset posts the form with the pre-settled TAR table', async () =
|
||||
assert.strictEqual(apiCalls[0].path, '/api/presets');
|
||||
assert.strictEqual(apiCalls[0].body.name, 'New card');
|
||||
assert.deepStrictEqual(apiCalls[0].body.keysets, [
|
||||
{ kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '' }]);
|
||||
{ kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' }]);
|
||||
assert.deepStrictEqual(apiCalls[0].body.tars, [
|
||||
{ role: 'isd', tar: '000000', msl: '16', desc: '' },
|
||||
{ role: 'uiccRfm', tar: 'B00000', msl: '16', desc: '' },
|
||||
@@ -359,7 +359,7 @@ test('saving a preset posts the form with the pre-settled TAR table', async () =
|
||||
test('saving refuses a free TAR row without its MSL or with a duplicate TAR', async () => {
|
||||
const els = setup();
|
||||
els['cards-name'].value = 'New card';
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB' });
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' });
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
const seen = [];
|
||||
globalThis.alert = msg => seen.push(msg);
|
||||
@@ -381,7 +381,7 @@ test('editing a preset updates it by its store id', async () => {
|
||||
globalThis.cards = [presetFixture({ id: 'abc123', name: 'Old' })];
|
||||
globalThis._cardsEditIdx = 0;
|
||||
els['cards-name'].value = 'Renamed';
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB' });
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' });
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
await cardsAdd();
|
||||
assert.strictEqual(apiCalls[0].path, '/api/presets/update');
|
||||
@@ -629,7 +629,7 @@ test('editing opens the editor with the preset title', () => {
|
||||
test('the editor refuses PIN/PUK codes that are not 4-8 digits', async () => {
|
||||
const els = setup();
|
||||
els['cards-name'].value = 'X';
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB' });
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' });
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
const seen = [];
|
||||
globalThis.alert = msg => seen.push(msg);
|
||||
@@ -644,3 +644,30 @@ test('the editor refuses PIN/PUK codes that are not 4-8 digits', async () => {
|
||||
assert.strictEqual(apiCalls.length, 0);
|
||||
assert.match(seen[0], /PUK2/);
|
||||
});
|
||||
|
||||
test('the editor refuses a counter that is not 1-10 hex digits', async () => {
|
||||
const els = setup();
|
||||
els['cards-name'].value = 'X';
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: 'XYZ' });
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
const seen = [];
|
||||
globalThis.alert = msg => seen.push(msg);
|
||||
await cardsAdd();
|
||||
assert.strictEqual(apiCalls.length, 0);
|
||||
assert.match(seen[0], /Counter must be 1-10 hex digits/);
|
||||
// a valid value - spaces included, the server strips them - is posted
|
||||
seen.length = 0;
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '00 00 00 00 01' });
|
||||
await cardsAdd();
|
||||
assert.strictEqual(apiCalls.length, 1, JSON.stringify(seen));
|
||||
assert.strictEqual(apiCalls[0].body.keysets[0].cntr, '00 00 00 00 01');
|
||||
// an empty counter is refused too (the value is required)
|
||||
seen.length = 0;
|
||||
apiCalls.length = 0;
|
||||
els['cards-name'].value = 'X';
|
||||
globalThis._cardsKeysetCount = 1;
|
||||
ksRow(els, 0, { kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '' });
|
||||
await cardsAdd();
|
||||
assert.strictEqual(apiCalls.length, 0);
|
||||
assert.match(seen[0], /Counter must be 1-10 hex digits/);
|
||||
});
|
||||
|
||||
@@ -155,8 +155,8 @@ test('the card editor groups its fields into labelled fieldsets', () => {
|
||||
// ... and mirror the TAR table: a fixed-layout table with headers
|
||||
assert.match(scp80, /<table class="w-full table-fixed text-sm mb-2">/);
|
||||
assert.match(scp80, /<tbody id="cards-keysets">/);
|
||||
for (const h of ['KIc', 'KID', 'KIc key', 'KID key', 'Counter']) {
|
||||
assert.match(scp80, new RegExp('>' + h + '</th>'));
|
||||
for (const h of ['KIc', 'KID', 'KIc key', 'KID key', 'Counter (hex)']) {
|
||||
assert.ok(scp80.includes('>' + h + '</th>'), h);
|
||||
}
|
||||
assert.match(scp81, /id="cards-psk-id"/);
|
||||
assert.match(scp81, /id="cards-psk-key"/);
|
||||
|
||||
Reference in New Issue
Block a user