Skip to content

Add unit tests #1669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

anandgupta42
Copy link
Contributor

@anandgupta42 anandgupta42 commented May 20, 2025

Summary

  • add more Altimate and DBTTerminal tests
  • expand utils test coverage and fix tmp path

Testing

  • npm test --silent -- --coverage

Important

Add extensive unit tests for AltimateRequest, DBTTerminal, CommandProcessExecution, and utility functions, and update jest.config.js for module mapping.

  • Tests:
    • Add tests for AltimateRequest in altimate.test.ts to cover credential messages, preview features, stream handling, and S3 uploads.
    • Add tests for DBTTerminal in dbtTerminal.test.ts to cover logging, telemetry, and terminal management.
    • Add tests for CommandProcessExecution in commandProcessExecution.test.ts to cover command execution, environment variables, and output streaming.
    • Add tests for utility functions in utils.test.ts to cover stream processing, object comparison, and configuration handling.
  • Configuration:
    • Update jest.config.js to map @extension to <rootDir>/src/modules.ts.

This description was created by Ellipsis for 8f98a71. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Tests

    • Added comprehensive new test cases to improve coverage for credential validation, streaming data handling, file upload, HTTP error responses, command output formatting, terminal logging, utility functions, and custom exceptions.
    • Enhanced test setup and cleanup for terminal-related tests to improve reliability and suppress unnecessary console output.
  • Chores

    • Updated Jest configuration to support a new module alias for improved module resolution in tests.

Copy link
Contributor

coderabbitai bot commented May 20, 2025

Walkthrough

This update adds a new module alias to the Jest configuration and introduces or extends several Jest test suites to improve coverage for modules handling credentials, streaming, file uploads, command execution, terminal output, and utility functions. No changes were made to exported or public entity declarations.

Changes

File(s) Change Summary
jest.config.js Added a new module alias "^@extension$" mapped to "<rootDir>/src/modules.ts" in moduleNameMapper for Jest module resolution.
src/test/suite/altimate.test.ts Extended the AltimateRequest test suite with new cases for credential message generation, preview feature handling, stream reading, file upload, and detailed HTTP error response handling.
src/test/suite/commandProcessExecution.test.ts Added test cases for output streaming to the terminal and text formatting in the CommandProcessExecution suite.
src/test/suite/dbtTerminal.test.ts Enhanced the DBTTerminal test suite by mocking console methods, restoring mocks after each test, and adding new cases for logging, terminal output, and error handling with string errors.
src/test/suite/utils.test.ts Introduced a comprehensive new test suite for utility functions and custom exceptions, covering stream processing, deep equality, string size, identifier quoting, column name handling, workspace path retrieval, YAML model selection, type guards, column test extraction, file system interactions, watcher event handling, custom exceptions, filtering, array equality, debouncing, error message extension, ANSI code stripping, date formatting, and code block detection.

Sequence Diagram(s)

sequenceDiagram
  participant TestSuite as Jest Test Suite
  participant AltimateRequest as AltimateRequest
  participant CommandProcessExecution as CommandProcessExecution
  participant DBTTerminal as DBTTerminal
  participant Utils as Utility Functions

  TestSuite->>AltimateRequest: Test credential message, preview features, stream reading, file upload, error handling
  TestSuite->>CommandProcessExecution: Test output streaming and text formatting
  TestSuite->>DBTTerminal: Test logging, terminal output, error handling
  TestSuite->>Utils: Test utility functions, custom exceptions, and helpers
Loading

Possibly related PRs

  • #1666: Extends the test suite for AltimateRequest, overlapping with credential message handling and preview feature gating.
  • #1527: Adds a new method and features to AltimateRequest; both PRs modify or extend this class and its tests.
  • #1533: Introduces the initial Jest testing framework setup; this PR builds on that infrastructure.

Suggested reviewers

  • mdesmet
  • saravmajestic

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn config production Use --omit=dev instead.
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-05-20T05_53_21_330Z-debug-0.log

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@anandgupta42 anandgupta42 requested a review from Copilot May 20, 2025 05:54
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");

Check failure

Code scanning / CodeQL

Insecure temporary file High test

Insecure creation of file in
the os temp dir
.
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");

Check failure

Code scanning / CodeQL

Insecure temporary file High test

Insecure creation of file in
the os temp dir
.

