diff --git a/README.md b/README.md index 58edad5..4bdeefb 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ buildscript { jcenter() } dependencies { - classpath 'org.fundacionjala.gradle.plugins.enforce:enforce-gradle-plugin:1.0.1' + classpath 'org.fundacionjala.gradle.plugins.enforce:enforce-gradle-plugin:1.0.4' } } diff --git a/example/build.gradle b/example/build.gradle index 87cc681..4887b66 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -9,7 +9,7 @@ buildscript { jcenter() } dependencies { - classpath 'org.fundacionjala.gradle.plugins.enforce:enforce-gradle-plugin:1.0.1' + classpath 'org.fundacionjala.gradle.plugins.enforce:enforce-gradle-plugin:1.0.4' } } diff --git a/release-notes.md b/release-notes.md index ec8b8e7..c8132c8 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,4 +1,55 @@ +## 1.0.5 - 2015-06-22 + +### Bugs fixed + +* Update command tries to delete packaged sub-components. +* @isTest annotation should be case insensitive. +* Special characters not deployed properly. +* The status task is showing empty space by every changed object . +* Update task doesn't support excludes parameter. +* Once that a document is added and the update task is executed, it didn't upload that document to your organization. +* Once that a document is deleted and the update task is executed, it deletes all documents from your organization. +* When I execute retrieve task using the -Pfiles with documents is not working. + + + +### Known issues + +* Once a folder of documents is deleted, it isn’t deleted from your organization. +* Update Command: 400 Bad Request error is displayed when trying to delete validation rules. + + +## 1.0.4 - 2015-06-10 + +### Features + +* Delete task was created to delete components from your organization based in your package xml file or using folder parameter. It doesn't truncate. + +### Bugs fixed + +* The deploy task ends with percentage less than 100%. +* Support deleteTemporaryFiles parameter for Retrieve task. +* Update task fails for files that have spaces in their name. +* Update/Deploy/Upload command does not take in account the package.xml info for packaged objects. +* Excludes parameter into deploy task doesn't take in account documents component without extension into package xml file. +* The validation of files parameter value does not work when it sends documents, reports or dashboard. + +### Enhancements + +* Use unzip method of Gradle instead of unzip method of AntBuilder for the Retrieve task. + +### Known issues + +* When the enforce version is changed and status task is executed all files are shown as deleted for the moment to avoid it you should execute reset task. +* When you execute the delete task using files parameter and you use a folder name as a value, It is listing all files from the project. +* When we use the status task to show objects it shows an empty line between objects names. +* If a document or report or dashboard are deleted all documents or reports or dashboards are deleted for the update task. +* Update task does not support the excludes parameter. +* Once retrieve task is executed using files parameter with document file as value the validation doesn’t work. + + + ## 1.0.3 - 2015-05-25 ### Features diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/EnforcePluginExtension.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/EnforcePluginExtension.groovy index 9eb2418..a14364d 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/EnforcePluginExtension.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/EnforcePluginExtension.groovy @@ -4,6 +4,9 @@ */ package org.fundacionjala.gradle.plugins.enforce + +import java.nio.charset.StandardCharsets + /** * This class creates a plugin extension to assign properties of the plugin. */ @@ -35,6 +38,8 @@ class EnforcePluginExtension { String integration = "no" + String encoding = StandardCharsets.UTF_8.displayName() + String foldersToDownload = "objects,staticresources,classes,pages,triggers,components" Map> interceptors diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHash.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHash.groovy index 8f130f8..02c5410 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHash.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHash.groovy @@ -1,5 +1,7 @@ package org.fundacionjala.gradle.plugins.enforce.filemonitor +import org.fundacionjala.gradle.plugins.enforce.utils.Util + /** * This class represents the state of the object component and its sub components */ @@ -38,18 +40,19 @@ class ObjectHash extends ComponentHash { private Map getChangedFields(ObjectHash objectHash) { Map result = [:] objectHash.subComponents.each { String fieldAPIName, String fieldHash -> - if (!this.subComponents.containsKey(fieldAPIName)) { + Boolean isPackaged = Util.isPackaged(fieldAPIName) + if (!isPackaged && !this.subComponents.containsKey(fieldAPIName)) { result.put(fieldAPIName, ComponentStates.ADDED) } - if (this.subComponents.containsKey(fieldAPIName) && + if (!isPackaged && this.subComponents.containsKey(fieldAPIName) && !this.subComponents.get(fieldAPIName).toString().equals(fieldHash)) { result.put(fieldAPIName, ComponentStates.CHANGED) } } this.subComponents.each { String fieldAPIName, String fieldHash -> - if(!objectHash.subComponents.containsKey(fieldAPIName)) { + if(!Util.isPackaged(fieldAPIName) && !objectHash.subComponents.containsKey(fieldAPIName)) { result.put(fieldAPIName, ComponentStates.DELETED) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTracker.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTracker.groovy index 7489391..bccf935 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTracker.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTracker.groovy @@ -15,10 +15,13 @@ class ObjectResultTracker extends ResultTracker { @Override public String toString() { - String result = ''; + StringBuilder result = new StringBuilder() subComponentsResult.each { field, fieldState -> - result += field + ' -> '+ fieldState.value() + '\n\t' + result.append('\n\t') + result.append(field) + result.append(' -> ') + result.append(fieldState.value()) } - return state.value() + '\n\t' + result + return state.value() + result.toString() } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/InterceptorManager.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/InterceptorManager.groovy index 1332255..84e4b7e 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/InterceptorManager.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/InterceptorManager.groovy @@ -10,6 +10,8 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.MetadataComponents import groovy.util.logging.Slf4j +import java.nio.charset.StandardCharsets + /** * This class manages all components created from source path */ @@ -19,7 +21,7 @@ class InterceptorManager { Map interceptors List truncatedDirectories = ['classes', 'objects', 'triggers', 'pages', 'components', 'workflows', 'tabs'] List interceptorsToExecute - + String encoding /** * Creates a new interceptor management from source path @@ -28,6 +30,7 @@ class InterceptorManager { InterceptorManager() { this.interceptors = [:] interceptorsToExecute = [] + encoding = StandardCharsets.UTF_8.displayName() } /** @@ -39,6 +42,7 @@ class InterceptorManager { FactoryInterceptor factoryComponent = new FactoryInterceptor() MetadataInterceptor interceptor = factoryComponent.getInterceptor(componentType) if (interceptor) { + interceptor.encoding = encoding interceptor.loadInterceptors() this.interceptors.put(componentType.directory, interceptor) } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/MetadataInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/MetadataInterceptor.groovy index b56867b..669857e 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/MetadataInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/MetadataInterceptor.groovy @@ -5,6 +5,9 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor import groovy.util.logging.Slf4j + +import java.nio.charset.StandardCharsets + /** * This class provides a skeletal implementation of the interceptor for all metadata types supported */ @@ -14,6 +17,8 @@ abstract class MetadataInterceptor { List files protected Map interceptors protected final int INDEX_ZERO = 0 + String encoding + /** * Initializes the class properties by default */ @@ -21,6 +26,7 @@ abstract class MetadataInterceptor { files = [] interceptors = new LinkedHashMap() interceptorsToExecute = [] + encoding = StandardCharsets.UTF_8.displayName() } Map getInterceptors() { diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Class.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Class.groovy index b492ade..752b6d2 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Class.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Class.groovy @@ -5,27 +5,37 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j import org.fundacionjala.gradle.plugins.enforce.utils.Util +import java.nio.charset.StandardCharsets + /** * Implements the truncated algorithm to truncate the class content */ +@Slf4j class Class { private final String CLASS_DECLARATION = 'public class %s {}' private final String EXCEPTION_FILE_NAME = 'Exception.cls' private final String CLASS_DECLARATION_EXCEPTION = 'public class %s extends %s {}' + String encoding + + Class() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to truncate the class content */ Closure execute = { file -> if (!file) return + String charset = Util.getCharset(file) String className = Util.getFileName(file.getName()) - file.text = String.format(CLASS_DECLARATION, className) + String content = String.format(CLASS_DECLARATION, className) if (file.getName().contains(EXCEPTION_FILE_NAME)) { String exceptionName = Util.getFileName(EXCEPTION_FILE_NAME) - file.text = String.format(CLASS_DECLARATION_EXCEPTION, className, exceptionName) + content = String.format(CLASS_DECLARATION_EXCEPTION, className, exceptionName) } - + Util.writeFile(file, content, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ClassAnnotation.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ClassAnnotation.groovy index b2e3cea..9ef8989 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ClassAnnotation.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ClassAnnotation.groovy @@ -5,22 +5,35 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets + /** * Implements the truncated algorithm remove any annotation in a class file */ +@Slf4j class ClassAnnotation { private final int INDEX_AT_SIGN = 0 private final int INDEX_FIRST_LETTER = 1 private final int INDEX_NEXT = 1 String annotation + String encoding + + ClassAnnotation() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to remove any annotation in a class file */ Closure execute = { file -> if (!file) return + String charset = Util.getCharset(file) String regex = "${annotation[INDEX_AT_SIGN]}[${annotation[INDEX_FIRST_LETTER].toUpperCase()}" regex = "${regex}${annotation[INDEX_FIRST_LETTER].toLowerCase()}]${annotation.substring(INDEX_FIRST_LETTER + INDEX_NEXT)}" - file.text = file.text.replaceAll(regex, '') + String content = file.text.replaceAll(regex, '') + Util.writeFile(file, content, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Component.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Component.groovy index b44a6dd..af2c313 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Component.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Component.groovy @@ -5,17 +5,27 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher /** * Implements the truncated algorithm to truncate the component content */ +@Slf4j class Component { private final String ATTRIBUTE_REGEX = // private final String ATTRIBUTE_BY_DEFAULT = "" private final String NAME_ATTRIBUTE = "name" private final String COMPONENT_BY_DEFAULT = "%s\n" private final int INDEX_ATTRIBUTE = 0 + String encoding + + Component() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to truncate the component content @@ -24,6 +34,7 @@ class Component { if (!file) { return } + String charset = Util.getCharset(file) String component = file.text String newAttributes = "" String attribute = "" @@ -40,7 +51,7 @@ class Component { attributeName = attribute.substring(indexIniName, indexEndName + 1) newAttributes += "\n${String.format(ATTRIBUTE_BY_DEFAULT, attributeName)}" } - - file.text = String.format(COMPONENT_BY_DEFAULT, newAttributes) + String content = String.format(COMPONENT_BY_DEFAULT, newAttributes) + Util.writeFile(file, content, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectActionOverride.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectActionOverride.groovy index 508b26e..34b66ce 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectActionOverride.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectActionOverride.groovy @@ -5,10 +5,16 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets + /** * Implements the truncated algorithm to replace an "action override" by default for all "action overrides" * that matches with the regex in an object file */ +@Slf4j class ObjectActionOverride { private final String ATTRIB_ACTION_NAME = 'actionName' private final String ATTRIB_TYPE = 'type' @@ -19,6 +25,11 @@ class ObjectActionOverride { private final String REPLACEMENT_TYPE = "<${ATTRIB_TYPE}>Default" private final String REPLACEMENT_TEXT = "<${ATTRIB_ACTION_OVERRIDE}><${ATTRIB_ACTION_NAME}>\$1${REPLACEMENT_TYPE}" + String encoding + + ObjectActionOverride() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to replace an "action override" by default for all "action override" @@ -26,6 +37,8 @@ class ObjectActionOverride { */ Closure execute = { file -> if (!file) return - file.text = file.text.replaceAll(REGEX_ACTION, REPLACEMENT_TEXT) + String charset = Util.getCharset(file) + String content = file.text.replaceAll(REGEX_ACTION, REPLACEMENT_TEXT) + Util.writeFile(file, content, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectField.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectField.groovy index cd0c206..b25b080 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectField.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectField.groovy @@ -5,11 +5,16 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher /** * Implements the truncated algorithm to replace a "field.description" and "field.inlineHelpText" by a default value */ +@Slf4j class ObjectField { private final String FIELDS_REGEX = /.*([^\n]*?\n+?)*?.*<\/fields>/ private final String DESCRIPTION_REGEX = /(([^\n]*?\n+?)*?.*<\/description>){0,1}/ @@ -19,6 +24,11 @@ class ObjectField { private final int HELP_TEXT_INDEX = 0 private final String DESCRIPTION_TAG = "new description" private final String HELP_TEXT_TAG = "new help text" + String encoding + + ObjectField() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to replace a "field.description" and "field.inlineHelpText" by default for all "fields" that matches @@ -28,6 +38,7 @@ class ObjectField { if (!file) { return } + String charset = Util.getCharset(file) String objectField = file.text Matcher fieldMatcher = objectField =~ FIELDS_REGEX fieldMatcher.each { fieldIt -> @@ -45,6 +56,6 @@ class ObjectField { objectField = objectField.replace(field, newField) } } - file.text = objectField + Util.writeFile(file, objectField, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFieldSet.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFieldSet.groovy index 085f486..10e7141 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFieldSet.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFieldSet.groovy @@ -5,6 +5,10 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher import java.util.regex.Pattern @@ -12,6 +16,7 @@ import java.util.regex.Pattern * Implements the truncated algorithm to replace a "field set" by default for all "field sets" * that matches with the regex in an object file */ +@Slf4j class ObjectFieldSet { private final String REGEX_FIELD_SETS = /\s*(\w*<\/fullName>)\s*([^\n]*?\n+?)+?.*<\/fieldSets>/ private final String TAG_FILE_SET_INI = "" @@ -19,13 +24,18 @@ class ObjectFieldSet { private final String TAG_DESCRIPTION = "Description" private final String TAG_LABEL = "" private final String REGEX_END = /<\/CustomObject>/ + String encoding + + ObjectFieldSet() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to replace a "field set" by default for all "field set" that matches with the regex in an object file */ Closure execute = { file -> if (!file) return - + String charset = Util.getCharset(file) Matcher matcher = Pattern.compile(REGEX_FIELD_SETS).matcher(file.text as String) StringBuilder fieldNames = new StringBuilder() int groupFieldFullName = 1 @@ -40,6 +50,6 @@ class ObjectFieldSet { } fieldNames.append(REGEX_END) contentResult = contentResult.replaceAll(REGEX_END, fieldNames.toString()) - file.text = contentResult + Util.writeFile(file, contentResult, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFormula.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFormula.groovy index d0f33d7..e29fceb 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFormula.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectFormula.groovy @@ -5,12 +5,17 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher /** * Implements the truncated algorithm to replace a formula by default for all formulas * that matches with the regex in an object file */ +@Slf4j class ObjectFormula { private final String FIELDS_REGEX = /.*([^\n]*?\n+?)*?.*<\/fields>/ private final String FORMULA_REGEX = /(([^\n]*?\n+?)*?.*)<\/formula>/ @@ -21,13 +26,18 @@ class ObjectFormula { private final String DATE_BY_DEFAULT = 'NOW()' private final String CHECKBOK_BY_DEFAULT = 'true' private final String TAG_FORMULA = '%s' + String encoding + + ObjectFormula() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to replace a formula by default for all formulas that matches with the regex in an object file */ Closure execute = { file -> if (!file) return - + String charset = Util.getCharset(file) String objectFormula = file.text Matcher fieldMatcher = objectFormula =~ FIELDS_REGEX fieldMatcher.each { fieldIt-> @@ -78,6 +88,6 @@ class ObjectFormula { } } } - file.text = objectFormula + Util.writeFile(file, objectFormula, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectWebLink.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectWebLink.groovy index 8e8f3a5..0be8bae 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectWebLink.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/ObjectWebLink.groovy @@ -5,12 +5,17 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher /** * Implements the truncated algorithm to replace a "web link" by default for all "web links" * that matches with the regex in an object file */ +@Slf4j class ObjectWebLink { private final String TAG_URL = '%s' private final String WEB_LINK_REGEX = /.*([^\n]*?\n+?)*?.*<\/webLinks>/ @@ -20,6 +25,11 @@ class ObjectWebLink { private final String URL_BY_DEFAULT = "http://www.google.com" private final int CONTENT_MATCHED_INDEX = 0 private final int TYPE_INDEX = 1 + String encoding + + ObjectWebLink() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to replace a "web link" by default for all "web links" @@ -27,6 +37,7 @@ class ObjectWebLink { */ Closure execute = { file -> if (!file) return + String charset = Util.getCharset(file) String objectWebLink = file.text Matcher webLinkMatcher = objectWebLink =~ WEB_LINK_REGEX webLinkMatcher.each { webLinkIt-> @@ -57,7 +68,7 @@ class ObjectWebLink { } } } - file.text = objectWebLink + Util.writeFile(file, objectWebLink, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Page.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Page.groovy index 75e7e8c..51e100a 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Page.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Page.groovy @@ -5,11 +5,16 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher /** * Implements the truncated algorithm to truncate the page content */ +@Slf4j class Page { private final String REGEX_PAGE = /([cC]ontroller|standard[cC]ontroller)\s*=\s*(\"\w*\")/ private final String STANDARD_CONTROLLER_NAME = 'standardcontroller' @@ -18,12 +23,18 @@ class Page { private final int CLASS_NAME_INDEX = 2 public static final String EMPTY_PAGE = ' ' private String PAGE_WITH_CONTROLLER = " " + String encoding + + Page() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to truncate the page content */ Closure execute = { file -> if (!file) return + String charset = Util.getCharset(file) String truncatedCode = EMPTY_PAGE Matcher matcher = file.text =~ REGEX_PAGE if (matcher) { @@ -33,6 +44,6 @@ class Page { truncatedCode = String.format(PAGE_WITH_CONTROLLER, controller, className) } } - file.text = truncatedCode + Util.writeFile(file, truncatedCode, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Tab.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Tab.groovy index c531b24..e1273d7 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Tab.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Tab.groovy @@ -5,9 +5,13 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j import groovy.xml.StreamingMarkupBuilder import org.fundacionjala.gradle.plugins.enforce.utils.Util +import java.nio.charset.StandardCharsets + +@Slf4j class Tab { private final String TAG_PAGES = "pages" private final String TAG_CUSTOM_OBJECT = "customObject" @@ -17,15 +21,19 @@ class Tab { private final String URL = "https://www.google.com" private final String ENCODING = "UTF-8" private final int FRAME = 600 + String encoding + Tab() { + this.encoding = StandardCharsets.UTF_8.displayName() + } Closure execute = { file -> if (!file) return - + String charset = Util.getCharset(file) if (!file.text.contains(TAG_PAGES) && !file.text.contains(TAG_CUSTOM_OBJECT)) { def nameFile = Util.getFileName(file.getName()) def contentWebTab = getWebTabString(nameFile) - file.text = contentWebTab + Util.writeFile(file, contentWebTab, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Trigger.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Trigger.groovy index 0e305ca..72abd19 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Trigger.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Trigger.groovy @@ -5,19 +5,30 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets import java.util.regex.Matcher import java.util.regex.Pattern /** * Implements the truncated algorithm to truncate the trigger content */ +@Slf4j class Trigger { private final String REGEX_TRIGGER = /trigger\s*(\w*)\son\s*(\w*)\s*\(([^\n]*?\n*?)+?.*\{/ + String encoding + Trigger() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to truncate the trigger content */ Closure execute = { file -> + if (!file) return + String charset = Util.getCharset(file) Pattern pattern = Pattern.compile(REGEX_TRIGGER) Matcher matcher = pattern.matcher(file.text as String) String truncatedCode = '' @@ -26,6 +37,6 @@ class Trigger { truncatedCode = truncatedCode.substring(1, truncatedCode.indexOf('{')) truncatedCode = "${truncatedCode}{}" } - file.text = truncatedCode + Util.writeFile(file, truncatedCode, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Workflow.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Workflow.groovy index 5079b1f..58907d8 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Workflow.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/commands/Workflow.groovy @@ -5,24 +5,36 @@ package org.fundacionjala.gradle.plugins.enforce.interceptor.commands +import groovy.util.logging.Slf4j +import org.fundacionjala.gradle.plugins.enforce.utils.Util + +import java.nio.charset.StandardCharsets + /** * Implements the truncated algorithm to truncate the workflow content */ +@Slf4j class Workflow { private final String FORMULA_BY_DEFAULT = 'true' private final String REGEX_FORMULA = /.*<\/formula>/ private final String REGEX_ACTIVE = /<\/active>/ private final String REGEX_CRITERIA_ITEM = /.*([^\n]*?\n+?)+?.*<\/criteriaItems>/ + String encoding + Workflow() { + this.encoding = StandardCharsets.UTF_8.displayName() + } /** * A closure to truncate the workflow content */ Closure execute = { file -> + if (!file) return + String charset = Util.getCharset(file) def truncatedContent = file.text truncatedContent = truncatedContent.replaceAll(REGEX_CRITERIA_ITEM, '') //Cleans criteria item truncatedContent = truncatedContent.replaceAll(REGEX_FORMULA, '') //Cleans formula truncatedContent = truncatedContent.replaceAll(REGEX_ACTIVE, "${FORMULA_BY_DEFAULT}") - file.text = truncatedContent + Util.writeFile(file, truncatedContent, charset, encoding) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ClassInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ClassInterceptor.groovy index f8d59db..7943225 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ClassInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ClassInterceptor.groovy @@ -33,10 +33,12 @@ class ClassInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - ClassAnnotation annotationCmd = new ClassAnnotation() - annotationCmd.annotation = DEPRECATE_ANNOTATION - addInterceptor(Interceptor.REMOVE_DEPRECATE.id, annotationCmd.execute) - Class contentCmd = new Class() - addInterceptor(Interceptor.TRUNCATE_CLASSES.id, contentCmd.execute) + ClassAnnotation classAnnotation = new ClassAnnotation() + classAnnotation.encoding = encoding + classAnnotation.annotation = DEPRECATE_ANNOTATION + addInterceptor(Interceptor.REMOVE_DEPRECATE.id, classAnnotation.execute) + Class classCmd = new Class() + classCmd.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_CLASSES.id, classCmd.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ComponentInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ComponentInterceptor.groovy index ca76e9b..c8aa240 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ComponentInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ComponentInterceptor.groovy @@ -31,6 +31,8 @@ class ComponentInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_COMPONENTS.id, new Component().execute) + Component component = new Component() + component.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_COMPONENTS.id, component.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ObjectInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ObjectInterceptor.groovy index 731bef7..daf6d67 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ObjectInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/ObjectInterceptor.groovy @@ -31,10 +31,20 @@ class ObjectInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_FORMULAS.id, new ObjectFormula().execute) - addInterceptor(Interceptor.TRUNCATE_WEB_LINKS.id, new ObjectWebLink().execute) - addInterceptor(Interceptor.TRUNCATE_FIELD_SETS.id, new ObjectFieldSet().execute) - addInterceptor(Interceptor.TRUNCATE_ACTION_OVERRIDES.id, new ObjectActionOverride().execute) - addInterceptor(Interceptor.TRUNCATE_FIELD.id, new ObjectField().execute) + ObjectFormula objectFormula = new ObjectFormula() + objectFormula.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_FORMULAS.id, objectFormula.execute) + ObjectWebLink objectWebLink = new ObjectWebLink() + objectWebLink.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_WEB_LINKS.id, objectWebLink.execute) + ObjectFieldSet objectFieldSet = new ObjectFieldSet() + objectFieldSet.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_FIELD_SETS.id, objectFieldSet.execute) + ObjectActionOverride objectActionOverride = new ObjectActionOverride() + objectActionOverride.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_ACTION_OVERRIDES.id, objectActionOverride.execute) + ObjectField objectField = new ObjectField() + objectField.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_FIELD.id, objectField.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/PageInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/PageInterceptor.groovy index 42839d6..9502b9f 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/PageInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/PageInterceptor.groovy @@ -31,6 +31,8 @@ class PageInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_PAGES.id, new Page().execute) + Page page = new Page() + page.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_PAGES.id, page.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TabInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TabInterceptor.groovy index 6deda9a..78cb4ba 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TabInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TabInterceptor.groovy @@ -31,6 +31,8 @@ class TabInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_TABS.id, new Tab().execute) + Tab tab = new Tab() + tab.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_TABS.id, tab.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TriggerInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TriggerInterceptor.groovy index 28c7367..fc62e40 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TriggerInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/TriggerInterceptor.groovy @@ -31,6 +31,8 @@ class TriggerInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_TRIGGERS.id, new Trigger().execute) + Trigger trigger = new Trigger() + trigger.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_TRIGGERS.id, trigger.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/WorkflowInterceptor.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/WorkflowInterceptor.groovy index e2068dd..f0e326b 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/WorkflowInterceptor.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/interceptor/interceptors/WorkflowInterceptor.groovy @@ -31,6 +31,8 @@ class WorkflowInterceptor extends MetadataInterceptor { */ @Override void loadInterceptors() { - addInterceptor(Interceptor.TRUNCATE_WORKFLOWS.id, new Workflow().execute) + Workflow workflow = new Workflow() + workflow.encoding = encoding + addInterceptor(Interceptor.TRUNCATE_WORKFLOWS.id, workflow.execute) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Delete.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Delete.groovy index bed9be0..feef3b4 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Delete.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Delete.groovy @@ -5,8 +5,11 @@ package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.deployment +import org.fundacionjala.gradle.plugins.enforce.undeploy.SmartFilesValidator import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.Util +import org.fundacionjala.gradle.plugins.enforce.wsc.rest.QueryBuilder +import org.fundacionjala.gradle.plugins.enforce.wsc.rest.ToolingAPI import java.nio.file.Paths @@ -40,8 +43,10 @@ class Delete extends Deployment { addFoldersToDeleteFiles() addFilesToDelete() excludeFilesToDelete() + validateFilesInOrg() showFilesToDelete() + if( System.console().readLine("\n"+Constants.QUESTION_CONTINUE_DELETE) == Constants.YES_OPTION ) { createDestructive() createPackageEmpty() @@ -52,6 +57,7 @@ class Delete extends Deployment { } } + /** * Adds all files into an org */ @@ -73,6 +79,29 @@ class Delete extends Deployment { filesToDeleted = addFilesTo(filesToDeleted) } + /** + * Excludes Files from filesExcludes map + */ + def excludeFilesToDelete() { + filesToDeleted = excludeFiles(filesToDeleted) + } + + /** + * Filter the files into Org + */ + def validateFilesInOrg() { + ToolingAPI toolingAPI = new ToolingAPI(credential) + QueryBuilder queryBuilder = new QueryBuilder() + ArrayList jsonQueries = [] + if(!parameters.get(Constants.PARAMETER_VALIDATE_ORG).equals(Constants.FALSE_OPTION)) { + queryBuilder.createQueryFromPackage(projectPackagePath).each { query -> + jsonQueries.push(toolingAPI.httpAPIClient.executeQuery(query as String)) + } + SmartFilesValidator smartFilesValidator = new SmartFilesValidator(jsonQueries) + filesToDeleted = smartFilesValidator.filterFilesAccordingOrganization(filesToDeleted, projectPath) + } + } + /** * Shows files to delete */ @@ -95,23 +124,16 @@ class Delete extends Deployment { }.each { group, files -> logger.quiet("[ " + files.size() + " ] " + group) } + logger.quiet(numComponentes+" components") } else { showFiles.each { File file -> logger.quiet( Util.getRelativePath(file, projectPath)) } - logger.quiet(numComponentes+" components") } logger.quiet("*********************************************") } - /** - * Excludes Files from filesExcludes map - */ - def excludeFilesToDelete() { - filesToDeleted = excludeFiles(filesToDeleted) - } - /** * Creates packages to all files which has been deleted */ diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Deployment.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Deployment.groovy index 2d84655..d2ff92a 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Deployment.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Deployment.groovy @@ -8,6 +8,7 @@ package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.deployment import org.fundacionjala.gradle.plugins.enforce.interceptor.InterceptorManager import org.fundacionjala.gradle.plugins.enforce.metadata.DeployMetadata import org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.SalesforceTask +import org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.filter.Filter import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.Util import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.MetadataComponents @@ -15,7 +16,6 @@ import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.PackageCombiner import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.component.validators.SalesforceValidator import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.component.validators.SalesforceValidatorManager import org.gradle.api.file.FileTree -import org.gradle.api.tasks.bundling.Zip import java.nio.file.Paths @@ -30,8 +30,7 @@ abstract class Deployment extends SalesforceTask { public final String EXCLUDES = 'excludes' public String excludes public final int FILE_NAME_POSITION = 1 - public final String SLASH = "/" - public final String BACKSLASH = "\\\\" + private Filter filter /** * Sets description and group task @@ -42,6 +41,7 @@ abstract class Deployment extends SalesforceTask { super(descriptionTask, groupTask) componentDeploy = new DeployMetadata() componentManager = new InterceptorManager() + componentManager.encoding = project.property(Constants.FORCE_EXTENSION).encoding componentManager.buildInterceptors() } @@ -171,8 +171,8 @@ abstract class Deployment extends SalesforceTask { public ArrayList getCriterias(String criterion) { ArrayList criterias = new ArrayList() criterion.split(Constants.COMMA).each { String critery -> - critery = critery.replaceAll(BACKSLASH, SLASH) - def criteriaSplitted = critery.split(SLASH) + critery = critery.replaceAll(Constants.BACK_SLASH, Constants.SLASH) + def criteriaSplitted = critery.split(Constants.SLASH) if (criteriaSplitted.size() == FILE_NAME_POSITION) { criterias.push("${critery}${File.separator}${Constants.WILDCARD}${Constants.WILDCARD}") return @@ -231,9 +231,10 @@ abstract class Deployment extends SalesforceTask { } validateParameter(fileNames) fileNames.split(Constants.COMMA).each {String fileName -> - def fileNameChanged = fileName.replaceAll(BACKSLASH, SLASH) - if (!fileNameChanged.contains(SLASH)) { - return files + def fileNameChanged = fileName.replaceAll(Constants.BACK_SLASH, Constants.SLASH) + if (!fileNameChanged.contains(Constants.SLASH)) { + filesName.push("${fileName}${File.separator}${Constants.WILDCARD}${Constants.WILDCARD}") + return } filesName.push(fileName) filesName.push("${fileName}${Constants.META_XML}") @@ -272,14 +273,14 @@ abstract class Deployment extends SalesforceTask { * @param parameterValues are files name that will be excluded */ public void validateParameter(String parameterValues) { - parameterValues = parameterValues.replaceAll(BACKSLASH, SLASH) + parameterValues = parameterValues.replaceAll(Constants.BACK_SLASH, Constants.SLASH) ArrayList fileNames = new ArrayList() ArrayList folderNames = new ArrayList() parameterValues.split(Constants.COMMA).each { String parameter -> if (parameter.contains(Constants.WILDCARD)) { return } - if (parameter.contains(SLASH)) { + if (parameter.contains(Constants.SLASH)) { fileNames.push(parameter) } else { folderNames.push(parameter) @@ -348,6 +349,10 @@ abstract class Deployment extends SalesforceTask { } } + /** + * Combines package that was updated from build folder and package from source directory + * @param buildPackagePath is path of package that is into build directory + */ public void combinePackage(String buildPackagePath) { PackageCombiner.packageCombine(projectPackagePath, buildPackagePath) if (excludes) { @@ -357,9 +362,9 @@ abstract class Deployment extends SalesforceTask { /** * Combines package from build folder and package from source directory - * @return + * @param buildPackagePath is path of package that is into build directory */ - def combinePackageToUpdate(String buildPackagePath) { + public void combinePackageToUpdate(String buildPackagePath) { PackageCombiner.packageCombineToUpdate(projectPackagePath, buildPackagePath) if (excludes) { PackageCombiner.removeMembersFromPackage(buildPackagePath, getFilesExcludes(excludes)) diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Update.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Update.groovy index f186d2f..c1788b5 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Update.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Update.groovy @@ -51,9 +51,8 @@ class Update extends Deployment { verifyParameter() excludeFilesFromFilesChanged() showFilesChanged() - if (packageGenerator.fileTrackerMap.isEmpty()) { - logger.quiet(Constants.NOT_FILES_CHANGED) - return + if(isEmptyChangedFiles()) { + return; } createDestructive() createPackage() @@ -139,7 +138,10 @@ class Update extends Deployment { /** * Prints files changed */ - def showFilesChanged() { + public void showFilesChanged() { + if (isEmptyChangedFiles()) { + logger.quiet(Constants.NOT_FILES_CHANGED) + } if (packageGenerator.fileTrackerMap.size() > 0) { logger.quiet("*********************************************") logger.quiet(" Status Files Changed ") @@ -151,6 +153,17 @@ class Update extends Deployment { } } + /** + * Verifies if there are not changed files + * @return boolean + */ + private boolean isEmptyChangedFiles() { + if(packageGenerator.fileTrackerMap.isEmpty()) { + return true + } + return false + } + /** * Shows files excluded if there are more than five this shows just a message. * @return @@ -175,8 +188,10 @@ class Update extends Deployment { /** * ExcludeFiles from filesExcludes map */ - private void excludeFilesFromFilesChanged() { - ArrayList filesFiltered = excludeFiles(packageGenerator.getFiles()) - filesExcludes = packageGenerator.excludeFiles(filesFiltered) + public void excludeFilesFromFilesChanged() { + ArrayList files = packageGenerator.getFiles(projectPath) + ArrayList filesFiltered = excludeFiles(files) + packageGenerator.updateFileTracker(filesFiltered) + filesExcludes = files - filesFiltered } } \ No newline at end of file diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Upload.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Upload.groovy index 265536c..a995902 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Upload.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/Upload.groovy @@ -48,7 +48,7 @@ class Upload extends Deployment { loadFilesChangedToUpload() loadParameter() loadAllFiles() - if (specificFilesToUpload.empty && !Util.isValidProperty(project, EXCLUDES) && all == Constants.FALSE) { + if (specificFilesToUpload.empty && !Util.isValidProperty(parameters, EXCLUDES) && all == Constants.FALSE) { logger.warn("${Constants.ALL_FILES_UPLOAD}${projectPath}") option = System.console().readLine(Constants.QUESTION_CONTINUE) @@ -113,8 +113,8 @@ class Upload extends Deployment { * By default the 'all' variable has the value equals to false. */ void loadAllFiles() { - if (Util.isValidProperty(project, Constants.ALL_FILES_TO_UPLOAD) && !Util.isEmptyProperty(project, Constants.ALL_FILES_TO_UPLOAD)) { - all = project.properties[Constants.ALL_FILES_TO_UPLOAD].toString() + if (Util.isValidProperty(parameters, Constants.ALL_FILES_TO_UPLOAD) && !Util.isEmptyProperty(parameters, Constants.ALL_FILES_TO_UPLOAD)) { + all = parameters[Constants.ALL_FILES_TO_UPLOAD].toString() } } @@ -122,8 +122,8 @@ class Upload extends Deployment { * Loads files that will be uploaded into specificFilesToUpload array. */ def loadParameter() { - if (Util.isValidProperty(project, Constants.FILES_TO_UPLOAD) && !Util.isEmptyProperty(project, Constants.FILES_TO_UPLOAD)) { - files = project.properties[Constants.FILES_TO_UPLOAD].toString() + if (Util.isValidProperty(parameters, Constants.FILES_TO_UPLOAD) && !Util.isEmptyProperty(parameters, Constants.FILES_TO_UPLOAD)) { + files = parameters[Constants.FILES_TO_UPLOAD].toString() } ArrayList filesName = new ArrayList() if (files == null) { @@ -131,8 +131,8 @@ class Upload extends Deployment { } validateParameter(files) files.split(Constants.COMMA).each {String fileName -> - def fileNameChanged = fileName.replaceAll(BACKSLASH, SLASH) - if (!fileNameChanged.contains(SLASH)) { + def fileNameChanged = fileName.replaceAll(Constants.BACK_SLASH, Constants.SLASH) + if (!fileNameChanged.contains(Constants.SLASH)) { filesName.push("${fileName}${File.separator}${Constants.WILDCARD}${Constants.WILDCARD}") return } @@ -149,7 +149,7 @@ class Upload extends Deployment { /** * Loads all files from project directory to specificFilesToUpload array */ - def loadFiles() { + public void loadFiles() { if (specificFilesToUpload.isEmpty()) { specificFilesToUpload = getFilesFiltered() } @@ -182,4 +182,4 @@ class Upload extends Deployment { sourceFiles.remove(new File(Paths.get(projectPath, Constants.PACKAGE_FILE_NAME).toString())) return sourceFiles } -} \ No newline at end of file +} diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/Filter.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/Filter.groovy new file mode 100644 index 0000000..cba441e --- /dev/null +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/Filter.groovy @@ -0,0 +1,81 @@ +package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.filter + +import org.apache.commons.lang.StringUtils +import org.fundacionjala.gradle.plugins.enforce.utils.Constants +import org.fundacionjala.gradle.plugins.enforce.utils.Util +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.MetadataComponents +import org.gradle.api.Project +import org.gradle.api.file.FileTree + +import java.nio.file.Paths + +class Filter { + private Project project + private String projectPath + + Filter(Project project, String projectPath) { + this.project = project + this.projectPath = projectPath + } + + /** + * Gets a criteria to folders files and wildcards + * @param criterion is an String with criteria + * @return an ArrayList of criteria + */ + public ArrayList getCriteria(String criterion) { + ArrayList criteria = new ArrayList() + criterion.split(Constants.COMMA).each { String critery -> + critery = critery.trim() + if (!critery.contains(Constants.WILDCARD)){ + File fileFromProjectDirectory = new File(Paths.get(projectPath, critery).toString()) + if (fileFromProjectDirectory.isDirectory()) { + criteria.push("${critery}${File.separator}${Constants.WILDCARD}${Constants.WILDCARD}") + return + } + } + criteria.push(critery) + criteria.push("${critery}${Constants.META_XML}") + } + return criteria + } + + /** + * Gets content parameters + * @param parametersName is an array lis with parameters names + * @param properties is a map with parameters names and its values + * @return a map with parameter name as key and its content as value + */ + public static Map getContentParameter(ArrayList parametersName, Map properties) { + Map result = [:] + parametersName.each {String parameter -> + if (Util.isValidProperty(properties, parameter) && !Util.isEmptyProperty(properties, parameter)) { + result.put(parameter, properties[parameter].toString()) + } + } + return result + } + + /** + * Gets files from project directory by parameter and all by default + * @param parametersName is an array list with parameters names + * @param properties is a map with parameter name as key and its content as value + * @return an array list of files + */ + public ArrayList getFiles(ArrayList parametersName, Map properties) { + Map contentParameterMap = getContentParameter(parametersName, properties) + ArrayList criteriaToExclude = [] + ArrayList criteriaToInclude = [] + + if(contentParameterMap.containsKey(Constants.PARAMETER_EXCLUDES)) { + criteriaToExclude = getCriteria(contentParameterMap.get(Constants.PARAMETER_EXCLUDES)) + } + + if(contentParameterMap.containsKey(Constants.PARAMETER_FILES)) { + criteriaToInclude = getCriteria(contentParameterMap.get(Constants.PARAMETER_FILES)) + } + FileTree fileTree = project.fileTree(dir: projectPath, includes: criteriaToInclude, excludes: criteriaToExclude) + + return fileTree.getFiles() as ArrayList + } +} \ No newline at end of file diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieval.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieval.groovy index c0c736a..13d1c74 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieval.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieval.groovy @@ -10,7 +10,7 @@ import org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.SalesforceTask import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.Util import org.fundacionjala.gradle.plugins.enforce.utils.ZipFileManager -import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.MetadataComponents +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.FileValidator import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.Package import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.PackageBuilder @@ -80,18 +80,10 @@ abstract class Retrieval extends SalesforceTask { * Validates names of files * @param filesName is type array list contents names of files */ - public void validateFiles(ArrayList filesName) { - ArrayList invalidFiles = new ArrayList() - filesName.each { String fileName -> - File file = new File(Paths.get(projectPath, fileName).toString()) - String extension = Util.getFileExtension(file) - String parentFileName = Util.getFirstPath(fileName) - if (!MetadataComponents.validExtension(extension) || !MetadataComponents.validFolder(parentFileName)) { - invalidFiles.push(fileName) - } - } - if (!invalidFiles.isEmpty()) { - throw new Exception("${Constants.INVALID_FILE}: ${invalidFiles}") + public void validateFiles(ArrayList files) { + Map> validatedMapFiles = FileValidator.validateFiles(projectPath, files) + if (!validatedMapFiles[Constants.INVALID_FILE].isEmpty()) { + throw new Exception("${Constants.INVALID_FILE}: ${validatedMapFiles[Constants.INVALID_FILE]}") } } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieve.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieve.groovy index e7d03c6..9e927ea 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieve.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/retrieve/Retrieve.groovy @@ -289,17 +289,17 @@ class Retrieve extends Retrieval { } String parameterValues = files parameterValues = parameterValues.replaceAll(BACKSLASH, SLASH) - ArrayList fileNames = new ArrayList() + ArrayList filesToRetrieve = new ArrayList() ArrayList folderNames = new ArrayList() parameterValues.split(Constants.COMMA).each { String parameter -> if (parameter.contains(SLASH)) { - fileNames.push(parameter) + filesToRetrieve.push(new File(Paths.get(projectPath,parameter).toString())) } else { folderNames.push(parameter) } } validateFolders(folderNames) - validateFiles(fileNames) + validateFiles(filesToRetrieve) } /** diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTask.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTask.groovy index d8c2f60..03a97d9 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTask.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTask.groovy @@ -8,6 +8,7 @@ package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.unittest import com.sforce.soap.apex.* import groovy.json.JsonBuilder import groovy.json.JsonSlurper +import org.apache.commons.lang.StringUtils import org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.SalesforceTask import org.fundacionjala.gradle.plugins.enforce.unittest.Apex.ApexClass import org.fundacionjala.gradle.plugins.enforce.unittest.Apex.ApexClasses @@ -31,41 +32,13 @@ import java.nio.file.Paths * GP is a gradle properties */ class RunTestTask extends SalesforceTask { - private final String CLASS_PARAM = 'cls' - private final String CLASS_DIRECTORY = 'classes' - private final String WILDCARD_ALL_TEST = '*' - - private final String NAME_FOLDER_REPORT = 'report' - private final String NAME_FOLDER_PAGES = 'pages' - private final String NAME_FILE = 'index.html' - private final String NAME_FILE_UNIT_TEXT_XML = 'unitTest.xml' - private final String NAME_FILE_COVERAGE_REPORT_XML = 'coverage.xml' - private final int TIME_RUN_TEST_ASYNC = 1000 - private final int ZERO_NUMBER = 0 - private final String PARAMETER_ASYNC = 'async' - - private final String QUERY_COVERAGE = "SELECT NumLinesCovered, NumLinesUncovered, ApexClassorTriggerId, Coverage" + - " FROM ApexCodeCoverageAggregate" - private final String QUERY_CLASSES = "SELECT Id, Name FROM ApexClass" - private final String QUERY_TRIGGERS = "SELECT Id, Name FROM ApexTrigger" - private String pathClasses private HtmlManager htmlManager - public static final String TEST_MESSAGE = "Unit Test Results" - public final String NOT_HAVE_UNIT_TEST_MESSAGE = "You don't have any test class to execute in your local repository" - - public final String IS_TEST = "@isTest" - - public final String UNIT_TEST_SUCCESS = 'Success' - public final String UNIT_TEST_FAIL = 'Fail' - Boolean async - String jsonByClasses String jsonCoverageLines String jsonByTriggers - FileWriter fileWriterReport String folderReport ToolingAPI toolingAPI @@ -84,20 +57,19 @@ class RunTestTask extends SalesforceTask { * @param group is the group typeName the task */ RunTestTask() { - super("This task runs unit tests and it also generates results of unit test and coverage", - "Test") + super("This task runs unit tests and it also generates results of unit test and coverage", "Test") } /** * Prepares directory for reports */ private void setupDirectory() { - pathClasses = Paths.get(projectPath, CLASS_DIRECTORY).toString() - folderReport = Paths.get(buildFolderPath, NAME_FOLDER_REPORT).toString() + pathClasses = Paths.get(projectPath, Constants.CLASS_DIRECTORY).toString() + folderReport = Paths.get(buildFolderPath, Constants.NAME_FOLDER_REPORT).toString() fileManager.createNewDirectory(folderReport) - String folderPages = Paths.get(folderReport, NAME_FOLDER_PAGES).toString() + String folderPages = Paths.get(folderReport, Constants.NAME_FOLDER_PAGES).toString() fileManager.createNewDirectory(folderPages) - fileWriterReport = new FileWriter(Paths.get(folderReport, NAME_FILE).toString()) + fileWriterReport = new FileWriter(Paths.get(folderReport, Constants.NAME_FILE).toString()) testResultReport = new TestResultReport(folderReport) apexTestResultArrayList = new ArrayList() @@ -113,31 +85,31 @@ class RunTestTask extends SalesforceTask { @Override void runTask() { - if (Util.isEmptyProperty(project, CLASS_PARAM)) { - throw new Exception("Enter valid parameter ${CLASS_PARAM}") + if (Util.isEmptyProperty(project, Constants.CLASS_PARAM)) { + throw new Exception("Enter valid parameter ${Constants.CLASS_PARAM}") } setupDirectory() toolingAPI = new ToolingAPI(credential) apexAPI = new ApexAPI(credential) - jsonByClasses = toolingAPI.httpAPIClient.executeQuery(QUERY_CLASSES) + jsonByClasses = toolingAPI.httpAPIClient.executeQuery(Constants.QUERY_CLASSES) if (!ApexClasses.checkForRecords(jsonByClasses)) { throw new Exception("Not found any class in your organization") } - jsonByTriggers = toolingAPI.httpAPIClient.executeQuery(QUERY_TRIGGERS) + jsonByTriggers = toolingAPI.httpAPIClient.executeQuery(Constants.QUERY_TRIGGERS) ArrayList classes = new ArrayList() - if (Util.isValidProperty(project, CLASS_PARAM)) { - classes = getClassNames(pathClasses, project.properties[CLASS_PARAM].toString()) + if (Util.isValidProperty(project, Constants.CLASS_PARAM)) { + classes = getClassNames(pathClasses, project.properties[Constants.CLASS_PARAM].toString()) } - if (existAsyncParameter() && !Util.isValidProperty(project, CLASS_PARAM)) { - classes = getClassNames(pathClasses, WILDCARD_ALL_TEST) + if (existAsyncParameter() && !Util.isValidProperty(project, Constants.CLASS_PARAM)) { + classes = getClassNames(pathClasses, Constants.WILDCARD_ALL_TEST) } - if (!existAsyncParameter() && !Util.isValidProperty(project, CLASS_PARAM)) { + if (!existAsyncParameter() && !Util.isValidProperty(project, Constants.CLASS_PARAM)) { classes = new ArrayList() } @@ -147,7 +119,7 @@ class RunTestTask extends SalesforceTask { if (async) { if (classes.empty) { - logger.error(NOT_HAVE_UNIT_TEST_MESSAGE) + logger.error(Constants.NOT_HAVE_UNIT_TEST_MESSAGE) return } runTestAsynchronous(classes) @@ -164,7 +136,8 @@ class RunTestTask extends SalesforceTask { * @return true if exist an async parameter with its value otherwise false */ def existAsyncParameter() { - return Util.isValidProperty(project, PARAMETER_ASYNC) && project.properties[PARAMETER_ASYNC].toString().equals("true") + return Util.isValidProperty(project, Constants.PARAMETER_ASYNC) && + project.properties[Constants.PARAMETER_ASYNC].toString().equals("true") } /** @@ -186,13 +159,13 @@ class RunTestTask extends SalesforceTask { String timeResult = Util.formatDurationHMS(runTestResult.totalTime as long) logger.log(LogLevel.INFO, "total time: $timeResult") - if (runTestResult && runTestResult.failures && runTestResult.failures.size() > ZERO_NUMBER) { + if (runTestResult && runTestResult.failures && runTestResult.failures.size() > Constants.ZERO_NUMBER) { logger.log(LogLevel.LIFECYCLE, "${TEST_MESSAGE}:\n") } runTestResult.failures.each { testFailures -> ApexRunTestResult apexRunTestResult = new ApexRunTestResult() - apexRunTestResult.outcome = UNIT_TEST_FAIL + apexRunTestResult.outcome = Constants.UNIT_TEST_FAIL apexRunTestResult.stackTrace = testFailures.stackTrace apexRunTestResult.TestTimestamp = testFailures.time apexRunTestResult.methodName = testFailures.methodName @@ -205,7 +178,7 @@ class RunTestTask extends SalesforceTask { runTestResult.successes.each { testFailures -> ApexRunTestResult apexRunTestResult = new ApexRunTestResult() - apexRunTestResult.outcome = UNIT_TEST_SUCCESS + apexRunTestResult.outcome = Constants.UNIT_TEST_SUCCESS apexRunTestResult.stackTrace = "" apexRunTestResult.TestTimestamp = testFailures.time apexRunTestResult.methodName = testFailures.methodName @@ -215,7 +188,8 @@ class RunTestTask extends SalesforceTask { } logger.log(LogLevel.INFO, "start generate report html") - htmlManager.generateReport(verifyExistFileCoverage(runTestResult.codeCoverage), apexTestResultArrayList, runTestResult.failures.size(), runTestResult.successes.size()) + htmlManager.generateReport(verifyExistFileCoverage(runTestResult.codeCoverage), + apexTestResultArrayList, runTestResult.failures.size(), runTestResult.successes.size()) fileWriterReport.close() } @@ -346,12 +320,12 @@ class RunTestTask extends SalesforceTask { progressLogger.started() while (!runTestListener.done) { - sleep(TIME_RUN_TEST_ASYNC) + sleep(Constants.TIME_RUN_TEST_ASYNC) progressLogger.progress("$toolingAPISoap.numberUnitTest/$toolingAPISoap.currentUnitTestCompleted") } progressLogger.completed() - jsonCoverageLines = toolingAPI.httpAPIClient.executeQuery(QUERY_COVERAGE) + jsonCoverageLines = toolingAPI.httpAPIClient.executeQuery(Constants.QUERY_COVERAGE) apexTestResultArrayList = runTestListener.apexTestItem.apexTestResults generateHtmlReportCoverageAsync(apexClasses) generateCoverageReportXml() @@ -365,7 +339,7 @@ class RunTestTask extends SalesforceTask { int unitTestSuccess = 0 apexTestResultArrayList.each { apexTestResult -> - if (apexTestResult.outcome == UNIT_TEST_FAIL) { + if (apexTestResult.outcome == Constants.UNIT_TEST_FAIL) { unitTestFail++ } else { unitTestSuccess++ @@ -375,7 +349,8 @@ class RunTestTask extends SalesforceTask { ApexClass apexClass = apexClasses.getClass(apexTestResult.apexClassId) apexTestResult.className = apexClass?apexClass.name:apexTestResult.className } - htmlManager.generateReport(verifyExistFileCoverage(getCodeCoverageResult()), apexTestResultArrayList, unitTestFail, unitTestSuccess) + htmlManager.generateReport(verifyExistFileCoverage(getCodeCoverageResult()), + apexTestResultArrayList, unitTestFail, unitTestSuccess) fileWriterReport.close() } @@ -384,7 +359,7 @@ class RunTestTask extends SalesforceTask { */ def generateUnitTestReportXml() { testResultReport.loadInformationUnitTest(apexTestResultArrayList, jsonByClasses) - FileWriter unitTestXML = new FileWriter(Paths.get(folderReport, NAME_FILE_UNIT_TEXT_XML).toString()) + FileWriter unitTestXML = new FileWriter(Paths.get(folderReport, Constants.NAME_FILE_UNIT_TEXT_XML).toString()) testResultReport.generateUnitTestXML(unitTestXML) unitTestXML.close() } @@ -394,7 +369,8 @@ class RunTestTask extends SalesforceTask { */ def generateCoverageReportXml() { testResultReport.loadInformationCoverage(jsonCoverageLines, jsonByClasses, jsonByTriggers, projectPath) - FileWriter coverageReportXML = new FileWriter(Paths.get(folderReport, NAME_FILE_COVERAGE_REPORT_XML).toString()) + FileWriter coverageReportXML = new FileWriter(Paths.get(folderReport, + Constants.NAME_FILE_COVERAGE_REPORT_XML).toString()) testResultReport.generateCoverageReportXML(coverageReportXML) coverageReportXML.close() } @@ -403,12 +379,13 @@ class RunTestTask extends SalesforceTask { * Gets all class names that match with the wildcard * @param wildCard is the property sets from user */ - ArrayList getClassNames(String path, String wildCard) { + public ArrayList getClassNames(String path, String wildCard) { FileTree tree = project.fileTree(dir: path) tree.include wildCard ArrayList classNames = new ArrayList() tree.each { File file -> - if (file.path.endsWith(".${MetadataComponents.CLASSES.getExtension()}") && file.text.contains(IS_TEST)) { + if (file.path.endsWith(".${MetadataComponents.CLASSES.getExtension()}") && + StringUtils.containsIgnoreCase(file.text, Constants.IS_TEST)) { classNames.add(Util.getFileName(file.name)) } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Constants.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Constants.groovy index b914a01..ca76b9f 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Constants.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Constants.groovy @@ -18,6 +18,7 @@ public class Constants { public static final String DEPLOYMENT = "Deployment" public static final String INVALID_FOLDER = "Invalid folders" public static final String INVALID_FILE = "Invalid files" + public static final String VALID_FILE = "valid files" public static final String DOES_NOT_EXIST_FILES = "Not exist files:" public static final String DOES_NOT_EXIST_FOLDER = "Not exist folders:" public static final String NOT_FILES = "There are not files into folders" @@ -47,6 +48,10 @@ public class Constants { public static final String PARAMETER_FOLDERS = 'folders' public static final String PARAMETER_FILES = 'files' public static final String PARAMETER_EXCLUDES = 'excludes' + public static final String PARAMETER_VALIDATE_ORG = 'validate' + public static final String YES_OPTION = 'y' + public static final String TRUE_OPTION = 'true' + public static final String FALSE_OPTION = 'false' //Deploy task constants public static final String DEPLOYING_TRUNCATED_CODE = 'Deploying truncated code' @@ -63,6 +68,7 @@ public class Constants { public static final String TRUNCATE_CODE = 'sourceCode' public static final Integer NOT_FOUND = -1 + public static final boolean CONTAINS_XML_FILE = true; public static final ArrayList FOLDERS_TO_TRUNCATE = ['classes', 'objects', 'triggers', 'pages', 'components', 'workflows'] @@ -89,7 +95,6 @@ public class Constants { public static final String DIR_UPLOAD_FOLDER = "upload" public static final String FILES_TO_UPLOAD = "files" public static final String ALL_FILES_TO_UPLOAD = "all" - public static final String YES_OPTION = 'y' //Update task constants public static final String UPDATE_DESCRIPTION = "This task deploys just the files that were changed" @@ -109,4 +114,25 @@ public class Constants { public static final String DIR_DELETE_FOLDER = "delete" public static final String PROCCES_DELETE_CANCELLED = "The delete process was canceled" public static final String NOT_FILES_DELETED = "There are not files to delete" -} + + //Unit test task + public static final String CLASS_PARAM = 'cls' + public static final String CLASS_DIRECTORY = 'classes' + public static final String WILDCARD_ALL_TEST = '*' + public static final String NAME_FOLDER_REPORT = 'report' + public static final String NAME_FOLDER_PAGES = 'pages' + public static final String NAME_FILE = 'index.html' + public static final String NAME_FILE_UNIT_TEXT_XML = 'unitTest.xml' + public static final String NAME_FILE_COVERAGE_REPORT_XML = 'coverage.xml' + public static final String PARAMETER_ASYNC = 'async' + public static final String QUERY_CLASSES = "SELECT Id, Name FROM ApexClass" + public static final String QUERY_TRIGGERS = "SELECT Id, Name FROM ApexTrigger" + public static final String NOT_HAVE_UNIT_TEST_MESSAGE = "You don't have any test class to execute in your local repository" + public static final String IS_TEST = "@isTest" + public static final String UNIT_TEST_SUCCESS = 'Success' + public static final String UNIT_TEST_FAIL = 'Fail' + public static final String QUERY_COVERAGE = "SELECT NumLinesCovered, NumLinesUncovered, ApexClassorTriggerId, Coverage" + + " FROM ApexCodeCoverageAggregate" + public static final int TIME_RUN_TEST_ASYNC = 1000 + public static final int ZERO_NUMBER = 0 +} \ No newline at end of file diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Util.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Util.groovy index 5eb7ba2..092a60f 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Util.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/Util.groovy @@ -5,6 +5,8 @@ package org.fundacionjala.gradle.plugins.enforce.utils +import org.apache.commons.lang.StringUtils +import groovy.util.logging.Slf4j import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.MetadataComponents import org.gradle.api.Project @@ -17,6 +19,7 @@ import java.util.regex.Pattern /** * A set methods of utility */ +@Slf4j class Util { private static final String PATTERN_EMAIL = '([\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)*(\\.[\\w-]+))' private static final String PATTERN_FILE_EXT = ~/[.][^.]+$/ @@ -37,7 +40,7 @@ class Util { * @param fullName is a tag of custom field * @return developerName of custom field */ - public static String getDeveloperName(String fullName){ + public static String getDeveloperName(String fullName) { return fullName.substring(fullName.indexOf('.') + 1, fullName.length() - 7) } @@ -234,7 +237,7 @@ class Util { foldersName.each { String folderName -> File file = new File(Paths.get(projectPath, folderName).toString()) if (file.isDirectory()) { - if (file.exists() && file.list().length == 0 ) { + if (file.exists() && file.list().length == 0) { emptyFolders.push(folderName) } } @@ -277,4 +280,49 @@ class Util { String objectName = subComponentMember.substring(0, subComponentMember.indexOf('.')) return objectName } + + /** + * Returns true if the apiName belongs on a packaged code and is a custom component/subComponent. The apiName parameter can also be used for + * CustomObjects, CustomFields, etc and any other kind of component/subComponent that follows SF API name format. + *
+ * EG: + *
+ *
    + *
  • myprefix__CustomObject__c
  • + *
  • myprefix__CustomFielName__c
  • + *
