diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend b/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend index de07c01e..5126486a 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend @@ -14,6 +14,11 @@ */ package org.utplsql.sqldev.model +import java.io.StringWriter +import javax.xml.transform.OutputKeys +import javax.xml.transform.TransformerFactory +import javax.xml.transform.dom.DOMSource +import javax.xml.transform.stream.StreamResult import javax.xml.xpath.XPathConstants import javax.xml.xpath.XPathFactory import org.w3c.dom.Node @@ -34,4 +39,29 @@ class XMLTools { val Node node = expr.evaluate(doc, XPathConstants.NODE) as Node return node } -} \ No newline at end of file + + def void trimWhitespace(Node node) { + val children = node.childNodes + for (i : 0 ..< children.length) { + val child = children.item(i) + if (child.nodeType == Node.TEXT_NODE) { + child.textContent = child.textContent.trim + } + trimWhitespace(child); + } + } + + def nodeToString(Node node, String cdataSectionElements) { + node.trimWhitespace + val writer = new StringWriter() + val factory = TransformerFactory.newInstance().newTransformer() + factory.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes") + factory.setOutputProperty(OutputKeys.INDENT, "yes") + factory.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3"); + factory.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements) + factory.transform(new DOMSource(node), new StreamResult(writer)) + val result = writer.toString() + val fixedResult = result.replaceAll('''<!\[CDATA\[\s*\]\]>''',"") + return fixedResult + } +} diff --git a/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend b/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend new file mode 100644 index 00000000..af3a7bb7 --- /dev/null +++ b/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Philipp Salvisberg <philipp.salvisberg@trivadis.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.utplsql.sqldev.snippet + +import java.io.BufferedReader +import java.io.File +import java.io.IOException +import java.io.InputStreamReader +import java.io.StringReader +import java.nio.charset.Charset +import java.nio.file.Files +import java.nio.file.Paths +import java.util.stream.Collectors +import javax.xml.parsers.DocumentBuilderFactory +import oracle.dbtools.util.Resource +import org.utplsql.sqldev.model.XMLTools +import org.xml.sax.InputSource + +class SnippetMerger { + val extension XMLTools xmlTools = new XMLTools + File userSnippetsFile + String utplsqlSnippets + + def getUtplsqlSnippetsAsString() throws IOException { + val stream = class.getResourceAsStream("/org/utplsql/sqldev/resources/UtplsqlSnippets.xml") + val reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset)) + return reader.lines.collect(Collectors.joining(System.lineSeparator)) + } + + new() { + // works in SQL Developer only, otherwise a ExceptionInInitializerError is thrown + this (new File(Resource.RAPTOR_USER.absolutePath + File.separator + "UserSnippets.xml")) + } + + new(File file) { + utplsqlSnippets = utplsqlSnippetsAsString + userSnippetsFile = file + } + + def merge() { + var String result + if (userSnippetsFile.exists) { + // file exists, proper merge required + val userSnippets = new String(Files.readAllBytes(Paths.get(userSnippetsFile.absolutePath))) + val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder() + val userSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(userSnippets))) + val userSnippetsGroups = userSnippetsDoc.getNodeList('''/snippets/group[not(@category="utPLSQL Annotations" or @category="utPLSQL Expectations")]''') + val utplsqlSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(utplsqlSnippets))) + val utplsqlSnippetsGroups = utplsqlSnippetsDoc.getNodeList('''/snippets/group''') + result = ''' + <?xml version = '1.0' encoding = 'UTF-8'?> + <snippets> + «FOR i : 0 ..< userSnippetsGroups.length» + «userSnippetsGroups.item(i).nodeToString("code")» + «ENDFOR» + «FOR i : 0 ..< utplsqlSnippetsGroups.length» + «utplsqlSnippetsGroups.item(i).nodeToString("code")» + «ENDFOR» + </snippets> + ''' + } else { + // just copy + result = utplsqlSnippets + + } + Files.write(Paths.get(userSnippetsFile.absolutePath), result.bytes) + } + + def getTemplate() { + return utplsqlSnippets + } + + def getFile() { + return userSnippetsFile + } + +} \ No newline at end of file diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend b/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend index 9633fac0..9425bb98 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend +++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend @@ -20,6 +20,7 @@ import java.awt.event.ActionListener import java.util.Map import javax.swing.JButton import javax.swing.JCheckBox +import javax.swing.JOptionPane import javax.swing.JPanel import javax.swing.JSpinner import javax.swing.JTabbedPane @@ -33,6 +34,7 @@ import oracle.ide.panels.TraversalException import oracle.javatools.ui.layout.FieldLayoutBuilder import org.utplsql.sqldev.model.preference.PreferenceModel import org.utplsql.sqldev.resources.UtplsqlResources +import org.utplsql.sqldev.snippet.SnippetMerger import org.utplsql.sqldev.ui.common.DirectoryChooser class PreferencePanel extends DefaultTraversablePanel { @@ -43,6 +45,7 @@ class PreferencePanel extends DefaultTraversablePanel { val JCheckBox clearScreenCheckBox = new JCheckBox val JCheckBox autoExecuteCheckBox = new JCheckBox val JCheckBox checkRunUtplsqlTestCheckBox = new JCheckBox + val JButton importSnippetsButton = new JButton(UtplsqlResources.getString("PREF_IMPORT_SNIPPETS_BUTTON_LABEL")) val JPanel realtimeReporterPanel = new JPanel val SpinnerNumberModel numberOfRunsInHistoryModel = new SpinnerNumberModel(1, 1, 100, 1); val JSpinner numberOfRunsInHistorySpinner = new JSpinner(numberOfRunsInHistoryModel); @@ -101,6 +104,7 @@ class PreferencePanel extends DefaultTraversablePanel { runTab.add( runTab.field.label.withText(UtplsqlResources.getString("PREF_CHECK_RUN_UTPLSQL_TEST_LABEL")).component( checkRunUtplsqlTestCheckBox)) + runTab.addRow(importSnippetsButton) runTab.addVerticalSpring // realtime reporter group @@ -200,6 +204,13 @@ class PreferencePanel extends DefaultTraversablePanel { builder.addVerticalField("", tabbedPane) builder.addVerticalSpring + // register action listener for import snippets button + importSnippetsButton.addActionListener(new ActionListener() { + override actionPerformed(ActionEvent event) { + importSnippets + } + }) + // register action listener for create code template button createCodeTemplatesButton.addActionListener(new ActionListener() { override actionPerformed(ActionEvent event) { @@ -216,6 +227,15 @@ class PreferencePanel extends DefaultTraversablePanel { }) } + private def importSnippets() { + val snippetMerger = new SnippetMerger + snippetMerger.merge + val file = snippetMerger.file.absolutePath + val message = String.format(UtplsqlResources.getString("PREF_CONFIRM_IMPORT_MESSAGE"), file) + JOptionPane.showMessageDialog(null, message, UtplsqlResources.getString("PREF_CONFIRM_IMPORT_TITLE"), + JOptionPane.INFORMATION_MESSAGE); + } + private def loadCodeTemplates() { val Map<String, String> map = CodeTemplateUtil.loadFiles() for (key : map.keySet) { diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties index 2cf4c1f8..8d12bcc5 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -31,6 +31,7 @@ PREF_RESET_PACKAGE_LABEL=Reset package before running utPLSQL? PREF_CLEAR_SCREEN_LABEL=Clear script output panel before running utPLSQL? PREF_AUTO_EXECUTE_LABEL=Execute unit test automatically? PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Check availability of menu option? +PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Import Snippets MENU_REALTIME_REPORTER_LABEL=Realtime Reporter PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Number of runs in history PREF_SHOW_DISABLED_COUNTER_LABEL=Show disabled counter? @@ -56,6 +57,8 @@ PREF_GENERATE_FILES_LABEL=Generate files? PREF_OUTPUT_DIRECTORY_LABEL=Output directory PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Browse PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory? +PREF_CONFIRM_IMPORT_TITLE=Snippets imported +PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect. MENU_RUN_TEST_LABEL=Run utPLSQL test MENU_CODE_COVERAGE_LABEL=Code coverage... MENU_GENERATE_TEST_LABEL=Generate utPLSQL test diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties index d80965a5..eb86a295 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties @@ -8,6 +8,7 @@ PREF_RESET_PACKAGE_LABEL=Package vor der Ausf PREF_CLEAR_SCREEN_LABEL=Skriptausgabe-Fenster vor der Ausf�hrung von utPLSQL leeren? PREF_AUTO_EXECUTE_LABEL=Unit Test automatisch ausf�hren? PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Verf�gbarkeit der Men�option pr�fen? +PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Code-Schnipsel importieren MENU_REALTIME_REPORTER_LABEL=Realtime Reporter PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Anzahl Ausf�hrungen in der Historie PREF_SHOW_DISABLED_COUNTER_LABEL=Deaktiviert-Z�hler anzeigen? @@ -33,6 +34,8 @@ PREF_GENERATE_FILES_LABEL=Dateien generieren? PREF_OUTPUT_DIRECTORY_LABEL=Ausgabeverzeichnis PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Ausw�hlen PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis l�schen? +PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert +PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese �nderung zu aktivieren. MENU_RUN_TEST_LABEL=utPLSQL Test ausf�hren MENU_CODE_COVERAGE_LABEL=Codeabdeckung... MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml new file mode 100644 index 00000000..8915628f --- /dev/null +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml @@ -0,0 +1,262 @@ +<?xml version = '1.0' encoding = 'UTF-8'?> +<snippets> + <group category="utPLSQL Annotations" language="PLSQL"> + <snippet name="suite" description="Package level. Mandatory. Marks package as a test suite. Optional suite description can be provided (see displayname)."> + <code> + <![CDATA[--%suite(<description>)]]> + </code> + </snippet> + <snippet name="suitepath" description="Package level. Similar to java package. The annotation allows logical grouping of suites into hierarchies."> + <code> + <![CDATA[--%suitepath(<path>)]]> + </code> + </snippet> + <snippet name="displayname" description="Package/procedure leve. Human-readable and meaningful description of a context/suite/test. Provides description to a context when used within context. When used with test or suite annotation, overrides the <description> provided with suite/test."> + <code> + <![CDATA[--%displayname(<description>)]]> + </code> + </snippet> + <snippet name="test" description="Procedure level. Denotes that the annotated procedure is a unit test procedure. Optional test description can by provided (see displayname)."> + <code> + <![CDATA[--%test(<description>)]]> + </code> + </snippet> + <snippet name="throws" description="Procedure level. Denotes that the annotated test procedure must throw one of the exceptions provided. Supported forms of exceptions are: numeric literals, numeric contant names, exception constant names, predefined Oracle exception names."> + <code> + <![CDATA[--%throws(<exception>[,...])]]> + </code> + </snippet> + <snippet name="beforeall" description="Procedure level. Denotes that the annotated procedure should be executed once before all elements of the suite."> + <code> + <![CDATA[--%beforeall]]> + </code> + </snippet> + <snippet name="afterall" description="Procedure level. Denotes that the annotated procedure should be executed once after all elements of the suite."> + <code> + <![CDATA[--%afterall]]> + </code> + </snippet> + <snippet name="beforeeach" description="Procedure level. 	Denotes that the annotated procedure should be executed before each %test procedure in the suite."> + <code> + <![CDATA[--%beforeeach]]> + </code> + </snippet> + <snippet name="aftereach" description="	Procedure level. Denotes that the annotated procedure should be executed after each %test procedure in the suite."> + <code> + <![CDATA[--%aftereach]]> + </code> + </snippet> + <snippet name="beforeall package level" description="Package level. Denotes that the mentioned procedure(s) should be executed once before all elements of the suite."> + <code> + <![CDATA[--%beforeall([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="afterall package level" description="Package level. 	Denotes that the mentioned procedure(s) should be executed once after all elements of the suite."> + <code> + <![CDATA[--%afterall([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="beforeeach package level" description="Package level. Denotes that the mentioned procedure(s) should be executed before each %test procedure in the suite."> + <code> + <![CDATA[--%beforeeach([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="aftereach package level" description="Package level. Denotes that the mentioned procedure(s) should be executed after each %test procedure in the suite."> + <code> + <![CDATA[--%aftereach([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="beforetest" description="Procedure level. Denotes that mentioned procedure(s) should be executed before the annotated %test procedure."> + <code> + <![CDATA[--%beforetest([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="aftertest" description="Procedure level. Denotes that mentioned procedure(s) should be executed after the annotated %test procedure"> + <code> + <![CDATA[--%aftertest([[<owner>.]<package>.]<procedure>[,...])]]> + </code> + </snippet> + <snippet name="rollback" description="Package/procedure level. Defines transaction control. Supported values: auto(default) - a savepoint is created before invocation of each “before block” is and a rollback to specific savepoint is issued after each “after” block; manual - rollback is never issued automatically"> + <code> + <![CDATA[--%rollback(<type>)]]> + </code> + </snippet> + <snippet name="disabled" description="Package/procedure level. Used to disable a suite or a test. Disabled suites/tests do not get executed, they are however marked and reported as disabled in a test run."> + <code> + <![CDATA[--%disabled]]> + </code> + </snippet> + <snippet name="context" description="Package level. Denotes start of a named context (sub-suite) in a suite package"> + <code> + <![CDATA[--%context(<name>)]]> + </code> + </snippet> + <snippet name="endcontext" description="Package level. Denotes end of a nested context (sub-suite) in a suite package"> + <code> + <![CDATA[--%endcontext]]> + </code> + </snippet> + <snippet name="tags" description="Package/procedure level. Used to label a test or a suite for purpose of identification"> + <code> + <![CDATA[--%tags]]> + </code> + </snippet> + </group> + <group category="utPLSQL Expectations" language="PLSQL"> + <snippet name="be_between" description="Validates that the actual value is between the lower and upper bound."> + <code> + <![CDATA[ut.expect(n1).to_be_between(n2);]]> + </code> + </snippet> + <snippet name="be_empty" description="Unary matcher that validates if the provided dataset is empty"> + <code> + <![CDATA[ut.expect(n).to_be_empty();]]> + </code> + </snippet> + <snippet name="be_false" description="Unary matcher that validates if the provided value is false."> + <code> + <![CDATA[ut.expect(n).to_be_false();]]> + </code> + </snippet> + <snippet name="be_greater_or_equal" description="Checks if the actual value is greater or equal than the expected."> + <code> + <![CDATA[ut.expect(n1).to_be_greater_or_equal(n2);]]> + </code> + </snippet> + <snippet name="be_greater_than" description="Checks if the actual value is greater than the expected."> + <code> + <![CDATA[ut.expect(n1).to_be_greater_than(n2);]]> + </code> + </snippet> + <snippet name="be_less_or_equal" description="Checks if the actual value is less or equal than the expected."> + <code> + <![CDATA[ut.expect(n1).to_be_less_or_equal(n2);]]> + </code> + </snippet> + <snippet name="be_less_than" description="Checks if the actual value is less than the expected."> + <code> + <![CDATA[ut.expect(n1).to_be_less_than(n2);]]> + </code> + </snippet> + <snippet name="be_like" description="Validates that the actual value is like the expected expression."> + <code> + <![CDATA[ut.expect(n1).to_be_like(n2);]]> + </code> + </snippet> + <snippet name="be_not_null" description="Unary matcher that validates if the actual value is not null."> + <code> + <![CDATA[ut.expect(n).to_be_not_null();]]> + </code> + </snippet> + <snippet name="be_null" description="Unary matcher that validates if the actual value is null."> + <code> + <![CDATA[ut.expect(n).to_be_null();]]> + </code> + </snippet> + <snippet name="be_true" description="Unary matcher that validates if the provided value is true."> + <code> + <![CDATA[ut.expect(n).to_be_true();]]> + </code> + </snippet> + <snippet name="have_count" description="Unary matcher that validates if the provided dataset count is equal to expected value."> + <code> + <![CDATA[ut.expect(n1).to_have_count(n2);]]> + </code> + </snippet> + <snippet name="match" description="Validates that the actual value is matching the expected regular expression."> + <code> + <![CDATA[ut.expect(n1).to_match(n2);]]> + </code> + </snippet> + <snippet name="equal" description="Validate that actual value is equal to expected"> + <code> + <![CDATA[ut.expect(n1).to_equal(n2);]]> + </code> + </snippet> + <snippet name="contain" description="This matcher supports only compound data comparison. It check if the give set contain all values from given subset."> + <code> + <![CDATA[ut.expect(n1).to_contain(n2);]]> + </code> + </snippet> + <snippet name="not_to_be_empty" description="Unary matcher that validates if the provided dataset is not empty"> + <code> + <![CDATA[ut.expect(n).not_to_be_empty();]]> + </code> + </snippet> + <snippet name="not_to_be_false" description="Unary matcher that validates if the provided value is not false."> + <code> + <![CDATA[ut.expect(n).not_to_be_false();]]> + </code> + </snippet> + <snippet name="not_to_be_greater_or_equal" description="Checks if the actual value is not greater or equal than the expected."> + <code> + <![CDATA[ut.expect(n1).not_to_be_greater_or_equal(n2);]]> + </code> + </snippet> + <snippet name="not_to_be_greater_than" description="Checks if the actual value is not greater than the expected."> + <code> + <![CDATA[ut.expect(n1).not_to_be_greater_than(n2);]]> + </code> + </snippet> + <snippet name="not_to_be_less_or_equal" description="Checks if the actual value is not less or equal than the expected."> + <code> + <![CDATA[ut.expect(n1).not_to_be_less_or_equal(n2);]]> + </code> + </snippet> + <snippet name="not_to_be_less_than" description="Checks if the actual value is not less than the expected."> + <code> + <![CDATA[ut.expect(n1).not_to_be_less_than(n2);]]> + </code> + </snippet> + <snippet name="not_to_be_like" description="Validates that the actual value is not like the expected expression."> + <code> + <![CDATA[ut.expect(n1).not_to_be_like(n2);]]> + </code> + </snippet> + <snippet name="not_to_have_count" description="Unary matcher that validates if the provided dataset count is not equal to expected value."> + <code> + <![CDATA[ut.expect(n1).not_to_have_count(n2);]]> + </code> + </snippet> + <snippet name="not_to_match" description="Validates that the actual value is not matching the expected regular expression."> + <code> + <![CDATA[ut.expect(n1).not_to_match(n2);]]> + </code> + </snippet> + <snippet name="not_to_equal" description="Validate that actual value is not equal to expected"> + <code> + <![CDATA[ut.expect(n1).not_to_equal(n2);]]> + </code> + </snippet> + <snippet name="not_to_contain" description="This matcher supports only compound data comparison. It check if the give set not contain all values from given subset."> + <code> + <![CDATA[ut.expect(n1).not_to_contain(n2);]]> + </code> + </snippet> + <snippet name=".include" description="Valid only for compound data types. Item, comma separated list of items or table of items to include"> + <code> + <![CDATA[.include(n)]]> + </code> + </snippet> + <snippet name=".exclude" description="Valid only for compound data types. Item, comma separated list of items or table of items to exclude"> + <code> + <![CDATA[.exclude(n)]]> + </code> + </snippet> + <snippet name=".unordered" description="Valid only for compound data types.ignore order of data sets when comparing data. Default when comparing data-sets with to_contain"> + <code> + <![CDATA[.unordered]]> + </code> + </snippet> + <snippet name=".join_by" description="Valid only for compound data types. Item, comma separated list of items or table of items to join by two cursors"> + <code> + <![CDATA[.join_by(n)]]> + </code> + </snippet> + <snippet name=".unordered_columns" description="Valid only for compound data types. Ignore the ordering of columns / attributes in compared data-sets. Column/attribute names will be used to identify data to be compared and the position will be ignored."> + <code> + <![CDATA[.unordered_columns]]> + </code> + </snippet> + </group> +</snippets> diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend new file mode 100644 index 00000000..1a7e2387 --- /dev/null +++ b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend @@ -0,0 +1,89 @@ +/* + * Copyright 2019 Philipp Salvisberg <philipp.salvisberg@trivadis.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.utplsql.sqldev.test + +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths +import org.junit.Assert +import org.junit.Test +import org.utplsql.sqldev.snippet.SnippetMerger + +class SnippetTest { + + @Test + def void mergeAsCopy() { + val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml") + file.delete + val merger = new SnippetMerger(file) + merger.merge + Assert.assertTrue(file.exists) + val userSnippetsXml = new String(Files.readAllBytes(Paths.get(file.absolutePath))) + Assert.assertEquals(merger.template, userSnippetsXml ) + } + + @Test + def void mergeKeepExisting() { + val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml") + file.delete + val userSnippetsXml = ''' + <?xml version = '1.0' encoding = 'UTF-8'?> + <snippets> + <group category="utPLSQL" language="PLSQL"> + <snippet name="test s" description="test s"> + <code> + <![CDATA[bla bla bla]]> + </code> + </snippet> + </group> + </snippets> + '''.toString + Files.write(Paths.get(file.absolutePath), userSnippetsXml.bytes) + val merger = new SnippetMerger(file) + merger.merge + Assert.assertTrue(file.exists) + val userSnippetsXml2 = new String(Files.readAllBytes(Paths.get(file.absolutePath))) + Assert.assertTrue(userSnippetsXml2.length > userSnippetsXml.length) + Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL" language="PLSQL">''')) + Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="PLSQL">''')) + Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="PLSQL">''')) + } + + @Test + def void mergeRemoveExisting() { + val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml") + file.delete + val userSnippetsXml = ''' + <?xml version = '1.0' encoding = 'UTF-8'?> + <snippets> + <group category="utPLSQL Annotations" language="XYZ"/> + <group category="utPLSQL Expectations" language="XYZ"/> + </snippets> + '''.toString + Files.write(Paths.get(file.absolutePath), userSnippetsXml.bytes) + val merger = new SnippetMerger(file) + merger.merge + Assert.assertTrue(file.exists) + val userSnippetsXml2 = new String(Files.readAllBytes(Paths.get(file.absolutePath))) + Assert.assertTrue(userSnippetsXml2.length > userSnippetsXml.length) + Assert.assertFalse(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="XYZ">''')) + Assert.assertFalse(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="XYZ">''')) + Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="PLSQL">''')) + Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="PLSQL">''')) + } + + +}