diff --git a/js/ui/components/RevertModal.js b/js/ui/components/RevertModal.js index 3e2d4ab0..13d19ac7 100644 --- a/js/ui/components/RevertModal.js +++ b/js/ui/components/RevertModal.js @@ -1,3 +1,4 @@ +import { getDTagValueFromTags } from "../../nostr/nip71.js"; import { Nip71FormManager } from "./nip71FormManager.js"; import { createModalAccessibility } from "./modalAccessibility.js"; import { @@ -354,7 +355,7 @@ export class RevertModal { if (this.subtitle) { const subtitleParts = []; - const dTagValue = this.extractDTagValue(video.tags); + const dTagValue = getDTagValueFromTags(video.tags); if (dTagValue) { subtitleParts.push(`d=${dTagValue}`); } @@ -604,7 +605,7 @@ export class RevertModal { typeof version.rawMagnet === "string" ? version.rawMagnet.trim() : ""; const displayMagnet = magnet || rawMagnet; const isPrivate = version.isPrivate === true; - const dTagValue = this.extractDTagValue(version.tags); + const dTagValue = getDTagValueFromTags(version.tags); const nip71Metadata = this.buildNip71DisplayMetadata(version); @@ -1488,21 +1489,5 @@ export class RevertModal { references, }; } - - - extractDTagValue(tags) { - if (!Array.isArray(tags)) { - return ""; - } - for (const tag of tags) { - if (!Array.isArray(tag) || tag.length < 2) { - continue; - } - if (tag[0] === "d" && typeof tag[1] === "string") { - return tag[1]; - } - } - return ""; - } } diff --git a/tests/nostr/nip71-d-tag.test.mjs b/tests/nostr/nip71-d-tag.test.mjs new file mode 100644 index 00000000..1e323690 --- /dev/null +++ b/tests/nostr/nip71-d-tag.test.mjs @@ -0,0 +1,47 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { getDTagValueFromTags } from '../../js/nostr/nip71.js'; + +test('getDTagValueFromTags utility', async (t) => { + await t.test('returns empty string for invalid inputs', () => { + assert.equal(getDTagValueFromTags(null), ''); + assert.equal(getDTagValueFromTags(undefined), ''); + assert.equal(getDTagValueFromTags({}), ''); + assert.equal(getDTagValueFromTags(''), ''); + assert.equal(getDTagValueFromTags(123), ''); + }); + + await t.test('returns empty string if no d-tag present', () => { + const tags = [['p', 'pubkey'], ['e', 'event-id']]; + assert.equal(getDTagValueFromTags(tags), ''); + }); + + await t.test('returns correct value for single d-tag', () => { + const tags = [['d', 'test-value']]; + assert.equal(getDTagValueFromTags(tags), 'test-value'); + }); + + await t.test('returns first value for multiple d-tags', () => { + const tags = [['d', 'first'], ['d', 'second']]; + assert.equal(getDTagValueFromTags(tags), 'first'); + }); + + await t.test('skips invalid d-tags (malformed)', () => { + const tags = [ + ['d'], // missing value + ['d', 123], // value not string + ['d', null], // value not string + 'invalid', // tag not array + ['d', 'valid'], + ]; + assert.equal(getDTagValueFromTags(tags), 'valid'); + }); + + await t.test('handles empty d-tag value correctly', () => { + // nip71 implementation returns empty string if value is empty string, OR skips it? + // Implementation: if (typeof tag[1] === "string" && tag[1]) { return tag[1]; } + // So it skips empty strings. + const tags = [['d', ''], ['d', 'fallback']]; + assert.equal(getDTagValueFromTags(tags), 'fallback'); + }); +});