Copilot Autofix

AI 16 days ago

To fix the issue, we will replace the insecure temporary file creation logic with the tmp library, which securely creates temporary files. The tmp library ensures that the file is unique and inaccessible to other users. Specifically, we will:

  1. Import the tmp library.
  2. Replace the path.join(os.tmpdir(), "up.txt") logic with tmp.fileSync() to securely create a temporary file.
  3. Use the name property of the returned object from tmp.fileSync() to get the file path.
  4. Ensure the temporary file is removed after use by calling the removeCallback method provided by tmp.

Suggested changeset 2
src/test/suite/altimate.test.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/test/suite/altimate.test.ts b/src/test/suite/altimate.test.ts
--- a/src/test/suite/altimate.test.ts
+++ b/src/test/suite/altimate.test.ts
@@ -14,4 +14,4 @@
 import * as fs from "fs";
-import * as path from "path";
-import * as os from "os";
+import * as tmp from "tmp";
+// Removed unused imports: path, os
 import { AltimateRequest } from "../../altimate";
@@ -233,9 +233,9 @@
       .mockReturnValueOnce("instance");
-    const file = path.join(os.tmpdir(), "up.txt");
-    fs.writeFileSync(file, "x");
+    const tmpFile = tmp.fileSync();
+    fs.writeFileSync(tmpFile.name, "x");
     const mockRes = new Response("ok", { status: 200, statusText: "OK" });
     fetchMock.mockResolvedValue(mockRes);
-    const res = await request.uploadToS3("http://s3", {}, file);
+    const res = await request.uploadToS3("http://s3", {}, tmpFile.name);
     expect(res.status).toBe(200);
-    fs.rmSync(file);
+    tmpFile.removeCallback();
   });
@@ -246,10 +246,10 @@
       .mockReturnValueOnce("instance");
-    const file = path.join(os.tmpdir(), "up.txt");
-    fs.writeFileSync(file, "x");
+    const tmpFile = tmp.fileSync();
+    fs.writeFileSync(tmpFile.name, "x");
     const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
     fetchMock.mockResolvedValue(mockRes);
-    await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
+    await expect(request.uploadToS3("http://s3", {}, tmpFile.name)).rejects.toThrow(
       "Failed to upload data",
     );
-    fs.rmSync(file);
+    tmpFile.removeCallback();
   });
EOF
@@ -14,4 +14,4 @@
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import * as tmp from "tmp";
// Removed unused imports: path, os
import { AltimateRequest } from "../../altimate";
@@ -233,9 +233,9 @@
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const tmpFile = tmp.fileSync();
fs.writeFileSync(tmpFile.name, "x");
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
const res = await request.uploadToS3("http://s3", {}, tmpFile.name);
expect(res.status).toBe(200);
fs.rmSync(file);
tmpFile.removeCallback();
});
@@ -246,10 +246,10 @@
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const tmpFile = tmp.fileSync();
fs.writeFileSync(tmpFile.name, "x");
const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
fetchMock.mockResolvedValue(mockRes);
await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
await expect(request.uploadToS3("http://s3", {}, tmpFile.name)).rejects.toThrow(
"Failed to upload data",
);
fs.rmSync(file);
tmpFile.removeCallback();
});
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -1401,3 +1401,4 @@
     "zeromq": "^6.1.0",
-    "zod-to-json-schema": "^3.24.3"
+    "zod-to-json-schema": "^3.24.3",
+    "tmp": "^0.2.3"
   },
EOF
@@ -1401,3 +1401,4 @@
"zeromq": "^6.1.0",
"zod-to-json-schema": "^3.24.3"
"zod-to-json-schema": "^3.24.3",
"tmp": "^0.2.3"
},
This fix introduces these dependencies
Package Version Security advisories
tmp (npm) 0.2.3 None
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Changes requested ❌

Reviewed everything up to 8f98a71 in 2 minutes and 38 seconds. Click for details.
  • Reviewed 525 lines of code in 5 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. jest.config.js:18
  • Draft comment:
    Verify that the '@extension' alias uses a clear, non‐abbreviated name consistent with project conventions.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
