44 escapeRegExp ,
55 textMatchesTerms ,
66 scoreTextField ,
7- scoreDatasetRelevance
7+ scoreDatasetRelevance ,
8+ readDcatExtra
89} from '../../src/tools/package' ;
910
1011describe ( 'extractQueryTerms' , ( ) => {
@@ -263,7 +264,9 @@ describe('scoreDatasetRelevance', () => {
263264 result . breakdown . title +
264265 result . breakdown . notes +
265266 result . breakdown . tags +
266- result . breakdown . organization
267+ result . breakdown . organization +
268+ result . breakdown . holder +
269+ result . breakdown . publisher
267270 ) ;
268271 } ) ;
269272
@@ -287,7 +290,7 @@ describe('scoreDatasetRelevance', () => {
287290 tags : [ ] ,
288291 organization : null
289292 } ;
290- const weights = { title : 10 , notes : 5 , tags : 3 , organization : 1 } ;
293+ const weights = { title : 10 , notes : 5 , tags : 3 , organization : 1 , holder : 4 , publisher : 2 } ;
291294 const result = scoreDatasetRelevance ( 'health' , dataset , weights ) ;
292295
293296 expect ( result . breakdown . title ) . toBe ( 10 ) ;
@@ -379,6 +382,8 @@ describe('scoreDatasetRelevance', () => {
379382 expect ( result . breakdown ) . toHaveProperty ( 'notes' ) ;
380383 expect ( result . breakdown ) . toHaveProperty ( 'tags' ) ;
381384 expect ( result . breakdown ) . toHaveProperty ( 'organization' ) ;
385+ expect ( result . breakdown ) . toHaveProperty ( 'holder' ) ;
386+ expect ( result . breakdown ) . toHaveProperty ( 'publisher' ) ;
382387 } ) ;
383388
384389 it ( 'includes extracted terms in result' , ( ) => {
@@ -391,3 +396,185 @@ describe('scoreDatasetRelevance', () => {
391396 } ) ;
392397 } ) ;
393398} ) ;
399+
400+ describe ( 'readDcatExtra' , ( ) => {
401+ it ( 'returns extras value when key is present' , ( ) => {
402+ const dataset = {
403+ extras : [
404+ { key : 'holder_name' , value : 'Comune di Lecce' }
405+ ]
406+ } ;
407+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'Comune di Lecce' ) ;
408+ } ) ;
409+
410+ it ( 'prefers extras over root field when both are present' , ( ) => {
411+ const dataset = {
412+ holder_name : 'Regione Puglia' ,
413+ extras : [
414+ { key : 'holder_name' , value : 'Comune di Lecce' }
415+ ]
416+ } ;
417+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'Comune di Lecce' ) ;
418+ } ) ;
419+
420+ it ( 'falls back to root field when key not in extras' , ( ) => {
421+ const dataset = {
422+ holder_name : 'Health Canada' ,
423+ extras : [
424+ { key : 'other_field' , value : 'something' }
425+ ]
426+ } ;
427+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'Health Canada' ) ;
428+ } ) ;
429+
430+ it ( 'falls back to root field when extras is empty' , ( ) => {
431+ const dataset = {
432+ holder_name : 'data.gov' ,
433+ extras : [ ]
434+ } ;
435+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'data.gov' ) ;
436+ } ) ;
437+
438+ it ( 'falls back to root field when extras is absent' , ( ) => {
439+ const dataset = {
440+ publisher_name : 'Open Government'
441+ } ;
442+ expect ( readDcatExtra ( dataset , 'publisher_name' ) ) . toBe ( 'Open Government' ) ;
443+ } ) ;
444+
445+ it ( 'returns empty string when neither extras nor root have the key' , ( ) => {
446+ const dataset = {
447+ extras : [ { key : 'other' , value : 'x' } ]
448+ } ;
449+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( '' ) ;
450+ } ) ;
451+
452+ it ( 'returns empty string for completely empty dataset' , ( ) => {
453+ const dataset = { } ;
454+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( '' ) ;
455+ } ) ;
456+
457+ it ( 'skips extras entry with empty string value' , ( ) => {
458+ const dataset = {
459+ holder_name : 'Root Value' ,
460+ extras : [
461+ { key : 'holder_name' , value : '' }
462+ ]
463+ } ;
464+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'Root Value' ) ;
465+ } ) ;
466+
467+ it ( 'skips extras entry with non-string value' , ( ) => {
468+ const dataset = {
469+ holder_name : 'Root Value' ,
470+ extras : [
471+ { key : 'holder_name' , value : 42 }
472+ ]
473+ } ;
474+ expect ( readDcatExtra ( dataset , 'holder_name' ) ) . toBe ( 'Root Value' ) ;
475+ } ) ;
476+
477+ it ( 'handles publisher_name key' , ( ) => {
478+ const dataset = {
479+ publisher_name : 'Root Publisher' ,
480+ extras : [
481+ { key : 'publisher_name' , value : 'Extras Publisher' }
482+ ]
483+ } ;
484+ expect ( readDcatExtra ( dataset , 'publisher_name' ) ) . toBe ( 'Extras Publisher' ) ;
485+ } ) ;
486+ } ) ;
487+
488+ describe ( 'scoreDatasetRelevance — holder and publisher' , ( ) => {
489+ it ( 'scores holder from extras (DCAT-AP_IT pattern)' , ( ) => {
490+ const dataset = {
491+ title : 'Defibrillatori DAE' ,
492+ organization : { name : 'regione-puglia' , title : 'Regione Puglia' } ,
493+ extras : [ { key : 'holder_name' , value : 'Comune di Lecce' } ]
494+ } ;
495+ const result = scoreDatasetRelevance ( 'Comune di Lecce' , dataset ) ;
496+
497+ expect ( result . breakdown . holder ) . toBeGreaterThan ( 0 ) ;
498+ expect ( result . breakdown . organization ) . toBe ( 0 ) ;
499+ } ) ;
500+
501+ it ( 'extras holder wins over root holder when they differ (federated portal fix)' , ( ) => {
502+ const dataset = {
503+ title : 'Dataset' ,
504+ holder_name : 'Regione Puglia' ,
505+ extras : [ { key : 'holder_name' , value : 'Comune di Mesagne' } ]
506+ } ;
507+ const withFix = scoreDatasetRelevance ( 'Mesagne' , dataset ) ;
508+ expect ( withFix . breakdown . holder ) . toBeGreaterThan ( 0 ) ;
509+
510+ const datasetRootOnly = {
511+ title : 'Dataset' ,
512+ holder_name : 'Comune di Mesagne'
513+ } ;
514+ const withRoot = scoreDatasetRelevance ( 'Mesagne' , datasetRootOnly ) ;
515+ expect ( withRoot . breakdown . holder ) . toBeGreaterThan ( 0 ) ;
516+ } ) ;
517+
518+ it ( 'scores publisher from extras' , ( ) => {
519+ const dataset = {
520+ title : 'Dataset' ,
521+ extras : [ { key : 'publisher_name' , value : 'Regione Siciliana' } ]
522+ } ;
523+ const result = scoreDatasetRelevance ( 'Siciliana' , dataset ) ;
524+
525+ expect ( result . breakdown . publisher ) . toBeGreaterThan ( 0 ) ;
526+ } ) ;
527+
528+ it ( 'holder and publisher contribute to total' , ( ) => {
529+ const dataset = {
530+ title : 'Dataset' ,
531+ extras : [
532+ { key : 'holder_name' , value : 'Comune di Lecce' } ,
533+ { key : 'publisher_name' , value : 'Comune di Lecce' }
534+ ]
535+ } ;
536+ const result = scoreDatasetRelevance ( 'Lecce' , dataset ) ;
537+
538+ expect ( result . breakdown . holder ) . toBeGreaterThan ( 0 ) ;
539+ expect ( result . breakdown . publisher ) . toBeGreaterThan ( 0 ) ;
540+ expect ( result . total ) . toBe (
541+ result . breakdown . title +
542+ result . breakdown . notes +
543+ result . breakdown . tags +
544+ result . breakdown . organization +
545+ result . breakdown . holder +
546+ result . breakdown . publisher
547+ ) ;
548+ } ) ;
549+
550+ it ( 'non-DCAT portal: holder and publisher score 0 when fields absent' , ( ) => {
551+ const dataset = {
552+ title : 'Health Dataset' ,
553+ organization : { name : 'health-canada' , title : 'Health Canada' }
554+ } ;
555+ const result = scoreDatasetRelevance ( 'health' , dataset ) ;
556+
557+ expect ( result . breakdown . holder ) . toBe ( 0 ) ;
558+ expect ( result . breakdown . publisher ) . toBe ( 0 ) ;
559+ } ) ;
560+
561+ it ( 'uses default weight 4 for holder' , ( ) => {
562+ const dataset = {
563+ title : 'Data' ,
564+ extras : [ { key : 'holder_name' , value : 'Comune di Lecce' } ]
565+ } ;
566+ const result = scoreDatasetRelevance ( 'Lecce' , dataset ) ;
567+
568+ expect ( result . breakdown . holder ) . toBe ( 4 ) ;
569+ } ) ;
570+
571+ it ( 'uses default weight 2 for publisher' , ( ) => {
572+ const dataset = {
573+ title : 'Data' ,
574+ extras : [ { key : 'publisher_name' , value : 'Comune di Lecce' } ]
575+ } ;
576+ const result = scoreDatasetRelevance ( 'Lecce' , dataset ) ;
577+
578+ expect ( result . breakdown . publisher ) . toBe ( 2 ) ;
579+ } ) ;
580+ } ) ;
0 commit comments