PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/resources/com/onresolve/jira/groovy/test/TestScriptedFields.groovy

https://bitbucket.org/sorin/jira-plugin-intellij
Groovy | 330 lines | 235 code | 72 blank | 23 comment | 11 complexity | f21a425c7d55c97845a6bcac26fb5efc MD5 | raw file
  1. package com.onresolve.jira.groovy.test
  2. import com.atlassian.core.util.collection.EasyList
  3. import com.atlassian.jira.ComponentManager
  4. import com.atlassian.jira.issue.Issue
  5. import com.atlassian.jira.issue.context.GlobalIssueContext
  6. import com.atlassian.jira.issue.customfields.CustomFieldSearcher
  7. import com.atlassian.jira.issue.customfields.CustomFieldType
  8. import com.atlassian.jira.issue.fields.CustomField
  9. import com.atlassian.jira.issue.fields.config.manager.FieldConfigSchemeManager
  10. import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem
  11. import com.atlassian.jira.issue.fields.layout.field.FieldLayoutManager
  12. import com.atlassian.jira.issue.search.SearchProvider
  13. import com.atlassian.jira.issue.search.SearchRequest
  14. import com.atlassian.jira.issue.search.SearchResults
  15. import com.atlassian.jira.jql.builder.JqlQueryBuilder
  16. import com.atlassian.jira.util.json.JSONObject
  17. import com.atlassian.jira.web.bean.PagerFilter
  18. import com.atlassian.query.Query
  19. import com.onresolve.jira.groovy.ViewScriptedFields
  20. import com.onresolve.jira.groovy.customfield.CustomFieldConfiguration
  21. import org.apache.log4j.Category
  22. import org.junit.After
  23. import org.junit.Before
  24. import org.junit.Test
  25. import org.ofbiz.core.entity.GenericValue
  26. import static junit.framework.Assert.*
  27. class TestScriptedFields extends BaseSubTaskTest{
  28. Category log = Category.getInstance(this.class)
  29. CustomField customField
  30. FieldConfigSchemeManager fieldConfigSchemeManager = ComponentManager.getComponentInstanceOfType(FieldConfigSchemeManager.class)
  31. SearchProvider searchProvider = componentManager.getSearchProvider()
  32. FieldLayoutManager fieldLayoutManager = componentManager.getFieldLayoutManager()
  33. @Before
  34. public void setUp() {
  35. assertNotNull(project)
  36. }
  37. public CustomField getTextCustomField() {
  38. String cfName = "TestScriptFieldSimpleText"
  39. String searcher = "com.onresolve.jira.groovy.groovyrunner:textsearcher"
  40. getScriptedCustomField(cfName, searcher)
  41. }
  42. public CustomField getNumberCustomField() {
  43. String cfName = "TestScriptFieldSimpleNumber"
  44. String searcher = "com.onresolve.jira.groovy.groovyrunner:exactnumber"
  45. getScriptedCustomField(cfName, searcher)
  46. }
  47. public CustomField getUserCustomField() {
  48. String cfName = "TestScriptFieldUser"
  49. String searcher = "com.onresolve.jira.groovy.groovyrunner:userpickersearcher"
  50. getScriptedCustomField(cfName, searcher)
  51. }
  52. public CustomField getDateCustomField() {
  53. String cfName = "TestScriptFieldDate"
  54. String searcher = "com.onresolve.jira.groovy.groovyrunner:datetimerange"
  55. getScriptedCustomField(cfName, searcher)
  56. }
  57. private getScriptedCustomField(String cfName, String searcher) {
  58. if (!customFieldManager.getCustomFieldObjectByName(cfName)) {
  59. log.debug("Create custom field: $cfName")
  60. customField = createScriptField(cfName, searcher)
  61. }
  62. else {
  63. customField = customFieldManager.getCustomFieldObjectByName(cfName)
  64. }
  65. customField
  66. }
  67. private Issue createAnIssue() {
  68. issue = componentManager.getIssueFactory().getIssue()
  69. issue.setProject(project.getGenericValue())
  70. issue.setSummary "my summary"
  71. issue.setReporterId "admin"
  72. issue.setCustomFieldValue(customFieldManager.getCustomFieldObjectByName("TextFieldA"), "custom field value")
  73. issue.setIssueType issueType.getGenericValue()
  74. issue.setPriorityId('1')
  75. GenericValue gv = issueManager.createIssue(adminUser, issue);
  76. return issueManager.getIssueObject(gv.get('key') as String)
  77. }
  78. @After
  79. public void tearDown() {
  80. customFieldManager.getCustomFieldObjects().each {CustomField cf ->
  81. if (cf.customFieldType.getClass().getName() == "com.onresolve.jira.groovy.GroovyCustomField" && cf.name.startsWith("Test")) {
  82. log.debug("Remove custom field: " + cf.getName())
  83. customFieldManager.removeCustomField(cf)
  84. }
  85. }
  86. deleteAllIssues()
  87. }
  88. @Test
  89. public void testCreateIssueWithTextSearcher() {
  90. customField = getTextCustomField()
  91. saveScript('return "AAA"', customField, "textarea")
  92. Issue issue = createAnIssue()
  93. log.debug("Created issue ${issue.key}")
  94. assertEquals("AAA", issue.getCustomFieldValue(customField))
  95. saveScript('return "BBB"', customField, "textarea")
  96. issue = createAnIssue()
  97. log.debug("Created issue ${issue.key}")
  98. assertEquals("BBB", issue.getCustomFieldValue(customField))
  99. // test searching works ok.
  100. String queryValue = "AAA"
  101. assertEquals(1, queryForCFValue(queryValue))
  102. queryValue = "BBB"
  103. assertEquals(1, queryForCFValue(queryValue))
  104. assertEquals("BBB", getHtml(issue, customField).trim())
  105. // reindex the second issue, eg update it, and we should have two results for BBB
  106. // todo: test multiple field configs
  107. // todo: do a test for no template configured
  108. // (ie programatically create the number custom field, then access an issue with it on),
  109. // this causes fatal error and need to restart jira
  110. // todo: test mismatched renderers and searchers
  111. // todo: test using a file
  112. // todo: test more complex script functions
  113. }
  114. @Test
  115. public void testScriptHelperFunctions() {
  116. customField = getTextCustomField()
  117. saveScript('return "AAA"', customField, "textarea")
  118. // Issue issue = createAnIssue()
  119. }
  120. @Test
  121. public void testSavingRetrievingConfig() {
  122. customField = getTextCustomField()
  123. saveScript('return "AAA"', customField, "textarea")
  124. def scriptManager = getScriptManager()
  125. ViewScriptedFields viewScriptedFields = new ViewScriptedFields(scriptManager)
  126. Map<Long, CustomFieldConfiguration> configs = viewScriptedFields.getConfigs()
  127. long oneAndOnlyFieldConfig = fieldConfigSchemeManager.getConfigSchemesForField(customField).get(0).id
  128. log.debug("Field config that is being set is: " + oneAndOnlyFieldConfig)
  129. CustomFieldConfiguration customFieldConfiguration = configs.get(oneAndOnlyFieldConfig)
  130. log.debug(customFieldConfiguration.getScriptFile() == null)
  131. log.debug scriptManager.getConfigFor(oneAndOnlyFieldConfig).getScriptFile() == null
  132. }
  133. @Test
  134. public void testCreateIssueWithCustomTemplate() {
  135. customField = getTextCustomField()
  136. def helloSailor = "HELLO SAILOR"
  137. saveScript('"bollo"', customField, "custom", null, helloSailor + ' $!value')
  138. Issue issue = createAnIssue()
  139. log.debug("Created issue ${issue.key}")
  140. // test custom field value
  141. assertEquals("bollo", issue.getCustomFieldValue(customField))
  142. // test rendering
  143. assertEquals(helloSailor + " bollo", getHtml(issue, customField).trim())
  144. }
  145. @Test
  146. public void testCreateIssueWithNumberSearcher() {
  147. customField = getNumberCustomField()
  148. saveScript('return 8 as Double', customField, "float")
  149. Issue issue = createAnIssue()
  150. log.debug("Created issue ${issue.key}")
  151. assertEquals(8 as Double, issue.getCustomFieldValue(customField))
  152. // test rendering
  153. assertEquals("8", getHtml(issue, customField).trim())
  154. }
  155. /**
  156. * Test using a file to hold the groovy script rather than have it inline
  157. */
  158. @Test
  159. public void testScriptFileNotInline() {
  160. customField = getUserCustomField()
  161. def file = File.createTempFile("test", ".groovy")
  162. file.write("return issue.reporter\n")
  163. saveScriptFile(file.absolutePath, customField, "userpicker")
  164. Issue issue = createAnIssue()
  165. log.debug("Created issue ${issue.key}")
  166. assertEquals(componentManager.getJiraAuthenticationContext().getUser(), issue.getCustomFieldValue(customField))
  167. // test rendering - actual returned text is some html with a hover etc
  168. assertTrue(getHtml(issue, customField).trim().contains("user_cf_admin"))
  169. file.delete()
  170. }
  171. @Test
  172. public void testCreateIssueWithUserSearcher() {
  173. customField = getUserCustomField()
  174. saveScript('return issue.reporter', customField, "userpicker")
  175. Issue issue = createAnIssue()
  176. log.debug("Created issue ${issue.key}")
  177. assertEquals(componentManager.getJiraAuthenticationContext().getUser(), issue.getCustomFieldValue(customField))
  178. // test rendering - actual returned text is some html with a hover etc
  179. assertTrue(getHtml(issue, customField).trim().contains("user_cf_admin"))
  180. }
  181. @Test
  182. public void testCreateIssueWithDateSearcher() {
  183. customField = getDateCustomField()
  184. saveScript('return Calendar.getInstance().getTime()', customField, "datetime")
  185. Issue issue = createAnIssue()
  186. log.debug("Created issue ${issue.key}")
  187. log.debug(issue.getCustomFieldValue(customField))
  188. // todo: +/- a second or so
  189. assertEquals(Calendar.getInstance().getTime().getDate(), (issue.getCustomFieldValue(customField) as Date).getDate())
  190. // log.debug(getHtml(issue, customField))
  191. assertTrue(getHtml(issue, customField).trim().contains("time datetime"))
  192. }
  193. @Test
  194. public void testUnitialisedScriptedField() {
  195. customField = getNumberCustomField()
  196. saveScript('return 8 as Double', customField, null)
  197. Issue issue = createAnIssue()
  198. log.debug("Created issue ${issue.key}")
  199. assertEquals(8 as Double, issue.getCustomFieldValue(customField))
  200. assertEquals("Field not set up correctly - view template is not defined", getHtml(issue, customField).trim())
  201. }
  202. private String getHtml(Issue issue, CustomField customField) {
  203. def groovyCustomField = customField.getCustomFieldType()
  204. FieldLayoutItem fieldLayoutItem = fieldLayoutManager.getFieldLayout(issue).getFieldLayoutItem(customField)
  205. return groovyCustomField.doVelocityMerge(groovyCustomField.getRealVelocityParameters(issue, customField, fieldLayoutItem))
  206. }
  207. private int queryForCFValue(String queryValue) {
  208. JqlQueryBuilder jqlQueryBuilder = JqlQueryBuilder.newBuilder()
  209. Query query = jqlQueryBuilder.where().customField(customField.idAsLong).like(queryValue).buildQuery()
  210. log.debug("Execute query: " + query.toString())
  211. SearchRequest sr = new SearchRequest(query)
  212. SearchResults results = searchProvider.search(sr.getQuery(), componentManager.getJiraAuthenticationContext().getUser(), PagerFilter.getUnlimitedFilter())
  213. results.total
  214. }
  215. private saveScriptFile(String file, CustomField customField, String modelTemplate) {
  216. saveScript(null, customField, modelTemplate, file)
  217. }
  218. private saveScript(String script, CustomField customField, String modelTemplate, String scriptFile = null, String customTemplate = null) {
  219. def scriptManager = getScriptManager()
  220. ViewScriptedFields viewScriptedFields = new ViewScriptedFields(scriptManager)
  221. Map<Long, CustomFieldConfiguration> configs = viewScriptedFields.getConfigs()
  222. long oneAndOnlyFieldConfig = fieldConfigSchemeManager.getConfigSchemesForField(customField).get(0).id
  223. log.debug("Field config that is being set is: " + oneAndOnlyFieldConfig)
  224. // todo: refactor all this stuff, it should not be in ViewScriptedFields
  225. CustomFieldConfiguration customFieldConfiguration = configs.get(oneAndOnlyFieldConfig)
  226. if (scriptFile) {
  227. customFieldConfiguration.setScriptFile(scriptFile) // relative paths work ok too
  228. }
  229. else {
  230. customFieldConfiguration.setScript(script)
  231. }
  232. log.debug "script is: " + (customFieldConfiguration.getScript() ?: customFieldConfiguration.getScriptFile())
  233. customFieldConfiguration.setModelTemplate(modelTemplate)
  234. if (modelTemplate == "custom") {
  235. customFieldConfiguration.setCustomTemplate(customTemplate)
  236. }
  237. Map mapToSave = new HashMap()
  238. configs.each {Long k, CustomFieldConfiguration v ->
  239. mapToSave.put(k as String, v.asMap())
  240. }
  241. JSONObject jSONObject = new JSONObject(mapToSave)
  242. scriptManager.saveConfig(jSONObject)
  243. }
  244. // duplicated to com.onresolve.jira.stdworkflows.StdProcessManagerImpl.createScriptField
  245. public CustomField createScriptField(String cfName, String searcher) {
  246. CustomFieldType customFieldType = customFieldManager.getCustomFieldType("com.onresolve.jira.groovy.groovyrunner:scripted-field")
  247. CustomFieldSearcher customFieldSearcher = customFieldManager.getCustomFieldSearcher(searcher)
  248. CustomField customField = customFieldManager.createCustomField(cfName,
  249. "an eg custom field",
  250. customFieldType,
  251. customFieldSearcher,
  252. EasyList.build(GlobalIssueContext.getInstance()),
  253. [null]);
  254. customFieldManager.clear()
  255. // todo: attach the field to a screen
  256. return customField
  257. }
  258. }