2. src/test/suite/utils.test.ts:225
  • Draft comment:
    Monkey-patching global.Date can be brittle; consider using a dedicated date-mocking library and ensure global Date is reliably restored.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% While the suggestion to use a dedicated date-mocking library is technically valid, the current implementation is actually quite reasonable. It properly saves and restores the original Date, is scoped to a single test, and is clear in its intent. The current approach is not causing any actual problems and the suggested change would be more of an opinion than a necessary fix. The comment does raise a valid point about brittleness - monkey-patching globals can be dangerous. The test could potentially interfere with other tests if the restore fails. However, the current implementation follows good practices by properly restoring the global state and keeping the change isolated. The suggested alternative wouldn't necessarily be better, just different. This comment is more of a style preference than a clear issue that needs fixing. The current implementation is reasonable and follows good practices.

Workflow ID: wflow_3TwxdJxenWQQeBzv

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.


it("readStreamToBlob collects stream data", async () => {
const stream = Readable.from(["a", "b"]);
const blob: any = await (request as any).readStreamToBlob(stream as any);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid casting to any for readStreamToBlob; consider adding an explicit return type in its definition to ease refactoring.

Suggested change
const blob: any = await (request as any).readStreamToBlob(stream as any);
const blob: Blob = await (request as any).readStreamToBlob(stream as any);

This comment was generated because it violated a code review rule: mrule_lKhrJQCKUgYAxwcS.

selection: { active: { line: 2, character: 5 } },
};
expect(getCurrentlySelectedModelNameInYamlConfig()).toBe("model_b");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After setting window.activeTextEditor in the YAML config test, consider cleaning it up to avoid state leakage across tests.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR significantly expands the unit test coverage by introducing comprehensive tests for utility functions, AltimateRequest, DBTTerminal, and CommandProcessExecution. Key changes include:

  • Adding tests for stream processing, deep equality, file handling, and configuration utilities.
  • Enhancing DBTTerminal tests with extended logging and telemetry verifications.
  • Incorporating detailed AltimateRequest tests for credential messaging, preview feature handling, stream-to-blob conversion, file uploads, and error handling.

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

File Description
src/test/suite/utils.test.ts Tests for various utility functions related to streams, objects, and configuration.
src/test/suite/dbtTerminal.test.ts Expanded tests covering terminal logging methods and telemetry.
src/test/suite/commandProcessExecution.test.ts New tests for command output streaming and newline formatting.
src/test/suite/altimate.test.ts Comprehensive tests for AltimateRequest including credential messages, preview features, and S3 uploads.

mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
expect(request.getCredentialsMessage()).toBeUndefined();
Copy link
Preview

Copilot AI May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a comment to clarify why undefined is the expected return value when both credentials are provided, so future maintainers understand this business logic.

Copilot uses AI. Check for mistakes.

"",
[],
);
expect(execution.formatText("a\n\nb")).toBe("a\r\n\rb");
Copy link
Preview

Copilot AI May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document the expected transformation logic of the formatText function for newline characters, ensuring its behavior is clear in the test.

Copilot uses AI. Check for mistakes.

Comment on lines +236 to +240
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
fs.rmSync(file);
Copy link
Preview

Copilot AI May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider encapsulating temporary file creation and removal within a try/finally block to ensure cleanup even if an assertion fails.

Suggested change
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
fs.rmSync(file);
try {
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
} finally {
fs.rmSync(file);
}

Copilot uses AI. Check for mistakes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/test/suite/utils.test.ts (4)

45-67: Consider adding error handling tests for streams.

While the current tests verify successful processing of both Node.js and Web streams, there's no testing for error cases. For complete coverage, add a test that verifies error propagation when a stream emits an error.

it("processStreamResponse propagates errors from Node streams", async () => {
  const stream = new Readable({
    read() {
      this.emit('error', new Error('Test error'));
    }
  });
  const cb = jest.fn();
  await expect(processStreamResponse(stream, cb)).rejects.toThrow('Test error');
  expect(cb).not.toHaveBeenCalled();
});

69-75: Expand deepEqual tests with more edge cases.

The current tests cover basic nested objects, but consider adding tests for:

  1. Arrays with same elements in different order
  2. Objects with null/undefined values
  3. Comparison with non-object values
