Skip to content

Commit f5f95ea

Browse files
committed
Parameterised crossref citedby xml validation tests
1 parent d6c4ef8 commit f5f95ea

1 file changed

Lines changed: 113 additions & 125 deletions

File tree

backend/src/test/kotlin/org/loculus/backend/service/crossref/CrossRefServiceTest.kt

Lines changed: 113 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import org.junit.jupiter.api.Assertions.assertEquals
44
import org.junit.jupiter.api.Assertions.assertTrue
55
import org.junit.jupiter.api.Test
66
import org.junit.jupiter.api.assertThrows
7+
import org.junit.jupiter.params.ParameterizedTest
8+
import org.junit.jupiter.params.provider.MethodSource
79
import org.loculus.backend.SpringBootTestWithoutDatabase
810
import org.loculus.backend.api.CitationContributor
911
import org.loculus.backend.api.CitationSource
@@ -97,55 +99,13 @@ class CrossRefServiceTest(@Autowired private val crossRefService: CrossRefServic
9799
assertTrue(result.validationErrors.isEmpty())
98100
}
99101

100-
@Test
101-
fun `parseCrossRefCitedByXML records validation error when forward_link is missing the seqSet DOI attribute`() {
102-
val xml = """
103-
<crossref_result>
104-
<forward_link>
105-
<journal_cite>
106-
<doi>10.5678/paper-1</doi>
107-
</journal_cite>
108-
</forward_link>
109-
</crossref_result>
110-
""".trimIndent()
111-
112-
val result = crossRefService.parseCrossRefCitedByXML(xml)
113-
assertTrue(result.sources.isEmpty())
114-
assertEquals(1, result.validationErrors.size)
115-
assertTrue(result.validationErrors[0].reason.contains("missing seqset doi", ignoreCase = true))
116-
}
117-
118-
@Test
119-
fun `parseCrossRefCitedByXML records validation error when forward_link has no citation element`() {
120-
val xml = """
121-
<crossref_result>
122-
<forward_link doi="10.1234/seqset-1"/>
123-
</crossref_result>
124-
""".trimIndent()
125-
126-
val result = crossRefService.parseCrossRefCitedByXML(xml)
127-
assertTrue(result.sources.isEmpty())
128-
assertEquals(1, result.validationErrors.size)
129-
assertTrue(result.validationErrors[0].reason.contains("no citation element", ignoreCase = true))
130-
}
131-
132-
@Test
133-
fun `parseCrossRefCitedByXML records validation error when citation source has no DOI`() {
134-
val xml = """
135-
<crossref_result>
136-
<forward_link doi="10.1234/seqset-1">
137-
<journal_cite>
138-
<title>A citing paper</title>
139-
<year>2024</year>
140-
</journal_cite>
141-
</forward_link>
142-
</crossref_result>
143-
""".trimIndent()
144-
145-
val result = crossRefService.parseCrossRefCitedByXML(xml)
102+
@ParameterizedTest(name = "parseCrossRefCitedByXML records validation error: {0}")
103+
@MethodSource("crossRefValidationErrorCases")
104+
fun `parseCrossRefCitedByXML records validation error for invalid XML`(case: CrossRefValidationErrorCase) {
105+
val result = crossRefService.parseCrossRefCitedByXML(case.xml)
146106
assertTrue(result.sources.isEmpty())
147107
assertEquals(1, result.validationErrors.size)
148-
assertTrue(result.validationErrors[0].reason.contains("source missing doi", ignoreCase = true))
108+
assertTrue(result.validationErrors[0].reason.contains(case.expectedReasonContains, ignoreCase = true))
149109
}
150110

151111
@Test
@@ -197,84 +157,6 @@ class CrossRefServiceTest(@Autowired private val crossRefService: CrossRefServic
197157
)
198158
}
199159

200-
@Test
201-
fun `parseCrossRefCitedByXML records validation error when citation source title is missing`() {
202-
val xml = """
203-
<crossref_result>
204-
<forward_link doi="10.1234/seqset-1">
205-
<journal_cite>
206-
<doi>10.5678/paper-1</doi>
207-
<year>2024</year>
208-
</journal_cite>
209-
</forward_link>
210-
</crossref_result>
211-
""".trimIndent()
212-
213-
val result = crossRefService.parseCrossRefCitedByXML(xml)
214-
assertTrue(result.sources.isEmpty())
215-
assertEquals(1, result.validationErrors.size)
216-
assertTrue(result.validationErrors[0].reason.contains("missing title", ignoreCase = true))
217-
}
218-
219-
@Test
220-
fun `parseCrossRefCitedByXML records validation error when citation source title is blank`() {
221-
val xml = """
222-
<crossref_result>
223-
<forward_link doi="10.1234/seqset-1">
224-
<journal_cite>
225-
<doi>10.5678/paper-1</doi>
226-
<title> </title>
227-
<year>2024</year>
228-
</journal_cite>
229-
</forward_link>
230-
</crossref_result>
231-
""".trimIndent()
232-
233-
val result = crossRefService.parseCrossRefCitedByXML(xml)
234-
assertTrue(result.sources.isEmpty())
235-
assertEquals(1, result.validationErrors.size)
236-
assertTrue(result.validationErrors[0].reason.contains("missing title", ignoreCase = true))
237-
}
238-
239-
@Test
240-
fun `parseCrossRefCitedByXML records validation error when citation source year is missing`() {
241-
val xml = """
242-
<crossref_result>
243-
<forward_link doi="10.1234/seqset-1">
244-
<journal_cite>
245-
<doi>10.5678/paper-1</doi>
246-
<title>A citing paper</title>
247-
</journal_cite>
248-
</forward_link>
249-
</crossref_result>
250-
""".trimIndent()
251-
252-
val result = crossRefService.parseCrossRefCitedByXML(xml)
253-
assertTrue(result.sources.isEmpty())
254-
assertEquals(1, result.validationErrors.size)
255-
assertTrue(result.validationErrors[0].reason.contains("missing or non-numeric year", ignoreCase = true))
256-
}
257-
258-
@Test
259-
fun `parseCrossRefCitedByXML records validation error when citation source year is non-numeric`() {
260-
val xml = """
261-
<crossref_result>
262-
<forward_link doi="10.1234/seqset-1">
263-
<journal_cite>
264-
<doi>10.5678/paper-1</doi>
265-
<title>A citing paper</title>
266-
<year>not-a-year</year>
267-
</journal_cite>
268-
</forward_link>
269-
</crossref_result>
270-
""".trimIndent()
271-
272-
val result = crossRefService.parseCrossRefCitedByXML(xml)
273-
assertTrue(result.sources.isEmpty())
274-
assertEquals(1, result.validationErrors.size)
275-
assertTrue(result.validationErrors[0].reason.contains("missing or non-numeric year", ignoreCase = true))
276-
}
277-
278160
@Test
279161
fun `parseCrossRefCitedByXML returns valid sources and records errors for invalid ones in a mixed batch`() {
280162
val xml = """
@@ -384,4 +266,110 @@ class CrossRefServiceTest(@Autowired private val crossRefService: CrossRefServic
384266

385267
assertEquals(crossRefXML, crossRefXMLReference)
386268
}
269+
270+
companion object {
271+
data class CrossRefValidationErrorCase(
272+
val description: String,
273+
val xml: String,
274+
val expectedReasonContains: String,
275+
)
276+
277+
@JvmStatic
278+
fun crossRefValidationErrorCases(): List<CrossRefValidationErrorCase> = listOf(
279+
CrossRefValidationErrorCase(
280+
description = "forward_link missing seqSet DOI attribute",
281+
xml = """
282+
<crossref_result>
283+
<forward_link>
284+
<journal_cite>
285+
<doi>10.5678/paper-1</doi>
286+
</journal_cite>
287+
</forward_link>
288+
</crossref_result>
289+
""".trimIndent(),
290+
expectedReasonContains = "missing seqset doi",
291+
),
292+
CrossRefValidationErrorCase(
293+
description = "forward_link has no citation element",
294+
xml = """
295+
<crossref_result>
296+
<forward_link doi="10.1234/seqset-1"/>
297+
</crossref_result>
298+
""".trimIndent(),
299+
expectedReasonContains = "no citation element",
300+
),
301+
CrossRefValidationErrorCase(
302+
description = "citation source has no DOI",
303+
xml = """
304+
<crossref_result>
305+
<forward_link doi="10.1234/seqset-1">
306+
<journal_cite>
307+
<title>A citing paper</title>
308+
<year>2024</year>
309+
</journal_cite>
310+
</forward_link>
311+
</crossref_result>
312+
""".trimIndent(),
313+
expectedReasonContains = "source missing doi",
314+
),
315+
CrossRefValidationErrorCase(
316+
description = "citation source title is missing",
317+
xml = """
318+
<crossref_result>
319+
<forward_link doi="10.1234/seqset-1">
320+
<journal_cite>
321+
<doi>10.5678/paper-1</doi>
322+
<year>2024</year>
323+
</journal_cite>
324+
</forward_link>
325+
</crossref_result>
326+
""".trimIndent(),
327+
expectedReasonContains = "missing title",
328+
),
329+
CrossRefValidationErrorCase(
330+
description = "citation source title is blank",
331+
xml = """
332+
<crossref_result>
333+
<forward_link doi="10.1234/seqset-1">
334+
<journal_cite>
335+
<doi>10.5678/paper-1</doi>
336+
<title> </title>
337+
<year>2024</year>
338+
</journal_cite>
339+
</forward_link>
340+
</crossref_result>
341+
""".trimIndent(),
342+
expectedReasonContains = "missing title",
343+
),
344+
CrossRefValidationErrorCase(
345+
description = "citation source year is missing",
346+
xml = """
347+
<crossref_result>
348+
<forward_link doi="10.1234/seqset-1">
349+
<journal_cite>
350+
<doi>10.5678/paper-1</doi>
351+
<title>A citing paper</title>
352+
</journal_cite>
353+
</forward_link>
354+
</crossref_result>
355+
""".trimIndent(),
356+
expectedReasonContains = "missing or non-numeric year",
357+
),
358+
CrossRefValidationErrorCase(
359+
description = "citation source year is non-numeric",
360+
xml = """
361+
<crossref_result>
362+
<forward_link doi="10.1234/seqset-1">
363+
<journal_cite>
364+
<doi>10.5678/paper-1</doi>
365+
<title>A citing paper</title>
366+
<year>not-a-year</year>
367+
</journal_cite>
368+
</forward_link>
369+
</crossref_result>
370+
""".trimIndent(),
371+
expectedReasonContains = "missing or non-numeric year",
372+
),
373+
)
374+
}
387375
}

0 commit comments

Comments
 (0)