This is an automated email from the ASF dual-hosted git repository.

rthomas320 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git


The following commit(s) were added to refs/heads/main by this push:
     new 418c91f  Fix broken TDML append, copy and execute functionality
418c91f is described below

commit 418c91f3d7b6b249ca5ad6ddf9d94a54c5a6dd5e
Author: Hitesh Dalsania <[email protected]>
AuthorDate: Thu May 2 19:27:08 2024 -0400

    Fix broken TDML append, copy and execute functionality
    
    Fixed review comments
    
    format check
    
    Fixed test
    
    lint updates
---
 .../main/scala/org.apache.daffodil.tdml/TDML.scala |  10 +-
 .../scala/org.apache.daffodil.tdml/TDMLSuite.scala |  12 +-
 package.json                                       |   7 +-
 src/adapter/activateDaffodilDebug.ts               | 175 +++++++++++++++++---
 src/daffodilDebugger/debugger.ts                   |  41 +++--
 src/tdmlEditor/utilities/tdmlXmlUtils.ts           | 181 +++++++++++++++++----
 src/tests/suite/tdmlXmlUtils.test.ts               |  29 ++--
 7 files changed, 377 insertions(+), 78 deletions(-)

diff --git a/debugger/src/main/scala/org.apache.daffodil.tdml/TDML.scala 
b/debugger/src/main/scala/org.apache.daffodil.tdml/TDML.scala
index f28cacd..3fa6f40 100644
--- a/debugger/src/main/scala/org.apache.daffodil.tdml/TDML.scala
+++ b/debugger/src/main/scala/org.apache.daffodil.tdml/TDML.scala
@@ -123,6 +123,7 @@ object TDML {
       .relativize(new File(path.toString()).toURI())
       .getPath()
       .toString()
+      .trim()
   }
 
   // Generate a new TDML file.
@@ -253,7 +254,13 @@ object TDML {
   // Returns a tuple containing the following (Path to DFDL Schema, Path to 
Data File)
   // All paths returned could be either relative or absolute - it depends on 
what exists in the TDML file
   def execute(tdmlName: String, tdmlDescription: String, tdmlPath: String): 
Option[(Path, Path)] = {
-    val basePath = Paths.get(tdmlPath).toAbsolutePath().getParent()
+
+    // Correct basepath for Windows OS
+    var basePath = ""
+    if (System.getProperty("os.name").toLowerCase.startsWith("win") == true)
+      (
+        basePath = Paths.get(tdmlPath).toAbsolutePath().getParent().toString()
+      )
 
     val testCaseList = JAXBContext
       .newInstance(classOf[TestSuite])
@@ -278,6 +285,7 @@ object TDML {
                 .asInstanceOf[JAXBElement[DocumentPartType]]
                 .getValue()
                 .getValue()
+                .trim()
             )
             .normalize()
           (schemaPath, dataPath)
diff --git a/debugger/src/test/scala/org.apache.daffodil.tdml/TDMLSuite.scala 
b/debugger/src/test/scala/org.apache.daffodil.tdml/TDMLSuite.scala
index ebc8a3f..d0b8b52 100644
--- a/debugger/src/test/scala/org.apache.daffodil.tdml/TDMLSuite.scala
+++ b/debugger/src/test/scala/org.apache.daffodil.tdml/TDMLSuite.scala
@@ -126,10 +126,18 @@ class TDMLSuite extends munit.FunSuite {
   }
 
   test("Test Execute") {
+
+    var schemaPathExecute = 
Paths.get("/debugger/src/test/data/emptySchema.xml")
+    var dataPathExecute = Paths.get("/debugger/src/test/data/emptyData.xml")
+
+    if (System.getProperty("os.name").toLowerCase.startsWith("win") == true) {
+      schemaPathExecute = schemaPath
+      dataPathExecute = dataPath
+    }
     TDML.generate(infosetPath, schemaPath, dataPath, tdmlName, 
tdmlDescription, tdmlPath.toString())
-    val executePaths = TDML.execute(tdmlName, tdmlDescription, 
tdmlPath.toString())
+    val executePaths = TDML.execute(tdmlName, tdmlDescription, 
tdmlPath.toAbsolutePath().toString())
 
-    assertEquals(executePaths, Option[(Path, Path)]((schemaPath.normalize(), 
dataPath.normalize())))
+    assertEquals(executePaths, Option[(Path, 
Path)]((schemaPathExecute.normalize(), dataPathExecute.normalize())))
   }
 
   test("Test convertToRelativePath") {
diff --git a/package.json b/package.json
index 6e68cde..6b13fd2 100644
--- a/package.json
+++ b/package.json
@@ -118,6 +118,7 @@
     "onCommand:extension.dfdl-debug.getTDMLDescription",
     "onCommand:extension.dfdl-debug.getTDMLPath",
     "onCommand:extension.dfdl-debug.getValidatedTDMLPath",
+    "onCommand:extension.dfdl-debug.getValidatedTDMLCopyPath",
     "onCommand:launch.config",
     "onCommand:extension.data.edit",
     "onCommand:extension.dfdl-debug.debugLastEditorContents"
@@ -749,7 +750,11 @@
         "variables": {
           "AskForSchemaName": "extension.dfdl-debug.getSchemaName",
           "AskForDataName": "extension.dfdl-debug.getDataName",
-          "AskForValidatedTDMLPath": 
"extension.dfdl-debug.getValidatedTDMLPath"
+          "AskForTDMLName": "extension.dfdl-debug.getTDMLName",
+          "AskForTDMLDescription": "extension.dfdl-debug.getTDMLDescription",
+          "AskForTDMLPath": "extension.dfdl-debug.getTDMLPath",
+          "AskForValidatedTDMLPath": 
"extension.dfdl-debug.getValidatedTDMLPath",
+          "AskForValidatedTDMLCopyPath": 
"extension.dfdl-debug.getValidatedTDMLCopyPath"
         }
       }
     ],
