• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse-frontend / 23954250439

03 Apr 2026 04:52PM UTC coverage: 97.448% (-0.6%) from 98.063%
23954250439

Pull #908

github

ChengShi-1
fix: test coverage
Pull Request #908: Manage Dataset Templates Integration

4563 of 4779 branches covered (95.48%)

Branch coverage included in aggregate %.

363 of 380 new or added lines in 26 files covered. (95.53%)

50 existing lines in 20 files now uncovered.

8876 of 9012 relevant lines covered (98.49%)

10431.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.57
/src/sections/templates/useCopyTemplate.ts
1
import { useCallback, useState } from 'react'
2
import { useTranslation } from 'react-i18next'
3
import { ReadError, WriteError } from '@iqss/dataverse-client-javascript'
4
import { toast } from 'react-toastify'
5
import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepository'
6
import { MetadataBlockInfoRepository } from '@/metadata-block-info/domain/repositories/MetadataBlockInfoRepository'
7
import { type MetadataField } from '@/metadata-block-info/domain/models/MetadataBlockInfo'
8
import { getTemplate } from '@/templates/domain/useCases/getTemplate'
9
import { createTemplate } from '@/templates/domain/useCases/createTemplate'
10
import { getMetadataBlockInfoByCollectionId } from '@/metadata-block-info/domain/useCases/getMetadataBlockInfoByCollectionId'
11
import { MetadataFieldsHelper } from '@/sections/shared/form/DatasetMetadataForm/MetadataFieldsHelper'
12
import { TemplateInfo } from '@/templates/domain/models/TemplateInfo'
13
import { JSDataverseReadErrorHandler } from '@/shared/helpers/JSDataverseReadErrorHandler'
14
import { JSDataverseWriteErrorHandler } from '@/shared/helpers/JSDataverseWriteErrorHandler'
15
import { type DatasetMetadataFieldsDTO } from '@/dataset/domain/useCases/DTOs/DatasetDTO'
16
import { type DatasetMetadataFields } from '@/dataset/domain/models/Dataset'
17

18
interface UseCopyTemplateProps {
19
  collectionId: string
20
  templateRepository: TemplateRepository
21
  metadataBlockInfoRepository: MetadataBlockInfoRepository
22
}
23

24
interface CopyTemplateResult {
25
  copyTemplate: (templateId: number) => Promise<boolean>
26
  isCopyingTemplate: boolean
27
  errorCopyTemplate: string | null
28
}
29

30
const toDatasetMetadataFieldsDTO = (fields: DatasetMetadataFields): DatasetMetadataFieldsDTO => {
33✔
31
  const sanitized: DatasetMetadataFieldsDTO = {}
28✔
32
  Object.entries(fields).forEach(([key, value]) => {
28✔
33
    sanitized[key] = value as DatasetMetadataFieldsDTO[typeof key]
28✔
34
  })
35
  return sanitized
28✔
36
}
37

38
export const useCopyTemplate = ({
33✔
39
  collectionId,
40
  templateRepository,
41
  metadataBlockInfoRepository
42
}: UseCopyTemplateProps): CopyTemplateResult => {
43
  const { t } = useTranslation('datasetTemplates')
2,166✔
44
  const [isCopyingTemplate, setIsCopyingTemplate] = useState(false)
2,166✔
45
  const [errorCopyTemplate, setErrorCopyTemplate] = useState<string | null>(null)
2,166✔
46

47
  const copyTemplate = useCallback(
2,166✔
48
    async (templateId: number) => {
49
      setIsCopyingTemplate(true)
38✔
50
      setErrorCopyTemplate(null)
38✔
51

52
      try {
38✔
53
        const template = await getTemplate(templateRepository, templateId)
38✔
54
        const metadataBlocksInfo = await getMetadataBlockInfoByCollectionId(
28✔
55
          metadataBlockInfoRepository,
56
          collectionId
57
        )
58

59
        const metadataFieldsForMapping = metadataBlocksInfo.reduce<
28✔
60
          Record<string, Record<string, MetadataField>>
61
        >((acc, block) => {
62
          acc[block.name] = block.metadataFields ?? {}
28!
63
          return acc
28✔
64
        }, {})
65

66
        const templateFields =
67
          template.datasetMetadataBlocks?.flatMap((metadataBlock) =>
28!
68
            MetadataFieldsHelper.buildTemplateFieldsFromMetadataValues(
28✔
69
              toDatasetMetadataFieldsDTO(metadataBlock.fields),
70
              metadataFieldsForMapping[metadataBlock.name] ?? {}
28!
71
            )
72
          ) ?? []
73

74
        const templatePayload: TemplateInfo = {
28✔
75
          name: t('copyNamePrefix', { name: template.name }),
76
          isDefault: template.isDefault,
77
          fields: templateFields,
78
          instructions: template.instructions
79
        }
80

81
        await createTemplate(templateRepository, templatePayload, collectionId)
28✔
82

83
        toast.success(t('alerts.copySuccess'))
11✔
84
        return true
11✔
85
      } catch (error) {
86
        if (error instanceof ReadError) {
27✔
87
          const handler = new JSDataverseReadErrorHandler(error)
10✔
88
          setErrorCopyTemplate(
10✔
89
            handler.getReasonWithoutStatusCode() ??
10✔
90
              /* istanbul ignore next */ handler.getErrorMessage()
91
          )
92
        } else if (error instanceof WriteError) {
17✔
93
          const handler = new JSDataverseWriteErrorHandler(error)
8✔
94
          setErrorCopyTemplate(
8✔
95
            handler.getReasonWithoutStatusCode() ??
8✔
96
              /* istanbul ignore next */ handler.getErrorMessage()
97
          )
98
        } else if (error instanceof Error && error.message) {
9!
99
          setErrorCopyTemplate(error.message)
9✔
100
        } else {
NEW
101
          setErrorCopyTemplate(t('alerts.copyError'))
×
102
        }
103

104
        toast.error(t('alerts.copyError'))
27✔
105
        return false
27✔
106
      } finally {
107
        setIsCopyingTemplate(false)
38✔
108
      }
109
    },
110
    [collectionId, metadataBlockInfoRepository, t, templateRepository]
111
  )
112

113
  return { copyTemplate, isCopyingTemplate, errorCopyTemplate }
2,166✔
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc