diff --git a/grails-app/services/au/org/ala/volunteer/ExportService.groovy b/grails-app/services/au/org/ala/volunteer/ExportService.groovy index 713213f0..b2d8b6a2 100644 --- a/grails-app/services/au/org/ala/volunteer/ExportService.groovy +++ b/grails-app/services/au/org/ala/volunteer/ExportService.groovy @@ -653,7 +653,7 @@ class ExportService { // Check Event Date's validity jsonMapValues["dwc:Event"].verbatimEventDate = jsonMapValues["dwc:Event"].eventDate // Check if the date parses for an ISO 8601 format. If not, wipe the eventDate field (as it's invalid). - if (jsonMapValues["dwc:Event"].eventDate ==~ /^\d{4}(?:-\d{1,2}(?:-\d{1,2}))(?:\/\d{4}(?:-\d{1,2}(?:-\d{1,2})))$/) { + if (jsonMapValues["dwc:Event"].eventDate ==~ /^\d{4}(?:-\d{1,2}(?:-\d{1,2})?)$/) { log.debug("Regex parse true: ${jsonMapValues["dwc:Event"].eventDate}") } else { log.debug("Regex parse false ${jsonMapValues["dwc:Event"].eventDate}") diff --git a/src/test/groovy/au/org/ala/volunteer/AjaxControllerSpec.groovy b/src/test/groovy/au/org/ala/volunteer/AjaxControllerSpec.groovy index 7525a10c..07337014 100644 --- a/src/test/groovy/au/org/ala/volunteer/AjaxControllerSpec.groovy +++ b/src/test/groovy/au/org/ala/volunteer/AjaxControllerSpec.groovy @@ -4,10 +4,9 @@ import au.org.ala.userdetails.UserDetailsFromIdListResponse import au.org.ala.volunteer.helper.FlybernateSpec import au.org.ala.web.AuthService import au.org.ala.web.UserDetails -import grails.test.hibernate.HibernateSpec import grails.testing.web.controllers.ControllerUnitTest +import groovy.util.logging.Slf4j -//import grails.test.mixin.TestFor import org.grails.web.json.JSONArray import org.grails.web.json.JSONObject @@ -15,7 +14,7 @@ import static au.org.ala.volunteer.helper.TaskDataHelper.setupProject import static au.org.ala.volunteer.helper.TaskDataHelper.setupTasks import static au.org.ala.volunteer.helper.TaskDataHelper.transcribe -//@TestFor(AjaxController) +@Slf4j class AjaxControllerSpec extends FlybernateSpec implements ControllerUnitTest<AjaxController> { String userId = 'u1' @@ -28,6 +27,9 @@ class AjaxControllerSpec extends FlybernateSpec implements ControllerUnitTest<Aj tasks.take(5).collect { task -> transcribe(task, userId, [:]) } controller.authService = Stub(AuthService) controller.authService.getUserDetailsById(_, _) >> { List<String> ids, boolean includeProps -> new UserDetailsFromIdListResponse(true, '', ['ud1' : new UserDetails(1L, 'First', 'Second', 'ud1@ud1.com', 'ud1', false, '', '', 'organisation', 'Canberra', 'ACT', '', ['ROLE_USER'] as Set)], []) } + controller.taskService = Stub(TaskService) + controller.fieldService = Stub(FieldService) + controller.exportService = Stub(ExportService) } def "test transcription feed"() { @@ -44,4 +46,16 @@ class AjaxControllerSpec extends FlybernateSpec implements ControllerUnitTest<Aj json.items.size() == 5 } + def "test json dwc export"() { + setup: + request.setParameters(['id': "${project.id}".toString()]) + + when: + controller.expeditionDwcJson() + + then: + def json = response.json + log.debug("json: ${json}") + json instanceof JSONObject + } } diff --git a/src/test/groovy/au/org/ala/volunteer/ExportServiceSpec.groovy b/src/test/groovy/au/org/ala/volunteer/ExportServiceSpec.groovy index b93b4dec..5ab2dbb5 100644 --- a/src/test/groovy/au/org/ala/volunteer/ExportServiceSpec.groovy +++ b/src/test/groovy/au/org/ala/volunteer/ExportServiceSpec.groovy @@ -4,19 +4,20 @@ import grails.plugins.csv.CSVMapReader import grails.testing.gorm.DataTest import grails.testing.services.ServiceUnitTest -//import grails.test.mixin.TestFor import grails.web.mapping.LinkGenerator +import groovy.util.logging.Slf4j import org.grails.plugins.testing.GrailsMockHttpServletResponse import spock.lang.Specification import java.text.DateFormat import java.text.SimpleDateFormat -//@TestFor(ExportService) +@Slf4j class ExportServiceSpec extends Specification implements ServiceUnitTest<ExportService>, DataTest { FieldService fieldService TaskService taskService + MultimediaService multimediaService GrailsMockHttpServletResponse response Project project LinkGenerator grailsLinkGenerator @@ -28,6 +29,8 @@ class ExportServiceSpec extends Specification implements ServiceUnitTest<ExportS Date defaultTranscriptionDate def setup() { + multimediaService = Mock(MultimediaService) + service.multimediaService = multimediaService fieldService = Mock(FieldService) service.fieldService = fieldService grailsApplication.config.exportCSVThreadPoolSize = 1 @@ -54,9 +57,16 @@ class ExportServiceSpec extends Specification implements ServiceUnitTest<ExportS } private Task createTask(String externalIdentifier = '') { - Task task = new Task(transcriptions: new HashSet(), project:project, externalIdentifier: externalIdentifier) + Task task = new Task(transcriptions: new HashSet(), multimedia: new HashSet(), project: project, externalIdentifier: externalIdentifier) + Multimedia mm = new Multimedia().tap { + filePath = "filepath.jpg" + filePathToThumbnail = "filepath_thumb.jpg" + created = new Date() + } + task.multimedia.add(mm) project.tasks.add(task) mockDomain(Task, [task]) + mockDomain(Multimedia, [mm]) task } @@ -362,4 +372,62 @@ class ExportServiceSpec extends Specification implements ServiceUnitTest<ExportS and: response.getHeader("Content-Disposition") == "attachment;filename=Project-Test-DwC.csv" } + + def "Task fields can be exported to JSON"() { + setup: + String today = dateFormat.format(new Date()) + Date transcriptionDate = dateTimeFormat.parse('01/07/2019 10:30:00') + Task task = createTask() + def multimedia = task.multimedia.first() + task.externalIdentifier = 'external id' + String userId = '1234' + List<Task> taskList = [project.tasks as List] + List<String> fieldNames = taskOrTranscriptionFields + List fieldData = [[name:"scientificName", value:"Magpie"], [name:"eventDate", value:"1984-03-23"]] + List fields = transcribeTask(task, fieldData, userId, transcriptionDate) + + when: + List result = service.exportJson(taskList, fields) + log.debug("Result: ${result}") + + then: + 1 * multimediaService.getImageUrl(multimedia) >> "" + 1 * multimediaService.getImageThumbnailUrl(multimedia) >> "" + + and: + result.size() == 1 // One row, not counting headers + result[0]['dwc:Occurrence'].size() == 2 + result[0]['dwc:Occurrence'].occurrenceId == "1" + result[0]['dwc:Event'].verbatimEventDate == "1984-03-23" + result[0]['dwc:Event'].eventDate == "1984-03-23" + } + + def "JSON export excludes non-conforming date pattern"() { + setup: + String today = dateFormat.format(new Date()) + Date transcriptionDate = dateTimeFormat.parse('01/07/2019 10:30:00') + Task task = createTask() + def multimedia = task.multimedia.first() + task.externalIdentifier = 'external id' + String userId = '1234' + List<Task> taskList = [project.tasks as List] + List<String> fieldNames = taskOrTranscriptionFields + List fieldData = [[name:"scientificName", value:"Magpie"], [name:"eventDate", value:"1984-IX"]] + List fields = transcribeTask(task, fieldData, userId, transcriptionDate) + + when: + List result = service.exportJson(taskList, fields) + log.debug("Result: ${result}") + + then: + 1 * multimediaService.getImageUrl(multimedia) >> "" + 1 * multimediaService.getImageThumbnailUrl(multimedia) >> "" + + and: + result.size() == 1 // One row, not counting headers + result[0]['dwc:Occurrence'].size() == 2 + result[0]['dwc:Occurrence'].occurrenceId == "1" + result[0]['dwc:Event'].verbatimEventDate == "1984-IX" + !result[0]['dwc:Event'].eventDate + } } diff --git a/src/test/groovy/au/org/ala/volunteer/helper/TaskDataHelper.groovy b/src/test/groovy/au/org/ala/volunteer/helper/TaskDataHelper.groovy index ff11d93d..56383b7c 100644 --- a/src/test/groovy/au/org/ala/volunteer/helper/TaskDataHelper.groovy +++ b/src/test/groovy/au/org/ala/volunteer/helper/TaskDataHelper.groovy @@ -3,6 +3,7 @@ package au.org.ala.volunteer.helper import au.org.ala.volunteer.Field import au.org.ala.volunteer.ForumMessage import au.org.ala.volunteer.ForumTopic +import au.org.ala.volunteer.Institution import au.org.ala.volunteer.Project import au.org.ala.volunteer.ProjectForumTopic import au.org.ala.volunteer.ProjectType @@ -37,6 +38,11 @@ class TaskDataHelper { viewParams = [param1:'value1'] viewParams2 = [param1:'value1'] } + p.institution = new Institution().tap { + name = "Test Institution" + contactName = "Test Institution Admin" + contactEmail = "test@institution.me" + } pt.save(failOnError:true) p.template.save(failOnError:true) p.save(failOnError:true, flush:true) diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index c6da00a8..e7a06349 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -11,7 +11,7 @@ <!-- <logger name="au.org.ala.volunteer" level="DEBUG" />--> <!-- <logger name="org.flywaydb" level="TRACE" />--> - <root level="info"> + <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration> \ No newline at end of file