+ * @param apiName, An string value to be verified. + * @return Boolean, It is true if apiName belongs on packaged code, otherwise false. + **/ + public static Boolean isPackaged(String apiName) { + return (apiName) ? (StringUtils.countMatches(apiName, "__") == 2) : false + } + + /** + * Gets the file charset + * @param file the file to get the encoding + * @return the charset + */ + public static String getCharset(File file) { + CharsetToolkit toolkit = new CharsetToolkit(file); + Charset guessedCharset = toolkit.getCharset(); + return guessedCharset.displayName() + } + + /** + * Writes new file content using original encoding if it doesn't exist uses encoding from user + * @param file the file to write new content + * @param content the new content + * @param charset the original encoding + * @param encoding the encoding from user + */ + public static void writeFile(File file, String content, String charset, String encoding){ + log.debug "[${file.name}]-->[charset:${charset}]" + if (charset) { + file.write(content, charset) + } else { + log.warn "No encoding detected for ${file.name}. The encoding by default is ${encoding}." + file.write(content, encoding) + } + } } diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidator.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidator.groovy new file mode 100644 index 0000000..5a6446d --- /dev/null +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidator.groovy @@ -0,0 +1,47 @@ +package org.fundacionjala.gradle.plugins.enforce.utils.salesforce + +import org.fundacionjala.gradle.plugins.enforce.utils.Constants +import org.fundacionjala.gradle.plugins.enforce.utils.Util +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.component.validators.SalesforceValidator +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.component.validators.SalesforceValidatorManager + +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +/** + * Validates files and folders defined in Salesforce + */ +class FileValidator { + + /** + * Validates names of files + * @param projectPath is a String that contains source path code for a project + * @param files is type array list + */ + public static Map> validateFiles(String projectPath, ArrayList files) { + Map> filesState = [:] + filesState.put(Constants.INVALID_FILE, new ArrayList()) + filesState.put(Constants.VALID_FILE, new ArrayList()) + filesState.put(Constants.DOES_NOT_EXIST_FILES, new ArrayList()) + files.each { File file -> + Path path = Paths.get(file.getPath()) + String relativePath = Util.getRelativePath(file, projectPath) + String parentFileName = Util.getFirstPath(relativePath) + SalesforceValidator validator = SalesforceValidatorManager.getValidator(parentFileName) + boolean isValid = true + if (!Files.exists(path)) { + filesState[Constants.DOES_NOT_EXIST_FILES].add(file) + isValid = false + } + if (!validator.validateFileByFolder(parentFileName, file)) { + filesState[Constants.INVALID_FILE].add(file) + isValid = false + } + if(isValid){ + filesState[Constants.VALID_FILE].add(file) + } + } + return filesState + } +} diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/MetadataComponents.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/MetadataComponents.groovy index 99ab898..dadf3da 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/MetadataComponents.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/MetadataComponents.groovy @@ -5,6 +5,7 @@ package org.fundacionjala.gradle.plugins.enforce.utils.salesforce +import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.Util import java.nio.file.Paths @@ -15,7 +16,7 @@ import java.nio.file.Paths public enum MetadataComponents { PERMISSIONSETS("PermissionSet", "permissionset", "permissionsets"), COMMUNITIES("Community", "community", "communities"), - SCONTROLS("Scontrol", "scf", "scontrols"), + SCONTROLS("Scontrol", "scf", "scontrols", Constants.CONTAINS_XML_FILE), SAMLSSOCONFIGS("SamlSsoConfig", "samlssoconfig", "samlssoconfigs"), WORKFLOWS("Workflow", "workflow", "workflows"), SETTINGS("Settings", "settings", "settings"), @@ -39,19 +40,19 @@ public enum MetadataComponents { FLOWS("Flow", "flow", "flows"), AUTHPROVIDERS("AuthProvider", "authprovider", "authproviders"), INSTALLEDPACKAGES("InstalledPackage", "installedPackage", "installedPackages"), - EMAIL("EmailTemplate", "email", "email"), + EMAIL("EmailTemplate", "email", "email", Constants.CONTAINS_XML_FILE), ROLES("Role", "role", "roles"), - COMPONENTS("ApexComponent", "component", "components"), + COMPONENTS("ApexComponent", "component", "components", Constants.CONTAINS_XML_FILE), CUSTOMAPPLICATIONCOMPONENTS("CustomApplicationComponent", "customApplicationComponent", "customApplicationComponents"), LAYOUTS("Layout", "layout", "layouts"), HOMEPAGELAYOUTS("HomePageLayout", "homePageLayout", "homePageLayouts"), ANALYTICSNAPSHOTS("AnalyticSnapshot", "analyticsnapshot", "analyticSnapshots"), AUTORESPONSERULES("AutoResponseRules", "autoResponseRules", "autoResponseRules"), DATACATEGORYGROUPS("DataCategoryGroup", "datacategorygroup", "datacategorygroups"), - CLASSES("ApexClass", "cls", "classes"), + CLASSES("ApexClass", "cls", "classes", Constants.CONTAINS_XML_FILE), SITES("CustomSite", "site", "sites"), - DOCUMENTS("Document", "", "documents"), - PAGES("ApexPage", "page", "pages"), + DOCUMENTS("Document", "", "documents", Constants.CONTAINS_XML_FILE), + PAGES("ApexPage", "page", "pages", Constants.CONTAINS_XML_FILE), LETTERHEAD("Letterhead", "letter", "letterhead"), REPORTTYPES("ReportType", "reportType", "reportTypes"), SYNONYMDICTIONARIES("SynonymDictionary", "synonymDictionary", "synonymDictionaries"), @@ -59,7 +60,7 @@ public enum MetadataComponents { QUICKACTIONS("QuickAction", "quickAction", "quickActions"), CALLCENTERS("CallCenter", "callCenter", "callCenters"), QUEUES("Queue", "queue", "queues"), - TRIGGERS("ApexTrigger", "trigger", "triggers"), + TRIGGERS("ApexTrigger", "trigger", "triggers", Constants.CONTAINS_XML_FILE), PROFILES("Profile", "profile", "profiles"), TABS("CustomTab", "tab", "tabs"), TRANSLATIONS("Translations", "translation", "translations"), @@ -88,11 +89,13 @@ public enum MetadataComponents { private final String typeName private final String extension private final String directory + private final boolean containsXMLFile - MetadataComponents(String typeName, String extension, String directory) { + MetadataComponents(String typeName, String extension, String directory, boolean containsXMLFile = false) { this.typeName = typeName this.extension = extension this.directory = directory + this.containsXMLFile = containsXMLFile } String getTypeName() { diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombiner.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombiner.groovy index 13b90fc..150a2ad 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombiner.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombiner.groovy @@ -84,9 +84,16 @@ class PackageCombiner { ArrayList objectToDelete = [] getMembersByNameType(packageFromSourceFolder).each { String name, ArrayList members -> - if (COMPONENTS_WITH_SUB_FOLDERS.contains(name) && membersByNameOfPackageBuild.containsKey(name)) { - packageFromBuildFolder.removeMembers(name, membersByNameOfPackageBuild.get(name)) - packageFromBuildFolder.update(name, members) + if (COMPONENTS_WITH_SUB_FOLDERS.contains(name) && membersByNameOfPackageBuild.containsKey(name) + && buildPackagePath.contains(Constants.PACKAGE_FILE_NAME)) { + ArrayList membersToUpdate = [] + membersByNameOfPackageBuild.get(name).each {String membersFromPackageBuild -> + String folderName = Util.getFirstPath(membersFromPackageBuild) + if (members.contains(folderName)) { + membersToUpdate.push(folderName) + } + } + packageFromBuildFolder.update(name, membersToUpdate.unique()) } if (SUB_COMPONENTS.contains(name) && membersByNameOfPackageBuild.containsKey(CUSTOM_OBJECT)) { diff --git a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGenerator.groovy b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGenerator.groovy index 82f6c72..ef211ab 100644 --- a/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGenerator.groovy +++ b/src/main/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGenerator.groovy @@ -5,6 +5,7 @@ import org.fundacionjala.gradle.plugins.enforce.filemonitor.ComponentStates import org.fundacionjala.gradle.plugins.enforce.filemonitor.ObjectResultTracker import org.fundacionjala.gradle.plugins.enforce.filemonitor.ResultTracker import org.fundacionjala.gradle.plugins.enforce.undeploy.SmartFilesValidator +import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.Util import org.fundacionjala.gradle.plugins.enforce.wsc.Credential @@ -41,10 +42,10 @@ class PackageGenerator { fileTrackerMap = componentMonitor.getComponentChanged(files) } - public ArrayList getFiles() { + public ArrayList getFiles(String projectPath) { ArrayList files = [] fileTrackerMap.each { fileName, resultTracker -> - files.add(new File(fileName)) + files.add(new File(Paths.get(projectPath, fileName).toString())) } return files } @@ -93,6 +94,7 @@ class PackageGenerator { public void buildPackage(Writer writer) { ArrayList files = getFiles(ComponentStates.ADDED) + getFiles(ComponentStates.CHANGED) + getSubComponents(ComponentStates.ADDED) + getSubComponents(ComponentStates.CHANGED) + files.sort() packageBuilder.createPackage(files, projectPath) packageBuilder.write(writer) } @@ -128,16 +130,20 @@ class PackageGenerator { fileTrackerMap = foldersFiltered; } - public ArrayList excludeFiles(ArrayList files) { + /** + * Updates the file tracker map according to the filtered files + * @param filteredFiles the filtered files + */ + public void updateFileTracker(ArrayList filteredFiles) { Map fileTrackerMapClone = fileTrackerMap.clone() as Map - ArrayList excludedFiles = [] fileTrackerMapClone.each { fileName, resultTracker -> File fileChanged = new File(fileName.toString()) - if (!files.contains(fileChanged)) { + ArrayList foundFile = filteredFiles.findAll { file-> + file.name == fileChanged.name + } + if (foundFile.size() == Constants.ZERO) { fileTrackerMap.remove(fileName.toString()) - excludedFiles.push(fileChanged) } } - return excludedFiles } } diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHashTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHashTest.groovy new file mode 100644 index 0000000..7c39141 --- /dev/null +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectHashTest.groovy @@ -0,0 +1,59 @@ +package org.fundacionjala.gradle.plugins.enforce.filemonitor + +import spock.lang.Shared +import spock.lang.Specification + +class ObjectHashTest extends Specification{ + @Shared + ObjectHash objectHash + @Shared + String fileName = "Object1__c" + @Shared + String hash = "14se7d85fgt63c25d" + @Shared + Map subComponents = [:] + + def setup() { + subComponents.put('MyField__c', 'asdqwe13456') + subComponents.put('myPrefix__MyField__c', 'wpolku980') + objectHash = new ObjectHash(fileName, hash, subComponents) + } + + def "Test should return a map with fields that changed without the fields that have prefix" () { + given: + Map subComponents = [:] + subComponents.put('MyField__c', 'newHash') + subComponents.put('myPrefix__MyField__c', 'anotherHash') + ObjectHash componentHash = new ObjectHash(fileName, 'hashChanged', subComponents) + when: + ObjectResultTracker objectResultTracker = objectHash.compare(componentHash) + then: + objectResultTracker.subComponentsResult.containsKey('MyField__c') + objectResultTracker.subComponentsResult.get('MyField__c') == ComponentStates.CHANGED + } + + def "Test should return a map with fields that were added" () { + given: + Map subComponents = [:] + subComponents.put('MyCustomField__c', 'thisIsHash') + ObjectHash componentHash = new ObjectHash(fileName, 'hashChanged', subComponents) + when: + ObjectResultTracker objectResultTracker = objectHash.compare(componentHash) + then: + objectResultTracker.subComponentsResult.containsKey('MyCustomField__c') + objectResultTracker.subComponentsResult.get('MyCustomField__c') == ComponentStates.ADDED + } + + def "Test should return a map with fields that were deleted" () { + given: + Map subComponents = [:] + subComponents.remove('MyField__c') + ObjectHash componentHash = new ObjectHash(fileName, 'hashChanged', subComponents) + when: + ObjectResultTracker objectResultTracker = objectHash.compare(componentHash) + then: + objectResultTracker.subComponentsResult.containsKey('MyField__c') + objectResultTracker.subComponentsResult.get('MyField__c') == ComponentStates.DELETED + } + +} diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTrackerTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTrackerTest.groovy index b2e5839..716a3ff 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTrackerTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/filemonitor/ObjectResultTrackerTest.groovy @@ -9,11 +9,28 @@ class ObjectResultTrackerTest extends Specification { ObjectResultTracker objectResultTracker def setup() { - objectResultTracker = new ObjectResultTracker() + objectResultTracker = new ObjectResultTracker(ComponentStates.CHANGED) } def "Test should be an instance of ObjectResult" () { expect: objectResultTracker instanceof ObjectResultTracker } + + def "Test should return a description for a ObjectResultTracker" () { + given: + Map subComponents = [:]; + subComponents.put('field1', ComponentStates.ADDED) + subComponents.put('field2', ComponentStates.DELETED) + subComponents.put('field3', ComponentStates.CHANGED) + objectResultTracker.subComponentsResult = subComponents + String expected = 'Changed\n' + + '\tfield1 -> Added\n' + + '\tfield2 -> Deleted\n' + + '\tfield3 -> Changed' + when: + String result = objectResultTracker.toString() + then: + expected == result + } } diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/DeployTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/DeployTest.groovy index f170b5e..93a6404 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/DeployTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/DeployTest.groovy @@ -131,7 +131,6 @@ class DeployTest extends Specification { new File(Paths.get(deployPath, 'classes', 'Class1.cls').toString()).exists() new File(Paths.get(deployPath, 'classes', 'Class1.cls-meta.xml').toString()).exists() new File(Paths.get(deployPath, 'objects', 'Object1__c.object').toString()).exists() - new File(Paths.get(deployPath, 'objects', 'Account.object').toString()).exists() new File(Paths.get(deployPath, 'triggers', 'Trigger1.trigger').toString()).exists() new File(Paths.get(deployPath, 'triggers', 'Trigger1.trigger-meta.xml').toString()).exists() new File(Paths.get(SRC_PATH, 'build', 'deploy.zip').toString()).exists() @@ -294,7 +293,6 @@ class DeployTest extends Specification { new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls-meta.xml').toString()), new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger').toString()), new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger-meta.xml').toString()), - new File(Paths.get(SRC_PATH, 'src', 'objects', 'Account.object').toString()), new File(Paths.get(SRC_PATH, 'src', 'objects', 'Object1__c.object').toString())] String criterion = "**${File.separator}*.cls" instanceDeploy.projectPath = Paths.get(SRC_PATH, 'src').toString() @@ -303,7 +301,6 @@ class DeployTest extends Specification { then: arrayFiltered.sort() == [new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger').toString()), new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger-meta.xml').toString()), - new File(Paths.get(SRC_PATH, 'src', 'objects', 'Account.object').toString()), new File(Paths.get(SRC_PATH, 'src', 'objects', 'Object1__c.object').toString())].sort() } @@ -395,11 +392,10 @@ class DeployTest extends Specification { String criterion = "**/Account.object" instanceDeploy.projectPath = SRC_PATH String accountObject1 = "objects${File.separator}Account.object" - String accountObject2 = "src${File.separator}objects${File.separator}Account.object" when: ArrayList result = instanceDeploy.getFilesExcludes(criterion) then: - result.sort() == [accountObject1, accountObject2].sort() + result.sort() == [accountObject1].sort() } def "Test should return Document component that was excluded"() { diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UpdateTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UpdateTest.groovy index 7b6f87b..756bf8f 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UpdateTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UpdateTest.groovy @@ -13,6 +13,7 @@ import org.fundacionjala.gradle.plugins.enforce.filemonitor.ComponentSerializer import org.fundacionjala.gradle.plugins.enforce.filemonitor.ComponentStates import org.fundacionjala.gradle.plugins.enforce.filemonitor.ResultTracker import org.fundacionjala.gradle.plugins.enforce.metadata.DeployMetadata +import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.ManagementFile import org.fundacionjala.gradle.plugins.enforce.wsc.Credential import org.fundacionjala.gradle.plugins.enforce.wsc.LoginType @@ -61,11 +62,10 @@ class UpdateTest extends Specification { def class1Cls = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls').toString()) def class1ClsXml = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls-meta.xml').toString()) def object1__c = new File(Paths.get(SRC_PATH, 'src', 'objects', 'Object1__c.object').toString()) - def account = new File(Paths.get(SRC_PATH, 'src', 'objects', 'Account.object').toString()) def trigger = new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger').toString()) def triggerXml = new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger-meta.xml').toString()) - def mapMock = componentMonitor.getComponentsSignature([class1, class1Cls, class1ClsXml, object1__c, object1__c, account, trigger, triggerXml]) + def mapMock = componentMonitor.getComponentsSignature([class1, class1Cls, class1ClsXml, object1__c, object1__c, trigger, triggerXml]) componentSerializer.save(mapMock) credential = new Credential() @@ -112,7 +112,8 @@ class UpdateTest extends Specification { System.out = stdOut def lineAux = is.readLines() then: - lineAux == [] + lineAux.size() == 1 + lineAux[0].contains('There are not files changed') } def "Test should create a package XML file" () { @@ -215,7 +216,7 @@ class UpdateTest extends Specification { def stdOut = System.out def os = new ByteArrayOutputStream() System.out = new PrintStream(os) - updateInstance.runTask() + updateInstance.showFilesChanged() def array = os.toByteArray() def is = new ByteArrayInputStream(array) System.out = stdOut @@ -230,11 +231,10 @@ class UpdateTest extends Specification { updateInstance.packageGenerator.fileTrackerMap = [:] def class1Cls = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls').toString()) def object1__c = new File(Paths.get(SRC_PATH, 'src', 'objects', 'Object1__c.object').toString()) - def account = new File(Paths.get(SRC_PATH, 'src', 'objects', 'Account.object').toString()) def trigger = new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger').toString()) componentMonitor.srcProject = Paths.get(SRC_PATH,'src').toString() componentSerializer.sourcePath = Paths.get(SRC_PATH,'src','.fileTracker.data').toString() - def mapMock = componentMonitor.getComponentsSignature([class1Cls, object1__c, account, trigger]) + def mapMock = componentMonitor.getComponentsSignature([class1Cls, object1__c,trigger]) componentSerializer.save(mapMock) updateInstance.buildFolderPath = Paths.get(SRC_PATH, 'build').toString() updateInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() @@ -256,8 +256,17 @@ class UpdateTest extends Specification { def packageExpect = "${""}${""}${"Class2ApexClass32.0"}" def destructiveExpect = "${""}${""}${"32.0"}${""}" when: - updateInstance.runTask() - println 'package ' + new File(Paths.get(SRC_PATH, 'build', 'update', 'package.xml').toString()).exists() + updateInstance.pathUpdate = Paths.get(updateInstance.buildFolderPath, Constants.DIR_UPDATE_FOLDER).toString() + updateInstance.updatePackagePath = Paths.get(updateInstance.pathUpdate, updateInstance.PACKAGE_NAME).toString() + updateInstance.createDeploymentDirectory(updateInstance.pathUpdate) + updateInstance.loadFilesChanged() + updateInstance.verifyParameter() + updateInstance.excludeFilesFromFilesChanged() + updateInstance.showFilesChanged() + updateInstance.createDestructive() + updateInstance.createPackage() + updateInstance.copyFilesChanged() + updateInstance.showFilesExcludes() def packageXml = new File(Paths.get(SRC_PATH, 'build', 'update', 'package.xml').toString()).text def destructiveXml = new File(Paths.get(SRC_PATH, 'build', 'update', 'destructiveChanges.xml').toString()).text def class2Xml = new File(Paths.get(SRC_PATH, 'build', 'update', 'classes', 'Class2.cls-meta.xml').toString()).text @@ -297,21 +306,201 @@ class UpdateTest extends Specification { writerClass.close() writerXml.close() def updateFileZipPath = Paths.get(SRC_PATH,'build','update.zip').toString() - def updateFolderPath = Paths.get(SRC_PATH,'build','update').toString() + def updateFolderPath = Paths.get(updateInstance.buildFolderPath, Constants.DIR_UPDATE_FOLDER).toString() File updateFileZip = new File(updateFileZipPath) File updateFolder = new File(updateFolderPath) when: - updateInstance.runTask() + updateInstance.pathUpdate = Paths.get(updateInstance.buildFolderPath, Constants.DIR_UPDATE_FOLDER).toString() + updateInstance.updatePackagePath = Paths.get(updateInstance.pathUpdate, updateInstance.PACKAGE_NAME).toString() + updateInstance.createDeploymentDirectory(updateInstance.pathUpdate) + updateInstance.loadFilesChanged() + updateInstance.verifyParameter() + updateInstance.excludeFilesFromFilesChanged() + updateInstance.showFilesChanged() + updateInstance.createDestructive() + updateInstance.createPackage() + updateInstance.copyFilesChanged() + updateInstance.showFilesExcludes() + updateInstance.deleteTemporaryFiles() then: !updateFileZip.exists() !updateFolder.exists() } - def cleanupSpec() { + def "should upload the new reports, documents or dashboard added to the organization with package.xml updated"() { + given: + updateInstance.packageGenerator.projectPath = Paths.get(SRC_PATH, 'src').toString() + updateInstance.packageGenerator.fileTrackerMap = [:] + def class1Cls = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls').toString()) + def object1__c = new File(Paths.get(SRC_PATH, 'src', 'objects', 'Object1__c.object').toString()) + def trigger = new File(Paths.get(SRC_PATH, 'src', 'triggers', 'Trigger1.trigger').toString()) + componentMonitor.srcProject = Paths.get(SRC_PATH,'src').toString() + componentSerializer.sourcePath = Paths.get(SRC_PATH,'src','.fileTracker.data').toString() + def mapMock = componentMonitor.getComponentsSignature([class1Cls, object1__c,trigger]) + componentSerializer.save(mapMock) + updateInstance.buildFolderPath = Paths.get(SRC_PATH, 'build').toString() + updateInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() + updateInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', 'package.xml').toString() + ManagementFile.createDirectories(Paths.get(SRC_PATH, 'src', 'reports/MyReports').toString()) + ManagementFile.createDirectories(Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards').toString()) + ManagementFile.createDirectories(Paths.get(SRC_PATH, 'src', 'documents/MyDocuments').toString()) + def newReportPath = Paths.get(SRC_PATH, 'src', 'reports/MyReports', 'newReport.report').toString() + def newDashboardPath = Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards', 'newDashboard.dashboard').toString() + def newDocumentPath = Paths.get(SRC_PATH, 'src', 'documents/MyDocuments', 'newDocument.txt').toString() + def newDocumentXmlPath = Paths.get(SRC_PATH, 'src', 'documents/MyDocuments', 'newDocument.txt-meta.xml').toString() + def myReportFolderXmlPath = Paths.get(SRC_PATH, 'src', 'reports/MyReports-meta.xml').toString() + def myDashboardFolderXmlPath = Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards-meta.xml').toString() + def myDocumentFolderXmlPath = Paths.get(SRC_PATH, 'src', 'documents/MyDocuments-meta.xml').toString() + FileWriter newReportFile = new FileWriter(newReportPath) + FileWriter newDashboardFile = new FileWriter(newDashboardPath) + FileWriter newDocumentFile = new FileWriter(newDocumentPath) + FileWriter newDocumentXmlFile = new FileWriter(newDocumentXmlPath) + FileWriter myReportFolderXmlFile = new FileWriter(myReportFolderXmlPath) + FileWriter myDashboardFolderXmlFile = new FileWriter(myDashboardFolderXmlPath) + FileWriter myDocumentFolderXmlFile = new FileWriter(myDocumentFolderXmlPath) + def reportContent = "\n" + + " \n" + + " USERS.NAME\n" + + " \n" + + " \n" + + " ACCOUNT.NAME\n" + + " \n" + + " Tabular\n" + + " newReport\n" + + " \n" + + " co\n" + + " 1\n" + + " \n" + + " AccountList\n" + + " user\n" + + " true\n" + + " \n" + + " CREATED_DATE\n" + + " INTERVAL_CUSTOM\n" + + " 2015-05-18\n" + + " \n" + + "" + def dashboardContent = "\n" + + "\n" + + " #FFFFFF\n" + + " Diagonal\n" + + " #FFFFFF\n" + + " SpecifiedUser\n" + + " \n" + + " Medium\n" + + " \n" + + " \n" + + " Medium\n" + + " \n" + + " \n" + + " Medium\n" + + " \n" + + " alex.rv11@gmail.com\n" + + " #000000\n" + + " newDashboard\n" + + " #000000\n" + + " 12\n" + + "" + def documentContent = "the test adds this document" + def documentXmlContent = "\n" + + "\n" + + " false\n" + + " newDocument\n" + + " false\n" + + "" + def myReportFolderXmlContent = "\n" + + "\n" + + " \n" + + " Manage\n" + + " alex.rv11@gmail.com\n" + + " User\n" + + " \n" + + " testFolder\n" + + "" + def myDashboardFolderXmlContent = "\n" + + "\n" + + " \n" + + " Manage\n" + + " alex.rv11@gmail.com\n" + + " User\n" + + " \n" + + " DashboardFolder\n" + + "" + def myDocumentFolderXmlContent = "\n" + + "\n" + + " Public\n" + + " DocumentTest\n" + + " ReadWrite\n" + + "" + newReportFile.write(reportContent) + newDashboardFile.write(dashboardContent) + newDocumentFile.write(documentContent) + newDocumentXmlFile.write(documentXmlContent) + myReportFolderXmlFile.write(myReportFolderXmlContent) + myDashboardFolderXmlFile.write(myDashboardFolderXmlContent) + myDocumentFolderXmlFile.write(myDocumentFolderXmlContent) + newReportFile.close() + newDashboardFile.close() + newDocumentFile.close() + newDocumentXmlFile.close() + myReportFolderXmlFile.close() + myDashboardFolderXmlFile.close() + myDocumentFolderXmlFile.close() + def packageExpect = "\n" + + "\t\n" + + "\t\tMyDashboards/newDashboard\n" + + "\t\tDashboard\n" + + "\t\n" + + "\t\n" + + "\t\tMyDocuments/newDocument\n" + + "\t\tDocument\n" + + "\t\n" + + "\t\n" + + " MyReports/newReport\n" + + " Report\n" + + "\t\n" + + "\t32.0\n" + + "" + when: + updateInstance.pathUpdate = Paths.get(updateInstance.buildFolderPath, Constants.DIR_UPDATE_FOLDER).toString() + updateInstance.updatePackagePath = Paths.get(updateInstance.pathUpdate, updateInstance.PACKAGE_NAME).toString() + updateInstance.createDeploymentDirectory(updateInstance.pathUpdate) + updateInstance.loadFilesChanged() + updateInstance.verifyParameter() + updateInstance.excludeFilesFromFilesChanged() + updateInstance.showFilesChanged() + updateInstance.createPackage() + updateInstance.copyFilesChanged() + updateInstance.showFilesExcludes() + def packageXml = new File(Paths.get(SRC_PATH, 'build', 'update', 'package.xml').toString()).text + XMLUnit.ignoreWhitespace = true + def packageXmlDifference = new Diff(packageXml, packageExpect) + then: + packageXmlDifference.similar() + new File((Paths.get(SRC_PATH, 'build', 'update', 'reports/MyReports', 'newReport.report').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'dashboards/MyDashboards', 'newDashboard.dashboard').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'documents/MyDocuments', 'newDocument.txt').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'documents/MyDocuments', 'newDocument.txt-meta.xml').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'reports/MyReports-meta.xml').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'dashboards/MyDashboards-meta.xml').toString())).exists() + new File((Paths.get(SRC_PATH, 'build', 'update', 'documents/MyDocuments-meta.xml').toString())).exists() + } + + def cleanup() { new File(Paths.get(SRC_PATH, 'build').toString()).deleteDir() new File(Paths.get(SRC_PATH, 'classes', 'Class2.cls').toString()).delete() new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls').toString()).delete() new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls-meta.xml').toString()).delete() new File(Paths.get(SRC_PATH, 'src', '.fileTracker.data').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'reports/MyReports', 'newReport.report').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards', 'newDashboard.dashboard').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'documents/MyDocuments', 'newDocument.txt-meta.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'documents/MyDocuments', 'newDocument.txt').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'reports/MyReports-meta.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards-meta.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'documents/MyDocuments-meta.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'reports/MyReports').toString()).deleteDir() + new File(Paths.get(SRC_PATH, 'src', 'dashboards/MyDashboards').toString()).deleteDir() + new File(Paths.get(SRC_PATH, 'src', 'documents/MyDocuments').toString()).deleteDir() } } \ No newline at end of file diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UploadTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UploadTest.groovy index 599b0b7..bca6ecd 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UploadTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/deployment/UploadTest.groovy @@ -5,13 +5,14 @@ package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.deployment +import org.custommonkey.xmlunit.Diff +import org.custommonkey.xmlunit.XMLUnit import org.fundacionjala.gradle.plugins.enforce.EnforcePlugin import org.fundacionjala.gradle.plugins.enforce.filemonitor.ComponentStates import org.fundacionjala.gradle.plugins.enforce.filemonitor.ResultTracker +import org.fundacionjala.gradle.plugins.enforce.utils.Constants import org.fundacionjala.gradle.plugins.enforce.utils.ManagementFile -import org.fundacionjala.gradle.plugins.enforce.utils.Util -import org.fundacionjala.gradle.plugins.enforce.wsc.Credential -import org.fundacionjala.gradle.plugins.enforce.wsc.LoginType +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.PackageBuilder import org.gradle.api.Project import org.gradle.testfixtures.ProjectBuilder import spock.lang.Shared @@ -21,21 +22,20 @@ import java.nio.file.Paths class UploadTest extends Specification { @Shared - def uploadInstance + def uploadInstance @Shared - Util util = Spy(Util) + Project project @Shared - Project project + def SRC_PATH = Paths.get(System.getProperty("user.dir"), "src", "test", "groovy", "org", + "fundacionjala", "gradle", "plugins", "enforce", "tasks", "salesforce", "resources").toString() @Shared - def SRC_PATH = Paths.get(System.getProperty("user.dir"), "src", "test", "groovy", "org", - "fundacionjala", "gradle", "plugins", "enforce", - "tasks", "salesforce", "resources").toString() + String pathUpload = Paths.get(SRC_PATH, 'build', Constants.DIR_UPLOAD_FOLDER) @Shared - Credential credential + Map> packagedExpected def setup() { project = ProjectBuilder.builder().build() @@ -44,14 +44,7 @@ class UploadTest extends Specification { uploadInstance = project.tasks.upload uploadInstance.project.enforce.deleteTemporaryFiles = false uploadInstance.fileManager = new ManagementFile(SRC_PATH) - uploadInstance.createDeploymentDirectory(Paths.get(SRC_PATH, 'build').toString()) - credential = new Credential() - credential.id = 'id' - credential.username = 'salesforce2014.test@gmail.com' - credential.password = '123qwe2014' - credential.token = 'UO1Jx5vDQl97xCKkwXBH8tg3T' - credential.loginFormat = LoginType.DEV.value() - credential.type = 'normal' + packagedExpected = [:] } def "Test shouldn't create a package xml file if specificFilesToUpload Array is empty "() { @@ -66,14 +59,14 @@ class UploadTest extends Specification { def "Test should create a package xml file"() { given: + uploadInstance.createDeploymentDirectory(pathUpload) uploadInstance.pathUpload = Paths.get(SRC_PATH, 'build').toString() uploadInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() uploadInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', 'package.xml').toString() uploadInstance.uploadPackagePath = Paths.get(SRC_PATH, 'build', 'package.xml').toString() uploadInstance.specificFilesToUpload = [new File(Paths.get(SRC_PATH, "src", "classes", "Class1.cls").toString()), new File(Paths.get(SRC_PATH, "src", "classes", "Class1.cls-meta.xml").toString()), - new File(Paths.get(SRC_PATH, "src", "objects", "Object1__c.object").toString()), - new File(Paths.get(SRC_PATH, "src", "objects", "Account.object").toString())] + new File(Paths.get(SRC_PATH, "src", "objects", "Object1__c.object").toString())] when: uploadInstance.createPackage() then: @@ -82,6 +75,7 @@ class UploadTest extends Specification { def "Test should copy files to upload"() { given: + uploadInstance.createDeploymentDirectory(pathUpload) uploadInstance.pathUpload = Paths.get(SRC_PATH, 'build').toString() uploadInstance.specificFilesToUpload = [new File(Paths.get(SRC_PATH, "src", "classes", "Class1.cls").toString()), new File(Paths.get(SRC_PATH, "src", "classes", "Class1.cls-meta.xml").toString()), @@ -203,7 +197,6 @@ class UploadTest extends Specification { given: uploadInstance.files = "objects${File.separator}*.object" uploadInstance.projectPath = SRC_PATH - new File(Paths.get(SRC_PATH, 'objects', 'object1.object').toString()) when: uploadInstance.loadParameter() then: @@ -219,8 +212,7 @@ class UploadTest extends Specification { when: uploadInstance.loadParameter() then: - uploadInstance.specificFilesToUpload.sort() == [new File(Paths.get(SRC_PATH, 'objects', 'Account.object').toString()), - new File(Paths.get(SRC_PATH, 'src', 'objects', 'Account.object').toString())].sort() + uploadInstance.specificFilesToUpload == [new File(Paths.get(SRC_PATH, 'objects', 'Account.object').toString())] } def "Test should fill specificFilesToUpload array following a wildcard sent '**/*.cls' "() { @@ -231,11 +223,176 @@ class UploadTest extends Specification { uploadInstance.loadParameter() then: uploadInstance.specificFilesToUpload.sort() == [new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls').toString()), - new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls-meta.xml').toString())].sort() + new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class1.cls-meta.xml').toString())].sort() + } + + def "Test should load files into build folder before to execute deploy to 'gradle upload -Pall=true' command"() { + given: + uploadInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() + uploadInstance.pathUpload = pathUpload + uploadInstance.uploadPackagePath = Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.parameters.put('all', 'true') + when: + uploadInstance.createDeploymentDirectory(pathUpload) + uploadInstance.loadFilesChangedToUpload() + uploadInstance.loadParameter() + uploadInstance.loadAllFiles() + uploadInstance.loadFiles() + uploadInstance.copyFilesToUpload() + uploadInstance.createPackage() + uploadInstance.truncate(pathUpload) + + File packageFromBuildDirectory = new File(Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString()) + PackageBuilder packageBuilder = new PackageBuilder() + FileReader fileReader = new FileReader(packageFromBuildDirectory) + packageBuilder.read(fileReader) + + packageBuilder.metaPackage.types.each{ type-> + packagedExpected.put(type.name as String, type.members as ArrayList) + } + then: + new File(Paths.get(pathUpload, 'classes', 'Class1.cls').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class1.cls-meta.xml').toString()).exists() + new File(Paths.get(pathUpload, 'objects', 'Object1__c.object').toString()).exists() + new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger').toString()).exists() + new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger-meta.xml').toString()).exists() + packagedExpected.containsKey('CustomObject') + packagedExpected.get('CustomObject') == ['Object1__c'] + packagedExpected.containsKey('ApexTrigger') + packagedExpected.get('ApexTrigger') == ['Trigger1'] + packagedExpected.containsKey('ApexClass') + packagedExpected.get('ApexClass') == ['Class1'] + } + + def "Test should load files into build folder before to execute deploy to 'gradle upload -Pfiles=classes,objects' command"() { + given: + uploadInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() + uploadInstance.pathUpload = pathUpload + uploadInstance.uploadPackagePath = Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.parameters.put('files', 'classes,objects') + when: + uploadInstance.createDeploymentDirectory(pathUpload) + uploadInstance.loadFilesChangedToUpload() + uploadInstance.loadParameter() + uploadInstance.loadAllFiles() + uploadInstance.loadFiles() + uploadInstance.copyFilesToUpload() + uploadInstance.createPackage() + uploadInstance.truncate(pathUpload) + + File packageFromBuildDirectory = new File(Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString()) + PackageBuilder packageBuilder = new PackageBuilder() + FileReader fileReader = new FileReader(packageFromBuildDirectory) + packageBuilder.read(fileReader) + + packageBuilder.metaPackage.types.each{ type-> + packagedExpected.put(type.name as String, type.members as ArrayList) + } + then: + new File(Paths.get(pathUpload, 'classes', 'Class1.cls').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class1.cls-meta.xml').toString()).exists() + new File(Paths.get(pathUpload, 'objects', 'Object1__c.object').toString()).exists() + !new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger').toString()).exists() + !new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger-meta.xml').toString()).exists() + packagedExpected.containsKey('CustomObject') + packagedExpected.get('CustomObject') == ['Object1__c'] + packagedExpected.containsKey('ApexClass') + packagedExpected.get('ApexClass') == ['Class1'] + + } + + def "Test should load files into build folder before to execute deploy to 'gradle upload -Pexcludes=classes' command"() { + given: + uploadInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() + uploadInstance.pathUpload = pathUpload + uploadInstance.uploadPackagePath = Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.parameters.put('excludes', 'classes') + when: + uploadInstance.createDeploymentDirectory(pathUpload) + uploadInstance.loadFilesChangedToUpload() + uploadInstance.loadParameter() + uploadInstance.loadAllFiles() + uploadInstance.loadFiles() + uploadInstance.copyFilesToUpload() + uploadInstance.createPackage() + uploadInstance.truncate(pathUpload) + + File packageFromBuildDirectory = new File(Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString()) + PackageBuilder packageBuilder = new PackageBuilder() + FileReader fileReader = new FileReader(packageFromBuildDirectory) + packageBuilder.read(fileReader) + + packageBuilder.metaPackage.types.each{ type-> + packagedExpected.put(type.name as String, type.members as ArrayList) + } + then: + !new File(Paths.get(pathUpload, 'classes', 'Class1.cls').toString()).exists() + !new File(Paths.get(pathUpload, 'classes', 'Class1.cls-meta.xml').toString()).exists() + new File(Paths.get(pathUpload, 'objects', 'Object1__c.object').toString()).exists() + new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger').toString()).exists() + new File(Paths.get(pathUpload, 'triggers', 'Trigger1.trigger-meta.xml').toString()).exists() + packagedExpected.containsKey('CustomObject') + packagedExpected.get('CustomObject') == ['Object1__c'] + packagedExpected.containsKey('ApexTrigger') + packagedExpected.get('ApexTrigger') == ['Trigger1'] + !packagedExpected.containsKey('ApexClass') + + } + + def "Test should load files into build folder before to execute deploy to 'gradle upload -Pfiles=classes -Pexcludes=classes/Class1.cls' command"() { + given: + File class2 = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls').toString()) + File classXml2 = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls-meta.xml').toString()) + class2.createNewFile() + classXml2.createNewFile() + File class3 = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class3.cls').toString()) + File classXml3 = new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class3.cls-meta.xml').toString()) + class3.createNewFile() + classXml3.createNewFile() + uploadInstance.projectPath = Paths.get(SRC_PATH, 'src').toString() + uploadInstance.pathUpload = pathUpload + uploadInstance.uploadPackagePath = Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.projectPackagePath = Paths.get(SRC_PATH, 'src', Constants.PACKAGE_FILE_NAME).toString() + uploadInstance.parameters.put('excludes', "classes${File.separator}Class1.cls") + uploadInstance.parameters.put('files', 'classes') + when: + uploadInstance.createDeploymentDirectory(pathUpload) + uploadInstance.loadFilesChangedToUpload() + uploadInstance.loadParameter() + uploadInstance.loadAllFiles() + uploadInstance.loadFiles() + uploadInstance.copyFilesToUpload() + uploadInstance.createPackage() + uploadInstance.truncate(pathUpload) + + File packageFromBuildDirectory = new File(Paths.get(pathUpload, Constants.PACKAGE_FILE_NAME).toString()) + PackageBuilder packageBuilder = new PackageBuilder() + FileReader fileReader = new FileReader(packageFromBuildDirectory) + packageBuilder.read(fileReader) + packageBuilder.metaPackage.types.each{ type-> + packagedExpected.put(type.name as String, type.members as ArrayList) + } + + then: + !new File(Paths.get(pathUpload, 'classes', 'Class1.cls').toString()).exists() + !new File(Paths.get(pathUpload, 'classes', 'Class1.cls-meta.xml').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class2.cls').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class2.cls-meta.xml').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class3.cls').toString()).exists() + new File(Paths.get(pathUpload, 'classes', 'Class3.cls-meta.xml').toString()).exists() + packagedExpected.containsKey('ApexClass') + packagedExpected.get('ApexClass').sort() == ['Class2', 'Class3'].sort() } def cleanupSpec() { new File(Paths.get(SRC_PATH, 'classes', 'class2.cls').toString()).delete() new File(Paths.get(SRC_PATH, 'build').toString()).deleteDir() + new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class2.cls-meta.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class3.cls').toString()).delete() + new File(Paths.get(SRC_PATH, 'src', 'classes', 'Class3.cls-meta.xml').toString()).delete() } } diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/FilterTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/FilterTest.groovy new file mode 100644 index 0000000..84d8498 --- /dev/null +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/filter/FilterTest.groovy @@ -0,0 +1,546 @@ +package org.fundacionjala.gradle.plugins.enforce.tasks.salesforce.filter + +import org.fundacionjala.gradle.plugins.enforce.EnforcePlugin +import org.fundacionjala.gradle.plugins.enforce.utils.Constants +import org.gradle.api.Project +import org.gradle.testfixtures.ProjectBuilder +import spock.lang.Shared +import spock.lang.Specification + +import java.nio.file.Paths + +class FilterTest extends Specification{ + @Shared + Filter filter + @Shared + String SRC_PATH = Paths.get(System.getProperty("user.dir"), "src", "test", "groovy", "org", + "fundacionjala", "gradle", "plugins","enforce","tasks", "salesforce", "resources").toString() + @Shared + Project project + @Shared + ArrayList allFiles + ArrayList classFiles + ArrayList triggerFiles + ArrayList objectFiles + ArrayList dashboardFiles + ArrayList dashboardsFolder1 + ArrayList documentFiles + ArrayList documentFolder1 + ArrayList documentFolder2 + + def setup() { + project = ProjectBuilder.builder().build() + project.apply(plugin: EnforcePlugin) + filter = new Filter(project, SRC_PATH) + + allFiles = [] + classFiles = [] + triggerFiles = [] + objectFiles = [] + dashboardFiles = [] + dashboardsFolder1 = [] + documentFiles = [] + documentFolder1 = [] + documentFolder2 = [] + + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls-meta.xml').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls-meta.xml').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class3.cls').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class3.cls-meta.xml').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class4.cls').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class4.cls-meta.xml').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class5.cls').toString())) + classFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class5.cls-meta.xml').toString())) + allFiles.addAll(classFiles) + + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger1.trigger').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger1.trigger-meta.xml').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger2.trigger').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger2.trigger-meta.xml').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger3.trigger').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger3.trigger-meta.xml').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger4.trigger').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger4.trigger-meta.xml').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger5.trigger').toString())) + triggerFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers','Trigger5.trigger-meta.xml').toString())) + allFiles.addAll(triggerFiles) + + + objectFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','objects','Object1__c.object').toString())) + objectFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','objects','Object2__c.object').toString())) + objectFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','objects','Object3__c.object').toString())) + objectFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','objects','Object4__c.object').toString())) + objectFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','objects','Object5__c.object').toString())) + allFiles.addAll(objectFiles) + + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1','DashboardTest_1_1.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1','DashboardTest_1_2.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1','DashboardTest_1_3.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1','DashboardTest_1_4.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1','DashboardTest_1_5.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2','DashboardTest_2_1.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2','DashboardTest_2_2.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2','DashboardTest_2_3.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2','DashboardTest_2_4.dashboards').toString())) + dashboardsFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2','DashboardTest_2_5.dashboards').toString())) + allFiles.addAll(dashboardsFolder1) + + dashboardFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1-meta.xml').toString())) + dashboardFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2-meta.xml').toString())) + allFiles.addAll(dashboardFiles) + + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_1.txt').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_2.docx').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_3.html').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_4.rar').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_5.jpg').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_1.txt-meta.xml').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_2.docx-meta.xml').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_3.html-meta.xml').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_4.rar-meta.xml').toString())) + documentFolder1.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_5.jpg-meta.xml').toString())) + allFiles.addAll(documentFolder1) + + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_1.txt').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_2.docx').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_3.html').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_4.rar').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_5.jpg').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_1.txt-meta.xml').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_2.docx-meta.xml').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_3.html-meta.xml').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_4.rar-meta.xml').toString())) + documentFolder2.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2','DocumentTest_2_5.jpg-meta.xml').toString())) + allFiles.addAll(documentFolder2) + + documentFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1-meta.xml').toString())) + documentFiles.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2-meta.xml').toString())) + allFiles.addAll(documentFiles) + + ArrayList folders = new ArrayList() + folders.add(new File(Paths.get(SRC_PATH,'src_temporary').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','classes').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','triggers').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','objects').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder1').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','dashboards','DashboardFolder2').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','documents').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1').toString())) + folders.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder2').toString())) + + folders.each { folder-> + new File(folder.getAbsolutePath()).mkdir() + } + + allFiles.each { file-> + new File(file.getAbsolutePath()).createNewFile() + } + } + + def "Test should be instance of Filter class"() { + expect: + filter instanceof Filter + } + + def "Test should return a map with parameter as key and its content as value"() { + given: + ArrayList parametersName = ['files'] + Map properties = [:] + properties.put('files', 'classes') + when: + Map result = filter.getContentParameter(parametersName, properties) + then: + result.containsKey('files') + result.get('files') == 'classes' + } + + def "Test should return a map with pall parameters and their values"() { + given: + ArrayList parametersName = ['files', 'excludes'] + Map properties = [:] + properties.put('files', 'classes,objects') + properties.put('excludes', "*${File.separator}class1.cls,objects${File.separator}Object1__c.object") + when: + Map result = filter.getContentParameter(parametersName, properties) + then: + result.containsKey('files') + result.get('files') == 'classes,objects' + result.containsKey('excludes') + result.get('excludes') == "*${File.separator}class1.cls,objects${File.separator}Object1__c.object" + } + + def "Test should return all classes from project path"() { + given: + ArrayList parametersName = ['files'] + Map properties = [:] + properties.put('files', 'classes') + when: + ArrayList result = filter.getFiles(parametersName, properties) + then: + result.sort() == [new File(Paths.get(SRC_PATH, 'classes', 'class1.cls').toString()), + new File(Paths.get(SRC_PATH, 'classes', 'class1.cls-meta.xml').toString())].sort() + } + + def "Test should return the Class1 file" () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/Class1.cls') + ArrayList filesExpected = [] + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls-meta.xml').toString())) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return the Class1,Class2 files" () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/Class1.cls,classes/Class2.cls') + ArrayList filesExpected = [] + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls-meta.xml').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls-meta.xml').toString())) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all classes with the criteria [files:classes/**] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/**') + ArrayList filesExpected = [] + filesExpected.addAll(classFiles) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all classes with the criteria [files:classes/*.cls] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/*.cls') + ArrayList filesExpected = [] + filesExpected.addAll(classFiles) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all classes [files:classes] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes') + ArrayList filesExpected = [] + filesExpected.addAll(classFiles) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all classes excluding class 3 and 4 with the criteria [files:classes/*.cls] [classes/Class3.cls,classes/Class4.cls] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/*.cls') + properties.put(Constants.PARAMETER_EXCLUDES, 'classes/Class3.cls,classes/Class4.cls') + ArrayList filesExpected = [] + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls-meta.xml').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class2.cls-meta.xml').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class5.cls').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class5.cls-meta.xml').toString())) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components [files:] [excludes:] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [] + Map properties = [:] + ArrayList filesExpected = allFiles.clone() + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all classes excludig Class1.cls [excludes:classes/Class1.cls] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'classes/Class1.cls') + ArrayList filesExpected = allFiles.clone() + filesExpected.remove(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls').toString())) + filesExpected.remove(new File(Paths.get(SRC_PATH,'src_temporary','classes','Class1.cls-meta.xml').toString())) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return cero components [files:classes/*.cls] [excludes:classes/*.cls] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes/*.cls') + properties.put(Constants.PARAMETER_EXCLUDES, 'classes/*.cls') + ArrayList filesExpected = [] + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less classes [excludes:triggers,objects] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'triggers,objects') + ArrayList filesExpected = [] + filesExpected.addAll(classFiles) + filesExpected.addAll(documentFiles) + filesExpected.addAll(documentFolder1) + filesExpected.addAll(documentFolder2) + filesExpected.addAll(dashboardFiles) + filesExpected.addAll(dashboardsFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less classes [excludes:triggers,objects,object,object/Object1__c.object] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'triggers,objects,object/Object1__c.object') + ArrayList filesExpected = [] + filesExpected.addAll(classFiles) + filesExpected.addAll(documentFiles) + filesExpected.addAll(documentFolder1) + filesExpected.addAll(documentFolder2) + filesExpected.addAll(dashboardFiles) + filesExpected.addAll(dashboardsFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less classes [excludes:triggers,objects,object,object/Object1__c.object] without parameters " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'triggers,objects,object/Object1__c.object') + ArrayList filesExpected = allFiles.clone() + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less classes [files:classes] without parameters " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'classes') + ArrayList filesExpected = allFiles.clone() + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all documents [files:documents/**] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/**') + ArrayList filesExpected = [] + filesExpected.addAll(documentFiles) + filesExpected.addAll(documentFolder1) + filesExpected.addAll(documentFolder2) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return documents in folder documents1 [files:documents/DocumentsFolder1/**] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/DocumentsFolder1/**') + ArrayList filesExpected = [] + filesExpected.addAll(documentFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return documents in folder documents2 [files:documents/DocumentsFolder2/*.*] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/DocumentsFolder2/*.*') + ArrayList filesExpected = [] + filesExpected.addAll(documentFolder2) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return documents in folder documents1 [files:documents/DocumentsFolder1] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/DocumentsFolder1') + ArrayList filesExpected = [] + filesExpected.addAll(documentFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less documents in folder documents1 [exclude:documents/DocumentsFolder1/**] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'documents/DocumentsFolder1/**') + ArrayList filesExpected = allFiles.clone() + filesExpected.removeAll(documentFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all components less documents in folder documents1 [exclude:documents/DocumentsFolder1] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_EXCLUDES, 'documents/DocumentsFolder1') + ArrayList filesExpected = allFiles.clone() + filesExpected.removeAll(documentFolder1) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return the documentes less documents in folder documents1 [files:documents/DocumentsFolder1/DocumentTest_1_1.txt] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/DocumentsFolder1/DocumentTest_1_1.txt') + ArrayList filesExpected = [] + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_1.txt').toString())) + filesExpected.add(new File(Paths.get(SRC_PATH,'src_temporary','documents','DocumentsFolder1','DocumentTest_1_1.txt-meta.xml').toString())) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return all folder documents less documents1 folder [files:documents/**] [excludes: documents/DocumentsFolder1/**] " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + ArrayList parametersName = [Constants.PARAMETER_FILES,Constants.PARAMETER_EXCLUDES] + Map properties = [:] + properties.put(Constants.PARAMETER_FILES, 'documents/**') + properties.put(Constants.PARAMETER_EXCLUDES, 'documents/DocumentsFolder1/**') + ArrayList filesExpected = [] + filesExpected.addAll(documentFiles) + filesExpected.addAll(documentFolder2) + when: + ArrayList result = myFilter.getFiles(parametersName, properties) + then: + result.sort() == filesExpected.sort() + } + + def "Test should return a criteria when you send a wildcard " () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + String criterion = "*${File.separator}*.cls" + when: + ArrayList result = myFilter.getCriteria(criterion) + then: + result.sort() == ["*${File.separator}*.cls", "*${File.separator}*.cls-meta.xml"].sort() + } + + def "Test should return a criteria when you send a folder name" () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + String criterion = "classes,objects" + when: + ArrayList result = myFilter.getCriteria(criterion) + then: + result.sort() == ["classes${File.separator}**", "objects${File.separator}**"].sort() + } + + def "Test should return a criteria when you send a sub folder name" () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + String criterion = "documents${File.separator}DocumentsFolder1" + when: + ArrayList result = myFilter.getCriteria(criterion) + then: + result.sort() == ["documents${File.separator}DocumentsFolder1${File.separator}**"].sort() + } + + def "Test should return a criteria when you send a folders name with spaces" () { + given: + Filter myFilter = new Filter(project, Paths.get(SRC_PATH, 'src_temporary').toString()) + String criterion = "documents, classes , objects" + when: + ArrayList result = myFilter.getCriteria(criterion) + then: + result.sort() == ["documents${File.separator}**", "classes${File.separator}**", "objects${File.separator}**"].sort() + } + + def cleanupSpec() { + new File(Paths.get(SRC_PATH,'src_temporary').toString()).deleteDir() + } +} diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/resources/src/objects/Account.object b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/resources/src/objects/Account.object deleted file mode 100644 index 8d06d7c..0000000 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/resources/src/objects/Account.object +++ /dev/null @@ -1,648 +0,0 @@ - - - - CallHighlightAction - Default - - - CancelEdit - Default - - - Delete - Default - - - Edit - Default - - - EmailHighlightAction - Default - - - EnableCustomerPortalUser - Default - - - Follow - Default - - - List - Default - - - ListClean - Default - - - MapHighlightAction - Default - - - New - Default - - - NewsHighlightAction - Default - - - RequestUpdate - Default - - - SaveEdit - Default - - - Tab - Default - - - View - Default - - - ViewCustomerPortalUser - Default - - - WebsiteHighlightAction - Default - - SYSTEM - true - false - - AccountNumber - false - - - AccountSource - - - Web - false - - - Phone Inquiry - false - - - Partner Referral - false - - - Purchased List - false - - - Other - false - - false - - false - Picklist - - - Active__c - false - - - - No - false - - - Yes - false - - false - - false - Picklist - - - AnnualRevenue - false - - - BillingAddress - false - - - CleanStatus - false - - - CustomField1__c - false - - 10 - false - false - Text - false - - - CustomerPriority__c - false - - - - High - false - - - Low - false - - - Medium - false - - false - - false - Picklist - - - DandbCompanyId - false - Lookup - - - Description - false - - - DunsNumber - false - - - Fax - false - - - Industry - - - Agriculture - false - - - Apparel - false - - - Banking - false - - - Biotechnology - false - - - Chemicals - false - - - Communications - false - - - Construction - false - - - Consulting - false - - - Education - false - - - Electronics - false - - - Energy - false - - - Engineering - false - - - Entertainment - false - - - Environmental - false - - - Finance - false - - - Food & Beverage - false - - - Government - false - - - Healthcare - false - - - Hospitality - false - - - Insurance - false - - - Machinery - false - - - Manufacturing - false - - - Media - false - - - Not For Profit - false - - - Recreation - false - - - Retail - false - - - Shipping - false - - - Technology - false - - - Telecommunications - false - - - Transportation - false - - - Utilities - false - - - Other - false - - false - - false - Picklist - - - Jigsaw - false - - - MyLookupField2__c - SetNull - false - - Object2__c - Field1__c - Account_To_Object2 - false - false - Lookup - - - NaicsCode - false - - - NaicsDesc - false - - - Name - true - - - NumberOfEmployees - false - - - NumberofLocations__c - false - - 3 - false - 0 - false - Number - false - - - OwnerId - true - Lookup - - - Ownership - - - Public - false - - - Private - false - - - Subsidiary - false - - - Other - false - - false - - false - Picklist - - - ParentId - false - Hierarchy - - - Phone - false - - - Rating - - - Hot - false - - - Warm - false - - - Cold - false - - false - - false - Picklist - - - SLAExpirationDate__c - false - - false - false - Date - - - SLASerialNumber__c - false - - 10 - false - false - Text - false - - - SLA__c - false - - - - Gold - false - - - Silver - false - - - Platinum - false - - - Bronze - false - - false - - false - Picklist - - - ShippingAddress - false - - - Sic - false - - - SicDesc - false - - - Site - false - - - TestLabelName__c - false - Phone & ", " & Sic - BlankAsZero - - false - Text - false - - - TickerSymbol - false - - - Tradestyle - false - - - Type - - - Prospect - false - - - Customer - Direct - false - - - Customer - Channel - false - - - Channel Partner / Reseller - false - - - Installation Partner - false - - - Technology Partner - false - - - Other - false - - false - - false - Picklist - - - UpsellOpportunity__c - false - - - - Maybe - false - - - No - false - - - Yes - false - - false - - false - Picklist - - - Website - false - - - YearStarted - false - - - AllAccounts - Everything - - - - MyAccounts - Mine - - - - NewLastWeek - Everything - - ACCOUNT.CREATED_DATE - equals - LAST_WEEK - - - - - NewThisWeek - Everything - - ACCOUNT.CREATED_DATE - equals - THIS_WEEK - - - - - PlatinumandGoldSLACustomers - ACCOUNT.NAME - ACCOUNT.SITE - ACCOUNT.ADDRESS1_STATE - ACCOUNT.PHONE1 - CORE.USERS.ALIAS - Everything - - - - ACCOUNT.NAME - ACCOUNT.ADDRESS1_CITY - ACCOUNT.PHONE1 - ACCOUNT.NAME - ACCOUNT.SITE - CORE.USERS.ALIAS - ACCOUNT.TYPE - ACCOUNT.NAME - ACCOUNT.SITE - CORE.USERS.ALIAS - ACCOUNT.TYPE - ACCOUNT.PHONE1 - ACCOUNT.NAME - ACCOUNT.SITE - ACCOUNT.PHONE1 - CORE.USERS.ALIAS - - ReadWrite - - Billing - online - link - UTF-8 - true - true - true - 600 - true - url - Billing - newWindow - none - false - true - true - http://www.genwatt.com/genwatt/billing.htm?actname={!Account.Name} - - \ No newline at end of file diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTaskTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTaskTest.groovy index 7007c8a..3f5c8ab 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTaskTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/tasks/salesforce/unittest/RunTestTaskTest.groovy @@ -60,19 +60,52 @@ class RunTestTaskTest extends Specification { def "Should get the class names from a wildcard"() { given: - project.enforce { - srcPath = SRC_PATH - standardObjects = ["Q2w_Test__c.object"] - tool = "metadata" - poll = 200 - waitTime = 10 - } - def classNames = [] + project.enforce { + srcPath = SRC_PATH + standardObjects = ["Q2w_Test__c.object"] + tool = "metadata" + poll = 200 + waitTime = 10 + } + def classNames = [] when: - RunTestTask runTestTask = project.tasks.findByName(RUN_TEST_TASK_NAME) as RunTestTask - def path = Paths.get(SRC_PATH, "test").toString() - classNames = runTestTask.getClassNames(path, "*Test*") + RunTestTask runTestTask = project.tasks.findByName(RUN_TEST_TASK_NAME) as RunTestTask + def path = Paths.get(SRC_PATH, "test").toString() + classNames = runTestTask.getClassNames(path, "*Test*") then: - classNames.sort() == ["FGW_Console_CTRLTest", "FGW_APIFactoryTest"].sort() + classNames.sort() == ["FGW_Console_CTRLTest", "FGW_APIFactoryTest"].sort() + } + + def "Test should return the class name when notation is case insensitive"() { + given: + project.enforce { + srcPath = SRC_PATH + } + + File testClass1 = new File(Paths.get(SRC_PATH, "test", "Class1Test.cls").toString()) + testClass1.write("@IsTest\n" + + "public class Class1Test {}") + + File testClass2 = new File(Paths.get(SRC_PATH, "test", "Class2Test.cls").toString()) + testClass2.write("@ISTEST\n" + + "public class Class2Test {}") + + File testClass3 = new File(Paths.get(SRC_PATH, "test", "Class3Test.cls").toString()) + testClass3.write("@istest\n" + + "public class Class3Test {}") + + RunTestTask runTestTask = project.tasks.findByName(RUN_TEST_TASK_NAME) as RunTestTask + String path = Paths.get(SRC_PATH, "test") + when: + ArrayList classNames = runTestTask.getClassNames(path, "*Test*") + then: + classNames.sort() == ["FGW_Console_CTRLTest", "FGW_APIFactoryTest", "Class1Test", "Class2Test", + "Class3Test"].sort() + } + + def cleanupSpec() { + new File(Paths.get(SRC_PATH, "test", "Class1Test.cls").toString()).delete() + new File(Paths.get(SRC_PATH, "test", "Class2Test.cls").toString()).delete() + new File(Paths.get(SRC_PATH, "test", "Class3Test.cls").toString()).delete() } } diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/ManagementFileTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/ManagementFileTest.groovy index da6f3be..6cd99d3 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/ManagementFileTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/ManagementFileTest.groovy @@ -5,6 +5,7 @@ package org.fundacionjala.gradle.plugins.enforce.utils +import org.fundacionjala.gradle.plugins.enforce.utils.salesforce.FileValidator import spock.lang.Shared import spock.lang.Specification @@ -34,6 +35,8 @@ class ManagementFileTest extends Specification { new File(Paths.get(targetPath, 'objects', 'Object2__c.object').toString()), new File(Paths.get(targetPath, 'reports', 'testFolder', 'testReport.report').toString()), new File(Paths.get(targetPath, 'reports', 'testFolder-meta.xml').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/doc1.doc').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/image.png').toString()), new File(Paths.get(targetPath, 'package.xml').toString())] then: arrayResult.sort() == arrayExpected.sort() @@ -49,6 +52,8 @@ class ManagementFileTest extends Specification { new File(Paths.get(targetPath, 'objects', 'Account.object').toString()), new File(Paths.get(targetPath, 'objects', 'Object1__c.object').toString()), new File(Paths.get(targetPath, 'objects', 'Object2__c.object').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/doc1.doc').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/image.png').toString()), new File(Paths.get(targetPath, 'reports', 'testFolder', 'testReport.report').toString())].sort() } @@ -63,6 +68,8 @@ class ManagementFileTest extends Specification { new File(Paths.get(targetPath, 'objects', 'Account.object').toString()), new File(Paths.get(targetPath, 'objects', 'Object1__c.object').toString()), new File(Paths.get(targetPath, 'objects', 'Object2__c.object').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/doc1.doc').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/image.png').toString()), new File(Paths.get(targetPath, 'package.xml').toString()), new File(Paths.get(targetPath, 'reports', 'testFolder', 'testReport.report').toString()), new File(Paths.get(targetPath, 'reports', 'testFolder-meta.xml').toString())].sort() @@ -74,7 +81,9 @@ class ManagementFileTest extends Specification { when: ArrayList arrayResult = managementFile.getValidElements(targetPath, typesToExclude) then: - arrayResult.sort() == [new File(Paths.get(targetPath, 'classes', 'class1.cls').toString())].sort() + arrayResult.sort() == [new File(Paths.get(targetPath, 'classes', 'class1.cls').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/doc1.doc').toString()), + new File(Paths.get(targetPath, 'documents', 'mydocs/image.png').toString())].sort() } def "Test should copy from source path"() { @@ -187,7 +196,7 @@ class ManagementFileTest extends Specification { def "Test load directories not deploy"() { expect: - managementFile.getFoldersNotDeploy(targetPath).sort() == ["web"].sort() + managementFile.getFoldersNotDeploy(targetPath).sort() == ["web", "encoding"].sort() } def "should throw a exception because managementFie constructor value is nothing"() { @@ -269,17 +278,18 @@ class ManagementFileTest extends Specification { def "should get subdirectories form source directory by file extension"() { given: - def dirNames = [] + def dirNames = [] when: - def files = managementFile.getSubdirectories() - files.each { - dirNames.add(it.name) - } + def files = managementFile.getSubdirectories() + files.each { + dirNames.add(it.name) + } then: - dirNames.sort() == ['classes', 'objects', 'reports', 'web'].sort() + dirNames.sort() == ['classes', 'documents', 'encoding', 'objects', 'reports', 'web'].sort() + } - def "Test should create the directories if it doesn't exist"(){ + def "Test should create the directories if it doesn't exist"() { expect: Path path = Paths.get(targetPath, 'test', 'testOne', 'testTwo', 'testThree') ManagementFile.createDirectories(path.toString()) diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/UtilTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/UtilTest.groovy index 8b66037..6be76f9 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/UtilTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/UtilTest.groovy @@ -12,10 +12,10 @@ import java.nio.file.Paths class UtilTest extends Specification { @Shared - String resourcesPath + String RESOURCES_PATH def setup() { - resourcesPath = Paths.get(System.getProperty("user.dir"), 'src', 'test', 'groovy', 'org', 'fundacionjala', 'gradle', 'plugins','enforce', 'utils', 'resources').toString() + RESOURCES_PATH = Paths.get(System.getProperty("user.dir"), 'src', 'test', 'groovy', 'org', 'fundacionjala', 'gradle', 'plugins','enforce', 'utils', 'resources').toString() } def "Test should return true if emails are valid"() { @@ -91,7 +91,7 @@ class UtilTest extends Specification { def "Test should return an arrayList empty if the folders aren't empty" () { given: def foldersName = ['objects', 'classes'] - def projectPath = resourcesPath + def projectPath = RESOURCES_PATH when: def result = Util.getEmptyFolders(foldersName, projectPath) then: @@ -100,9 +100,9 @@ class UtilTest extends Specification { def "Test should return an arrayList with folders empty" () { given: - new File(Paths.get(resourcesPath, 'triggers').toString()).mkdir() + new File(Paths.get(RESOURCES_PATH, 'triggers').toString()).mkdir() def foldersName = ['objects', 'classes', 'triggers'] - def projectPath = resourcesPath + def projectPath = RESOURCES_PATH when: def result = Util.getEmptyFolders(foldersName, projectPath) then: @@ -111,7 +111,7 @@ class UtilTest extends Specification { def "Test should return an extension from a file" () { given: - def file = new File(Paths.get(resourcesPath, 'objects', 'Maintenance_Ticket_WO__c.object').toString()) + def file = new File(Paths.get(RESOURCES_PATH, 'objects', 'Maintenance_Ticket_WO__c.object').toString()) when: def extension = Util.getFileExtension(file) then: @@ -120,7 +120,7 @@ class UtilTest extends Specification { def "Test should return an extension from a file if there is more than one dot" () { given: - def file = new File(Paths.get(resourcesPath, 'objects', 'My_New.CustomObject__c.object').toString()) + def file = new File(Paths.get(RESOURCES_PATH, 'objects', 'My_New.CustomObject__c.object').toString()) when: def extension = Util.getFileExtension(file) then: @@ -157,7 +157,7 @@ class UtilTest extends Specification { def "Test get relative path"() { given: - String basePath = Paths.get(resourcesPath, 'relativeTest') + String basePath = Paths.get(RESOURCES_PATH, 'relativeTest') File file = new File(Paths.get(basePath, "classes/class1").toString()) when: def relativePath = Util.getRelativePath(file, basePath) @@ -167,7 +167,7 @@ class UtilTest extends Specification { def "Test should gets relative path when the path has a space"() { given: - String basePath = Paths.get(resourcesPath, 'relativeTest') + String basePath = Paths.get(RESOURCES_PATH, 'relativeTest') File file = new File(Paths.get(basePath, "classes/class 1").toString()) when: def relativePath = Util.getRelativePath(file, basePath) @@ -182,8 +182,41 @@ class UtilTest extends Specification { objectName == 'Object5__c' } + def "Test should return true if api name has prefix" () { + when: + def result = Util.isPackaged('myprefix__CustomObject__c') + then: + result + } + + def "Test should return false if api name hasn't perfix" () { + when: + def result = Util.isPackaged('CustomObject__c') + then: + !result + } + + def "Test should get file encoding" () { + given: + def path = Paths.get(RESOURCES_PATH, 'encoding').toString() + def fileEncodingUTF16BE = new File(Paths.get(path, "Client.cls").toString()) + def fileEncodingUTF16LE = new File(Paths.get(path, "Client.cls-meta.xml").toString()) + def fileEncodingUTF8 = new File(Paths.get(path, "Opportunity.cls").toString()) + def fileEncodingUTF16LE1 = new File(Paths.get(path, "Opportunity.cls-meta.xml").toString()) + when: + def encodingUTF16BE = Util.getCharset(fileEncodingUTF16BE) + def encodingUTF16LE = Util.getCharset(fileEncodingUTF16LE) + def encodingUTF8 = Util.getCharset(fileEncodingUTF8) + def encodingUTF16LE1 = Util.getCharset(fileEncodingUTF16LE1) + then: + encodingUTF16BE + encodingUTF16LE + encodingUTF8 + encodingUTF16LE1 + } + def cleanupSpec() { - new File(Paths.get(resourcesPath, 'triggers').toString()).deleteDir() - new File(Paths.get(resourcesPath, 'relativeTest').toString()).deleteDir() + new File(Paths.get(RESOURCES_PATH, 'triggers').toString()).deleteDir() + new File(Paths.get(RESOURCES_PATH, 'relativeTest').toString()).deleteDir() } } diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/documents/mydocs/doc1.doc b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/documents/mydocs/doc1.doc new file mode 100644 index 0000000..e69de29 diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/documents/mydocs/image.png b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/documents/mydocs/image.png new file mode 100644 index 0000000..e69de29 diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls new file mode 100644 index 0000000..95f21bc Binary files /dev/null and b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls differ diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls-meta.xml b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls-meta.xml new file mode 100644 index 0000000..85c2f3d Binary files /dev/null and b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Client.cls-meta.xml differ diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls new file mode 100644 index 0000000..e29cbb9 --- /dev/null +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls @@ -0,0 +1,10 @@ + + +public with sharing class OpportunityToSmartsheet { + + public Opportunity opp1 {get;set;} + public Opportunity opp2 {get;set;} + public List oppRecords {get;set;} + + +} \ No newline at end of file diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls-meta.xml b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls-meta.xml new file mode 100644 index 0000000..85c2f3d Binary files /dev/null and b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/encoding/Opportunity.cls-meta.xml differ diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/objects/InvalidObject__c.obj b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources/objects/InvalidObject__c.obj new file mode 100644 index 0000000..e69de29 diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidatorTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidatorTest.groovy new file mode 100644 index 0000000..96e8177 --- /dev/null +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/FileValidatorTest.groovy @@ -0,0 +1,102 @@ +package org.fundacionjala.gradle.plugins.enforce.utils.salesforce + +import org.fundacionjala.gradle.plugins.enforce.utils.Constants +import spock.lang.Shared +import spock.lang.Specification + +import java.nio.file.Paths + +class FileValidatorTest extends Specification { + @Shared + String projectPath + + def setup() { + def userDir = System.getProperty("user.dir") + projectPath = Paths.get(userDir, 'src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/resources').toString() + } + + def "Test should returns all invalid files" () { + given: + File invalidFolderByDocument = new File(Paths.get(projectPath, 'reports/mydocs/doc1.doc').toString()) + File invalidExtensionFile = new File(Paths.get(projectPath, 'classes/Class1.cls-meta.xml').toString()) + File invalidFileWithoutExtension = new File(Paths.get(projectPath, 'classes/Class1').toString()) + ArrayList files = [] + files.add(new File(Paths.get(projectPath, 'documents/mydocs/doc1.doc').toString())) + files.add(new File(Paths.get(projectPath, 'documents/mydocs/image.png').toString())) + files.add(invalidFolderByDocument) + files.add(new File(Paths.get(projectPath, 'reports/myreports/report1.report').toString())) + files.add(new File(Paths.get(projectPath, 'objects/obj__c.object').toString())) + files.add(new File(Paths.get(projectPath, 'classes/Class1.cls').toString())) + files.add(invalidExtensionFile) + files.add(invalidFileWithoutExtension) + Map> expected = [:] + ArrayList invalidFiles = [] + invalidFiles.add(invalidFolderByDocument) + invalidFiles.add(invalidFileWithoutExtension) + invalidFiles.add(invalidExtensionFile) + expected.put(Constants.INVALID_FILE, invalidFiles) + when: + Map> result = FileValidator.validateFiles(projectPath, files) + then: + result[Constants.INVALID_FILE].sort() == expected[Constants.INVALID_FILE].sort() + } + + def "Test should returns a map that contains all files by states: invalid, not_found, and valid" () { + given: + //invalid files + File invalidFolderFile = new File(Paths.get(projectPath, 'web/InvalidClass.cls').toString()) + File invalidObjectExtension = new File(Paths.get(projectPath, 'objects/InvalidObject__c.obj').toString()) + File invalidExtensionFile = new File(Paths.get(projectPath, 'classes/other.data').toString()) + + // valid files + File validDoc = new File(Paths.get(projectPath, 'documents/mydocs/doc1.doc').toString()) + File validPng = new File(Paths.get(projectPath, 'documents/mydocs/image.png').toString()) + File validReport = new File(Paths.get(projectPath, 'reports/testFolder/testReport.report').toString()) + File validObj = new File(Paths.get(projectPath, 'objects/Object1__c.object').toString()) + File validClass = new File(Paths.get(projectPath, 'classes/class1.cls').toString()) + + // not found files + File notFoundDoc = new File(Paths.get(projectPath, 'documents/mydocs/notFoundDoc.doc').toString()) + File notFoundReport = new File(Paths.get(projectPath, 'reports/testFolder/notFoundReport.report').toString()) + File notFoundClass = new File(Paths.get(projectPath, 'classes/notFoundClass1.cls').toString()) + + ArrayList files = [] + files.add(validDoc) + files.add(validPng) + files.add(invalidObjectExtension) + files.add(invalidFolderFile) + files.add(validReport) + files.add(validObj) + files.add(validClass) + files.add(invalidExtensionFile) + files.add(notFoundReport) + files.add(notFoundClass) + files.add(notFoundDoc) + + Map> expected = [:] + ArrayList invalidFiles = [] + invalidFiles.add(invalidObjectExtension) + invalidFiles.add(invalidExtensionFile) + invalidFiles.add(invalidFolderFile) + ArrayList notFoundFiles = [] + notFoundFiles.add(notFoundClass) + notFoundFiles.add(notFoundDoc) + notFoundFiles.add(notFoundReport) + + ArrayList validFiles = [] + validFiles.add(validPng) + validFiles.add(validClass) + validFiles.add(validDoc) + validFiles.add(validObj) + validFiles.add(validReport) + expected.put(Constants.INVALID_FILE, invalidFiles) + expected.put(Constants.VALID_FILE, validFiles) + expected.put(Constants.DOES_NOT_EXIST_FILES, notFoundFiles) + when: + Map> result = FileValidator.validateFiles(projectPath, files) + then: + result[Constants.INVALID_FILE].sort() == expected[Constants.INVALID_FILE].sort() + result[Constants.VALID_FILE].sort() == expected[Constants.VALID_FILE].sort() + result[Constants.DOES_NOT_EXIST_FILES].sort() == expected[Constants.DOES_NOT_EXIST_FILES].sort() + } +} diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombinerTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombinerTest.groovy index 42095c1..48ffc4e 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombinerTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageCombinerTest.groovy @@ -408,7 +408,7 @@ class PackageCombinerTest extends Specification { def 'Test should take in account documents with their folders name as member into package xml file '() { given: String projectPackagePath = Paths.get(SRC_PATH, 'projectPackage.xml') - String buildPackagePath = Paths.get(SRC_PATH, 'buildPackage.xml') + String buildPackagePath = Paths.get(SRC_PATH, 'package.xml') String projectPackageContent = ''' @@ -475,6 +475,12 @@ class PackageCombinerTest extends Specification { Object4__c CustomObject + + MyDocuments/doc2.txt + MyDocuments/doc1.txt + MyDocuments + Document + Class1 ApexClass @@ -483,12 +489,6 @@ class PackageCombinerTest extends Specification { Object1__c.MyCustomField1 CustomField - - MyDocuments - MyDocuments/doc2.txt - MyDocuments/doc1.txt - Document - Object1__c.MyFieldSet1 FieldSet @@ -505,9 +505,106 @@ class PackageCombinerTest extends Specification { xmlDiff.similar() } + def 'Test should take in account documents with their folders name when it is added '() { + given: + String projectPackagePath = Paths.get(SRC_PATH, 'projectPackage.xml') + String buildPackagePath = Paths.get(SRC_PATH, 'package.xml') + //the next variable is content of my project package + String projectPackageContent = ''' + + + MyDocuments + MyDocuments/doc2.txt + MyDocuments/doc1.txt + Document + + 32.0 + + ''' + //The next is the content of my build package + String buildPackageContent =''' + + + MyDocuments/doc3.txt + Document + + 32.0 + ''' + File projectPackageFile = new File(projectPackagePath) + projectPackageFile.write(projectPackageContent) + File buildPackageFile = new File(buildPackagePath) + buildPackageFile.write(buildPackageContent) + String packageContentExpect = ''' + + + MyDocuments/doc3.txt + MyDocuments + Document + + 32.0 + + ''' + when: + PackageCombiner.packageCombineToUpdate(projectPackagePath, buildPackagePath) + XMLUnit.ignoreWhitespace = true + def xmlDiff = new Diff(buildPackageFile.text, packageContentExpect) + then: + new File(Paths.get(SRC_PATH, 'buildPackage.xml').toString()).exists() + xmlDiff.similar() + } + + def "Test shouldn't take in account documents with their folders name when it is deleted "() { + given: + String projectPackagePath = Paths.get(SRC_PATH, 'projectPackage.xml') + String destructivePath = Paths.get(SRC_PATH, 'destructiveChanges.xml') + //the next variable is content of my project package + String projectPackageContent = ''' + + + MyDocuments + MyDocuments/doc2.txt + MyDocuments/doc1.txt + Document + + 32.0 + + ''' + //The next is the content of my build package + String destructiveContent =''' + + + MyDocuments/doc1.txt + Document + + 32.0 + ''' + File projectPackageFile = new File(projectPackagePath) + projectPackageFile.write(projectPackageContent) + File buildPackageFile = new File(destructivePath) + buildPackageFile.write(destructiveContent) + String packageContentExpect = ''' + + + MyDocuments/doc1.txt + Document + + 32.0 + + ''' + when: + PackageCombiner.packageCombineToUpdate(projectPackagePath, destructivePath) + XMLUnit.ignoreWhitespace = true + def xmlDiff = new Diff(buildPackageFile.text, packageContentExpect) + then: + new File(Paths.get(SRC_PATH, 'destructiveChanges.xml').toString()).exists() + xmlDiff.similar() + } + def cleanupSpec() { new File(Paths.get(SRC_PATH, 'projectPackage.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'package.xml').toString()).delete() new File(Paths.get(SRC_PATH, 'buildPackage.xml').toString()).delete() + new File(Paths.get(SRC_PATH, 'destructiveChanges.xml').toString()).delete() new File(Paths.get(SRC_PATH, 'packageTest.xml').toString()).delete() new File(Paths.get(SRC_PATH, 'packageTestDocument.xml').toString()).delete() new File(Paths.get(SRC_PATH, 'packageTestReport.xml').toString()).delete() diff --git a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGeneratorTest.groovy b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGeneratorTest.groovy index 8930be4..861985c 100644 --- a/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGeneratorTest.groovy +++ b/src/test/groovy/org/fundacionjala/gradle/plugins/enforce/utils/salesforce/PackageGeneratorTest.groovy @@ -117,14 +117,16 @@ class PackageGeneratorTest extends Specification { packageGenerator.packageBuilder.metaPackage.types[0].members[0] == "File" packageGenerator.packageBuilder.metaPackage.types[0].members[1] == "Util" packageGenerator.packageBuilder.metaPackage.types[0].name == "ApexClass" - packageGenerator.packageBuilder.metaPackage.types[1].members[0] == "ObjectUtil" - packageGenerator.packageBuilder.metaPackage.types[1].members[1] == "ObjectFile" - packageGenerator.packageBuilder.metaPackage.types[1].name == "CustomObject" - packageGenerator.packageBuilder.metaPackage.types[2].members[0] == "ObjectFile.fieldTwo" - packageGenerator.packageBuilder.metaPackage.types[2].members[1] == "ObjectFile.fieldOne" - packageGenerator.packageBuilder.metaPackage.types[2].members[2] == "ObjectFile.fieldThree" - packageGenerator.packageBuilder.metaPackage.types[2].name == "CustomField" + packageGenerator.packageBuilder.metaPackage.types[1].members[0] == "ObjectFile.fieldOne" + packageGenerator.packageBuilder.metaPackage.types[1].members[1] == "ObjectFile.fieldThree" + packageGenerator.packageBuilder.metaPackage.types[1].members[2] == "ObjectFile.fieldTwo" + packageGenerator.packageBuilder.metaPackage.types[1].name == "CustomField" + + + packageGenerator.packageBuilder.metaPackage.types[2].members[0] == "ObjectFile" + packageGenerator.packageBuilder.metaPackage.types[2].members[1] == "ObjectUtil" + packageGenerator.packageBuilder.metaPackage.types[2].name == "CustomObject" } def "Test should build a package from deleted files"() { @@ -196,8 +198,8 @@ class PackageGeneratorTest extends Specification { packageGenerator.fileTrackerMap = fileTrackerMap ArrayList files = [new File('classes/Class2.cls')] when: - ArrayList result = packageGenerator.excludeFiles(files) + packageGenerator.updateFileTracker(files) then: - result == [new File('classes/Class1.cls')] + packageGenerator.fileTrackerMap['classes/Class2.cls'].state == ComponentStates.CHANGED } }