it("deepEqual handles edge cases correctly", () => {
  // Arrays with different order
  expect(deepEqual([1, 2], [2, 1])).toBe(false);
  
  // Objects with null/undefined
  expect(deepEqual({a: null}, {a: null})).toBe(true);
  expect(deepEqual({a: undefined}, {a: null})).toBe(false);
  
  // Primitive comparisons
  expect(deepEqual(null, null)).toBe(true);
  expect(deepEqual(undefined, undefined)).toBe(true);
  expect(deepEqual(null, undefined)).toBe(false);
});

103-107: Consider testing the primary path for getFirstWorkspacePath.

While the test covers the fallback behavior when no workspace is present, it would be valuable to also test the primary path where a workspace is available.

it("getFirstWorkspacePath returns first workspace path when available", () => {
  (workspace.workspaceFolders as any) = [
    { uri: { fsPath: "/workspace/path" } }
  ];
  expect(getFirstWorkspacePath()).toBe("/workspace/path");
});

109-123: Add tests for error handling in YAML parsing.

The getCurrentlySelectedModelNameInYamlConfig test only covers the happy path. Consider adding tests for error conditions like invalid YAML, cursor position outside any model, or when no models are defined.

it("getCurrentlySelectedModelNameInYamlConfig handles invalid YAML", () => {
  const invalidYaml = `models:\n  - name: model_a\n  invalid: - name:`;
  const document = {
    languageId: "yaml",
    getText: () => invalidYaml,
    offsetAt: jest.fn()
  } as any;
  (window as any).activeTextEditor = {
    document,
    selection: { active: { line: 2, character: 5 } }
  };
  
  // Should return empty string on parsing error
  expect(getCurrentlySelectedModelNameInYamlConfig()).toBe("");
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35df42f and 8f98a71.

📒 Files selected for processing (5)
  • jest.config.js (1 hunks)
  • src/test/suite/altimate.test.ts (2 hunks)
  • src/test/suite/commandProcessExecution.test.ts (1 hunks)
  • src/test/suite/dbtTerminal.test.ts (3 hunks)
  • src/test/suite/utils.test.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/test/suite/utils.test.ts (3)
src/utils.ts (18)
  • processStreamResponse (138-172)
  • deepEqual (174-202)
  • getStringSizeInMb (382-398)
  • isQuotedIdentifier (237-256)
  • getColumnNameByCase (204-212)
  • isColumnNameEqual (214-235)
  • getCurrentlySelectedModelNameInYamlConfig (413-466)
  • isRelationship (286-296)
  • isAcceptedValues (298-305)
  • getColumnTestConfigFromYml (307-369)
  • getExternalProjectNamesFromDbtLoomConfig (258-284)
  • setupWatcherHandler (93-100)
  • notEmpty (77-79)
  • arrayEquals (81-83)
  • debounce (85-91)
  • stripANSI (113-118)
  • getFormattedDateTime (371-380)
  • isEnclosedWithinCodeBlock (20-75)
src/test/mock/vscode.ts (2)
  • workspace (74-91)
  • Position (21-26)
src/exceptions/rateLimitException.ts (1)
  • RateLimitException (1-9)
🪛 GitHub Check: CodeQL
src/test/suite/altimate.test.ts

[failure] 235-235: Insecure temporary file
Insecure creation of file in the os temp dir.


[failure] 248-248: Insecure temporary file
Insecure creation of file in the os temp dir.

🔇 Additional comments (24)
jest.config.js (1)

20-20: LGTM: Good addition to module mapping

The addition of the @extension module alias correctly maps to the src/modules.ts file, which will simplify imports in test files.

src/test/suite/commandProcessExecution.test.ts (2)

123-132: Good test for terminal output streaming

This test properly verifies that command output is correctly streamed to the terminal and confirms both the returned output and that the terminal's log method is called.


134-141: Good test for formatText implementation

This test verifies the text formatting functionality that replaces newlines with carriage return + newline sequences for proper terminal display.

src/test/suite/dbtTerminal.test.ts (6)

30-35: Good practice: Mocking console methods

Mocking these console methods prevents test output from being cluttered with console logs, making test results cleaner and easier to read.


42-42: Better test isolation with restoreAllMocks

Changing from clearAllMocks() to restoreAllMocks() is an improvement as it fully restores the original implementation of mocked functions, preventing test interference.


51-56: Good test for logLine method

This test verifies that logLine correctly handles both the message and the newline sequence.


58-62: Good test for logNewLine method

This test ensures the logNewLine method properly logs the carriage return + line feed sequence.


64-71: Good test for terminal writing functionality

This test verifies that the terminal's write emitter is correctly triggered when the terminal is active.


136-139: Good test for string error handling

This test verifies that the error method correctly handles string errors, ensuring proper formatting.

src/test/suite/altimate.test.ts (5)

13-18: Good addition of required imports

The new imports properly support the expanded test cases for streaming, file operations, and error handling.


179-201: Good test coverage for credentials message logic

These tests thoroughly verify the getCredentialsMessage method's behavior across different configuration scenarios, ensuring appropriate messages are returned based on available credentials.


203-221: Good test coverage for preview features handling

These tests verify both scenarios for the handlePreviewFeatures method - when credentials are missing and when they exist, ensuring the message is only shown when needed.


223-228: Good test for stream data collection

This test verifies that the readStreamToBlob method correctly accumulates data from a readable stream.


257-318: Good test coverage for error handling in fetchAsStream

These tests thoroughly verify the error handling logic in the fetchAsStream method for different HTTP status codes and error conditions, including:

  • 404 NotFound errors
  • 429 RateLimiting with retry header
  • 403 Forbidden/invalid credentials
  • Empty response body handling
  • 402 Payment required / executions exhausted

This comprehensive coverage will help ensure robust error handling.

src/test/suite/utils.test.ts (10)

1-39: Comprehensive imports and organization structure.

The test file includes all necessary imports from Jest, Node.js modules, VSCode API, utility functions, and custom exceptions. Good organization helps set up proper test coverage for the extensive utility functions in the codebase.


77-82: Good test for multibyte character handling in size calculation.

The test properly verifies the size calculation for both ASCII and multibyte characters, using toBeCloseTo for floating-point comparison. This is important for correctly measuring string sizes in memory.


84-101: Well-structured tests for configuration-dependent functions.

These tests effectively mock the workspace configuration and verify both the isQuotedIdentifier and getColumnNameByCase/isColumnNameEqual functions with different configurations. Good coverage of the configuration-dependent behavior.


125-157: Good coverage of type guards and test config extraction.

The tests for isRelationship, isAcceptedValues, and getColumnTestConfigFromYml are well-structured and cover multiple scenarios, including different test types and array value matching regardless of order.


159-171: Excellent file system testing approach.

Using temporary files and directories for testing file system operations is a good practice. The test correctly cleans up resources and tests both successful file reading and handling of missing files.


173-183: Effective event handler testing.

The test for setupWatcherHandler properly verifies that event handlers are wired correctly by checking that callbacks are invoked and disposables are returned.


185-190: Complete custom exceptions validation.

The test verifies that both custom exceptions (RateLimitException and NoCredentialsError) correctly expose their properties, which is crucial for error handling throughout the application.


192-212: Well-implemented utility function tests.

The tests for notEmpty, arrayEquals, and debounce are thorough and validate the expected behavior, including edge cases. The debounce test particularly makes good use of Jest's fake timers.


214-234: Good testing of string manipulation and date formatting.

The tests for extendErrorWithSupportLinks, stripANSI, and getFormattedDateTime properly verify the behavior of these utility functions. The date formatting test correctly mocks the global Date object and restores it afterward.


236-249: Thorough code block detection testing.

The test for isEnclosedWithinCodeBlock effectively verifies the detection of code blocks within a document by testing both positive and negative cases with well-mocked document and position data.

Comment on lines +230 to +255
it("uploadToS3 uploads file", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
fs.rmSync(file);
});

it("uploadToS3 throws on failure", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
fetchMock.mockResolvedValue(mockRes);
await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
"Failed to upload data",
);
fs.rmSync(file);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Security issue in temporary file creation

The tests are creating temporary files with fixed names in the system temp directory, which could cause issues if multiple test instances run in parallel or allow potential information leakage.

Consider using a secure method to create temporary files:

-const file = path.join(os.tmpdir(), "up.txt");
-fs.writeFileSync(file, "x");
+const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'altimate-test-'));
+const file = path.join(tmpdir, "up.txt");
+fs.writeFileSync(file, "x");
 // Test code
 fs.rmSync(file);
