Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Bulk refactor - increase test coverage and add integration tests, extract some difficult to test methods#541

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
jaggederest wants to merge73 commits intomain
base:main
Choose a base branch
Loading
fromjaggederest/refactor_extension
Open
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
73 commits
Select commitHold shift + click to select a range
7e1bce9
pretest working
jaggederestJun 16, 2025
c693a46
enable vscode-test and bump tsconfig to modern settings
jaggederestJun 16, 2025
240b649
Merge branch 'main' into jaggederest/integration_tests
jaggederestJun 16, 2025
0e58a31
test: fix integration tests to run without Remote SSH extension
jaggederestJun 16, 2025
872b7e8
Merge remote-tracking branch 'origin/jaggederest/integration_tests' i…
jaggederestJun 16, 2025
01c2d80
autocorrect formatting
jaggederestJun 16, 2025
8ddbf26
bump node version to 22
jaggederestJun 16, 2025
9b74df4
fix: configure Vitest to properly exclude VS Code integration tests
jaggederestJun 16, 2025
adec211
whitespace
jaggederestJun 16, 2025
d9b543a
fix: update tsconfig.json and convert pretty-bytes imports to standar…
jaggederestJun 17, 2025
a7afdd6
Remove testmode flag in favor of checking existence of remote ssh ext…
jaggederestJun 17, 2025
3097d8f
remove superfluous async, enable lint rule
jaggederestJun 18, 2025
a2d2bc8
fix: resolve ESLint @typescript-eslint/require-await errors
jaggederestJun 18, 2025
32dfda4
Update configurations and remove pointless Promise.all
jaggederestJun 18, 2025
12b0124
Tweak eslint config to better handle json/md, remove compile-tests sc…
jaggederestJun 18, 2025
cf58040
feat: expand integration tests and add coverage analysis
jaggederestJun 19, 2025
1be94c3
fix: update integration tests to match actual commands
jaggederestJun 19, 2025
67c47e0
feat: switch to VS Code built-in coverage for integration tests
jaggederestJun 19, 2025
62c88f4
feat: add comprehensive integration test framework
jaggederestJun 20, 2025
907347e
feat: implement comprehensive integration tests for CLI, URI handler,…
jaggederestJun 20, 2025
7563580
feat: add comprehensive unit test coverage for all source files
jaggederestJun 20, 2025
379b9ee
fix: resolve all broken unit tests with proper vscode and API mocking
jaggederestJun 20, 2025
f2863b5
feat: enhance api.ts test coverage to 95.52%
jaggederestJun 20, 2025
ced86e9
feat: achieve 48.4% overall test coverage with incremental improvements
jaggederestJun 21, 2025
1dbee30
docs: update TODO.md and CLAUDE.md to reflect test coverage progress
jaggederestJun 21, 2025
6d93e76
test: add unit tests for commands.ts - improved coverage from 28% to …
jaggederestJun 21, 2025
2471b72
test: improve unit test coverage from 48.4% to 60.11%
jaggederestJun 21, 2025
3e38dca
test: improve remote.ts coverage from 32.61% to 49.21%
jaggederestJun 22, 2025
797b656
test: improve test coverage for commands, storage, and workspacesProv…
jaggederestJun 22, 2025
8f150cb
feat: add structured logging foundation with TDD approach
jaggederestJun 22, 2025
07bffb8
docs: update TODO.md with testing synthesis and logging plan
jaggederestJun 22, 2025
fe296b2
feat: integrate logger into Storage class with TDD approach
jaggederestJun 22, 2025
32b4df0
refactor: create type-safe mock builders and clean up api-helper.test.ts
jaggederestJun 22, 2025
bfd4b34
refactor: clean up type casting in test files
jaggederestJun 22, 2025
d4af4ed
fix: update test-helpers to use proper Storage type
jaggederestJun 22, 2025
6c947fe
docs: update TODO.md with test quality improvement progress
jaggederestJun 22, 2025
f8b6dbb
test: add Logger factory and verify backward compatibility
jaggederestJun 22, 2025
a57d676
fix: address ESLint errors in api.test.ts
jaggederestJun 22, 2025
97ff5fb
docs: simplify TODO.md and update progress
jaggederestJun 22, 2025
8021706
docs: update CLAUDE.md with TDD patterns and techniques from session
jaggederestJun 22, 2025
b624614
feat: integrate Logger into remote.ts with TDD approach
jaggederestJun 22, 2025
2629397
feat: integrate Logger into extension.ts with initialization
jaggederestJun 22, 2025
53272c1
test: add Logger integration tests for headers.ts
jaggederestJun 22, 2025
92c548a
test: add Logger integration tests for workspaceMonitor
jaggederestJun 22, 2025
9e8ed6d
test: add Logger integration tests for inbox
jaggederestJun 22, 2025
3595bda
docs: update TODO.md with Logger integration progress
jaggederestJun 22, 2025
9aac82d
test: add Logger integration tests for error.ts
jaggederestJun 22, 2025
341cc67
test: add Logger integration tests for workspacesProvider
jaggederestJun 23, 2025
dfd55e1
test: add Logger integration tests for commands.ts
jaggederestJun 23, 2025
6285043
docs: mark Logger integration as complete in TODO.md
jaggederestJun 23, 2025
eca919f
refactor: extract helper functions from monolithic activate() in exte…
jaggederestJun 23, 2025
8505c4f
refactor: complete TDD extraction of all functions from activate()
jaggederestJun 23, 2025
8b8edc7
test: consolidate test mocks into reusable factories
jaggederestJun 23, 2025
1a43dd3
docs: update TODO.md and CLAUDE.md with test improvements
jaggederestJun 23, 2025
a1af9cb
test: improve integration tests from 86 to 100 passing
jaggederestJun 23, 2025
eaee610
test: clean up pointless integration tests and enable 3 more
jaggederestJun 23, 2025
c4a2156
test: remove 9 more pointless integration tests
jaggederestJun 23, 2025
1a9f34f
test: remove all skipped integration tests for fresh start
jaggederestJun 24, 2025
6291f7f
refactor: improve testability through dependency injection and test s…
jaggederestJun 26, 2025
a72e943
test: remove flaky UI tests and improve test stability
jaggederestJun 26, 2025
eb787f8
test: simplify test files and reduce verbosity
jaggederestJun 27, 2025
fa1f576
test: reduce test verbosity by 41% while maintaining 84% coverage
jaggederestJun 27, 2025
c73c742
test: simplify test suite by removing low-value tests
jaggederestJun 27, 2025
9a3b37d
fix: resolve Uri type errors in extension tests
jaggederestJun 27, 2025
89ac9ee
refactor: dramatically simplify extension activation flow
jaggederestJun 27, 2025
d84ee78
more test cleanup
jaggederestJun 27, 2025
c17f927
tweak api-helper tests
jaggederestJun 27, 2025
85293fe
refactor: extract classes into separate files for better organization
jaggederestJun 27, 2025
a9db00f
remove .DS_Store
jaggederestJun 27, 2025
33b5142
Delete COVERAGE.md
jaggederestJun 27, 2025
a71d9fc
Delete TODO.md
jaggederestJun 27, 2025
af14ff3
Merge main and move integration tests to src/test
jaggederestJun 27, 2025
7af665b
Merge remote-tracking branch 'origin/jaggederest/refactor_extension' …
jaggederestJun 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
test: add Logger factory and verify backward compatibility
- Add createMockOutputChannelWithLogger factory function for consistent test setup- Verify Logger class implements the Logger interface required by error.ts- Add tests confirming writeToCoderOutputChannel backward compatibility- Update existing tests to use the new factory function- Prepare for systematic replacement of writeToCoderOutputChannel calls🤖 Generated with [Claude Code](https://claude.ai/code)Co-Authored-By: Claude <noreply@anthropic.com>
  • Loading branch information
@jaggederest@claude
jaggederest andclaude committedJun 22, 2025
commitf8b6dbb41dc3cfb501ec75a736eb1a93c966ac67
97 changes: 97 additions & 0 deletionssrc/error.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
X509_ERR_CODE,
getErrorDetail,
} from "./error";
import { createMockOutputChannelWithLogger } from "./test-helpers";

