From 1aa632d442b805ef762c36f1c14caf1624a4f4c0 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Fri, 13 Dec 2024 10:03:19 +0100 Subject: [PATCH 01/19] Fixed wrong Test Results message log. --- src/testPane.ts | 7 ++++++- src/utilities.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/testPane.ts b/src/testPane.ts index 2a4a0ae9..c1267a96 100644 --- a/src/testPane.ts +++ b/src/testPane.ts @@ -40,6 +40,7 @@ import { import { addLaunchConfiguration, + cleanTestResultsPaneMessage, forceLowerCaseDriveLetter, loadLaunchFile, openFileWithLineSelected, @@ -850,7 +851,11 @@ export async function runNode( const status = executionResult.status; // We show stdout from execution in the "Test Results" pane - run.appendOutput(executionResult.details.stdOut); + // We need to clean the string first because the logs in the Test Results pane are handled differently + let cleanedOutput = cleanTestResultsPaneMessage( + executionResult.details.stdOut + ); + run.appendOutput(cleanedOutput); if (status == testStatus.didNotRun) { run.skipped(node); diff --git a/src/utilities.ts b/src/utilities.ts index 9d37c3f0..06484401 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -305,3 +305,31 @@ export function removeFilePattern(enviroPath: string, pattern: string) { fs.unlinkSync(filePath); } } + +/** + * Cleans the message we want to show in the output. The Test Results pane handles logs differently. + * @param testResultString Test result we want to clean + * @returns Cleaned message, ready for the Test Results pane + */ +export function cleanTestResultsPaneMessage(testResultString: string) { + let cleanedOutput = testResultString.split("\n"); + + // Determine the leading spaces in the second line + // We want that the first line is left-aligned, and all subsequent lines are aligned to the second line + let secondLine = cleanedOutput[1] || ""; + let secondLinePadding = secondLine.match(/^(\s*)/)?.[0] || ""; + + // Align all lines after the first one to match the second line's padding + let alignedOutput = cleanedOutput + .map((line, index) => { + // First line stays unmodified + if (index === 0) { + return line.trim(); + } + // Apply second line padding to subsequent lines + return secondLinePadding + line.trim(); + }) + .join("\r\n"); + + return alignedOutput; +} From 664b9c4ed367c5e9802ef55a39839d8a42540ee1 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 09:21:15 +0100 Subject: [PATCH 02/19] Added tst autocompletion for issue #170 --- langServer/tstCompletion.ts | 88 +++++++++++++++++++ langServer/tstValidation.ts | 161 +++++++++++++++++++++------------- syntax/vcast.tst.grammar.json | 18 ++++ 3 files changed, 205 insertions(+), 62 deletions(-) diff --git a/langServer/tstCompletion.ts b/langServer/tstCompletion.ts index 20111174..449c472a 100644 --- a/langServer/tstCompletion.ts +++ b/langServer/tstCompletion.ts @@ -17,11 +17,66 @@ import { emptyChoiceData, getChoiceData, } from "./pythonUtilities"; +import { promisify } from "util"; +import { exec } from "child_process"; function filterArray(currentArray: string[], whatToRemove: string) { return currentArray.filter((element) => element !== whatToRemove); } +/** + * Checks if a specific VectorCAST option is set to a given value in the specified environment. + * + * @param {string} enviroPath - The file path to the environment where the command should be executed. + * @param {string} option - The VectorCAST option to check (e.g., 'VCAST_CODED_TESTS_SUPPORT'). + * @param {string} optionValue - The expected value of the option (e.g., 'True', ...). + * @returns {Promise} - Resolves to `true` if the option value matches, otherwise `false`. + */ +export async function checkClicastOption( + enviroPath: string, + option: string, + optionValue: string +): Promise { + const execAsync = promisify(exec); + const getCodedTestsSupportCommand = `${process.env.VECTORCAST_DIR}/clicast option ${option}`; + + try { + const { stdout } = await execAsync(getCodedTestsSupportCommand, { + cwd: enviroPath, + }); + + return stdout.includes(`${optionValue}`); + } catch (stderr) { + console.error(`Error executing command: ${stderr}`); + return false; + } +} + +/** + * Checks if a specific keyword followed by a colon and a given value exists in the extracted text. + * + * @param {string} extractedText - The text to search within. + * @param {string} keyword - The keyword to search for. + * @param {string} value - The value that should follow the colon after the keyword. + * @returns {Promise} - Resolves to `true` if the keyword and value are found in the text, otherwise `false`. + */ +export function checkForKeywordInLine( + extractedText: string, + keyword: string, + value: string +): boolean { + const regex = new RegExp(`^${keyword}:${value}$`); + const lines = extractedText.split(/\r?\n/); + + for (const line of lines) { + if (regex.test(line.trim())) { + return true; + } + } + + return false; +} + export async function getTstCompletionData( currentDocument: TextDocument, completionData: CompletionParams @@ -29,6 +84,17 @@ export async function getTstCompletionData( let returnData: choiceDataType = emptyChoiceData; const testScriptPath = url.fileURLToPath(completionData.textDocument.uri); const enviroPath = getEnviroNameFromTestScript(testScriptPath); + const extractedText = currentDocument.getText(); + + let codedTestsEnabled; + + if (enviroPath) { + codedTestsEnabled = checkClicastOption( + enviroPath, + "VCAST_CODED_TESTS_SUPPORT", + "True" + ); + } if (enviroPath && fs.existsSync(enviroPath)) { // The work we do is dependent on the trigger @@ -54,6 +120,24 @@ export async function getTstCompletionData( } else if (trigger == "DOT" && upperCaseLine == "TEST.") { returnData.choiceKind = "Keyword"; returnData.choiceList = testCommandList; + + const codedTestsDriverInSubprogram = checkForKeywordInLine( + extractedText, + "TEST.SUBPROGRAM", + "coded_tests_driver" + ); + if (codedTestsEnabled && codedTestsDriverInSubprogram) { + // Check if its already there, otherwise it will be pushed multiple times + if (!returnData.choiceList.includes("CODED_TEST_FILE")) { + returnData.choiceList.push("CODED_TEST_FILE"); + } + + // Remove "VALUE" and "EXPECTED" as it is not allowed with coded_tests_driver + // TODO: Check if we can get rid of those in getFunctionList() + returnData.choiceList = returnData.choiceList.filter( + (item) => item !== "VALUE" && item !== "EXPECTED" + ); + } } else if (trigger == "COLON" && upperCaseLine == "TEST.NAME:") { returnData.choiceKind = "Text"; returnData.choiceList = [""]; @@ -128,6 +212,10 @@ export async function getTstCompletionData( const title = pieces[1].trim().replace(/['"]+/g, ""); returnData.choiceList[i] = `${key} | ${title}`; } + // No autocompletion yet for TEST.CODED_TEST_FILE: + } else if (upperCaseLine.startsWith("TEST.CODED_TEST_FILE:")) { + returnData.choiceKind = "Keyword"; + returnData.choiceList = []; } } // enviroPath is valid diff --git a/langServer/tstValidation.ts b/langServer/tstValidation.ts index b7030f67..929a54e3 100644 --- a/langServer/tstValidation.ts +++ b/langServer/tstValidation.ts @@ -6,6 +6,7 @@ import { } from "vscode-languageserver"; import { testCommandList, scriptFeatureList } from "./serverUtilities"; +import { checkForKeywordInLine } from "./tstCompletion"; export function getDiagnosticObject( line: number, @@ -37,6 +38,7 @@ export function validateTextDocument(textDocument: TextDocument) { let diagnosticList: Diagnostic[] = []; + let lineIndex = 0; let text = textDocument.getText(); let lineList = text.split(/\r?\n/g); @@ -48,12 +50,17 @@ export function validateTextDocument(textDocument: TextDocument) { let withinValueUserCode: boolean = false; let withinExpectedUserCode: boolean = false; let withinImportFailures = false; + const codedTestsDriverInSubprogram = checkForKeywordInLine( + text, + "TEST.SUBPROGRAM", + "coded_tests_driver" + ); - for (let lineIndex = 0; lineIndex < lineList.length; lineIndex++) { + for (lineIndex = 0; lineIndex < lineList.length; lineIndex++) { let thisLine: string = lineList[lineIndex]; if (thisLine.startsWith("TEST")) { - const pieces = thisLine.split(/(? 1) command = pieces[1].trim(); @@ -116,17 +123,41 @@ export function validateTextDocument(textDocument: TextDocument) { 'Commands cannot be nested in a "IMPORT_FAILURES" block' ) ); - } else if ( - command == "VALUE" || - command == "EXPECTED" || + // If TEST.SUBPROGRAM is coded_tests_driver, check for disallowed TEST.VALUE and TEST.EXPECTED + } else if (command == "VALUE" || command == "EXPECTED") { + if (codedTestsDriverInSubprogram) { + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "TEST.VALUE and TEST.EXPECTED are not valid when TEST.SUBPROGRAM is set to coded_tests_driver" + ) + ); + } else { + // Handle general VALUE or EXPECTED validation + } + } + // Other commands (TBD: validate in Python) + else if ( command == "STUB" || command == "SLOT" || command == "REQUIREMENT_KEY" ) { + // When TEST.SUBPROGRAM is set to coded_tests_driver, TEST.CODED_TEST_FILE should throw an error + } else if (command == "CODED_TEST_FILE") { + if (!codedTestsDriverInSubprogram) { + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "TEST.CODED_TEST_FILE is not valid when TEST.SUBPROGRAM is not set to coded_tests_driver" + ) + ); + } // TBD: we should validate in python } else if (command == "NAME") { - // nothing to be done for TEST.NAME - // including this for completeness } else if (command == "NOTES") { withinNotes = true; } else if (command == "FLOW") { @@ -142,76 +173,82 @@ export function validateTextDocument(textDocument: TextDocument) { } } //file-level commands - else if (testCommandList.indexOf(command) < 0) { - diagnosticList.push( - getDiagnosticObject( - lineIndex, - 0, - 1000, - "Invalid command, type TEST. to see all command values" - ) - ); - } else if (command == "UNIT") { - currentUnit = pieces[2]; - } else if (command == "SUBPROGRAM") { - currentFunction = pieces[2]; - if ( - currentUnit == "" && - !specialSubprogramNames.includes(currentFunction) - ) + else { + if (testCommandList.indexOf(command) < 0) { diagnosticList.push( getDiagnosticObject( lineIndex, 0, 1000, - "TEST.UNIT is required but missing" + "Invalid command, type TEST. to see all command values" ) ); - } else if (command == "NEW" || command == "REPLACE" || command == "ADD") { - if (currentFunction == "") { - diagnosticList.push( - getDiagnosticObject( - lineIndex, - 0, - 1000, - "TEST.SUBPRORGRAM is required but missing" - ) - ); - } - withinTest = true; - } else if (command == "END") { - if (!withinTest) { - diagnosticList.push( - getDiagnosticObject( - lineIndex, - 0, - 1000, - "TEST.NEW | REPLACE is required but missing" - ) - ); - } - } else if (command == "SCRIPT_FEATURE" && pieces.length > 2) { - const featureName = pieces[2].trim(); - if (scriptFeatureList.indexOf(featureName) < 0) { + } else if (command == "UNIT") { + currentUnit = pieces[2]; + } else if (command == "SUBPROGRAM") { + currentFunction = pieces[2]; + if ( + currentUnit == "" && + !specialSubprogramNames.includes(currentFunction) + ) + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "TEST.UNIT is required but missing" + ) + ); + } else if ( + command == "NEW" || + command == "REPLACE" || + command == "ADD" + ) { + if (currentFunction == "") { + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "TEST.SUBPRORGRAM is required but missing" + ) + ); + } + withinTest = true; + } else if (command == "END") { + if (!withinTest) { + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "TEST.NEW | REPLACE is required but missing" + ) + ); + } + } else if (command == "SCRIPT_FEATURE" && pieces.length > 2) { + const featureName = pieces[2].trim(); + if (scriptFeatureList.indexOf(featureName) < 0) { + diagnosticList.push( + getDiagnosticObject( + lineIndex, + 0, + 1000, + "Invalid feature flag, type TEST.SCRIPT_FEATURE: to see a all flags" + ) + ); + } + } else { + // this is a valid TEST command, but it does not belong in the file scope diagnosticList.push( getDiagnosticObject( lineIndex, 0, 1000, - "Invalid feature flag, type TEST.SCRIPT_FEATURE: to see a all flags" + "Command is only valid within a TEST.NEW | REPLACE -> TEST.END block " ) ); } - } else { - // this is a valid TEST command, but it does not belong in the file scope - diagnosticList.push( - getDiagnosticObject( - lineIndex, - 0, - 1000, - "Command is only valid within a TEST.NEW | REPLACE -> TEST.END block " - ) - ); } } // end if this is a TEST command else if ( diff --git a/syntax/vcast.tst.grammar.json b/syntax/vcast.tst.grammar.json index b7c85630..903ab378 100644 --- a/syntax/vcast.tst.grammar.json +++ b/syntax/vcast.tst.grammar.json @@ -26,6 +26,24 @@ } } }, + { + "match": "^TEST\\.CODED_TEST_FILE(:)(.*?)(:|$)(.*)$", + "name": "keyword", + "captures": { + "1": { + "name": "keyword" + }, + "2": { + "name": "string", + "patterns": [ + { + "match": "(\\.\\./|\\./|/)?[^\\s]*", + "name": "path" + } + ] + } + } + }, { "match": "^TEST\\.(?:VALUE|EXPECTED)(:)(.*?)(? Date: Wed, 18 Dec 2024 11:50:07 +0100 Subject: [PATCH 03/19] Changed TEST.SUBPROGRAM autocompletion. --- langServer/pythonUtilities.ts | 16 +++++--- langServer/tstCompletion.ts | 28 +++++++------- python/testEditorInterface.py | 68 ++++++++++++++++++++-------------- python/tstUtilities.py | 26 ++++++++++++- python/vcastDataServer.py | 5 ++- python/vcastDataServerTypes.py | 21 +++++++---- src-common/vcastServer.ts | 2 +- 7 files changed, 110 insertions(+), 56 deletions(-) diff --git a/langServer/pythonUtilities.ts b/langServer/pythonUtilities.ts index 6329ba87..8e2599e0 100644 --- a/langServer/pythonUtilities.ts +++ b/langServer/pythonUtilities.ts @@ -101,7 +101,8 @@ export const emptyChoiceData: choiceDataType = { export async function getChoiceDataFromServer( kind: choiceKindType, enviroPath: string, - lineSoFar: string + lineSoFar: string, + unit?: string ): Promise { // We are re-using options for the line fragment in the request @@ -113,6 +114,7 @@ export async function getChoiceDataFromServer( command: commandToUse, path: enviroPath, options: lineSoFar, + ...(unit !== undefined && { unit }), // only add unitName if it is defined }; let transmitResponse: transmitResponseType = @@ -138,11 +140,12 @@ export enum choiceKindType { export function getChoiceDataFromPython( kind: choiceKindType, enviroName: string, - lineSoFar: string + lineSoFar: string, + unit?: string ): choiceDataType { // NOTE: we cannot use executeCommand() here because it is in the client only! // commandOutput is a buffer: (Uint8Array) - const commandToRun = `${vPythonCommandToUse} ${testEditorScriptPath} ${kind} ${enviroName} "${lineSoFar}"`; + const commandToRun = `${vPythonCommandToUse} ${testEditorScriptPath} --mode ${kind} --enviroName ${enviroName} --inputLine "${lineSoFar}" --unit ${unit}`; let commandOutputBuffer = execSync(commandToRun).toString(); // see detailed comment with the function definition @@ -157,15 +160,16 @@ export function getChoiceDataFromPython( export async function getChoiceData( kind: choiceKindType, enviroPath: string, - lineSoFar: string + lineSoFar: string, + unit?: string ): Promise { // let jsonData: any; if (globalEnviroDataServerActive) { - jsonData = await getChoiceDataFromServer(kind, enviroPath, lineSoFar); + jsonData = await getChoiceDataFromServer(kind, enviroPath, lineSoFar, unit); } else { - jsonData = getChoiceDataFromPython(kind, enviroPath, lineSoFar); + jsonData = getChoiceDataFromPython(kind, enviroPath, lineSoFar, unit); } for (const msg of jsonData.messages) { diff --git a/langServer/tstCompletion.ts b/langServer/tstCompletion.ts index 449c472a..88bb53a7 100644 --- a/langServer/tstCompletion.ts +++ b/langServer/tstCompletion.ts @@ -38,18 +38,18 @@ export async function checkClicastOption( optionValue: string ): Promise { const execAsync = promisify(exec); - const getCodedTestsSupportCommand = `${process.env.VECTORCAST_DIR}/clicast option ${option}`; + const getCodedTestsSupportCommand = `${process.env.VECTORCAST_DIR}/clicast get_option ${option}`; - try { - const { stdout } = await execAsync(getCodedTestsSupportCommand, { - cwd: enviroPath, - }); + const { stdout, stderr } = await execAsync(getCodedTestsSupportCommand, { + cwd: enviroPath, + }); - return stdout.includes(`${optionValue}`); - } catch (stderr) { + if (stderr) { console.error(`Error executing command: ${stderr}`); return false; } + + return stdout.includes(`${optionValue}`); } /** @@ -89,7 +89,7 @@ export async function getTstCompletionData( let codedTestsEnabled; if (enviroPath) { - codedTestsEnabled = checkClicastOption( + codedTestsEnabled = await checkClicastOption( enviroPath, "VCAST_CODED_TESTS_SUPPORT", "True" @@ -154,21 +154,23 @@ export async function getTstCompletionData( returnData.choiceList = scriptFeatureList; } else if (trigger == "COLON" && upperCaseLine == "TEST.SUBPROGRAM:") { // find closest TEST.UNIT above this line ... - const unitName = getNearest( + const unit = getNearest( currentDocument, "UNIT", completionData.position.line ); + // TBD will need to change how this is done during the fix for issue #170 // we use python to get a list of subprograms by creating a fake VALUE line // with the unitName set to what we found - let choiceArray = ["<>", "<>"]; - let choiceKind = "Keyword"; - if (unitName.length > 0) { + let choiceKind = ""; + let choiceArray: string[] = []; + if (unit.length > 0) { const choiceData = await getChoiceData( choiceKindType.choiceListTST, enviroPath, - "TEST.VALUE:" + unitName + "." + upperCaseLine, + unit ); returnData.extraText = choiceData.extraText; returnData.messages = choiceData.messages; diff --git a/python/testEditorInterface.py b/python/testEditorInterface.py index eaee10a2..3ed9af44 100644 --- a/python/testEditorInterface.py +++ b/python/testEditorInterface.py @@ -9,21 +9,52 @@ and the VectorCAST environment, using the VectorCAST dataAPI """ +import argparse import json import re import sys +import os +# Available modes +modeChoices = ["choiceList-ct", "choiceList-tst"] from tstUtilities import ( buildChoiceResponse, choiceDataType, globalOutputLog, processTstLine, - processTstLine, processMockDefinition, ) +def setupArgs(): + """ + Add Command Line Args + """ + parser = argparse.ArgumentParser(description="VectorCAST Test Editor Interface") + + parser.add_argument( + "--mode", + choices=modeChoices, + required=True, + help="Test Editor Mode: choiceList-ct or choiceList-tst", + ) + + parser.add_argument( + "--enviroName", + required=True, + help="Path to the environment directory or cbt file", + ) + + parser.add_argument( + "--inputLine", required=True, help="Contents of the line from the editor so far" + ) + + parser.add_argument("--unit", help="Unit name (optional)") + + return parser + + def main(): # ------------------------------------------------------ # Main function, called by the VS Code language server @@ -33,40 +64,23 @@ def main(): # We get here when the user types a "." or ":" # argv has the name of the script as arg 1 and then user args - if len(sys.argv) == 4: - # What to do choiceList-ct or choiceList-tst - mode = sys.argv[1] - - # Path to the environment folder - enviroPath = sys.argv[2] - - # Contents of the line from the editor so far - inputLine = sys.argv[3] - - if mode == "choiceList-ct": - # if the line starts with "void vmock" then we are processing vmock definition - if re.match("^\s*\/\/\s*vmock", inputLine): - choiceData = processMockDefinition(enviroPath, inputLine) - else: - # noting to be done - choiceData = choiceDataType() - - elif mode == "choiceList-tst": - choiceData = processTstLine(enviroPath, inputLine) + argParser = setupArgs() + args, restOfArgs = argParser.parse_known_args() + pathToUse = os.path.abspath(args.enviroName) + if args.mode == "choiceList-ct": + if re.match("^\s*\/\/\s*vmock", args.inputLine): + choiceData = processMockDefinition(pathToUse, args.inputLine) else: choiceData = choiceDataType() - globalOutputLog.append("Invalid mode: " + mode) + elif args.mode == "choiceList-tst": + choiceData = processTstLine(pathToUse, args.inputLine, args.unit) else: choiceData = choiceDataType() - # first arg is the name of the script, so we subtract 1 - globalOutputLog.append( - f"Invalid number of arguments: {len(sys.argv)-1}, 3 expected" - ) + globalOutputLog.append("Invalid mode: " + args.mode) outputDictionary = buildChoiceResponse(choiceData) - print(json.dumps(outputDictionary, indent=4)) sys.exit(0) diff --git a/python/tstUtilities.py b/python/tstUtilities.py index 74d68dee..0ba5e8dc 100644 --- a/python/tstUtilities.py +++ b/python/tstUtilities.py @@ -413,6 +413,28 @@ def toDict(self): return data +def processSubprogramLines(api, pieces, triggerCharacter, unit): + """ + This function will handle the TEST.SUBPROGRAM line completions + """ + global globalOutputLog + returnData = choiceDataType() + lengthOfCommand = len(pieces) + globalOutputLog.append("Last piece: " + pieces[2]) + globalOutputLog.append("pieces length: " + str(lengthOfCommand)) + # TEST.SUBPROGRAM: + if lengthOfCommand == 3 and triggerCharacter == ":": + objectList = api.Unit.all() + returnData.choiceList = getFunctionList(api, unit) + returnData.choiceKind = choiceKindType.Function + returnData.choiceList.append("<>") + returnData.choiceList.append("<>") + else: + # TODO: Current implementation just to make it work. --> See what alse can come after + processStandardLines(api, pieces, triggerCharacter) + return returnData + + def processRequirementLines(api, pieces, triggerCharacter): """ This function will compute the list of possible requirement keys and return @@ -985,7 +1007,7 @@ def buildChoiceResponse(choiceData: choiceDataType): return responseObject -def processTstLine(enviroPath, line): +def processTstLine(enviroPath, line, unit=None): """ This function will process TEST. line completions @@ -1039,6 +1061,8 @@ def processTstLine(enviroPath, line): returnData = processSlotLines(api, pieces, triggerCharacter) elif line.upper().startswith("TEST.REQUIREMENT_KEY"): returnData = processRequirementLines(api, pieces, triggerCharacter) + elif line.upper().startswith("TEST.SUBPROGRAM"): + returnData = processSubprogramLines(api, pieces, triggerCharacter, unit) else: returnData = processStandardLines(api, pieces, triggerCharacter) diff --git a/python/vcastDataServer.py b/python/vcastDataServer.py index fa657241..36192dd0 100644 --- a/python/vcastDataServer.py +++ b/python/vcastDataServer.py @@ -105,8 +105,11 @@ def runcommand(clientRequest, clientRequestText): # because we are not restarting, we need to clear the global output log testEditorInterface.globalOutputLog.clear() + logMessage( + f" clientRequest '{clientRequest.options}' ###### '{clientRequest.path}' ##### '{clientRequest.unit}'" + ) choiceData = testEditorInterface.processTstLine( - clientRequest.path, clientRequest.options + clientRequest.path, clientRequest.options, clientRequest.unit ) returnData = tstUtilities.buildChoiceResponse(choiceData) logMessage(f" line received: '{clientRequest.options}'") diff --git a/python/vcastDataServerTypes.py b/python/vcastDataServerTypes.py index ac61a035..0c94e01a 100644 --- a/python/vcastDataServerTypes.py +++ b/python/vcastDataServerTypes.py @@ -37,20 +37,27 @@ class commandType(str, Enum): class clientRequest: - def __init__(self, command, clicast="", path="", test="", options=""): + def __init__( + self, + command, + clicast="", + path="", + options="", + unit="", + ): self.command = command self.clicast = clicast self.path = path - self.test = test self.options = options + self.unit = unit def toDict(self): data = {} data["command"] = self.command data["clicast"] = self.clicast data["path"] = self.path - data["test"] = self.test data["options"] = self.options + data["unit"] = self.unit return data @classmethod @@ -62,13 +69,13 @@ def fromDict(cls, data): clicast = "" if "clicast" in data: clicast = data["clicast"] - test = "" - if "test" in data: - test = data["test"] options = "" if "options" in data: options = data["options"] - return cls(command, clicast, path, test, options) + unit = "" + if "unit" in data: + unit = data["unit"] + return cls(command, clicast, path, options, unit) class environmentData: diff --git a/src-common/vcastServer.ts b/src-common/vcastServer.ts index dc36e66d..1d12d091 100644 --- a/src-common/vcastServer.ts +++ b/src-common/vcastServer.ts @@ -27,8 +27,8 @@ export enum vcastCommandType { export interface clientRequestType { command: vcastCommandType; path: string; - test?: string; options?: string; + unit?: string; } // This is set when the VectorCAST Data Server process is started From 0c5d15a8cd1e3fa8a88f29fd6acf849aab164cf4 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 13:25:55 +0100 Subject: [PATCH 04/19] Adapted tests --- python/tstUtilities.py | 7 ++- tests/unit/setup-unit-test.ts | 1 - tests/unit/tst-completion.test.ts | 90 +++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/python/tstUtilities.py b/python/tstUtilities.py index 0ba5e8dc..ce4d88c8 100644 --- a/python/tstUtilities.py +++ b/python/tstUtilities.py @@ -427,8 +427,7 @@ def processSubprogramLines(api, pieces, triggerCharacter, unit): objectList = api.Unit.all() returnData.choiceList = getFunctionList(api, unit) returnData.choiceKind = choiceKindType.Function - returnData.choiceList.append("<>") - returnData.choiceList.append("<>") + returnData.choiceList.extend(["<>", "<>", "coded_tests_driver"]) else: # TODO: Current implementation just to make it work. --> See what alse can come after processStandardLines(api, pieces, triggerCharacter) @@ -1062,6 +1061,10 @@ def processTstLine(enviroPath, line, unit=None): elif line.upper().startswith("TEST.REQUIREMENT_KEY"): returnData = processRequirementLines(api, pieces, triggerCharacter) elif line.upper().startswith("TEST.SUBPROGRAM"): + if unit == None: + globalOutputLog.append( + "Additional 'unit' parameter is requiered for TEST.SUBPROGRAM: autocompletion." + ) returnData = processSubprogramLines(api, pieces, triggerCharacter, unit) else: returnData = processStandardLines(api, pieces, triggerCharacter) diff --git a/tests/unit/setup-unit-test.ts b/tests/unit/setup-unit-test.ts index 061c96d7..d3348d69 100644 --- a/tests/unit/setup-unit-test.ts +++ b/tests/unit/setup-unit-test.ts @@ -13,7 +13,6 @@ module.exports = async () => { // If PACKAGE_PATH is already defined by vscode launch.json (debugger) --> Don't override it process.env.PACKAGE_PATH ??= process.env.INIT_CWD; process.env.TST_FILENAME = tstFilename; - process.env.VECTORCAST_DIR = ""; const checkVpython: string = process.platform === "win32" ? "where vpython" : "which vpython"; diff --git a/tests/unit/tst-completion.test.ts b/tests/unit/tst-completion.test.ts index 7a7e66ca..282e2f49 100644 --- a/tests/unit/tst-completion.test.ts +++ b/tests/unit/tst-completion.test.ts @@ -147,6 +147,17 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; +const suprogrammWithoutCTDriver = `-- Environment: @TEST +TEST.UNIT: +TEST.SUBPROGRAM:bar +TEST.NEW +TEST.CODED_TEST_FILE: +TEST.NAME: +TEST.VALUE: +TEST.NOTES: +TEST.END_NOTES: +TEST.END`; + describe("Text Completion", () => { test( "validate tst completion for TEST.SUBPROGRAM:", @@ -167,22 +178,28 @@ describe("Text Completion", () => { expect(generatedCompletionData).toEqual([ { - label: "<>", - kind: 3, - detail: "", data: 0, + detail: "", + kind: 3, + label: "bar", }, { - label: "<>", - kind: 3, - detail: "", data: 1, + detail: "", + kind: 3, + label: "<>", }, { - label: "bar", + data: 2, + detail: "", kind: 3, + label: "<>", + }, + { + data: 3, detail: "", - data: 2, + kind: 3, + label: "coded_tests_driver", }, ]); }, @@ -1001,19 +1018,25 @@ describe("Text Completion", () => { data: 0, detail: "", kind: 3, - label: "<>", + label: "bar", }, { data: 1, detail: "", kind: 3, - label: "<>", + label: "<>", }, { data: 2, detail: "", kind: 3, - label: "bar", + label: "<>", + }, + { + data: 3, + detail: "", + kind: 3, + label: "coded_tests_driver", }, ]); }, @@ -1058,19 +1081,25 @@ describe("Text Completion", () => { data: 0, detail: "", kind: 3, - label: "<>", + label: "bar", }, { data: 1, detail: "", kind: 3, - label: "<>", + label: "<>", }, { data: 2, detail: "", kind: 3, - label: "bar", + label: "<>", + }, + { + data: 3, + detail: "", + kind: 3, + label: "coded_tests_driver", }, ]); }, @@ -1097,19 +1126,25 @@ describe("Text Completion", () => { data: 0, detail: "", kind: 3, - label: "<>", + label: "bar", }, { data: 1, detail: "", kind: 3, - label: "<>", + label: "<>", }, { data: 2, detail: "", kind: 3, - label: "bar", + label: "<>", + }, + { + data: 3, + detail: "", + kind: 3, + label: "coded_tests_driver", }, ]); }, @@ -1264,4 +1299,25 @@ describe("Text Completion", () => { }, timeout ); + + test( + "validate that TEST.CODED_TEST_FILE has no autocompletion.", + async () => { + const tstText = suprogrammWithoutCTDriver; + const lineToComplete = "TEST.CODED_TEST_FILE:"; + const completionPosition = getCompletionPositionForLine( + lineToComplete, + tstText + ); + const triggerCharacter = lineToComplete.at(-1); + + const generatedCompletionData = await generateCompletionData( + tstText, + completionPosition, + triggerCharacter + ); + expect(generatedCompletionData).toEqual([]); + }, + timeout + ); }); From a5eb2c6cf07b790c6a00b0d7364c6e8f6dedabc7 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 15:28:04 +0100 Subject: [PATCH 05/19] Added map to cache clicast options --- langServer/tstCompletion.ts | 35 ++++++++++++++++++++++++++++------- src/vcastUtilities.ts | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/langServer/tstCompletion.ts b/langServer/tstCompletion.ts index 88bb53a7..18896a69 100644 --- a/langServer/tstCompletion.ts +++ b/langServer/tstCompletion.ts @@ -24,6 +24,10 @@ function filterArray(currentArray: string[], whatToRemove: string) { return currentArray.filter((element) => element !== whatToRemove); } +// This is a cache map for the clicast option so that we don't have to check it every time +// Otherwise we would run everytime we want autocompletion +const clicastOptionCache = new Map(); + /** * Checks if a specific VectorCAST option is set to a given value in the specified environment. * @@ -38,18 +42,35 @@ export async function checkClicastOption( optionValue: string ): Promise { const execAsync = promisify(exec); + + // Create a unique cache key using the parameters + const cacheKey = `${enviroPath}:${option}:${optionValue}`; + + // Check if the result is already cached + if (clicastOptionCache.has(cacheKey)) { + return clicastOptionCache.get(cacheKey)!; + } + const getCodedTestsSupportCommand = `${process.env.VECTORCAST_DIR}/clicast get_option ${option}`; - const { stdout, stderr } = await execAsync(getCodedTestsSupportCommand, { - cwd: enviroPath, - }); + try { + const { stdout, stderr } = await execAsync(getCodedTestsSupportCommand, { + cwd: enviroPath, + }); + + if (stderr) { + console.error(`Error executing command: ${stderr}`); + return false; + } - if (stderr) { - console.error(`Error executing command: ${stderr}`); + const result = stdout.includes(`${optionValue}`); + // Store the result in the cache + clicastOptionCache.set(cacheKey, result); + return result; + } catch (error: any) { + console.error(`Error executing command: ${error.message}`); return false; } - - return stdout.includes(`${optionValue}`); } /** diff --git a/src/vcastUtilities.ts b/src/vcastUtilities.ts index aee38cee..3b1db205 100644 --- a/src/vcastUtilities.ts +++ b/src/vcastUtilities.ts @@ -414,7 +414,7 @@ export function getClientRequestObject( const requestObject: clientRequestType = { command: command, path: path, - test: testArgWithoutQuotes, + options: testArgWithoutQuotes, }; return requestObject; From 8a51b26185fa5fe14b849b3aaed5038d4adfcca8 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 16:24:07 +0100 Subject: [PATCH 06/19] Added test attribute in clientRequest --- python/vcastDataServer.py | 3 --- python/vcastDataServerTypes.py | 8 +++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python/vcastDataServer.py b/python/vcastDataServer.py index 36192dd0..dfe71af6 100644 --- a/python/vcastDataServer.py +++ b/python/vcastDataServer.py @@ -105,9 +105,6 @@ def runcommand(clientRequest, clientRequestText): # because we are not restarting, we need to clear the global output log testEditorInterface.globalOutputLog.clear() - logMessage( - f" clientRequest '{clientRequest.options}' ###### '{clientRequest.path}' ##### '{clientRequest.unit}'" - ) choiceData = testEditorInterface.processTstLine( clientRequest.path, clientRequest.options, clientRequest.unit ) diff --git a/python/vcastDataServerTypes.py b/python/vcastDataServerTypes.py index 0c94e01a..374c2836 100644 --- a/python/vcastDataServerTypes.py +++ b/python/vcastDataServerTypes.py @@ -42,12 +42,14 @@ def __init__( command, clicast="", path="", + test="", options="", unit="", ): self.command = command self.clicast = clicast self.path = path + self.test = test self.options = options self.unit = unit @@ -56,6 +58,7 @@ def toDict(self): data["command"] = self.command data["clicast"] = self.clicast data["path"] = self.path + data["test"] = self.test data["options"] = self.options data["unit"] = self.unit return data @@ -69,13 +72,16 @@ def fromDict(cls, data): clicast = "" if "clicast" in data: clicast = data["clicast"] + test = "" + if "test" in data: + test = data["test"] options = "" if "options" in data: options = data["options"] unit = "" if "unit" in data: unit = data["unit"] - return cls(command, clicast, path, options, unit) + return cls(command, clicast, path, test, options, unit) class environmentData: From c55a2acb2a36976a9cd685666aa68be6f9140f88 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 16:32:37 +0100 Subject: [PATCH 07/19] Renamed variable (xo) --- tests/unit/tst-completion.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/tst-completion.test.ts b/tests/unit/tst-completion.test.ts index 282e2f49..e7faefd0 100644 --- a/tests/unit/tst-completion.test.ts +++ b/tests/unit/tst-completion.test.ts @@ -147,7 +147,7 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; -const suprogrammWithoutCTDriver = `-- Environment: @TEST +const subprogramWithoutCodedTestsDriver = `-- Environment: @TEST TEST.UNIT: TEST.SUBPROGRAM:bar TEST.NEW @@ -1303,7 +1303,7 @@ describe("Text Completion", () => { test( "validate that TEST.CODED_TEST_FILE has no autocompletion.", async () => { - const tstText = suprogrammWithoutCTDriver; + const tstText = subprogramWithoutCodedTestsDriver; const lineToComplete = "TEST.CODED_TEST_FILE:"; const completionPosition = getCompletionPositionForLine( lineToComplete, From be6216a8f7363c1132f24c5fe6827af366b2122d Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 18 Dec 2024 17:16:30 +0100 Subject: [PATCH 08/19] Added as clientRequest attribute --- src-common/vcastServer.ts | 1 + src/vcastUtilities.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src-common/vcastServer.ts b/src-common/vcastServer.ts index 1d12d091..f2783e10 100644 --- a/src-common/vcastServer.ts +++ b/src-common/vcastServer.ts @@ -27,6 +27,7 @@ export enum vcastCommandType { export interface clientRequestType { command: vcastCommandType; path: string; + test?: string; options?: string; unit?: string; } diff --git a/src/vcastUtilities.ts b/src/vcastUtilities.ts index 3b1db205..aee38cee 100644 --- a/src/vcastUtilities.ts +++ b/src/vcastUtilities.ts @@ -414,7 +414,7 @@ export function getClientRequestObject( const requestObject: clientRequestType = { command: command, path: path, - options: testArgWithoutQuotes, + test: testArgWithoutQuotes, }; return requestObject; From 68784f7a4c5aad3824fd715ad696fd9e016ab216 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 19 Dec 2024 16:10:22 +0100 Subject: [PATCH 09/19] Added tests for ct autocompletion --- .../e2e/test/specs/vcast_coded_tests.test.ts | 5 - ...ast_coded_tests_tst_autocompletion.test.ts | 211 ++++++++++++++++++ tests/internal/e2e/test/specs_config.ts | 12 +- 3 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts diff --git a/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts b/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts index 49eb9393..adaf6d6c 100644 --- a/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts +++ b/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts @@ -1308,9 +1308,4 @@ describe("vTypeCheck VS Code Extension", () => { await webview.close(); await editorView.closeAllEditors(); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts b/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts new file mode 100644 index 00000000..832ccec2 --- /dev/null +++ b/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts @@ -0,0 +1,211 @@ +// Test/specs/vcast.test.ts +import { + type BottomBarPanel, + type TextEditor, + type Workbench, + type TreeItem, +} from "wdio-vscode-service"; +import { Key } from "webdriverio"; +import { + getViewContent, + findSubprogram, + findSubprogramMethod, + openTestScriptFor, + updateTestID, + checkIfRequestInLogs, + editTestScriptFor, + getGeneratedTooltipTextAt, +} from "../test_utils/vcast_utils"; +import { TIMEOUT } from "../test_utils/vcast_utils"; +import { checkForServerRunnability } from "../../../../unit/getToolversion"; + +describe("vTypeCheck VS Code Extension", () => { + let bottomBar: BottomBarPanel; + let workbench: Workbench; + let useDataServer: boolean = true; + before(async () => { + workbench = await browser.getWorkbench(); + // Opening bottom bar and problems view before running any tests + bottomBar = workbench.getBottomBar(); + await bottomBar.toggle(true); + process.env.E2E_TEST_ID = "0"; + let releaseIsSuitableForServer = await checkForServerRunnability(); + if (process.env.VCAST_USE_PYTHON || !releaseIsSuitableForServer) { + useDataServer = false; + } + }); + + it("test 1: should be able to load VS Code", async () => { + await updateTestID(); + expect(await workbench.getTitleBar().getTitle()).toBe( + "[Extension Development Host] vcastTutorial - Visual Studio Code" + ); + }); + + it("should activate vcastAdapter", async () => { + await updateTestID(); + + await browser.keys([Key.Control, Key.Shift, "p"]); + // Typing Vector in the quick input box + // This brings up VectorCAST Test Explorer: Configure + // so just need to hit Enter to activate + for (const character of "vector") { + await browser.keys(character); + } + + await browser.keys(Key.Enter); + + const activityBar = workbench.getActivityBar(); + const viewControls = await activityBar.getViewControls(); + for (const viewControl of viewControls) { + console.log(await viewControl.getTitle()); + } + + await bottomBar.toggle(true); + const outputView = await bottomBar.openOutputView(); + + console.log("Waiting for VectorCAST activation"); + await $("aria/VectorCAST Test Pane Initialization"); + console.log("WAITING FOR TESTING"); + await browser.waitUntil( + async () => (await activityBar.getViewControl("Testing")) !== undefined, + { timeout: TIMEOUT } + ); + console.log("WAITING FOR TEST EXPLORER"); + await browser.waitUntil(async () => + (await outputView.getChannelNames()) + .toString() + .includes("VectorCAST Test Explorer") + ); + await outputView.selectChannel("VectorCAST Test Explorer"); + console.log("Channel selected"); + console.log("WAITING FOR LANGUAGE SERVER"); + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes("Starting the language server"), + { timeout: TIMEOUT } + ); + + const testingView = await activityBar.getViewControl("Testing"); + await testingView?.openView(); + }); + + it("should edit Test Script check for autocompletion", async () => { + await updateTestID(); + + console.log("Opening Testing View"); + const vcastTestingViewContent = await getViewContent("Testing"); + let subprogram: TreeItem; + + for (const vcastTestingViewSection of await vcastTestingViewContent.getSections()) { + if (!(await vcastTestingViewSection.isExpanded())) + await vcastTestingViewSection.expand(); + + for (const vcastTestingViewContentSection of await vcastTestingViewContent.getSections()) { + console.log(await vcastTestingViewContentSection.getTitle()); + await vcastTestingViewContentSection.expand(); + subprogram = await findSubprogram( + "manager", + vcastTestingViewContentSection + ); + if (subprogram) { + if (!(await subprogram.isExpanded())) await subprogram.expand(); + break; + } + } + } + + if (!subprogram) { + throw new Error("Subprogram 'manager' not found"); + } + + const subprogramMethod = await findSubprogramMethod( + subprogram, + "Manager::PlaceOrder" + ); + if (!subprogramMethod) { + throw new Error("Subprogram method 'Manager::PlaceOrder' not found"); + } + + if (!subprogramMethod.isExpanded()) { + await subprogramMethod.select(); + } + + await openTestScriptFor(subprogramMethod); + const editorView = workbench.getEditorView(); + + const tab = (await editorView.openEditor( + "vcast-template.tst" + )) as TextEditor; + + console.log("Check for TEST.SUBPROGRAM:coded_tests_driver autocompletion"); + // Need to activate contentAssist before getting the object + // That way we avoid a timeout that is a result of + // toggleContentAssist() implementation + await browser.keys([Key.Ctrl, Key.Space]); + const contentAssist = await tab.toggleContentAssist(true); + + let currentLine = await tab.getLineOfText( + "TEST.SUBPROGRAM:Manager::PlaceOrder" + ); + + await tab.setTextAtLine(currentLine, "TEST.SUBPROGRAM"); + + await tab.typeTextAt(currentLine, "TEST.SUBPROGRAM".length + 1, ":"); + await tab.save(); + + // Really important to wait until content assist appears + await browser.waitUntil( + async () => (await contentAssist.getItems()).length === 10 + ); + expect(await contentAssist.hasItem("coded_tests_driver")).toBe(true); + await tab.typeTextAt( + currentLine, + "TEST.SUBPROGRAM:".length + 1, + "coded_tests_driver" + ); + await tab.save(); + + //######################################################################################## + + console.log( + "Test for TEST.VALUE & TEST.EXPECTED Hover when TEST.SUBPROGRAM:coded_tests_driver is set" + ); + + currentLine = await tab.getLineOfText("TEST.VALUE"); + + // Get the tooltip text when hovering over the "// vmock" comment + let hoverText = await getGeneratedTooltipTextAt( + currentLine, + "TEST.VALUE".length - 1, + tab + ); + + let expectedText = `TEST.VALUE and TEST.EXPECTED are not valid when TEST.SUBPROGRAM is set to coded_tests_driver`; + expect(hoverText).toContain(expectedText); + + //######################################################################################## + + console.log( + "Test for TEST.CODED_TEST_FILE error hover when TEST.SUBPROGRAM:coded_tests_driver is NOT set" + ); + currentLine = await tab.getLineOfText("TEST.SUBPROGRAM:coded_tests_driver"); + await tab.setTextAtLine(currentLine, "TEST.SUBPROGRAM:Manager::PlaceOrder"); + currentLine = await tab.getLineOfText("TEST.NEW"); + await tab.moveCursor(currentLine, "TEST.NEW".length + 1); + await browser.keys([Key.Enter]); + currentLine += 1; + + await tab.setTextAtLine(currentLine, "TEST.CODED_TEST_FILE"); + + hoverText = await getGeneratedTooltipTextAt( + currentLine, + "TEST.CODED_TEST_FILE".length - 1, + tab + ); + expectedText = `TEST.CODED_TEST_FILE is not valid when TEST.SUBPROGRAM is not set to coded_tests_driver`; + expect(hoverText).toContain(expectedText); + }); +}); diff --git a/tests/internal/e2e/test/specs_config.ts b/tests/internal/e2e/test/specs_config.ts index 4b26cc0a..f08cf729 100755 --- a/tests/internal/e2e/test/specs_config.ts +++ b/tests/internal/e2e/test/specs_config.ts @@ -122,7 +122,11 @@ export function getSpecGroups(useVcast24: boolean) { }; specGroups["coded_tests"] = { - specs: ["./**/**/vcast_coded_tests.test.ts"], + specs: [ + "./**/**/vcast_coded_tests.test.ts", + "./**/**/vcast.create_script_1.test.ts", + "./**/**/vcast_coded_tests_tst_autocompletion.test.ts", + ], env: { VCAST_USE_PYTHON: "True" }, params: {}, }; @@ -237,7 +241,11 @@ export function getSpecGroups(useVcast24: boolean) { }; specGroups["coded_tests_server"] = { - specs: ["./**/**/vcast_coded_tests.test.ts"], + specs: [ + "./**/**/vcast_coded_tests.test.ts", + "./**/**/vcast.create_script_1.test.ts", + "./**/**/vcast_coded_tests_tst_autocompletion.test.ts", + ], env: {}, params: {}, }; From b8c1daaabdfde8478b55752d390dc9ff2425657b Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 19 Dec 2024 17:02:00 +0100 Subject: [PATCH 10/19] Minor comment changes --- .../specs/vcast_coded_tests_tst_autocompletion.test.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts b/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts index 832ccec2..36912a60 100644 --- a/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts +++ b/tests/internal/e2e/test/specs/vcast_coded_tests_tst_autocompletion.test.ts @@ -92,7 +92,7 @@ describe("vTypeCheck VS Code Extension", () => { await testingView?.openView(); }); - it("should edit Test Script check for autocompletion", async () => { + it("should edit Test Script and check for autocompletion", async () => { await updateTestID(); console.log("Opening Testing View"); @@ -141,9 +141,6 @@ describe("vTypeCheck VS Code Extension", () => { )) as TextEditor; console.log("Check for TEST.SUBPROGRAM:coded_tests_driver autocompletion"); - // Need to activate contentAssist before getting the object - // That way we avoid a timeout that is a result of - // toggleContentAssist() implementation await browser.keys([Key.Ctrl, Key.Space]); const contentAssist = await tab.toggleContentAssist(true); @@ -175,8 +172,6 @@ describe("vTypeCheck VS Code Extension", () => { ); currentLine = await tab.getLineOfText("TEST.VALUE"); - - // Get the tooltip text when hovering over the "// vmock" comment let hoverText = await getGeneratedTooltipTextAt( currentLine, "TEST.VALUE".length - 1, From 2b1705b8022201f1d55ad0056ccccc9ecc57a5a2 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 19 Dec 2024 17:09:35 +0100 Subject: [PATCH 11/19] Comments --- langServer/tstCompletion.ts | 1 - python/tstUtilities.py | 1 - 2 files changed, 2 deletions(-) diff --git a/langServer/tstCompletion.ts b/langServer/tstCompletion.ts index 18896a69..131607d2 100644 --- a/langServer/tstCompletion.ts +++ b/langServer/tstCompletion.ts @@ -154,7 +154,6 @@ export async function getTstCompletionData( } // Remove "VALUE" and "EXPECTED" as it is not allowed with coded_tests_driver - // TODO: Check if we can get rid of those in getFunctionList() returnData.choiceList = returnData.choiceList.filter( (item) => item !== "VALUE" && item !== "EXPECTED" ); diff --git a/python/tstUtilities.py b/python/tstUtilities.py index ce4d88c8..3d5b057e 100644 --- a/python/tstUtilities.py +++ b/python/tstUtilities.py @@ -429,7 +429,6 @@ def processSubprogramLines(api, pieces, triggerCharacter, unit): returnData.choiceKind = choiceKindType.Function returnData.choiceList.extend(["<>", "<>", "coded_tests_driver"]) else: - # TODO: Current implementation just to make it work. --> See what alse can come after processStandardLines(api, pieces, triggerCharacter) return returnData From 265346f47f3d1a2bda59ea03cf5c5e455c889ea0 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Fri, 20 Dec 2024 17:40:48 +0100 Subject: [PATCH 12/19] Added unit tests and adapted some code. --- langServer/pythonUtilities.ts | 4 +- langServer/serverUtilities.ts | 1 + langServer/tstCompletion.ts | 42 +++++------ python/tstUtilities.py | 2 +- tests/unit/tst-completion.test.ts | 111 +++++++++++++++++++++++++++- tests/unit/tst-validation.test.ts | 115 +++++++++++++++++++++++++++++- 6 files changed, 243 insertions(+), 32 deletions(-) diff --git a/langServer/pythonUtilities.ts b/langServer/pythonUtilities.ts index 8e2599e0..ec375023 100644 --- a/langServer/pythonUtilities.ts +++ b/langServer/pythonUtilities.ts @@ -102,7 +102,7 @@ export async function getChoiceDataFromServer( kind: choiceKindType, enviroPath: string, lineSoFar: string, - unit?: string + unitName?: string ): Promise { // We are re-using options for the line fragment in the request @@ -114,7 +114,7 @@ export async function getChoiceDataFromServer( command: commandToUse, path: enviroPath, options: lineSoFar, - ...(unit !== undefined && { unit }), // only add unitName if it is defined + unit: unitName, }; let transmitResponse: transmitResponseType = diff --git a/langServer/serverUtilities.ts b/langServer/serverUtilities.ts index 97e66df1..d0c8d128 100644 --- a/langServer/serverUtilities.ts +++ b/langServer/serverUtilities.ts @@ -264,6 +264,7 @@ export const testCommandList = [ "END", // test scope "NAME", + "CODED_TEST_FILE", "NOTES", "END_NOTES", "FLOW", diff --git a/langServer/tstCompletion.ts b/langServer/tstCompletion.ts index 131607d2..8fe95377 100644 --- a/langServer/tstCompletion.ts +++ b/langServer/tstCompletion.ts @@ -54,15 +54,9 @@ export async function checkClicastOption( const getCodedTestsSupportCommand = `${process.env.VECTORCAST_DIR}/clicast get_option ${option}`; try { - const { stdout, stderr } = await execAsync(getCodedTestsSupportCommand, { + const { stdout } = await execAsync(getCodedTestsSupportCommand, { cwd: enviroPath, }); - - if (stderr) { - console.error(`Error executing command: ${stderr}`); - return false; - } - const result = stdout.includes(`${optionValue}`); // Store the result in the cache clicastOptionCache.set(cacheKey, result); @@ -72,7 +66,6 @@ export async function checkClicastOption( return false; } } - /** * Checks if a specific keyword followed by a colon and a given value exists in the extracted text. * @@ -107,16 +100,6 @@ export async function getTstCompletionData( const enviroPath = getEnviroNameFromTestScript(testScriptPath); const extractedText = currentDocument.getText(); - let codedTestsEnabled; - - if (enviroPath) { - codedTestsEnabled = await checkClicastOption( - enviroPath, - "VCAST_CODED_TESTS_SUPPORT", - "True" - ); - } - if (enviroPath && fs.existsSync(enviroPath)) { // The work we do is dependent on the trigger const context = completionData.context; @@ -147,16 +130,26 @@ export async function getTstCompletionData( "TEST.SUBPROGRAM", "coded_tests_driver" ); - if (codedTestsEnabled && codedTestsDriverInSubprogram) { - // Check if its already there, otherwise it will be pushed multiple times - if (!returnData.choiceList.includes("CODED_TEST_FILE")) { - returnData.choiceList.push("CODED_TEST_FILE"); - } + let codedTestsEnabled; + + if (enviroPath) { + codedTestsEnabled = await checkClicastOption( + enviroPath, + "VCAST_CODED_TESTS_SUPPORT", + "TRUE" + ); + } + if (codedTestsEnabled && codedTestsDriverInSubprogram) { // Remove "VALUE" and "EXPECTED" as it is not allowed with coded_tests_driver returnData.choiceList = returnData.choiceList.filter( (item) => item !== "VALUE" && item !== "EXPECTED" ); + } else { + // If coded tests are not enabled, remove "CODED_TEST_FILE" + returnData.choiceList = returnData.choiceList.filter( + (item) => item !== "CODED_TEST_FILE" + ); } } else if (trigger == "COLON" && upperCaseLine == "TEST.NAME:") { returnData.choiceKind = "Text"; @@ -180,9 +173,6 @@ export async function getTstCompletionData( completionData.position.line ); - // TBD will need to change how this is done during the fix for issue #170 - // we use python to get a list of subprograms by creating a fake VALUE line - // with the unitName set to what we found let choiceKind = ""; let choiceArray: string[] = []; if (unit.length > 0) { diff --git a/python/tstUtilities.py b/python/tstUtilities.py index 3d5b057e..94b4f133 100644 --- a/python/tstUtilities.py +++ b/python/tstUtilities.py @@ -1062,7 +1062,7 @@ def processTstLine(enviroPath, line, unit=None): elif line.upper().startswith("TEST.SUBPROGRAM"): if unit == None: globalOutputLog.append( - "Additional 'unit' parameter is requiered for TEST.SUBPROGRAM: autocompletion." + "Additional 'unit' parameter is required for TEST.SUBPROGRAM: autocompletion." ) returnData = processSubprogramLines(api, pieces, triggerCharacter, unit) else: diff --git a/tests/unit/tst-completion.test.ts b/tests/unit/tst-completion.test.ts index e7faefd0..cacee88c 100644 --- a/tests/unit/tst-completion.test.ts +++ b/tests/unit/tst-completion.test.ts @@ -1,13 +1,16 @@ import path from "node:path"; import process from "node:process"; -import { describe, expect, test } from "vitest"; +import { beforeEach, describe, expect, test, vi } from "vitest"; import { TextDocument, TextDocuments } from "vscode-languageserver"; import URI from "vscode-uri"; import { getCompletionPositionForLine, generateCompletionData, storeNewDocument, + runCommand, } from "./utils"; +import { getToolVersion } from "./getToolversion"; +import { checkClicastOption } from "../../langServer/tstCompletion"; const timeout = 30_000; // 30 seconds @@ -123,7 +126,7 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; -const globalValueTst = ` +const globalValueTst = ` vi.mocked(promisify).mockReturnValue(execAsyncMock); TEST.NEW TEST.NAME:fieldValTest TEST.VALUE:unit.<>. @@ -158,7 +161,22 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; +const codedTestFileTst = ` +TEST.UNIT: +TEST.SUBPROGRAM:coded_tests_driver +TEST. +TEST.NEW +TEST.NAME: +TEST.VALUE: +TEST.NOTES: +TEST.END_NOTES: +TEST.END`; + describe("Text Completion", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + test( "validate tst completion for TEST.SUBPROGRAM:", async () => { @@ -1320,4 +1338,93 @@ describe("Text Completion", () => { }, timeout ); + + test( + "validate completion for TEST.CODED_TEST_FILE with codedTestsEnabled and codedTestsDriverInSubprogram", + async () => { + const testEnvPath = path.join( + process.env.PACKAGE_PATH as string, + "tests", + "unit", + "vcast", + "TEST" + ); + const clicastExecutablePath = `${process.env.VECTORCAST_DIR}/clicast`; + const toolVersion = await getToolVersion(clicastExecutablePath.trimEnd()); + + // Coded tests support only for >= vc24 + // We are setting Coded test support to be true in order to get the TEST.CODED_TEST_FILE completion + if (toolVersion >= 24) { + const setCoded = `cd ${testEnvPath} && ${clicastExecutablePath.trimEnd()} -lc option VCAST_CODED_TESTS_SUPPORT TRUE`; + await runCommand(setCoded); + + const tstText = codedTestFileTst; + + const lineToComplete = "TEST."; + const completionPosition = getCompletionPositionForLine( + lineToComplete, + tstText + ); + const triggerCharacter = "."; + + const generatedCompletionData = await generateCompletionData( + tstText, + completionPosition, + triggerCharacter + ); + + const expectedCompletionData = [ + { data: 0, detail: "", kind: 14, label: "SCRIPT_FEATURE" }, + { data: 1, detail: "", kind: 14, label: "UNIT" }, + { data: 2, detail: "", kind: 14, label: "SUBPROGRAM" }, + { data: 3, detail: "", kind: 14, label: "NEW" }, + { data: 4, detail: "", kind: 14, label: "REPLACE" }, + { data: 5, detail: "", kind: 14, label: "ADD" }, + { data: 6, detail: "", kind: 14, label: "END" }, + { data: 7, detail: "", kind: 14, label: "NAME" }, + { data: 8, detail: "", kind: 14, label: "CODED_TEST_FILE" }, + { data: 9, detail: "", kind: 14, label: "NOTES" }, + { data: 10, detail: "", kind: 14, label: "END_NOTES" }, + { data: 11, detail: "", kind: 14, label: "FLOW" }, + { data: 12, detail: "", kind: 14, label: "END_FLOW" }, + { data: 13, detail: "", kind: 14, label: "SLOT" }, + { data: 14, detail: "", kind: 14, label: "STUB" }, + { data: 15, detail: "", kind: 14, label: "REQUIREMENT_KEY" }, + { data: 16, detail: "", kind: 14, label: "VALUE_USER_CODE" }, + { data: 17, detail: "", kind: 14, label: "END_VALUE_USER_CODE" }, + { data: 18, detail: "", kind: 14, label: "EXPECTED_USER_CODE" }, + { data: 19, detail: "", kind: 14, label: "END_EXPECTED_USER_CODE" }, + { data: 20, detail: "", kind: 14, label: "IMPORT_FAILURES" }, + { data: 21, detail: "", kind: 14, label: "END_IMPORT_FAILURES" }, + { data: 22, detail: "", kind: 14, label: "COMPOUND_ONLY" }, + ]; + + expect(generatedCompletionData).toEqual(expectedCompletionData); + } + }, + timeout + ); + + test("should test the error catch of checkClicastOption", async () => { + // Mock execAsync to throw an error + const execAsyncMock = vi.fn(); + execAsyncMock.mockRejectedValue(new Error("Command failed")); + + const consoleErrorSpy = vi + .spyOn(console, "error") + .mockImplementation(() => {}); + const result = await checkClicastOption( + "/some/path", + "someOption", + "someValue" + ); + + // If an error is thrown --> false should be returned + expect(result).toBe(false); + expect(consoleErrorSpy).toHaveBeenCalledWith( + "Error executing command: spawn /bin/sh ENOENT" + ); + + consoleErrorSpy.mockRestore(); + }); }); diff --git a/tests/unit/tst-validation.test.ts b/tests/unit/tst-validation.test.ts index 61b44a12..5afcb2b7 100644 --- a/tests/unit/tst-validation.test.ts +++ b/tests/unit/tst-validation.test.ts @@ -1,5 +1,7 @@ import { describe, expect, test } from "vitest"; -import { generateDiagnosticMessages } from "./utils"; +import { generateDiagnosticMessages, runCommand } from "./utils"; +import path from "path"; +import { getToolVersion } from "./getToolversion"; const timeout = 30_000; // 30 seconds @@ -116,6 +118,39 @@ TEST.STUB: TEST.END `; +const codedTestFileTst = ` +TEST.UNIT:unit +TEST.SUBPROGRAM:definitely_NOT_coded_tests_driver +TEST.NEW +TEST.NAME: +TEST.CODED_TEST_FILE +TEST.VALUE: +TEST.NOTES: +TEST.END_NOTES: +TEST.END`; + +const testValueWithCTDriver = ` +TEST.UNIT:unit +TEST.SUBPROGRAM:coded_tests_driver +TEST.NEW +TEST.NAME: +TEST.CODED_TEST_FILE +TEST.VALUE: +TEST.NOTES: +TEST.END_NOTES: +TEST.END`; + +const testExpectedWithCTDriver = ` +TEST.UNIT:unit +TEST.SUBPROGRAM:coded_tests_driver +TEST.NEW +TEST.NAME: +TEST.CODED_TEST_FILE +TEST.EXPECTED: +TEST.NOTES: +TEST.END_NOTES: +TEST.END`; + describe("Text Document Validator", () => { test( "validate error detection when typing commands in TEST.NOTES block", @@ -324,4 +359,82 @@ describe("Text Document Validator", () => { }, timeout ); + + test( + "validate error detection when TEST.SUBPROGRAM is not set to coded_tests_driver and TEST.CODED_TEST_FILE is used", + async () => { + const tstText = codedTestFileTst; + const diagnosticMessages = generateDiagnosticMessages(tstText); + expect(diagnosticMessages).toEqual( + expect.arrayContaining([ + expect.stringContaining( + "TEST.CODED_TEST_FILE is not valid when TEST.SUBPROGRAM is not set to coded_tests_driver" + ), + ]) + ); + }, + timeout + ); + + test( + "validate error detection when TEST.SUBPROGRAM is set to coded_tests_driver and TEST.VALUE is used", + async () => { + const testEnvPath = path.join( + process.env.PACKAGE_PATH as string, + "tests", + "unit", + "vcast", + "TEST" + ); + const clicastExecutablePath = `${process.env.VECTORCAST_DIR}/clicast`; + const toolVersion = await getToolVersion(clicastExecutablePath.trimEnd()); + + // Coded tests support only for >= vc24 + if (toolVersion >= 24) { + const setCoded = `cd ${testEnvPath} && ${clicastExecutablePath.trimEnd()} -lc option VCAST_CODED_TESTS_SUPPORT TRUE`; + await runCommand(setCoded); + const tstText = testValueWithCTDriver; + const diagnosticMessages = generateDiagnosticMessages(tstText); + expect(diagnosticMessages).toEqual( + expect.arrayContaining([ + expect.stringContaining( + "TEST.VALUE and TEST.EXPECTED are not valid when TEST.SUBPROGRAM is set to coded_tests_driver" + ), + ]) + ); + } + }, + timeout + ); + + test( + "validate error detection when TEST.SUBPROGRAM is set to coded_tests_driver and TEST.EXPECTED is used", + async () => { + const testEnvPath = path.join( + process.env.PACKAGE_PATH as string, + "tests", + "unit", + "vcast", + "TEST" + ); + const clicastExecutablePath = `${process.env.VECTORCAST_DIR}/clicast`; + const toolVersion = await getToolVersion(clicastExecutablePath.trimEnd()); + + // Coded tests support only for >= vc24 + if (toolVersion >= 24) { + const setCoded = `cd ${testEnvPath} && ${clicastExecutablePath.trimEnd()} -lc option VCAST_CODED_TESTS_SUPPORT TRUE`; + await runCommand(setCoded); + const tstText = testExpectedWithCTDriver; + const diagnosticMessages = generateDiagnosticMessages(tstText); + expect(diagnosticMessages).toEqual( + expect.arrayContaining([ + expect.stringContaining( + "TEST.VALUE and TEST.EXPECTED are not valid when TEST.SUBPROGRAM is set to coded_tests_driver" + ), + ]) + ); + } + }, + timeout + ); }); From adbe679c275835ca7b60dbd8d4fa52170cfd3a66 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Fri, 20 Dec 2024 18:27:39 +0100 Subject: [PATCH 13/19] Addressed xo --- tests/unit/tst-completion.test.ts | 8 ++++++-- tests/unit/tst-validation.test.ts | 15 ++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/unit/tst-completion.test.ts b/tests/unit/tst-completion.test.ts index cacee88c..3f0b1efe 100644 --- a/tests/unit/tst-completion.test.ts +++ b/tests/unit/tst-completion.test.ts @@ -3,6 +3,7 @@ import process from "node:process"; import { beforeEach, describe, expect, test, vi } from "vitest"; import { TextDocument, TextDocuments } from "vscode-languageserver"; import URI from "vscode-uri"; +import { checkClicastOption } from "../../langServer/tstCompletion"; import { getCompletionPositionForLine, generateCompletionData, @@ -10,7 +11,6 @@ import { runCommand, } from "./utils"; import { getToolVersion } from "./getToolversion"; -import { checkClicastOption } from "../../langServer/tstCompletion"; const timeout = 30_000; // 30 seconds @@ -1410,9 +1410,13 @@ describe("Text Completion", () => { const execAsyncMock = vi.fn(); execAsyncMock.mockRejectedValue(new Error("Command failed")); + // Just log something, xo does not like empty functions const consoleErrorSpy = vi .spyOn(console, "error") - .mockImplementation(() => {}); + .mockImplementation((message?: any, ...optionalParameters: any[]) => { + console.log(message, ...optionalParameters); + }); + const result = await checkClicastOption( "/some/path", "someOption", diff --git a/tests/unit/tst-validation.test.ts b/tests/unit/tst-validation.test.ts index 5afcb2b7..2ad64f8a 100644 --- a/tests/unit/tst-validation.test.ts +++ b/tests/unit/tst-validation.test.ts @@ -1,6 +1,7 @@ +/* eslint-disable n/prefer-global/process */ +import path from "node:path"; import { describe, expect, test } from "vitest"; import { generateDiagnosticMessages, runCommand } from "./utils"; -import path from "path"; import { getToolVersion } from "./getToolversion"; const timeout = 30_000; // 30 seconds @@ -129,7 +130,7 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; -const testValueWithCTDriver = ` +const testValueWithCtDriver = ` TEST.UNIT:unit TEST.SUBPROGRAM:coded_tests_driver TEST.NEW @@ -140,7 +141,7 @@ TEST.NOTES: TEST.END_NOTES: TEST.END`; -const testExpectedWithCTDriver = ` +const testExpectedWithCtDriver = ` TEST.UNIT:unit TEST.SUBPROGRAM:coded_tests_driver TEST.NEW @@ -380,7 +381,7 @@ describe("Text Document Validator", () => { "validate error detection when TEST.SUBPROGRAM is set to coded_tests_driver and TEST.VALUE is used", async () => { const testEnvPath = path.join( - process.env.PACKAGE_PATH as string, + process.env.PACKAGE_PATH!, "tests", "unit", "vcast", @@ -393,7 +394,7 @@ describe("Text Document Validator", () => { if (toolVersion >= 24) { const setCoded = `cd ${testEnvPath} && ${clicastExecutablePath.trimEnd()} -lc option VCAST_CODED_TESTS_SUPPORT TRUE`; await runCommand(setCoded); - const tstText = testValueWithCTDriver; + const tstText = testValueWithCtDriver; const diagnosticMessages = generateDiagnosticMessages(tstText); expect(diagnosticMessages).toEqual( expect.arrayContaining([ @@ -411,7 +412,7 @@ describe("Text Document Validator", () => { "validate error detection when TEST.SUBPROGRAM is set to coded_tests_driver and TEST.EXPECTED is used", async () => { const testEnvPath = path.join( - process.env.PACKAGE_PATH as string, + process.env.PACKAGE_PATH!, "tests", "unit", "vcast", @@ -424,7 +425,7 @@ describe("Text Document Validator", () => { if (toolVersion >= 24) { const setCoded = `cd ${testEnvPath} && ${clicastExecutablePath.trimEnd()} -lc option VCAST_CODED_TESTS_SUPPORT TRUE`; await runCommand(setCoded); - const tstText = testExpectedWithCTDriver; + const tstText = testExpectedWithCtDriver; const diagnosticMessages = generateDiagnosticMessages(tstText); expect(diagnosticMessages).toEqual( expect.arrayContaining([ From 710a8fe3978194cd35aebf90cf785df5942401dc Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 15 Jan 2025 11:44:29 +0100 Subject: [PATCH 14/19] Changed ATG generation function for tests --- .../internal/e2e/test/test_utils/vcast_utils.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/internal/e2e/test/test_utils/vcast_utils.ts b/tests/internal/e2e/test/test_utils/vcast_utils.ts index c64dd7a3..ca0f6632 100644 --- a/tests/internal/e2e/test/test_utils/vcast_utils.ts +++ b/tests/internal/e2e/test/test_utils/vcast_utils.ts @@ -347,10 +347,10 @@ export async function getTestHandle( } for (const testHandle of await customSubprogramMethod.getChildren()) { - if ( - (await (await (testHandle as CustomTreeItem).elem).getText()) === - expectedTestName - ) { + const testName = await ( + await (testHandle as CustomTreeItem).elem + ).getText(); + if (testName.includes(expectedTestName)) { return testHandle; } } @@ -697,8 +697,16 @@ export async function generateAndValidateAllTestsFor( let testHandle: TreeItem; for (const vcastTestingViewSection of await vcastTestingViewContent.getSections()) { subprogram = await findSubprogram(unitName, vcastTestingViewSection); + console.log(unitName); + console.log(vcastTestingViewSection); if (subprogram) { await subprogram.expand(); + console.log("#######################################"); + console.log(subprogram); + console.log(functionName); + console.log(testName); + console.log(Object.entries(tests).length); + console.log("#######################################"); await browser.waitUntil( async () => (await getTestHandle( From 15db2bebc06a79699a73d2994c44893505bf44d8 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 15 Jan 2025 14:32:28 +0100 Subject: [PATCH 15/19] Deleted not required cleanup in tests at the end --- tests/internal/e2e/test/specs/vcast.rest_3.test.ts | 6 ------ .../e2e/test/specs/vcast_coded_tests.test.ts | 1 - .../e2e/test/specs/vcast_testdel_env_atg.test.ts | 12 +----------- .../e2e/test/specs/vcast_testdel_env_basis.test.ts | 12 +----------- .../e2e/test/specs/vcast_testdel_func_atg.test.ts | 7 ------- .../e2e/test/specs/vcast_testdel_func_basis.test.ts | 6 ------ .../e2e/test/specs/vcast_testdel_unit_atg.test.ts | 7 ------- .../e2e/test/specs/vcast_testdel_unit_basis.test.ts | 7 ------- .../e2e/test/specs/vcast_testgen_bugs_2.test.ts | 6 ------ .../e2e/test/specs/vcast_testgen_env_atg.test.ts | 3 --- .../e2e/test/specs/vcast_testgen_flask_icon.test.ts | 7 ------- 11 files changed, 2 insertions(+), 72 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast.rest_3.test.ts b/tests/internal/e2e/test/specs/vcast.rest_3.test.ts index 634e457b..1a87b52b 100755 --- a/tests/internal/e2e/test/specs/vcast.rest_3.test.ts +++ b/tests/internal/e2e/test/specs/vcast.rest_3.test.ts @@ -18,7 +18,6 @@ import { getTestHandle, deleteTest, updateTestID, - cleanup, assertTestsDeleted, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -280,9 +279,4 @@ describe("vTypeCheck VS Code Extension", () => { console.log(stdout); } }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts b/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts index adaf6d6c..0b38d6e4 100644 --- a/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts +++ b/tests/internal/e2e/test/specs/vcast_coded_tests.test.ts @@ -19,7 +19,6 @@ import { getTestHandle, findSubprogramMethod, updateTestID, - cleanup, checkForLogsInTestResults, checkElementExistsInHTML, } from "../test_utils/vcast_utils"; diff --git a/tests/internal/e2e/test/specs/vcast_testdel_env_atg.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_env_atg.test.ts index 5b9c5198..223b2618 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_env_atg.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_env_atg.test.ts @@ -5,12 +5,7 @@ import { type Workbench, } from "wdio-vscode-service"; import { Key } from "webdriverio"; -import { - updateTestID, - deleteAllTestsForEnv, - validateTestDeletionForFunction, - cleanup, -} from "../test_utils/vcast_utils"; +import { updateTestID, deleteAllTestsForEnv } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; describe("vTypeCheck VS Code Extension", () => { @@ -90,9 +85,4 @@ describe("vTypeCheck VS Code Extension", () => { `Validating deletion of all ATG tests for the environment ${envName}` ); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testdel_env_basis.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_env_basis.test.ts index 499488df..b8921cb6 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_env_basis.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_env_basis.test.ts @@ -5,12 +5,7 @@ import { type Workbench, } from "wdio-vscode-service"; import { Key } from "webdriverio"; -import { - updateTestID, - deleteAllTestsForEnv, - validateTestDeletionForFunction, - cleanup, -} from "../test_utils/vcast_utils"; +import { updateTestID, deleteAllTestsForEnv } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; describe("vTypeCheck VS Code Extension", () => { @@ -87,9 +82,4 @@ describe("vTypeCheck VS Code Extension", () => { console.log(`Deleting all BASIS PATH tests for the environment ${envName}`); await deleteAllTestsForEnv(envName); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testdel_func_atg.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_func_atg.test.ts index 4d947bd1..5d09df54 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_func_atg.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_func_atg.test.ts @@ -5,8 +5,6 @@ import { updateTestID, testGenMethod, deleteAllTestsForFunction, - validateTestDeletionForFunction, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -84,9 +82,4 @@ describe("vTypeCheck VS Code Extension", () => { testGenMethod.ATG ); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testdel_func_basis.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_func_basis.test.ts index 3c81058a..a2c5de0e 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_func_basis.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_func_basis.test.ts @@ -6,7 +6,6 @@ import { testGenMethod, deleteAllTestsForFunction, assertTestsDeleted, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -113,9 +112,4 @@ describe("vTypeCheck VS Code Extension", () => { await browser.takeScreenshot(); await browser.saveScreenshot("info_deleted_func_basis_tests.png"); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testdel_unit_atg.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_unit_atg.test.ts index d8d338c7..27cecf6a 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_unit_atg.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_unit_atg.test.ts @@ -5,8 +5,6 @@ import { updateTestID, testGenMethod, deleteAllTestsForUnit, - validateTestDeletionForFunction, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -81,9 +79,4 @@ describe("vTypeCheck VS Code Extension", () => { console.log("Deleting all ATG tests for unit database"); await deleteAllTestsForUnit("database", testGenMethod.ATG); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testdel_unit_basis.test.ts b/tests/internal/e2e/test/specs/vcast_testdel_unit_basis.test.ts index 6c8cab9c..00734602 100644 --- a/tests/internal/e2e/test/specs/vcast_testdel_unit_basis.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testdel_unit_basis.test.ts @@ -5,8 +5,6 @@ import { updateTestID, testGenMethod, deleteAllTestsForUnit, - validateTestDeletionForFunction, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -81,9 +79,4 @@ describe("vTypeCheck VS Code Extension", () => { await deleteAllTestsForUnit("database", testGenMethod.BasisPath); console.log("Validating deletion of BASIS PATH tests for unit database"); }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testgen_bugs_2.test.ts b/tests/internal/e2e/test/specs/vcast_testgen_bugs_2.test.ts index e467ef6e..a6d3a5b4 100644 --- a/tests/internal/e2e/test/specs/vcast_testgen_bugs_2.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testgen_bugs_2.test.ts @@ -8,7 +8,6 @@ import { validateGeneratedTestsForFunction, deleteAllTestsForFunction, validateTestDeletionForFunction, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -153,9 +152,4 @@ describe("vTypeCheck VS Code Extension", () => { console.log("Skipping ATG tests"); } }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); diff --git a/tests/internal/e2e/test/specs/vcast_testgen_env_atg.test.ts b/tests/internal/e2e/test/specs/vcast_testgen_env_atg.test.ts index 498e76e0..da3d025c 100644 --- a/tests/internal/e2e/test/specs/vcast_testgen_env_atg.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testgen_env_atg.test.ts @@ -11,10 +11,7 @@ import { expandWorkspaceFolderSectionInExplorer, updateTestID, testGenMethod, - deleteAllTestsForEnv, - validateTestDeletionForFunction, generateAndValidateAllTestsFor, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; diff --git a/tests/internal/e2e/test/specs/vcast_testgen_flask_icon.test.ts b/tests/internal/e2e/test/specs/vcast_testgen_flask_icon.test.ts index 7afea5c7..1ad3ec36 100644 --- a/tests/internal/e2e/test/specs/vcast_testgen_flask_icon.test.ts +++ b/tests/internal/e2e/test/specs/vcast_testgen_flask_icon.test.ts @@ -10,8 +10,6 @@ import { generateFlaskIconTestsFor, validateGeneratedTest, deleteGeneratedTest, - validateSingleTestDeletion, - cleanup, } from "../test_utils/vcast_utils"; import { TIMEOUT } from "../test_utils/vcast_utils"; @@ -235,9 +233,4 @@ describe("vTypeCheck VS Code Extension", () => { ); } }); - - it("should clean up", async () => { - await updateTestID(); - await cleanup(); - }); }); From 430f25fcf809bf848bf0b67c5042429a9e6d13ec Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 15 Jan 2025 15:42:42 +0100 Subject: [PATCH 16/19] Added env expanding in testing pane while generating ATG tests. --- tests/internal/e2e/test/test_utils/vcast_utils.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/internal/e2e/test/test_utils/vcast_utils.ts b/tests/internal/e2e/test/test_utils/vcast_utils.ts index ca0f6632..b0ce0e22 100644 --- a/tests/internal/e2e/test/test_utils/vcast_utils.ts +++ b/tests/internal/e2e/test/test_utils/vcast_utils.ts @@ -696,17 +696,10 @@ export async function generateAndValidateAllTestsFor( let subprogram: TreeItem; let testHandle: TreeItem; for (const vcastTestingViewSection of await vcastTestingViewContent.getSections()) { + await vcastTestingViewSection.expand(); subprogram = await findSubprogram(unitName, vcastTestingViewSection); - console.log(unitName); - console.log(vcastTestingViewSection); if (subprogram) { await subprogram.expand(); - console.log("#######################################"); - console.log(subprogram); - console.log(functionName); - console.log(testName); - console.log(Object.entries(tests).length); - console.log("#######################################"); await browser.waitUntil( async () => (await getTestHandle( From cf77ecb5b216b0279a411eecb49cdb62408bc38a Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 15 Jan 2025 16:53:28 +0100 Subject: [PATCH 17/19] Changing workflow strategy job index --- .github/workflows/run-tests-workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests-workflow.yml b/.github/workflows/run-tests-workflow.yml index ee215ef4..94c3b617 100644 --- a/.github/workflows/run-tests-workflow.yml +++ b/.github/workflows/run-tests-workflow.yml @@ -104,7 +104,7 @@ jobs: ./test-output.xml - name: Show coverage summary - if: ${{ always() && strategy.job-index == '0' }} + if: ${{ always() && strategy.job-index == '1' }} run: | echo "### Coverage summary - Unit tests" >> $GITHUB_STEP_SUMMARY { @@ -114,7 +114,7 @@ jobs: } >> $GITHUB_STEP_SUMMARY - name: Upload coverage artifacts - if: ${{ always() && strategy.job-index == '0' }} + if: ${{ always() && strategy.job-index == '1' }} run: | curl -Os https://uploader.codecov.io/v0.7.1/linux/codecov chmod +x codecov From d494b5c5d2fc79ad68100da4fc39a716ee1f79f8 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 15 Jan 2025 17:20:35 +0100 Subject: [PATCH 18/19] Changing job index of workflow so that the latest version is uploaded to codecov --- .github/workflows/run-tests-workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests-workflow.yml b/.github/workflows/run-tests-workflow.yml index 94c3b617..911cc0fe 100644 --- a/.github/workflows/run-tests-workflow.yml +++ b/.github/workflows/run-tests-workflow.yml @@ -104,7 +104,7 @@ jobs: ./test-output.xml - name: Show coverage summary - if: ${{ always() && strategy.job-index == '1' }} + if: ${{ always() && strategy.job-index == '3' }} run: | echo "### Coverage summary - Unit tests" >> $GITHUB_STEP_SUMMARY { @@ -114,7 +114,7 @@ jobs: } >> $GITHUB_STEP_SUMMARY - name: Upload coverage artifacts - if: ${{ always() && strategy.job-index == '1' }} + if: ${{ always() && strategy.job-index == '3' }} run: | curl -Os https://uploader.codecov.io/v0.7.1/linux/codecov chmod +x codecov From dc6093ccc93184bbec954d5cd6436016993a74e9 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 16 Jan 2025 14:57:56 +0100 Subject: [PATCH 19/19] Minor comment --- src/testPane.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/testPane.ts b/src/testPane.ts index c1267a96..2c938524 100644 --- a/src/testPane.ts +++ b/src/testPane.ts @@ -90,7 +90,6 @@ const crypto = require("crypto"); // Note that if you pass in a fileURI, then the test tree node will have // a "go to test" icon, and clicking on it will open the file at the test location // and double click on the test will open the test file. -// function addTestNodes( testList: any[], parentNode: vcastTestItem,