fix(ext/popup): preserve unsupported-kind fields + totp expanded state
Two fixes from the T3+T4 code review: C1 (Critical): renderSectionBlock previously rendered all fields regardless of kind. For fields with kind url/date/month_year/totp/etc. (from CLI-created items), the editor showed a blank value input; if the user typed anything, the input handler cast the kind to the wrong thing and silently overwrote the structured value with a string — destroying data. Fix: filter editor to supported kinds (text/password/concealed); key data-* attributes by field.id (not by index) so handlers look up the correct field regardless of what the render loop emitted. Unsupported-kind fields survive save untouched. A small muted note "N fields of unsupported kind (edit via CLI)" flags preserved entries. +2 tests. I1 (Important): totp.ts's kind-toggle reRender read the module- scope sectionsExpanded flag which was only updated on structural mutations — so toggling the disclosure open without adding/removing anything left the flag stale, and clicking Random/BIP39 collapsed the disclosure. Fix: read data-expanded from the live DOM before innerHTML swap.
This commit is contained in:
@@ -105,7 +105,7 @@ describe('wireSectionsEditor', () => {
|
||||
] }];
|
||||
document.body.innerHTML = renderSectionsEditor(sections, true);
|
||||
wireSectionsEditor(document.body, sections, vi.fn());
|
||||
const deleteBtn = document.querySelector('[data-delete-field="0-0"]') as HTMLButtonElement;
|
||||
const deleteBtn = document.querySelector('[data-delete-field="f0"]') as HTMLButtonElement;
|
||||
deleteBtn.click();
|
||||
expect(sections[0].fields).toHaveLength(1);
|
||||
expect(sections[0].fields[0].id).toBe('f1');
|
||||
@@ -142,7 +142,7 @@ describe('wireSectionsEditor', () => {
|
||||
document.body.innerHTML = renderSectionsEditor(sections, true);
|
||||
const rerender = vi.fn();
|
||||
wireSectionsEditor(document.body, sections, rerender);
|
||||
const labelInput = document.querySelector('[data-field-label="0-0"]') as HTMLInputElement;
|
||||
const labelInput = document.querySelector('[data-field-label="f0"]') as HTMLInputElement;
|
||||
labelInput.value = 'new';
|
||||
labelInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
expect(sections[0].fields[0].label).toBe('new');
|
||||
@@ -155,9 +155,45 @@ describe('wireSectionsEditor', () => {
|
||||
] }];
|
||||
document.body.innerHTML = renderSectionsEditor(sections, true);
|
||||
wireSectionsEditor(document.body, sections, vi.fn());
|
||||
const valueInput = document.querySelector('[data-field-value-input="0-0"]') as HTMLInputElement;
|
||||
const valueInput = document.querySelector('[data-field-value-input="f0"]') as HTMLInputElement;
|
||||
valueInput.value = 'new';
|
||||
valueInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
expect(sections[0].fields[0].value).toEqual({ kind: 'text', value: 'new' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('wireSectionsEditor preserves unsupported-kind fields on save', () => {
|
||||
it('renders preserved note when section contains unsupported-kind fields', () => {
|
||||
const sections: Section[] = [{
|
||||
name: 'mixed',
|
||||
fields: [
|
||||
{ id: 'f0000001', label: 'note', kind: 'text',
|
||||
value: { kind: 'text', value: 'ok' }, hidden_by_default: false },
|
||||
{ id: 'f0000002', label: 'when', kind: 'date' as any,
|
||||
value: { kind: 'date', value: '2026-01-01' } as any, hidden_by_default: false },
|
||||
],
|
||||
}];
|
||||
document.body.innerHTML = renderSectionsEditor(sections, true);
|
||||
expect(document.body.innerHTML).toContain('1 field of unsupported kind');
|
||||
expect(document.body.innerHTML).not.toContain('f0000002');
|
||||
});
|
||||
|
||||
it('add-text then save does not destroy unsupported-kind fields', () => {
|
||||
const sections: Section[] = [{
|
||||
name: 'mixed',
|
||||
fields: [
|
||||
{ id: 'f0000002', label: 'when', kind: 'date' as any,
|
||||
value: { kind: 'date', value: '2026-01-01' } as any, hidden_by_default: false },
|
||||
],
|
||||
}];
|
||||
document.body.innerHTML = renderSectionsEditor(sections, true);
|
||||
wireSectionsEditor(document.body, sections, vi.fn());
|
||||
const addText = document.querySelector('[data-add-field="text"][data-section-idx="0"]') as HTMLButtonElement;
|
||||
addText.click();
|
||||
expect(sections[0].fields).toHaveLength(2);
|
||||
// Unsupported-kind field preserved untouched.
|
||||
const dateField = sections[0].fields.find((f) => f.id === 'f0000002');
|
||||
expect(dateField).toBeDefined();
|
||||
expect(dateField!.value).toEqual({ kind: 'date', value: '2026-01-01' });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user