// Before each test we make a request to sanity check that we really get the
// error we are expecting, then we run it through CertificateError.
Expand DownExpand Up@@ -58,6 +59,7 @@ vi.mock("coder/site/src/api/errors", () => ({
}),
}));

// Use a mock logger that throws on error messages to ensure tests fail if unexpected logs occur
const logger = {
writeToCoderOutputChannel(message: string) {
throw new Error(message);
Expand DownExpand Up@@ -387,6 +389,101 @@ describe("CertificateError.maybeWrap error handling", () => {
});
});

describe("CertificateError with real Logger", () => {
it("should be backward compatible with existing mock logger", () => {
// Verify our Logger class implements the Logger interface used by error.ts
const { mockOutputChannel, logger: realLogger } =
createMockOutputChannelWithLogger();

// Verify the Logger has the required writeToCoderOutputChannel method
expect(typeof realLogger.writeToCoderOutputChannel).toBe("function");

// Verify it works like the mock logger
realLogger.writeToCoderOutputChannel("Test message");
expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
expect.stringMatching(/\[.*\] \[INFO\] Test message/),
);
});

it("should work with our Logger implementation", async () => {
// Create a real Logger instance with mock output channel
const { mockOutputChannel, logger: realLogger } =
createMockOutputChannelWithLogger();

// Mock CertificateError.determineVerifyErrorCause to throw an error
const originalDetermine = CertificateError.determineVerifyErrorCause;
CertificateError.determineVerifyErrorCause = vi
.fn()
.mockRejectedValue(new Error("Failed to parse certificate"));

const axiosError = {
isAxiosError: true,
code: X509_ERR_CODE.UNABLE_TO_VERIFY_LEAF_SIGNATURE,
message: "unable to verify leaf signature",
};

// Test that maybeWrap works with our real Logger
const result = await CertificateError.maybeWrap(
axiosError,
"https://test.com",
realLogger,
);

// Should return original error when determineVerifyErrorCause fails
expect(result).toBe(axiosError);

// Verify the message was logged through our Logger
expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
expect.stringMatching(
/\[.*\] \[INFO\] Failed to parse certificate from https:\/\/test.com/,
),
);

// Verify the log was stored in the Logger
const logs = realLogger.getLogs();
expect(logs).toHaveLength(1);
expect(logs[0].level).toBe("INFO");
expect(logs[0].message).toContain(
"Failed to parse certificate from https://test.com",
);

// Restore original method
CertificateError.determineVerifyErrorCause = originalDetermine;
});

