/src/main/resources/com/onresolve/jira/groovy/test/TestScriptedFields.groovy
Groovy | 330 lines | 235 code | 72 blank | 23 comment | 11 complexity | f21a425c7d55c97845a6bcac26fb5efc MD5 | raw file
- package com.onresolve.jira.groovy.test
-
- import com.atlassian.core.util.collection.EasyList
- import com.atlassian.jira.ComponentManager
- import com.atlassian.jira.issue.Issue
- import com.atlassian.jira.issue.context.GlobalIssueContext
- import com.atlassian.jira.issue.customfields.CustomFieldSearcher
- import com.atlassian.jira.issue.customfields.CustomFieldType
- import com.atlassian.jira.issue.fields.CustomField
- import com.atlassian.jira.issue.fields.config.manager.FieldConfigSchemeManager
- import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem
- import com.atlassian.jira.issue.fields.layout.field.FieldLayoutManager
- import com.atlassian.jira.issue.search.SearchProvider
- import com.atlassian.jira.issue.search.SearchRequest
- import com.atlassian.jira.issue.search.SearchResults
- import com.atlassian.jira.jql.builder.JqlQueryBuilder
- import com.atlassian.jira.util.json.JSONObject
- import com.atlassian.jira.web.bean.PagerFilter
- import com.atlassian.query.Query
- import com.onresolve.jira.groovy.ViewScriptedFields
- import com.onresolve.jira.groovy.customfield.CustomFieldConfiguration
- import org.apache.log4j.Category
- import org.junit.After
- import org.junit.Before
- import org.junit.Test
- import org.ofbiz.core.entity.GenericValue
-
- import static junit.framework.Assert.*
-
- class TestScriptedFields extends BaseSubTaskTest{
-
- Category log = Category.getInstance(this.class)
- CustomField customField
- FieldConfigSchemeManager fieldConfigSchemeManager = ComponentManager.getComponentInstanceOfType(FieldConfigSchemeManager.class)
- SearchProvider searchProvider = componentManager.getSearchProvider()
- FieldLayoutManager fieldLayoutManager = componentManager.getFieldLayoutManager()
-
- @Before
- public void setUp() {
- assertNotNull(project)
- }
-
- public CustomField getTextCustomField() {
- String cfName = "TestScriptFieldSimpleText"
- String searcher = "com.onresolve.jira.groovy.groovyrunner:textsearcher"
- getScriptedCustomField(cfName, searcher)
- }
-
- public CustomField getNumberCustomField() {
- String cfName = "TestScriptFieldSimpleNumber"
- String searcher = "com.onresolve.jira.groovy.groovyrunner:exactnumber"
- getScriptedCustomField(cfName, searcher)
- }
-
- public CustomField getUserCustomField() {
- String cfName = "TestScriptFieldUser"
- String searcher = "com.onresolve.jira.groovy.groovyrunner:userpickersearcher"
- getScriptedCustomField(cfName, searcher)
- }
-
- public CustomField getDateCustomField() {
- String cfName = "TestScriptFieldDate"
- String searcher = "com.onresolve.jira.groovy.groovyrunner:datetimerange"
- getScriptedCustomField(cfName, searcher)
- }
-
- private getScriptedCustomField(String cfName, String searcher) {
- if (!customFieldManager.getCustomFieldObjectByName(cfName)) {
- log.debug("Create custom field: $cfName")
- customField = createScriptField(cfName, searcher)
- }
- else {
- customField = customFieldManager.getCustomFieldObjectByName(cfName)
- }
- customField
- }
-
-
- private Issue createAnIssue() {
- issue = componentManager.getIssueFactory().getIssue()
- issue.setProject(project.getGenericValue())
- issue.setSummary "my summary"
- issue.setReporterId "admin"
- issue.setCustomFieldValue(customFieldManager.getCustomFieldObjectByName("TextFieldA"), "custom field value")
- issue.setIssueType issueType.getGenericValue()
- issue.setPriorityId('1')
- GenericValue gv = issueManager.createIssue(adminUser, issue);
- return issueManager.getIssueObject(gv.get('key') as String)
- }
-
- @After
- public void tearDown() {
- customFieldManager.getCustomFieldObjects().each {CustomField cf ->
- if (cf.customFieldType.getClass().getName() == "com.onresolve.jira.groovy.GroovyCustomField" && cf.name.startsWith("Test")) {
- log.debug("Remove custom field: " + cf.getName())
- customFieldManager.removeCustomField(cf)
- }
- }
- deleteAllIssues()
- }
-
- @Test
- public void testCreateIssueWithTextSearcher() {
- customField = getTextCustomField()
-
- saveScript('return "AAA"', customField, "textarea")
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
- assertEquals("AAA", issue.getCustomFieldValue(customField))
-
- saveScript('return "BBB"', customField, "textarea")
- issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
- assertEquals("BBB", issue.getCustomFieldValue(customField))
-
- // test searching works ok.
- String queryValue = "AAA"
- assertEquals(1, queryForCFValue(queryValue))
-
- queryValue = "BBB"
- assertEquals(1, queryForCFValue(queryValue))
-
- assertEquals("BBB", getHtml(issue, customField).trim())
-
-
- // reindex the second issue, eg update it, and we should have two results for BBB
-
- // todo: test multiple field configs
-
- // todo: do a test for no template configured
- // (ie programatically create the number custom field, then access an issue with it on),
- // this causes fatal error and need to restart jira
-
- // todo: test mismatched renderers and searchers
-
- // todo: test using a file
- // todo: test more complex script functions
-
- }
-
- @Test
- public void testScriptHelperFunctions() {
- customField = getTextCustomField()
-
- saveScript('return "AAA"', customField, "textarea")
- // Issue issue = createAnIssue()
-
- }
-
- @Test
- public void testSavingRetrievingConfig() {
- customField = getTextCustomField()
- saveScript('return "AAA"', customField, "textarea")
-
- def scriptManager = getScriptManager()
- ViewScriptedFields viewScriptedFields = new ViewScriptedFields(scriptManager)
-
- Map<Long, CustomFieldConfiguration> configs = viewScriptedFields.getConfigs()
-
- long oneAndOnlyFieldConfig = fieldConfigSchemeManager.getConfigSchemesForField(customField).get(0).id
- log.debug("Field config that is being set is: " + oneAndOnlyFieldConfig)
-
- CustomFieldConfiguration customFieldConfiguration = configs.get(oneAndOnlyFieldConfig)
- log.debug(customFieldConfiguration.getScriptFile() == null)
-
- log.debug scriptManager.getConfigFor(oneAndOnlyFieldConfig).getScriptFile() == null
-
- }
-
- @Test
- public void testCreateIssueWithCustomTemplate() {
- customField = getTextCustomField()
- def helloSailor = "HELLO SAILOR"
- saveScript('"bollo"', customField, "custom", null, helloSailor + ' $!value')
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
-
- // test custom field value
- assertEquals("bollo", issue.getCustomFieldValue(customField))
-
- // test rendering
- assertEquals(helloSailor + " bollo", getHtml(issue, customField).trim())
- }
-
-
- @Test
- public void testCreateIssueWithNumberSearcher() {
- customField = getNumberCustomField()
- saveScript('return 8 as Double', customField, "float")
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
- assertEquals(8 as Double, issue.getCustomFieldValue(customField))
-
- // test rendering
- assertEquals("8", getHtml(issue, customField).trim())
- }
-
- /**
- * Test using a file to hold the groovy script rather than have it inline
- */
- @Test
- public void testScriptFileNotInline() {
- customField = getUserCustomField()
- def file = File.createTempFile("test", ".groovy")
- file.write("return issue.reporter\n")
- saveScriptFile(file.absolutePath, customField, "userpicker")
-
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
-
- assertEquals(componentManager.getJiraAuthenticationContext().getUser(), issue.getCustomFieldValue(customField))
-
- // test rendering - actual returned text is some html with a hover etc
- assertTrue(getHtml(issue, customField).trim().contains("user_cf_admin"))
-
- file.delete()
- }
-
- @Test
- public void testCreateIssueWithUserSearcher() {
- customField = getUserCustomField()
- saveScript('return issue.reporter', customField, "userpicker")
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
- assertEquals(componentManager.getJiraAuthenticationContext().getUser(), issue.getCustomFieldValue(customField))
-
- // test rendering - actual returned text is some html with a hover etc
- assertTrue(getHtml(issue, customField).trim().contains("user_cf_admin"))
- }
-
- @Test
- public void testCreateIssueWithDateSearcher() {
- customField = getDateCustomField()
-
- saveScript('return Calendar.getInstance().getTime()', customField, "datetime")
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
- log.debug(issue.getCustomFieldValue(customField))
- // todo: +/- a second or so
- assertEquals(Calendar.getInstance().getTime().getDate(), (issue.getCustomFieldValue(customField) as Date).getDate())
-
- // log.debug(getHtml(issue, customField))
- assertTrue(getHtml(issue, customField).trim().contains("time datetime"))
- }
-
-
- @Test
- public void testUnitialisedScriptedField() {
- customField = getNumberCustomField()
- saveScript('return 8 as Double', customField, null)
- Issue issue = createAnIssue()
- log.debug("Created issue ${issue.key}")
-
- assertEquals(8 as Double, issue.getCustomFieldValue(customField))
- assertEquals("Field not set up correctly - view template is not defined", getHtml(issue, customField).trim())
- }
-
- private String getHtml(Issue issue, CustomField customField) {
- def groovyCustomField = customField.getCustomFieldType()
- FieldLayoutItem fieldLayoutItem = fieldLayoutManager.getFieldLayout(issue).getFieldLayoutItem(customField)
- return groovyCustomField.doVelocityMerge(groovyCustomField.getRealVelocityParameters(issue, customField, fieldLayoutItem))
- }
-
-
- private int queryForCFValue(String queryValue) {
- JqlQueryBuilder jqlQueryBuilder = JqlQueryBuilder.newBuilder()
- Query query = jqlQueryBuilder.where().customField(customField.idAsLong).like(queryValue).buildQuery()
- log.debug("Execute query: " + query.toString())
- SearchRequest sr = new SearchRequest(query)
- SearchResults results = searchProvider.search(sr.getQuery(), componentManager.getJiraAuthenticationContext().getUser(), PagerFilter.getUnlimitedFilter())
- results.total
- }
-
- private saveScriptFile(String file, CustomField customField, String modelTemplate) {
- saveScript(null, customField, modelTemplate, file)
- }
-
- private saveScript(String script, CustomField customField, String modelTemplate, String scriptFile = null, String customTemplate = null) {
- def scriptManager = getScriptManager()
- ViewScriptedFields viewScriptedFields = new ViewScriptedFields(scriptManager)
- Map<Long, CustomFieldConfiguration> configs = viewScriptedFields.getConfigs()
-
- long oneAndOnlyFieldConfig = fieldConfigSchemeManager.getConfigSchemesForField(customField).get(0).id
- log.debug("Field config that is being set is: " + oneAndOnlyFieldConfig)
-
- // todo: refactor all this stuff, it should not be in ViewScriptedFields
- CustomFieldConfiguration customFieldConfiguration = configs.get(oneAndOnlyFieldConfig)
-
- if (scriptFile) {
- customFieldConfiguration.setScriptFile(scriptFile) // relative paths work ok too
- }
- else {
- customFieldConfiguration.setScript(script)
- }
- log.debug "script is: " + (customFieldConfiguration.getScript() ?: customFieldConfiguration.getScriptFile())
-
- customFieldConfiguration.setModelTemplate(modelTemplate)
- if (modelTemplate == "custom") {
- customFieldConfiguration.setCustomTemplate(customTemplate)
- }
-
-
- Map mapToSave = new HashMap()
- configs.each {Long k, CustomFieldConfiguration v ->
- mapToSave.put(k as String, v.asMap())
- }
- JSONObject jSONObject = new JSONObject(mapToSave)
- scriptManager.saveConfig(jSONObject)
- }
-
- // duplicated to com.onresolve.jira.stdworkflows.StdProcessManagerImpl.createScriptField
- public CustomField createScriptField(String cfName, String searcher) {
-
- CustomFieldType customFieldType = customFieldManager.getCustomFieldType("com.onresolve.jira.groovy.groovyrunner:scripted-field")
- CustomFieldSearcher customFieldSearcher = customFieldManager.getCustomFieldSearcher(searcher)
-
- CustomField customField = customFieldManager.createCustomField(cfName,
- "an eg custom field",
- customFieldType,
- customFieldSearcher,
- EasyList.build(GlobalIssueContext.getInstance()),
- [null]);
-
- customFieldManager.clear()
-
- // todo: attach the field to a screen
-
- return customField
- }
- }