diff --git a/src/adapter/activateDaffodilDebug.ts 
b/src/adapter/activateDaffodilDebug.ts
index c205e90..0c9ac96 100644
--- a/src/adapter/activateDaffodilDebug.ts
+++ b/src/adapter/activateDaffodilDebug.ts
@@ -29,7 +29,7 @@ import * as dfdlExt from '../language/semantics/dfdlExt'
 import {
   appendTestCase,
   getTmpTDMLFilePath,
-  readTDMLFileContents,
+  copyTestCase,
 } from '../tdmlEditor/utilities/tdmlXmlUtils'
 import xmlFormat from 'xml-formatter'
 
@@ -85,6 +85,46 @@ async function getFile(fileRequested, label, title) {
   return file
 }
 
+/** Method to show dialog to save TDML file
+ * Details:
+ *   Required so that the vscode api commands:
+ *     - extension.dfdl-debug.getValidatedTDMLCopyPath
+ *   can be sent a file instead of always opening up a prompt.
+ */
+async function showTDMLSaveDialog(fileRequested, label, title) {
+  let file = ''
+
+  file = await vscode.window
+    .showSaveDialog({
+      saveLabel: label,
+      title: title,
+      filters: {
+        TDML: ['tdml'],
+      },
+    })
+    .then((fileUri) => {
+      if (fileUri) {
+        let path = fileUri.fsPath
+
+        if (
+          process.platform === 'win32' &&
+          path.length > 2 &&
+          path.charCodeAt(0) > 97 &&
+          path.charCodeAt(0) <= 122 &&
+          path.charAt(1) === ':'
+        ) {
+          path = path.charAt(0).toUpperCase() + path.slice(1)
+        }
+
+        return path
+      }
+
+      return ''
+    })
+
+  return file
+}
+
 // Function for setting up the commands for Run and Debug file
 function createDebugRunFileConfigs(
   resource: vscode.Uri,
@@ -115,6 +155,12 @@ function createDebugRunFileConfigs(
 
       if (tdmlAction) {
         tdmlConfig.action = tdmlAction
+
+        if (tdmlAction === 'execute') {
+          tdmlConfig.name = '${command:AskForTDMLName}'
+          tdmlConfig.description = '${command:AskForTDMLDescription}'
+          tdmlConfig.path = targetResource.fsPath
+        }
       }
 
       vscode.debug.startDebugging(
@@ -124,11 +170,12 @@ function createDebugRunFileConfigs(
           request: 'launch',
           type: 'dfdl',
           schema: {
-            path: targetResource.fsPath,
+            path: tdmlConfig.action === 'execute' ? '' : targetResource.fsPath,
             rootName: null,
             rootNamespace: null,
           },
-          data: '${command:AskForDataName}',
+          data:
+            tdmlConfig.action === 'execute' ? '' : '${command:AskForDataName}',
           debugServer: false,
           infosetFormat: 'xml',
           infosetOutput: {
@@ -189,10 +236,7 @@ export function activateDaffodilDebug(
           targetResource = vscode.window.activeTextEditor.document.uri
         }
         if (targetResource) {
-          appendTestCase(
-            await readTDMLFileContents(getTmpTDMLFilePath()),
-            await readTDMLFileContents(targetResource.fsPath)
-          )
+          appendTestCase(getTmpTDMLFilePath(), targetResource.fsPath)
             .then((appendedBuffer) => {
               fs.writeFileSync(targetResource.fsPath, 
xmlFormat(appendedBuffer))
             })
@@ -209,19 +253,43 @@ export function activateDaffodilDebug(
         createDebugRunFileConfigs(resource, 'run', 'execute')
       }
     ),
-    vscode.commands.registerCommand('extension.dfdl-debug.copyTDML', (_) => {
-      // Ask for destination path
-      // Copy file in /tmp to destination path
-      // TDMLConfig.path should not be used here because that only matters 
when sending to the server
-      // We could make it so that if someone wants to specify the path and set 
the action to 'copy', but
-      //   that doesn't make a whole lot of sense.
-      let targetResource = vscode.commands.executeCommand(
-        'extension.dfdl-debug.getTDMLPath'
-      )
+    vscode.commands.registerCommand(
+      'extension.dfdl-debug.copyTDML',
+      async (_) => {
+        // Ask for destination path
+        // Copy file in /tmp to destination path
+        // TDMLConfig.path should not be used here because that only matters 
when sending to the server
+        // We could make it so that if someone wants to specify the path and 
set the action to 'copy', but
+        //   that doesn't make a whole lot of sense.
+        let targetResource = await vscode.commands.executeCommand(
+          'extension.dfdl-debug.getValidatedTDMLCopyPath'
+        )
 
-      // Is there a better way of error checking this?
-      fs.copyFileSync(getTmpTDMLFilePath(), targetResource as unknown as 
string)
-    }),
+        // Is there a better way of error checking this?
+        if (targetResource) {
+          copyTestCase(
+            getTmpTDMLFilePath(),
+            targetResource as unknown as string
+          )
+            .then((copiedBuffer) => {
+              fs.writeFileSync(
+                targetResource as unknown as string,
+                xmlFormat(copiedBuffer)
+              )
+            })
+            .catch((reason) => {
+              // Not sure if we need to do something different/more here
+              console.log(reason)
+            })
+        }
+
+        // fs.copyFile(
+        //   getTmpTDMLFilePath(),
+        //   targetResource as unknown as string,
+        //   (_) => {}
+        // )
+      }
+    ),
     vscode.commands.registerCommand(
       'extension.dfdl-debug.toggleFormatting',
       (_) => {
@@ -272,6 +340,74 @@ export function activateDaffodilDebug(
     )
   )
 
+  context.subscriptions.push(
+    vscode.commands.registerCommand(
+      'extension.dfdl-debug.getValidatedTDMLCopyPath',
+      async (fileRequested = null) => {
+        // Open native file explorer to allow user to select data file from 
anywhere on their machine
+        if (fileRequested && fs.existsSync(fileRequested)) {
+          return fileRequested
+        } else if (fileRequested && !fs.existsSync(fileRequested)) {
+          return ''
+        } else {
+          return await showTDMLSaveDialog(
+            fileRequested,
+            'Save TDML File',
+            'Save TDML File'
+          )
+        }
+      }
+    )
+  )
+
+  context.subscriptions.push(
+    vscode.commands.registerCommand(
+      'extension.dfdl-debug.getTDMLName',
+      async (_) => {
+        return await vscode.window
+          .showInputBox({
+            prompt: 'Test Case Name: ',
+            value: 'Default Test Case',
+          })
+          .then((value) => {
+            return value
+          })
+      }
+    )
+  )
+
+  context.subscriptions.push(
+    vscode.commands.registerCommand(
+      'extension.dfdl-debug.getTDMLDescription',
+      async (_) => {
+        return await vscode.window
+          .showInputBox({
+            prompt: 'Test Case Description: ',
+            value: 'Generated by DFDL VSCode Extension',
+          })
+          .then((value) => {
+            return value
+          })
+      }
+    )
+  )
+
+  context.subscriptions.push(
+    vscode.commands.registerCommand(
+      'extension.dfdl-debug.getTDMLPath',
+      async (_) => {
+        return await vscode.window
+          .showInputBox({
+            prompt: 'TDML File: ',
+            value: '${workspaceFolder}/infoset.tdml',
+          })
+          .then((value) => {
+            return value
+          })
+      }
+    )
+  )
+
   // register a configuration provider for 'dfdl' debug type
   const provider = new DaffodilConfigurationProvider(context)
   context.subscriptions.push(
@@ -462,6 +598,7 @@ class DaffodilConfigurationProvider
       !dataFolder.includes('${command:AskForSchemaName}') &&
       !dataFolder.includes('${command:AskForDataName}') &&
       !dataFolder.includes('${workspaceFolder}') &&
+      config.tdmlConfig.action !== 'execute' &&
       vscode.workspace.workspaceFolders &&
       dataFolder !== vscode.workspace.workspaceFolders[0].uri.fsPath &&
       dataFolder.split('.').length === 1 &&
diff --git a/src/daffodilDebugger/debugger.ts b/src/daffodilDebugger/debugger.ts
index 5bdd736..11df384 100644
--- a/src/daffodilDebugger/debugger.ts
+++ b/src/daffodilDebugger/debugger.ts
@@ -23,6 +23,7 @@ import { runDebugger, stopDebugger, stopDebugging } from 
'./utils'
 import {
   getDefaultTDMLTestCaseDescription,
   getDefaultTDMLTestCaseName,
+  getTmpTDMLFilePath,
 } from '../tdmlEditor/utilities/tdmlXmlUtils'
 
 // Function to get data file given a folder
@@ -57,22 +58,42 @@ async function getTDMLConfig(
     // Might need to add `schema` here if we move the `Execute TDML` command
     //   away from the detected dfdl language in VSCode.
     config.data = ''
+    config.schema.path = ''
 
     if (config?.tdmlConfig?.path === undefined)
       config.tdmlConfig.path = await vscode.commands.executeCommand(
         'extension.dfdl-debug.getValidatedTDMLPath'
       )
-  }
 
-  if (
-    config?.tdmlConfig?.action === 'generate' ||
-    config?.tdmlConfig?.action === 'execute'
-  ) {
     if (config?.tdmlConfig?.name === undefined)
-      config.tdmlConfig.name = getDefaultTDMLTestCaseName()
+      config.tdmlConfig.name = await vscode.commands.executeCommand(
+        'extension.dfdl-debug.getTDMLName'
+      )
 
     if (config?.tdmlConfig?.description === undefined)
+      config.tdmlConfig.description = await vscode.commands.executeCommand(
+        'extension.dfdl-debug.getTDMLDescription'
+      )
+  }
+
+  if (config?.tdmlConfig?.action === 'generate') {
+    if (
+      config?.tdmlConfig?.name === undefined ||
+      config?.tdmlConfig?.name === 'undefined'
+    )
+      config.tdmlConfig.name = getDefaultTDMLTestCaseName()
+
+    if (
+      config?.tdmlConfig?.description === undefined ||
+      config?.tdmlConfig?.description === 'undefined'
+    )
       config.tdmlConfig.description = getDefaultTDMLTestCaseDescription()
+
+    if (
+      config?.tdmlConfig?.path === undefined ||
+      config?.tdmlConfig?.path === 'undefined'
+    )
+      config.tdmlConfig.path = getTmpTDMLFilePath()
   }
 
   if (config?.tdmlConfig?.action !== 'execute' && config.data === '') {
@@ -133,6 +154,10 @@ export async function getDebugger(
   if (vscode.workspace.workspaceFolders !== undefined) {
     await stopDebugger()
 
+    if (!(await getTDMLConfig(config))) {
+      return await stopDebugging().then((_) => undefined)
+    }
+
     // Get schema file before debugger starts to avoid timeout
     if (config.schema.path.includes('${command:AskForSchemaName}')) {
       config.schema.path = await vscode.commands.executeCommand(
@@ -147,10 +172,6 @@ export async function getDebugger(
       )
     }
 
-    if (!(await getTDMLConfig(config))) {
-      return await stopDebugging().then((_) => undefined)
-    }
-
     let workspaceFolder = vscode.workspace.workspaceFolders[0].uri.fsPath
 
     // Get daffodilDebugger class paths to be added to the debugger
diff --git a/src/tdmlEditor/utilities/tdmlXmlUtils.ts 
b/src/tdmlEditor/utilities/tdmlXmlUtils.ts
index 427c778..84ecb1a 100644
--- a/src/tdmlEditor/utilities/tdmlXmlUtils.ts
+++ b/src/tdmlEditor/utilities/tdmlXmlUtils.ts
@@ -17,7 +17,7 @@
 
 import { readFileSync, writeFileSync } from 'fs'
 import os from 'os'
-import { join } from 'path'
+import { join, resolve, sep, relative, dirname } from 'path'
 import { Element, ElementCompact, js2xml, xml2js } from 'xml-js'
 
 /*
@@ -240,9 +240,9 @@ export async function getTestCaseDisplayData(
 /*
  * Append the test case in one XML file into another file's test suite
  *
- * xmlBuffer: String containing the XML file contents of a TDML file with
+ * xmlFilePath: String containing the XML file path of a TDML file with
  *   exactly one test case
- * destinationBuffer: String containing XML file contents. The test case in
+ * destinationFilePath: String containing XML file path. The test case in
  *   xmlBuffer will be added to this buffer's test suite.
  * Returns string containing modified XML
  *
@@ -252,9 +252,36 @@ export async function getTestCaseDisplayData(
  * See the 'Invalid Append TDML - duplicate' and 'Append TDML Test Case' tests 
for examples
  */
 export async function appendTestCase(
-  xmlBuffer: string,
-  destinationBuffer: string
+  xmlFilePath: string,
+  destinationFilePath: string
+) {
+  return copyTestCase(xmlFilePath, destinationFilePath, true)
+}
+
+/*
+ * Copy and optionally append test case in one XML file into another file's 
test suite
+ *
+ * xmlFilePath: String containing the XML file path of a TDML file with
+ *   exactly one test case
+ * destinationFilePath: String containing XML file path. The test case in
+ *   xmlBuffer will be added to this buffer's test suite.
+ * append: boolean variable to enable append functionality. By default it is 
false
+ *
+ * Returns string containing modified XML
+ *
+ * Throws when an error is found. To catch errors, call with something similar 
to:
+ *   appendTestCase(buf, destBuf).then((result) => 
writeResult()).catch((reason) => console.log(reason))
+ * Then is only called on success and catch is only called on failure (when we 
throw)
+ * See the 'Invalid Append TDML - duplicate' and 'Append TDML Test Case' tests 
for examples
+ */
+export async function copyTestCase(
+  xmlFilePath: string,
+  destinationFilePath: string,
+  append = false
 ) {
+  var xmlBuffer = await readTDMLFileContents(xmlFilePath)
+  var destinationBuffer = await readTDMLFileContents(destinationFilePath)
+
   var xmlObj: Element | ElementCompact = xml2js(xmlBuffer)
   var destinationObj: Element | ElementCompact = xml2js(destinationBuffer)
 
@@ -282,35 +309,133 @@ export async function appendTestCase(
     throw `More than one test case found in source XML buffer`
   }
 
-  const destinationTestSuite = (destinationObj as Element).elements?.filter(
-    (node) => node.name?.endsWith(testSuiteElement)
+  const rootNode = (xmlObj as Element).elements?.filter((node) =>
+    node.name?.endsWith(testSuiteElement)
   )
 
-  if (destinationTestSuite === undefined) {
-    throw `No test suites found in destination XML buffer`
+  if (
+    sourceTestCase[0].attributes !== undefined &&
+    sourceTestCase[0].attributes[testCaseModelAttribute] !== undefined &&
+    rootNode !== undefined
+  ) {
+    // Each TDML file contains at least one test case
+    const testCases = rootNode[0].elements?.filter((node) =>
+      node.name?.endsWith(testCaseElement)
+    )
+
+    sourceTestCase[0].attributes[testCaseModelAttribute] = relative(
+      destinationFilePath,
+      sourceTestCase[0].attributes[testCaseModelAttribute].toString()
+    )
+
+    // Each test case may contain any number of documents
+    testCases?.forEach((testCaseNode) => {
+      testCaseNode.elements
+        ?.filter((childNode) => childNode.name?.endsWith(documentElement))
+        .forEach((documentNode) =>
+          documentNode.elements
+            ?.filter((childNode) =>
+              childNode.name?.endsWith(documentPartElement)
+            )
+            .forEach((documentPartNode) => {
+              if (
+                documentPartNode.elements !== undefined &&
+                documentPartNode.elements[0].text !== undefined
+              )
+                documentPartNode.elements[0].text = relative(
+                  destinationFilePath,
+                  documentPartNode.elements[0].text.toString()
+                )
+            })
+        )
+    })
+
+    // Each test case may contain any number of infoset
+    testCases?.forEach((testCaseNode) => {
+      testCaseNode.elements
+        ?.filter((childNode) => childNode.name?.endsWith(infosetElement))
+        .forEach((infosetNode) =>
+          infosetNode.elements
+            ?.filter((childNode) =>
+              childNode.name?.endsWith(dfdlInfosetElement)
+            )
+            .forEach((dfdlInfosetNode) => {
+              if (
+                dfdlInfosetNode.elements !== undefined &&
+                dfdlInfosetNode.elements[0].text !== undefined
+              )
+                dfdlInfosetNode.elements[0].text = relative(
+                  destinationFilePath,
+                  dfdlInfosetNode.elements[0].text.toString()
+                )
+            })
+        )
+    })
   }
 
-  if (destinationTestSuite.length !== 1) {
-    throw `More than one test suite found in destination XML buffer`
-  }
+  if (append) {
+    const destinationTestSuite = (destinationObj as Element).elements?.filter(
+      (node) => node.name?.endsWith(testSuiteElement)
+    )
 
-  const destinationTestCases = destinationTestSuite[0].elements?.filter(
-    (childNode) => childNode.name?.endsWith(testCaseElement)
-  )
-  destinationTestCases?.forEach((testCase) => {
-    // Check to see if we are trying to append a duplicate
-    // Per the TDML spec, a duplicate is a name-only check
-    if (
-      testCase.attributes !== undefined &&
-      sourceTestCase[0].attributes !== undefined &&
-      testCase.attributes[testCaseNameAttribute] ===
-        sourceTestCase[0].attributes[testCaseNameAttribute]
-    ) {
-      throw `Duplicate Test Case Name Found`
+    if (destinationTestSuite === undefined) {
+      throw `No test suites found in destination XML buffer`
     }
-  })
 
-  destinationTestSuite[0].elements?.push(sourceTestCase[0])
+    if (destinationTestSuite.length !== 1) {
+      throw `More than one test suite found in destination XML buffer`
+    }
+
+    const destinationTestCases = destinationTestSuite[0].elements?.filter(
+      (childNode) => childNode.name?.endsWith(testCaseElement)
+    )
+    destinationTestCases?.forEach((testCase) => {
+      // Check to see if we are trying to append a duplicate
+      // Per the TDML spec, a duplicate is a name-only check
+      if (
+        testCase.attributes !== undefined &&
+        sourceTestCase[0].attributes !== undefined &&
+        testCase.attributes[testCaseNameAttribute] ===
+          sourceTestCase[0].attributes[testCaseNameAttribute]
+      ) {
+        throw `Duplicate Test Case Name Found`
+      }
+    })
+    destinationTestSuite[0].elements?.push(sourceTestCase[0])
+
+    return js2xml(destinationObj)
+  } else {
+    return js2xml(xmlObj)
+  }
+}
+
+// Convert an absolute path into a path relative to the current working 
directory
+//
+// path: Absolute path to convert into a relative path
+// tdmlPath: Absolute path to the TDML file to make
+//
+// Returns the relative path. Note that this path is given as a string.
+//THIS FUNCTION CURRENTLY NOT USED BECAUSE PATHS COULD NOT BE PROPERLY 
NORMALIZED FROM CALLING FUNCTON
+
+export async function convertToRelativePath(
+  path: string,
+  tdmlPath: string
+): Promise<string> {
+  // Get the absolute path of the workspace directory
+  // The path is the path to a file. To get the proper relative path, we need
+  //   to start at the parent of the file.
+  var workingDir = dirname(resolve(tdmlPath))
+  var prefix = ''
+
+  // This is used to back up the path tree in order to find the first common 
ancestor of both paths
+  // If a user wants to use a file not in or under the current working 
directory, this will be required to
+  //   produce the expected output.
+  // A possible use case of this is where a user has a data folder and a 
schema folder that are siblings.
+  while (!path.startsWith(workingDir) && dirname(workingDir) != null) {
+    workingDir = dirname(workingDir)
+    // Need to add the dots to represent that we've gone back a step up the 
path
+    prefix += '..' + sep
+  }
 
-  return js2xml(destinationObj)
+  return prefix + relative(workingDir, path)
 }
diff --git a/src/tests/suite/tdmlXmlUtils.test.ts 
b/src/tests/suite/tdmlXmlUtils.test.ts
index a69de85..612240b 100644
--- a/src/tests/suite/tdmlXmlUtils.test.ts
+++ b/src/tests/suite/tdmlXmlUtils.test.ts
@@ -152,15 +152,11 @@ suite('TDML Utils Test Suite', () => {
   })
 
   test('Append TDML Test Case', async () => {
-    var xmlBuffer = await readTDMLFileContents(
-      join(data_directory, 'test-second.tdml')
-    )
-    var destinationBuffer = await readTDMLFileContents(
+    var appendedBuffer = await appendTestCase(
+      join(data_directory, 'test-second.tdml'),
       join(data_directory, 'test.tdml')
     )
 
-    var appendedBuffer = await appendTestCase(xmlBuffer, destinationBuffer)
-
     return readTDMLFileContents(join(data_directory, 'test-appended.tdml'))
       .then((buf) => {
         strictEqual(xmlFormat(appendedBuffer), buf)
@@ -171,17 +167,16 @@ suite('TDML Utils Test Suite', () => {
   })
 
   test('Invalid Append TDML - duplicate', async () => {
-    return readTDMLFileContents(join(data_directory, 'test.tdml')).then(
-      (buf) => {
-        return appendTestCase(buf, buf)
-          .then((_) => {
-            // This is not checked because we threw
-          })
-          .catch((reason) => {
-            // This is checked because we threw
-            strictEqual(reason, 'Duplicate Test Case Name Found')
-          })
-      }
+    return appendTestCase(
+      join(data_directory, 'test.tdml'),
+      join(data_directory, 'test.tdml')
     )
+      .then((_) => {
+        // This is not checked because we threw
+      })
+      .catch((reason) => {
+        // This is checked because we threw
+        strictEqual(reason, 'Duplicate Test Case Name Found')
+      })
   })
 })

Reply via email to