it("should log successful certificate wrapping with real Logger", async () => {
const { logger: realLogger } = createMockOutputChannelWithLogger();
const address = await startServer("chain");

const request = axios.get(address);
await expect(request).rejects.toHaveProperty(
"code",
X509_ERR_CODE.SELF_SIGNED_CERT_IN_CHAIN,
);

try {
await request;
} catch (error) {
// Clear any existing logs
realLogger.clear();

const wrapped = await CertificateError.maybeWrap(
error,
address,
realLogger,
);
expect(wrapped instanceof CertificateError).toBeTruthy();
expect((wrapped as CertificateError).x509Err).toBe(
X509_ERR.UNTRUSTED_CHAIN,
);

// Since the certificate error was successfully wrapped, no error should be logged
const logs = realLogger.getLogs();
expect(logs).toHaveLength(0);
}
});
});

describe("CertificateError instance methods", () => {
it("should update configuration and show message when allowInsecure is called", async () => {
const vscode = await import("vscode");
Expand Down
71 changes: 48 additions & 23 deletionssrc/logger.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import { Logger, LoggerService } from "./logger";
import { createMockOutputChannelWithLogger } from "./test-helpers";

describe("Logger", () => {
let logger: Logger;
let mockOutputChannel: {
appendLine: ReturnType<typeof vi.fn>;
};

beforeEach(() => {
logger = new Logger();
mockOutputChannel = {
appendLine: vi.fn(),
};
logger = new Logger(mockOutputChannel);
});

it("should log error messages", () => {
Expand DownExpand Up@@ -80,27 +87,52 @@ describe("Logger", () => {

describe("Logger with OutputChannel", () => {
it("should write logs to output channel when provided", () => {
const mockOutputChannel = {
appendLine: vi.fn(),
};

const logger = new Logger(mockOutputChannel);
const { mockOutputChannel, logger } = createMockOutputChannelWithLogger();
logger.info("Test message");

expect(mockOutputChannel.appendLine).toHaveBeenCalledOnce();
expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
expect.stringContaining("[INFO] Test message"),
);
});

it("should implement writeToCoderOutputChannel for backward compatibility", () => {
const { mockOutputChannel, logger } = createMockOutputChannelWithLogger();

logger.writeToCoderOutputChannel("Test message");

expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
expect.stringMatching(/\[.*\] \[INFO\] Test message/),
);
});

it("should log writeToCoderOutputChannel messages as INFO level", () => {
const logger = new Logger();

logger.writeToCoderOutputChannel("Backward compatible message");

const logs = logger.getLogs();
expect(logs).toHaveLength(1);
expect(logs[0].level).toBe("INFO");
expect(logs[0].message).toBe("Backward compatible message");
});

it("should handle error-like messages appropriately", () => {
const { mockOutputChannel, logger } = createMockOutputChannelWithLogger();

logger.writeToCoderOutputChannel("Error: Something went wrong");

expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
expect.stringMatching(/\[.*\] \[INFO\] Error: Something went wrong/),
);
});
});

describe("Logger with log level filtering", () => {
it("should filter debug logs when verbose is false", () => {
const mockOutputChannel = {
appendLine: vi.fn(),
};

const logger = new Logger(mockOutputChannel, { verbose: false });
const { mockOutputChannel, logger } = createMockOutputChannelWithLogger({
verbose: false,
});
logger.debug("Debug message");
logger.info("Info message");
logger.warn("Warn message");
Expand All@@ -113,13 +145,10 @@ describe("Logger with log level filtering", () => {
});

it("should include debug logs when verbose is true", () => {
const mockOutputChannel = {
appendLine: vi.fn(),
};

const logger = new Logger(mockOutputChannel, { verbose: true });
logger.debug("Debug message");
logger.info("Info message");
const { mockOutputChannel, logger: verboseLogger } =
createMockOutputChannelWithLogger({ verbose: true });
verboseLogger.debug("Debug message");
verboseLogger.info("Info message");

expect(mockOutputChannel.appendLine).toHaveBeenCalledTimes(2);
expect(mockOutputChannel.appendLine).toHaveBeenCalledWith(
Expand All@@ -128,11 +157,7 @@ describe("Logger with log level filtering", () => {
});

it("should include data in output when provided", () => {
const mockOutputChannel = {
appendLine: vi.fn(),
};

const logger = new Logger(mockOutputChannel);
const { mockOutputChannel, logger } = createMockOutputChannelWithLogger();
const data = { userId: 123, action: "login" };
logger.info("User action", data);

Expand Down
8 changes: 8 additions & 0 deletionssrc/logger.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -98,6 +98,14 @@ export class Logger {
this.outputChannel.appendLine(message);
}
}

/**
* Backward compatibility method for existing code using writeToCoderOutputChannel
* Logs messages at INFO level
*/
writeToCoderOutputChannel(message: string): void {
this.info(message);
}
}

export interface WorkspaceConfiguration {
Expand Down
24 changes: 22 additions & 2 deletionssrc/test-helpers.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,7 @@ import type {
} from "coder/site/src/api/typesGenerated";
import { vi } from "vitest";
import type * as vscode from "vscode";
import { Logger } from "./logger";
import type { Storage } from "./storage";

/**
Expand DownExpand Up@@ -164,6 +165,25 @@ export function createMockConfiguration(
};
}

/**
* Create a mock output channel and Logger instance for testing
* Returns both the mock output channel and a real Logger instance
*/
export function createMockOutputChannelWithLogger(options?: {
verbose?: boolean;
}): {
mockOutputChannel: {
appendLine: ReturnType<typeof vi.fn>;
};
logger: Logger;
} {
const mockOutputChannel = {
appendLine: vi.fn(),
};
const logger = new Logger(mockOutputChannel, options);
return { mockOutputChannel, logger };
}

/**
* Create a partial mock Storage with only the methods needed
*/
Expand All@@ -172,10 +192,10 @@ export function createMockStorage(
getHeaders: ReturnType<typeof vi.fn>;
writeToCoderOutputChannel: ReturnType<typeof vi.fn>;
}> = {},
):Partial<Storage> {
): Storage {
return {
getHeaders: overrides.getHeaders ?? vi.fn().mockResolvedValue({}),
writeToCoderOutputChannel: overrides.writeToCoderOutputChannel ?? vi.fn(),
...overrides,
};
} as unknown as Storage;
}

[8]ページ先頭

©2009-2025 Movatter.jp