diff --git a/.github/workflows/testarch.yml b/.github/workflows/testarch.yml new file mode 100644 index 0000000..1ba1710 --- /dev/null +++ b/.github/workflows/testarch.yml @@ -0,0 +1,63 @@ +name: Nodejs Build Test + +on: + pull_request: + branches: + - main + +jobs: + package: + name: Package + runs-on: ubuntu-latest + strategy: + matrix: + os: [linux, darwin, win32] # Define the platforms + arch: [x64, arm64] # Define the architectures + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + # Install npm dependencies based on the architecture + - name: Install dependencies + run: | + if [ "${{ matrix.arch }}" == "arm64" ]; then + npm_config_arch=arm64 npm install --build-from-source + else + npm_config_arch=x64 npm install --build-from-source + fi + + # Run Rollup for compilation + - name: Run Rollup + run: npm run rollupci + + - name: List contents of out/compiled directory (for debugging) + run: ls -R out/compiled + + - name: Install vsce + run: npm install -g @vscode/vsce + + - name: Package VSIX for the target platform + run: | + case "${{ matrix.os }}" in + linux) vsce package --target linux-${{ matrix.arch }} ;; + darwin) vsce package --target darwin-${{ matrix.arch }} ;; + win32) vsce package --target win32-${{ matrix.arch }} ;; + esac + + - name: Capture VSIX filename + id: capture_vsix_file + run: | + VSIX_FILE=$(ls *.vsix) + echo "VSIX_FILE=$VSIX_FILE" >> $GITHUB_ENV + shell: bash + + - name: Print VSIX filename + id: print_vsix_file # Renamed to be unique + run: | + echo "Generated package for platform ${{ matrix.os }} and architecture ${{ matrix.arch }}:" + ls *.vsix diff --git a/.vscode-test.mjs b/.vscode-test.mjs index b62ba25..1507065 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -1,5 +1,5 @@ import { defineConfig } from '@vscode/test-cli'; export default defineConfig({ - files: 'out/test/**/*.test.js', + files: 'out/*.test.js', }); diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a13060..f89388c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,3 +55,15 @@ First Release for Vs Code Extension. ## [1.0.12] - Fixing wrong file test generation in express mongoose + +## [1.0.13] + +- Separate release for arm and amd user + +## [1.0.14] + +- Back button refactored for better User Experience + +## [1.0.15] + +- Reverting to universal release diff --git a/package.json b/package.json index dbe7286..04fab29 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "keployio", "displayName": "Keploy", "description": "Streamline testing with the power of Keploy, directly in your favorite IDE.", - "version": "1.0.12", + "version": "1.0.15", "publisher": "Keploy", "icon": "media/logo.png", "pricing": "Free", diff --git a/scripts/bash/keploy_record_script.sh b/scripts/bash/keploy_record_script.sh index f48d389..39aab23 100755 --- a/scripts/bash/keploy_record_script.sh +++ b/scripts/bash/keploy_record_script.sh @@ -1,6 +1,5 @@ #!/bin/bash -i -# folderpath="$2" log_file_path="$1" # Extract command from keploy.yml @@ -11,9 +10,7 @@ if [[ ! -f "$keploy_config" ]]; then fi command=$(awk '/command:/ { $1=""; sub(/^ /, ""); print }' "$keploy_config") -# echo "Command in yml file: $command" -# Check if command is empty if [[ -z "$command" ]]; then echo "Command is not specified in keploy.yml." exit 1 @@ -31,22 +28,14 @@ if [[ "$command" =~ .*"go".* ]]; then go build -o application elif [[ "$command" =~ .*"python3".* ]]; then - # echo "Python3 command found" python3 -m venv venv - # echo "venv created" source venv/bin/activate - # echo "venv activated" pip install -r requirements.txt - # echo "requirements installed" elif [[ "$command" =~ .*"python".* ]] ; then -# echo "Python command found" python -m venv venv - # echo "venv created" source venv/bin/activate - # echo "venv activated" pip install -r requirements.txt - # echo "requirements installed" elif [[ "$command" =~ .*"node".* ]]; then npm install @@ -58,7 +47,7 @@ fi # Check if running on WSL if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then export PATH=$(echo "$PATH" | tr ' ' '\n' | grep -v " " | tr '\n' ':') - keploycmd="sudo -E keploy" + keploycmd="sudo -E env PATH=\"$PATH\" keploy" else keploycmd="sudo -E env PATH=\"$PATH\" keploy" fi @@ -75,15 +64,17 @@ cat_pid=$! (while true; do sleep 1; done) & dummy_pid=$! -# Execute the keploy command, redirecting output to the named pipe -sudo -E $keploycmd record > "$fifo" 2>&1 +# Function to Terminate the dummy process and the logging process +kill_all() { + kill $dummy_pid + rm -f "$fifo" +} + +# Execute the keploy command with the trap, redirecting output to the named pipe +( + trap 'kill_all' SIGINT SIGTERM EXIT + $keploycmd record > "$fifo" 2>&1 +) # Clean up: Wait for keploy command to finish -wait $! -touch ./log_file.txt - - -# Terminate the dummy process and the logging process -kill $dummy_pid -wait $cat_pid -rm "$fifo" +wait $! \ No newline at end of file diff --git a/scripts/bash/keploy_test_script.sh b/scripts/bash/keploy_test_script.sh index d824ef6..9e46da7 100755 --- a/scripts/bash/keploy_test_script.sh +++ b/scripts/bash/keploy_test_script.sh @@ -1,6 +1,5 @@ #!/bin/bash -i -# folderpath="$2" log_file_path="$1" # Create log file if it doesn't exist @@ -12,57 +11,59 @@ chmod 666 "$log_file_path" # Extract the command from keploy.yml command=$(awk -F: '/command:/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}' keploy.yml) -# echo "Command in yml file: $command" -# echo "Command in yml file: $command" if [[ "$command" =~ .*"go".* ]]; then - # echo "Go is present." go mod download go build -o application elif [[ "$command" =~ .*"python3".* ]]; then - # echo "Python 3 is present, Activating Virtual Environment 🐍" python3 -m venv venv source venv/bin/activate - # echo 'Installing requirements 📦' pip install -r requirements.txt - # echo 'Test Mode Starting 🎉' elif [[ "$command" =~ .*"python".* ]] ; then - # echo "Python is present, Activating Virtual Environment 🐍" python -m venv venv source venv/bin/activate - # echo 'Installing requirements 📦' pip install -r requirements.txt - # echo 'Test Mode Starting 🎉' elif [[ "$command" =~ .*"node".* ]]; then - # echo "Node is present." npm install elif [[ "$command" =~ .*"java".* ]] || [[ "$command" =~ .*"mvn".* ]]; then - # echo "Java is present." mvn clean install - fi # Check if running on WSL if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then - # echo "Running on WSL" - # Temporarily modify PATH export PATH=$(echo "$PATH" | tr ' ' '\n' | grep -v " " | tr '\n' ':') - keploycmd="sudo -E keploy" + keploycmd="sudo -E env PATH=\"$PATH\" keploy" else - # echo "Not running on WSL" - # Original PATH handling keploycmd="sudo -E env PATH=\"$PATH\" keploy" fi -# echo "Keploy command: $keploycmd" +# Create a named pipe +fifo=$(mktemp -u) +mkfifo "$fifo" + +# Background process to read from the named pipe and write to the log file +cat "$fifo" | tee -a "$log_file_path" & +cat_pid=$! + +# Dummy background process to keep the parent script running +(while true; do sleep 1; done) & +dummy_pid=$! + +# Function to Terminate the dummy process and the logging process +kill_all() { + kill $dummy_pid + rm -f "$fifo" +} -# cd "$folderpath" +# Execute the keploy command with the trap, redirecting output to the named pipe +( + trap 'kill_all' SIGINT SIGTERM EXIT + $keploycmd test > "$fifo" 2>&1 +) -# Execute the keploy command and append the output to the log file -sudo $keploycmd test | tee -a "$log_file_path" -touch ./log_file.txt - +# Clean up: Wait for keploy command to finish +wait $! diff --git a/scripts/zsh/keploy_record_script.sh b/scripts/zsh/keploy_record_script.sh new file mode 100755 index 0000000..231f214 --- /dev/null +++ b/scripts/zsh/keploy_record_script.sh @@ -0,0 +1,83 @@ +#!/bin/zsh -i + +log_file_path="$1" + +# Extract command from keploy.yml +keploy_config="keploy.yml" +if [[ ! -f "$keploy_config" ]]; then + echo "keploy.yml file not found in the current directory." + exit 1 +fi + +command=$(awk '/command:/ { $1=""; sub(/^ /, ""); print }' "$keploy_config") + +# Check if command is empty +if [[ -z "$command" ]]; then + echo "Command is not specified in keploy.yml." + exit 1 +fi + +# Create log file if it doesn't exist +touch "$log_file_path" +: > "$log_file_path" # Clear the log file + +# Set permissions of the log file +chmod 666 "$log_file_path" + +if [[ "$command" =~ .*"go".* ]]; then + go mod download + go build -o application + +elif [[ "$command" =~ .*"python3".* ]]; then + python3 -m venv venv + source venv/bin/activate + pip install -r requirements.txt + +elif [[ "$command" =~ .*"python".* ]] ; then + python -m venv venv + source venv/bin/activate + pip install -r requirements.txt + +elif [[ "$command" =~ .*"node".* ]]; then + npm install + +elif [[ "$command" =~ .*"java".* ]] || [[ "$command" =~ .*"mvn".* ]]; then + mvn clean install +fi + +# Create a named pipe +fifo=$(mktemp -u) +mkfifo "$fifo" + +# Disable job control messages +set +m + +# Background process to read from the named pipe and write to the log file +cat "$fifo" | tee -a "$log_file_path" & +cat_pid=$! + +# Dummy background process to keep the parent script running +(while true; do sleep 1; done) & +dummy_pid=$! + +kill_all() { + kill $dummy_pid 2>/dev/null + rm -f "$fifo" +} + +# Check if running on WSL +if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then + ( + trap 'kill_all' SIGINT SIGTERM EXIT + sudo -E env "PATH=$PATH" keploy record > "$fifo" 2>&1 + ) +else + keploycmd="sudo -E env PATH=\"$PATH\" keploy" + ( + trap 'kill_all' SIGINT SIGTERM EXIT + eval $keploycmd record > "$fifo" 2>&1 + ) +fi + +# Clean up: Wait for keploy command to finish +wait $! \ No newline at end of file diff --git a/scripts/zsh/keploy_record_script.zsh b/scripts/zsh/keploy_record_script.zsh deleted file mode 100755 index c452ae9..0000000 --- a/scripts/zsh/keploy_record_script.zsh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/zsh -i - -echo "Executing keploy_record_script.zsh" - -folderpath="$2" -log_file_path="$1" - -# Command is all of the CLI args after the 2nd arg -command="${@:3}" - -# Create log file if it doesn't exist -touch "$log_file_path" -> "$log_file_path" # Clear the log file - -# Set permissions of the log file -chmod 666 "$log_file_path" - -echo "Command: $command" - -if [[ "$command" =~ .*"go".* ]]; then - # echo "Go is present." - go mod download - go build -o application -fi - -# Adding sudo here worked -keploycmd="sudo -E env PATH=\"$PATH\" keploy" - -cd "$folderpath" - -# Create a named pipe -fifo=$(mktemp -u) -mkfifo "$fifo" - -# Background process to read from the named pipe and write to the log file -(cat "$fifo" | tee -a "$log_file_path") & -cat_pid=$! - -# Dummy background process to keep the parent script running -(while true; do sleep 1; done) & -dummy_pid=$! - -# Execute the keploy command, redirecting output to the named pipe -# echo $keploycmd record -c "$command" -sudo $keploycmd record -c "$command" > "$fifo" 2>&1 - -# Clean up: Wait for keploy command to finish -wait $! - -# Terminate the dummy process and the logging process -kill $dummy_pid -wait $cat_pid -rm "$fifo" diff --git a/scripts/zsh/keploy_test_script.sh b/scripts/zsh/keploy_test_script.sh new file mode 100755 index 0000000..07e21fa --- /dev/null +++ b/scripts/zsh/keploy_test_script.sh @@ -0,0 +1,73 @@ +#!/bin/zsh -i + +log_file_path="$1" + +# Create log file if it doesn't exist +touch "$log_file_path" +: > "$log_file_path" # Clear the log file + +# Set permissions of the log file +chmod 666 "$log_file_path" + +# Extract the command from keploy.yml +command=$(awk -F: '/command:/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}' keploy.yml) + +if [[ "$command" =~ .*"go".* ]]; then + go mod download + go build -o application + +elif [[ "$command" =~ .*"python3".* ]]; then + python3 -m venv venv + source venv/bin/activate + pip install -r requirements.txt + +elif [[ "$command" =~ .*"python".* ]] ; then + python -m venv venv + source venv/bin/activate + pip install -r requirements.txt + +elif [[ "$command" =~ .*"node".* ]]; then + npm install + +elif [[ "$command" =~ .*"java".* ]] || [[ "$command" =~ .*"mvn".* ]]; then + mvn clean install + +fi + +# Create a named pipe +fifo=$(mktemp -u) +mkfifo "$fifo" + +# Disable job control messages +set +m + +# Background process to read from the named pipe and write to the log file +cat "$fifo" | tee -a "$log_file_path" & +cat_pid=$! + +# Dummy background process to keep the parent script running +(while true; do sleep 1; done) & +dummy_pid=$! + +# Function to Terminate the dummy process and the logging process +kill_all() { + kill $dummy_pid 2>/dev/null + rm -f "$fifo" +} + +# Check if running on WSL +if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then + ( + trap 'kill_all' SIGINT SIGTERM EXIT + sudo -E env "PATH=$PATH" keploy test > "$fifo" 2>&1 + ) +else + keploycmd="sudo -E env PATH=\"$PATH\" keploy" + ( + trap 'kill_all' SIGINT SIGTERM EXIT + eval $keploycmd test > "$fifo" 2>&1 + ) +fi + +# Clean up: Wait for keploy command to finish +wait $! \ No newline at end of file diff --git a/scripts/zsh/keploy_test_script.zsh b/scripts/zsh/keploy_test_script.zsh deleted file mode 100755 index 73b5f6e..0000000 --- a/scripts/zsh/keploy_test_script.zsh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/zsh -i - -folderpath="$2" -log_file_path="$1" - -# Command is all of the CLI args after the 2nd arg -command="${@:3}" - -# Create log file if it doesn't exist -touch "$log_file_path" -> "$log_file_path" # Clear the log file - -# Set permissions of the log file -chmod 666 "$log_file_path" - -if [ "$command" = *go* ]; then -# echo "Go is present." - go mod download - go build -o application -fi - -keploycmd="sudo -E env PATH=\"$PATH\" keploy" - -cd "$folderpath" - -sudo $keploycmd test -c "$command" | tee -a "$log_file_path" diff --git a/sidebar/sidebar.js b/sidebar/sidebar.js index 83f52f6..8bb8cdd 100644 --- a/sidebar/sidebar.js +++ b/sidebar/sidebar.js @@ -35,11 +35,13 @@ const viewTestLogsButton = document.getElementById('viewTestLogsButton'); const viewRecordLogsButton = document.getElementById('viewRecordLogsButton'); const apiResponseElement = document.getElementById('apiResponseDisplay'); const backConfigbutton = document.getElementById('backConfig'); +let actionStarted = false; // const apiResponseDisplayLog = document.getElementById('apiResponseDisplay'); // const selectRecordFolderButton = document.getElementById('selectRecordFolderButton'); // const selectTestFolderButton = document.getElementById('selectTestFolderButton'); const navigateToConfigButton = document.getElementById('backtoHome'); const backtoHome = document.getElementById('backArrow'); +const selectedIconButton = document.getElementById('selectedIconNumber'); let FilePath = ""; //cleanup required @@ -129,12 +131,43 @@ if (rerunTestSuiteButton) { if(backConfigbutton){ backConfigbutton.addEventListener('click',async () =>{ - console.log("backconfig button clicked") - vscode.postMessage({ - type:"navigate", - value:"Config" - }) + if(selectedIconButton.textContent == '1'){ + console.log("selectedIconButton: " , selectedIconButton.textContent ); + console.log("backconfig button clicked") + + if(actionStarted == true){ + vscode.postMessage({ + type: "stopRecordingCommand", + value: `Stop Recording` + }); + + vscode.postMessage({ + type: "stopTestingCommand", + value: `Stop Testing` + }); + + vscode.postMessage({ + type:"navigate", + value:"IntegrationTest" + }) + + }else{ + vscode.postMessage({ + type:"navigate", + value:"Config" + }) + } + }else{ + + + vscode.postMessage({ + type:"navigate", + value:"IntegrationTest" + }) + } }) +}else{ + console.log("no back butoon"); } if (navigateToConfigButton) { @@ -202,6 +235,7 @@ if (viewRecordLogsButton) { if (startRecordingButton) { startRecordingButton.addEventListener('click', async () => { console.log("startRecordingButton clicked"); + actionStarted = true; resetUI(); // let commandValue = appCommand.value; @@ -224,6 +258,7 @@ if (startRecordingButton) { if (stopRecordingButton) { stopRecordingButton.addEventListener('click', async () => { console.log("stopRecordingButton clicked"); + actionStarted = false; vscode.postMessage({ type: "stopRecordingCommand", value: `Stop Recording` @@ -233,6 +268,7 @@ if (stopRecordingButton) { if (startTestButton) { startTestButton.addEventListener('click', async () => { console.log("startTestButton clicked"); + actionStarted = true; resetUI(); // const commandValue = appCommand.value; @@ -254,7 +290,7 @@ if (startTestButton) { if (stopTestButton) { stopTestButton.addEventListener('click', async () => { console.log("stopTestButton clicked"); - + actionStarted = false; vscode.postMessage({ type: "stopTestingCommand", value: `Stop Testing` @@ -297,6 +333,18 @@ if (initialiseConfigButton) { if (displayPreviousTestResults) { displayPreviousTestResults.addEventListener('click', async () => { console.log("displayPreviousTestResults clicked"); + console.log("stopping the recording and testing") + vscode.postMessage({ + type: "stopRecordingCommand", + value: `Stop Recording` + }); + + + vscode.postMessage({ + type: "stopTestingCommand", + value: `Stop Testing` + }); + vscode.postMessage({ type: "viewPreviousTestResults", value: `viewPreviousTestResults` @@ -308,6 +356,18 @@ if (displayPreviousTestResults) { if (openConfigButton) { openConfigButton.addEventListener('click', async () => { console.log("openConfigButton clicked"); + console.log("stopping the recording and testing") + + vscode.postMessage({ + type: "stopRecordingCommand", + value: `Stop Recording` + }); + + + vscode.postMessage({ + type: "stopTestingCommand", + value: `Stop Testing` + }); vscode.postMessage({ type: "openConfigFile", value: `/keploy.yml` @@ -324,7 +384,6 @@ if (setupConfigButton) { }); } - document.addEventListener('ciCdStepClick', function (e) { // Logic to handle CI/CD setup click event if (e.detail.step === 'ci-cd-setup') { @@ -383,6 +442,9 @@ window.addEventListener('message', event => { } else if (message.type === 'testcaserecorded') { console.log("message.textContent", message.textContent); + if(stopRecordingButton){ + stopRecordingButton.click(); + } recordStatus.style.display = "block"; recordedTestCasesDiv.style.display = "grid"; diff --git a/src/OneClickInstall.ts b/src/OneClickInstall.ts index 7b1b25f..c6b47d8 100644 --- a/src/OneClickInstall.ts +++ b/src/OneClickInstall.ts @@ -5,7 +5,7 @@ export default function executeKeployOneClickCommand(): void { const checkKeployExistsCommand = `keploy`; // The command to download and install Keploy - const installationCommand = `curl --silent -L https://keploy.io/install.sh -o /tmp/install.sh && chmod +x /tmp/install.sh && bash /tmp/install.sh -noRoot`; + const installationCommand = `curl --silent -L https://keploy.io/install.sh -o /tmp/install.sh && chmod +x /tmp/install.sh && /tmp/install.sh -noRoot`; exec(checkKeployExistsCommand, (error, stdout, stderr) => { if (error) { // Execute the installation command diff --git a/src/Record.ts b/src/Record.ts index b1a32d4..3c1c786 100644 --- a/src/Record.ts +++ b/src/Record.ts @@ -1,5 +1,5 @@ import * as vscode from 'vscode'; -import { readFileSync , appendFile} from 'fs'; +import { readFileSync, appendFile } from 'fs'; import * as child_process from 'child_process'; import * as os from 'os'; import * as Sentry from './sentryInit'; @@ -7,13 +7,13 @@ import * as Sentry from './sentryInit'; function extractTestSetName(logContent: string) { // Define the regular expression pattern to find the test set name const regex = /Keploy has captured test cases for the user's application\.\s*{"path": ".*\/(test-set-\d+)\/tests"/; - + // Execute the regular expression on the log content const match = regex.exec(logContent); - + // Check if a match was found and return the test set name, otherwise return null return match ? match[1] : null; - } +} export async function displayRecordedTestCases(logfilePath: string, webview: any): Promise { console.log('Displaying Recorded test cases'); let logData; @@ -23,39 +23,40 @@ export async function displayRecordedTestCases(logfilePath: string, webview: any } catch (error) { appendFile(logfilePath, "", function (err) { - if (err) { console.log("err here" + err); } + if (err) { console.log("err here" + err); } }); logData = readFileSync(logfilePath, 'utf8'); } const testSetName = extractTestSetName(logData); - // Split the log data into lines - const logLines = logData.split('\n'); - // Filter out the lines containing the desired information - const capturedTestLines = logLines.filter(line => line.includes('🟠 Keploy has captured test cases')); - // Display the captured test cases in your frontend - if (capturedTestLines.length === 0) { - webview.postMessage({ - type: 'testcaserecorded', - value: 'Test Case has been recorded', - textContent: "No test cases captured. Please try again.", - noTestCases: true + // Split the log data into lines + const logLines = logData.split('\n'); + // Filter out the lines containing the desired information + const capturedTestLines = logLines.filter(line => line.includes('🟠 Keploy has captured test cases')); + // Display the captured test cases in your frontend + if (capturedTestLines.length === 0) { + webview.postMessage({ + type: 'testcaserecorded', + value: 'Test Case has been recorded', + textContent: "No test cases captured. Please try again.", + noTestCases: true + }); + return; + } + capturedTestLines.forEach(testLine => { + const testCaseInfo = JSON.parse(testLine.substring(testLine.indexOf('{'))); + const textContent = `"${testCaseInfo['testcase name']}"`; + const path = testCaseInfo.path + '/' + testCaseInfo['testcase name'] + '.yaml'; + webview.postMessage({ + type: 'testcaserecorded', + value: 'Test Case has been recorded', + textContent: textContent, + path: path, + testSetName: testSetName + }); }); - return; } - capturedTestLines.forEach(testLine => { - const testCaseInfo = JSON.parse(testLine.substring(testLine.indexOf('{'))); - const textContent = `"${testCaseInfo['testcase name']}"`; - const path = testCaseInfo.path + '/' + testCaseInfo['testcase name'] + '.yaml'; - webview.postMessage({ - type: 'testcaserecorded', - value: 'Test Case has been recorded', - textContent: textContent, - path: path, - testSetName: testSetName - }); - });} - catch(error){ + catch (error) { console.log(error); webview.postMessage({ type: 'testcaserecorded', @@ -69,30 +70,41 @@ export async function displayRecordedTestCases(logfilePath: string, webview: any } } -export async function stopRecording(){ - try{ - vscode.window.activeTerminal?.sendText('\x03', true); - //set timeout for 5 seconds - setTimeout(() => { - vscode.window.activeTerminal?.dispose(); - }, 5000); - - return; - } - catch(error){ - Sentry?.default?.captureException(error); - console.log(error); - throw error; - } +export async function stopRecording() { + try { + let pid: number | undefined; + await Promise.all(vscode.window.terminals.map(async (terminal) => { + if (terminal.name === 'Keploy Terminal') { + pid = await terminal.processId; + terminal.sendText('\x03', true); + } + })); + setTimeout(async () => { + await Promise.all(vscode.window.terminals.map(async (terminal) => { + if (terminal.name === 'Keploy Terminal') { + const currentPid = await terminal.processId; + if (pid && currentPid && pid === currentPid) { + vscode.window.activeTerminal?.dispose(); + } + } + })); + }, 5000); + return; + } + catch (error) { + Sentry?.default?.captureException(error); + console.log(error); + throw error; + } } -export async function startRecording( wslscriptPath: string, wsllogfilePath: string, bashScriptPath: string, zshScriptPath : string , logfilePath: string, webview: any): Promise { +export async function startRecording(wslscriptPath: string, wsllogfilePath: string, bashScriptPath: string, zshScriptPath: string, logfilePath: string, webview: any): Promise { try { return new Promise((resolve, reject) => { try { let terminalPath: string; - let currentShell =''; + let currentShell = ''; if (process.platform === 'win32') { terminalPath = 'wsl.exe'; @@ -108,7 +120,7 @@ export async function startRecording( wslscriptPath: string, wsllogfilePath: str console.log(`Current default shell: ${currentShell}`); //uncomment the below line if you want to use the default shell (for zsh test) - // terminalPath = currentShell; + terminalPath = currentShell; } console.log(`Terminal path: ${terminalPath}`); const terminal = vscode.window.createTerminal({ @@ -124,7 +136,7 @@ export async function startRecording( wslscriptPath: string, wsllogfilePath: str if (currentShell.includes('zsh')) { // Use a Zsh-specific script if needed //replace bashScriptPath with zshScriptPath for zsh - recordCmd = `"${bashScriptPath}" "${logfilePath}" `; + recordCmd = `"${zshScriptPath}" "${logfilePath}" ;exit 0`; } else { // Default to Bash script recordCmd = `"${bashScriptPath}" "${logfilePath}" ;exit 0`; diff --git a/src/SidebarProvider.ts b/src/SidebarProvider.ts index 9602f13..190d568 100644 --- a/src/SidebarProvider.ts +++ b/src/SidebarProvider.ts @@ -6,9 +6,41 @@ import { startRecording, stopRecording } from "./Record"; import { startTesting, stopTesting, displayTestCases, displayPreviousTestResults } from "./Test"; import { existsSync } from "fs"; import { handleInitializeKeployConfigFile, handleOpenKeployConfigFile } from "./Config"; -import SignIn from "./SignIn"; import SignInWithGitHub from "./SignIn"; import oneClickInstall from './OneClickInstall'; +import * as path from 'path'; +import * as fs from 'fs'; +import { workspace } from 'vscode'; + +function precheckFunction(): Promise { + const workspacePath = workspace.workspaceFolders ? workspace.workspaceFolders[0].uri.fsPath : ''; + + return new Promise((resolve, reject) => { + try { + if (!workspacePath) { + return reject('Workspace path not found.'); + } + + const pomFilePath = path.join(workspacePath, 'pom.xml'); + const goModFilePath = path.join(workspacePath, 'go.mod'); + const packageJsonFilePath = path.join(workspacePath, 'package.json'); + + let projectType: string = 'python'; // Default project type is python + if (fs.existsSync(pomFilePath)) { + projectType = 'java'; + } else if (fs.existsSync(goModFilePath)) { + projectType = 'go'; + } else if (fs.existsSync(packageJsonFilePath)) { + projectType = 'javascript'; + } + resolve(projectType); + } catch (error) { + reject(`Error checking project files: ${(error as Error).message}`); + } + }); +} + + const recordOptions: vscode.OpenDialogOptions = { canSelectFolders: true, @@ -30,7 +62,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { _doc?: vscode.TextDocument; _interval?: NodeJS.Timeout; // Store the interval reference - constructor(private readonly _extensionUri: vscode.Uri , private readonly _context: vscode.ExtensionContext) { + constructor(private readonly _extensionUri: vscode.Uri, private readonly _context: vscode.ExtensionContext) { } public postMessage(type: any, value: any) { @@ -58,7 +90,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { const apiResponse = this._context.globalState.get('apiResponse') || "No response"; const signedIn = this._context.globalState.get('SignedOthers') || "false"; - console.log("signedIn others value" , signedIn); + console.log("signedIn others value", signedIn); let scriptUri = webviewView.webview.asWebviewUri( @@ -70,13 +102,13 @@ export class SidebarProvider implements vscode.WebviewViewProvider { webviewView.webview.html = this._getHtmlForWebview(webviewView.webview, compiledCSSUri, scriptUri); - - this._sendApiResponseToWebview(apiResponse,signedIn); + + this._sendApiResponseToWebview(apiResponse, signedIn); // Start sending the updated `apiResponse` to the webview every 3 seconds this._startApiResponseUpdates(); -; + ; @@ -141,7 +173,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { console.log('Start Recording button clicked'); const bashScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "bash", "keploy_record_script.sh"); - const zshScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "zsh", "keploy_record_script.zsh"); + const zshScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "zsh", "keploy_record_script.sh"); const logfilePath = vscode.Uri.joinPath(this._extensionUri, "scripts", "logs", "record_mode.log"); let wslscriptPath = bashScript.fsPath; let wsllogPath = logfilePath.fsPath; @@ -190,7 +222,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { try { console.log('Start Testing button clicked'); const bashScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "bash", "keploy_test_script.sh"); - const zshScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "zsh", "keploy_test_script.zsh"); + const zshScript = vscode.Uri.joinPath(this._extensionUri, "scripts", "zsh", "keploy_test_script.sh"); const logfilePath = vscode.Uri.joinPath(this._extensionUri, "scripts", "logs", "test_mode.log"); let wslscriptPath = bashScript.fsPath; let wsllogPath = logfilePath.fsPath; @@ -305,10 +337,18 @@ export class SidebarProvider implements vscode.WebviewViewProvider { break; } - case "openLink":{ - if (!data.url) { - return; + case "signinwithstate": { + try { + await vscode.commands.executeCommand('keploy.SignInWithOthers'); + } catch (error) { + console.error('Error while signing in:', error); + vscode.window.showErrorMessage('Failed to sign in. Please try again.'); } + break; + } + + case "openLink": { + try { console.log("Opening external link: " + data.url); vscode.env.openExternal(vscode.Uri.parse(data.url)); @@ -419,30 +459,33 @@ export class SidebarProvider implements vscode.WebviewViewProvider { } break; } - // case "signIn": { - // if (!data.value) { - // return; - // } - // try { - // console.log('Signing in...'); - // const response: any = await SignIn(); - // console.log('Response from SignIn', response); - // } catch (error) { - // this._view?.webview.postMessage({ type: 'error', value: `Failed to sign in ${error}` }); - // } - // break; - // } + case "detectProjectType": { + try { + console.log('Detecting Project Type...'); + precheckFunction() + .then(projectType => { + console.log("Project type detected:", projectType); + this._view?.webview.postMessage({ type: 'projectDetected', projectType: projectType }); + }) + .catch(error => { + console.error("Error detecting project type:", error); + }); + } catch (error) { + console.log('Error in detecting project type', error); + } + break; + } } }); } - private _startApiResponseUpdates() { + private _startApiResponseUpdates() { this._interval = setInterval(() => { const apiResponse = this._context.globalState.get('apiResponse') || "No response"; const signedIn = this._context.globalState.get('SignedOthers') || "false"; - this._sendApiResponseToWebview(apiResponse , signedIn); + this._sendApiResponseToWebview(apiResponse, signedIn); }, 3000); // 3 seconds } @@ -454,7 +497,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { } // Helper function to send `apiResponse` to the webview - private _sendApiResponseToWebview(apiResponse: string , signedIn:string) { + private _sendApiResponseToWebview(apiResponse: string, signedIn: string) { if (this._view) { // console.log("api response withing 3 seconds" , apiResponse); this._view.webview.postMessage({ diff --git a/src/Test.ts b/src/Test.ts index 9240a1d..730ee2a 100644 --- a/src/Test.ts +++ b/src/Test.ts @@ -322,7 +322,7 @@ export async function startTesting(wslscriptPath: string, wsllogfilePath: string console.log(`Current default shell: ${currentShell}`); //uncomment the below line if you want to use the default shell (for zsh test) - // terminalPath = currentShell; + terminalPath = currentShell; } console.log(`Terminal path: ${terminalPath}`); const terminal = vscode.window.createTerminal({ @@ -341,7 +341,7 @@ export async function startTesting(wslscriptPath: string, wsllogfilePath: string // Use a Zsh-specific script if needed console.log('Using Zsh script'); //replace bashScriptPath with zshScriptPath for zsh - testCmd = `"${bashScriptPath}" "${logfilePath}"; exit 0`; + testCmd = `"${zshScriptPath}" "${logfilePath}"; exit 0`; } else { // Default to Bash script testCmd = `"${bashScriptPath}" "${logfilePath}" ; exit 0`; @@ -378,8 +378,23 @@ export async function startTesting(wslscriptPath: string, wsllogfilePath: string export async function stopTesting(): Promise { try { - vscode.window.activeTerminal?.sendText('\x03', true); - vscode.window.activeTerminal?.dispose(); + let pid: number | undefined; + await Promise.all(vscode.window.terminals.map(async (terminal) => { + if (terminal.name === 'Keploy Terminal') { + pid = await terminal.processId; + terminal.sendText('\x03', true); + } + })); + setTimeout(async () => { + await Promise.all(vscode.window.terminals.map(async (terminal) => { + if (terminal.name === 'Keploy Terminal') { + const currentPid = await terminal.processId; + if (pid && currentPid && pid === currentPid) { + vscode.window.activeTerminal?.dispose(); + } + } + })); + }, 5000); return ; } catch (error) { diff --git a/src/extension.test.ts b/src/extension.test.ts index 4ca0ab4..a02f59d 100644 --- a/src/extension.test.ts +++ b/src/extension.test.ts @@ -1,15 +1,134 @@ -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it +import assert = require('assert'); import * as vscode from 'vscode'; -// import * as myExtension from '../../extension'; +import sinon from 'sinon'; +import { SidebarProvider } from './SidebarProvider'; + +const createMockExtensionContext = (): vscode.ExtensionContext => ({ + subscriptions: [], + extensionPath: '/mock/path', + extensionUri: vscode.Uri.parse('file:///mock/path'), + globalState: { + get: sinon.stub(), + update: sinon.stub(), + }, + workspaceState: { + get: sinon.stub(), + update: sinon.stub(), + }, + asAbsolutePath: sinon.stub().returns('/mock/absolute/path'), + storagePath: '/mock/storage/path', + globalStoragePath: '/mock/global/storage/path', + logPath: '/mock/log/path', +} as unknown as vscode.ExtensionContext); + +// Mock classes for FakeWebview and FakeWebviewView to simulate behavior +class FakeWebview implements vscode.Webview { + public html = ''; + public options = {}; + public cspSource = ''; + public onDidReceiveMessage = sinon.spy(); + public asWebviewUri(uri: vscode.Uri): vscode.Uri { + return uri; + } + public postMessage(message: any): Thenable { + this.onDidReceiveMessage(message); // Trigger the spy with the message + return Promise.resolve(true); + } +} + +class FakeWebviewView implements vscode.WebviewView { + constructor(public webview: vscode.Webview) {} + viewType: any; + badge?: vscode.ViewBadge | undefined; + show(preserveFocus?: boolean): void { + throw new Error('Method not implemented.'); + } + public title = ''; + public description = ''; + public onDidDispose = sinon.spy(); + public onDidChangeVisibility = sinon.spy(); + public onDidChangeViewState = sinon.spy(); + public visible = true; + public dispose() {} +} + +suite('Sidebar Test Suite', () => { + + let mockContext: vscode.ExtensionContext; + let extensionUri: vscode.Uri; + + setup(() => { + mockContext = createMockExtensionContext(); + extensionUri = vscode.Uri.parse('http://www.example.com/some/path'); + }); + + test('Sidebar Provider Registration', () => { + const sidebarProvider = new SidebarProvider(extensionUri, mockContext); + + const registerWebviewViewProviderSpy = sinon.spy(vscode.window, 'registerWebviewViewProvider'); + + vscode.window.registerWebviewViewProvider('Test-Sidebar', sidebarProvider); + + assert(registerWebviewViewProviderSpy.calledOnce); + assert( + registerWebviewViewProviderSpy.calledWith( + 'Test-Sidebar', + sinon.match.instanceOf(SidebarProvider) + ) + ); -suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); + registerWebviewViewProviderSpy.restore(); + }); + - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); + test('Sidebar Content Rendering', async () => { + const sidebarProvider = new SidebarProvider(extensionUri, mockContext); + const webview = new FakeWebview() as vscode.Webview; + const view = new FakeWebviewView(webview) as vscode.WebviewView; + + await sidebarProvider.resolveWebviewView(view); + + assert.strictEqual( + webview.html.includes(''), + true + ); + // Clean up + + }); + + test('Sidebar Comprehensive Functionality', async () => { + const sidebarProvider = new SidebarProvider(extensionUri, mockContext); + const webview = new FakeWebview() as vscode.Webview; + const view = new FakeWebviewView(webview) as unknown as vscode.WebviewView; + + await sidebarProvider.resolveWebviewView(view); + + // Simulate the creation of the webview panel + assert.strictEqual(webview.html.includes(''), true, 'DOCTYPE is missing'); + assert.strictEqual(webview.html.includes(''), true, 'HTML tag is missing'); + assert.strictEqual(webview.html.includes(''), true, 'Head tag is missing'); + assert.strictEqual(webview.html.includes(''), true, 'UTF-8 charset meta tag is missing'); + assert.strictEqual(webview.html.includes(' - let showSettings = false; + import { onMount } from "svelte"; + +let showSettings = false; const vscode = acquireVsCodeApi(); + let userSignedIn = false; - function handleTestSelection(testType) { + function navigateToKeploy() { vscode.postMessage({ + type: "signinwithstate", + }); + } + + + onMount(() => { + // Add event listener for messages from the VSCode extension + window.addEventListener("message", (event) => { + const message = event.data; + + if(message.type === "signedIn"){ + const signedInResponse = message.value; + if(signedInResponse == "false"){ + userSignedIn = false; + // console.log("Progress Bar is not Visible") + }else{ + // console.log("Progress Bar is Visible") + userSignedIn = true; + } + } + }); + }); + + function handleTestSelection(testType) { + + if(testType != "Unit Testing"){ + if(userSignedIn){ + vscode.postMessage({ type: "navigate", - value: testType === "Unit Testing" ? "UtgDocs" : "IntegrationTest", + value: "IntegrationTest", }); + }else{ + navigateToKeploy(); + } + }else{ + vscode.postMessage({ + type: "navigate", + value: "UtgDocs" + }); + } + + } diff --git a/webviews/components/IntegrationTest.svelte b/webviews/components/IntegrationTest.svelte index e31c90e..df8dbd9 100644 --- a/webviews/components/IntegrationTest.svelte +++ b/webviews/components/IntegrationTest.svelte @@ -9,12 +9,34 @@ let initialiseConfigButton; const vscode = acquireVsCodeApi(); + let isPrecheckDone = false; + let projectType = ""; + function handleProjectTypeDetection(event) { + if (event.data && event.data.type === 'projectDetected') { + projectType = event.data.projectType; + console.log("Project type detected:", projectType); + isPrecheckDone = true; + } + } + onMount(() => { + vscode.postMessage({ + type: 'detectProjectType', + }); vscode.postMessage({ type: "openConfigFile", value: `/keploy.yml`, }); - + if (!window.hasProjectTypeListener) { + window.addEventListener('message', handleProjectTypeDetection); + window.hasProjectTypeListener = true; // Mark that the listener has been added + } + return () => { + if (window.hasProjectTypeListener) { + window.removeEventListener('message', handleProjectTypeDetection); + window.hasProjectTypeListener = false; + } + }; }); @@ -74,27 +96,39 @@ id="configCommand" />
-
-
- -

go run main.go

-
-
- -

npm run start

-
-
-
-
- -

Python3 main.py

+
+ {#if projectType === 'go'} +
+ +

go run main.go

+
+ {/if} + + {#if projectType === 'javascript'} +
+ +

npm run start

+
+ {/if}
-
- -

java xyz.jar

+ +
+ {#if projectType === 'python'} +
+ +

Python3 main.py

+
+ {/if} + + {#if projectType === 'java'} +
+ +

java xyz.jar

+
+ {/if}
-
+
+ +