+fs.rmdirSync(tmpdir);

Let's check how this is handled in other parts of the codebase:


🏁 Script executed:

#!/bin/bash
# Search for patterns of temporary file creation to see how it's handled elsewhere
rg -A 3 "os\.tmpdir\(\)" --type ts

Length of output: 1833



---

🏁 Script executed:

```shell
#!/bin/bash
# Verify if any other tests use the same fixed temp filename "up.txt"
rg '"up.txt"' 

Length of output: 181


Ensure unique temporary directories in altimate tests

The altimate.test.ts specs currently write to a fixed file (up.txt) under os.tmpdir(), which can collide when tests run in parallel and may expose sensitive files. Other tests (e.g. utils.test.ts) already use fs.mkdtempSync to isolate temp folders—let’s do the same here.

Files to update:

  • src/test/suite/altimate.test.ts (both uploadToS3 cases around lines 230–255)

Recommended diff:

   it("uploadToS3 uploads file", async () => {
-    const file = path.join(os.tmpdir(), "up.txt");
-    fs.writeFileSync(file, "x");
+    const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "altimate-test-"));
+    const file = path.join(tmpDir, "up.txt");
+    fs.writeFileSync(file, "x");
     const mockRes = new Response("ok", { status: 200, statusText: "OK" });
     fetchMock.mockResolvedValue(mockRes);
     const res = await request.uploadToS3("http://s3", {}, file);
     expect(res.status).toBe(200);
-    fs.rmSync(file);
+    fs.rmSync(file);
+    fs.rmdirSync(tmpDir);
   });

   it("uploadToS3 throws on failure", async () => {
-    const file = path.join(os.tmpdir(), "up.txt");
-    fs.writeFileSync(file, "x");
+    const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "altimate-test-"));
+    const file = path.join(tmpDir, "up.txt");
+    fs.writeFileSync(file, "x");
     const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
     fetchMock.mockResolvedValue(mockRes);
     await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
       "Failed to upload data",
     );
-    fs.rmSync(file);
+    fs.rmSync(file);
+    fs.rmdirSync(tmpDir);
   });

This aligns with existing patterns (utils.test.ts) and avoids name collisions or leakage.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("uploadToS3 uploads file", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
fs.rmSync(file);
});
it("uploadToS3 throws on failure", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
const file = path.join(os.tmpdir(), "up.txt");
fs.writeFileSync(file, "x");
const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
fetchMock.mockResolvedValue(mockRes);
await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
"Failed to upload data",
);
fs.rmSync(file);
});
it("uploadToS3 uploads file", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
- const file = path.join(os.tmpdir(), "up.txt");
- fs.writeFileSync(file, "x");
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "altimate-test-"));
+ const file = path.join(tmpDir, "up.txt");
+ fs.writeFileSync(file, "x");
const mockRes = new Response("ok", { status: 200, statusText: "OK" });
fetchMock.mockResolvedValue(mockRes);
const res = await request.uploadToS3("http://s3", {}, file);
expect(res.status).toBe(200);
- fs.rmSync(file);
+ fs.rmSync(file);
+ fs.rmdirSync(tmpDir);
});
it("uploadToS3 throws on failure", async () => {
mockPythonEnv.getResolvedConfigValue
.mockReturnValueOnce("key")
.mockReturnValueOnce("instance");
- const file = path.join(os.tmpdir(), "up.txt");
- fs.writeFileSync(file, "x");
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "altimate-test-"));
+ const file = path.join(tmpDir, "up.txt");
+ fs.writeFileSync(file, "x");
const mockRes = new Response("bad", { status: 500, statusText: "ERR" });
fetchMock.mockResolvedValue(mockRes);
await expect(request.uploadToS3("http://s3", {}, file)).rejects.toThrow(
"Failed to upload data",
);
- fs.rmSync(file);
+ fs.rmSync(file);
+ fs.rmdirSync(tmpDir);
});
🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 235-235: Insecure temporary file
Insecure creation of file in the os temp dir.


[failure] 248-248: Insecure temporary file
Insecure creation of file in the os temp dir.

🤖 Prompt for AI Agents
In src/test/suite/altimate.test.ts around lines 230 to 255, the tests create
temporary files with a fixed name "up.txt" in the system temp directory, which
risks collisions and security issues during parallel test runs. To fix this,
replace the fixed filename with a unique temporary directory created using
fs.mkdtempSync, then create the file inside this directory. Ensure to clean up
by removing the entire temporary directory after the test completes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant