Unverified 提交 a5e191f1 authored 作者: Will Chen's avatar Will Chen 提交者: GitHub

Fix clear githubuser (#2091)

<!-- CURSOR_SUMMARY --> > [!NOTE] > Ensures GitHub disconnect fully removes credentials and verifies via targeted e2e coverage. > > - Clear both `githubAccessToken` and `githubUser` in `GitHubIntegration` when disconnecting > - New Playwright test `github clear integration settings` verifies the disconnect button disappears and snapshots only the settings delta > - Test helpers: add `captureSettings()` and `snapshotSettingsDelta()` to diff `user-settings.json` for concise snapshots > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0c47bee06d145737e10c58c8133da35c0c9553bb. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Disconnecting from GitHub now clears both the access token and user info to prevent stale credentials. Added an e2e test to verify the settings file is cleaned and the UI updates correctly. - **Bug Fixes** - Clear githubUser alongside githubAccessToken on disconnect. - Added Playwright e2e to ensure both fields are removed and the disconnect button disappears. <sup>Written for commit 0c47bee06d145737e10c58c8133da35c0c9553bb. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWilliam Chen <will@mac.lan>
上级 b210eea2
...@@ -143,3 +143,36 @@ test("create and sync to existing repo - custom branch", async ({ po }) => { ...@@ -143,3 +143,36 @@ test("create and sync to existing repo - custom branch", async ({ po }) => {
operation: "create", operation: "create",
}); });
}); });
test("github clear integration settings", async ({ po }) => {
await po.setUp({ autoApprove: true });
await po.sendPrompt("tc=basic");
await po.getTitleBarAppNameButton().click();
await po.githubConnector.connect();
await expect(po.githubConnector.getCreateNewRepoModeButton()).toBeVisible();
// Capture settings before disconnecting
await po.clickOpenInChatButton();
// Make sure we are committing so that githubUser.email is getting set.
await po.sendPrompt("tc=write-index");
const beforeSettings = po.captureSettings();
// Navigate to settings
await po.goToSettingsTab();
// Verify the "Disconnect from GitHub" button is visible (meaning we're connected)
const disconnectButton = po.page.getByRole("button", {
name: "Disconnect from GitHub",
});
// Click disconnect
await disconnectButton.click();
// Verify the button is no longer visible (component returns null when not connected)
await expect(disconnectButton).not.toBeVisible();
// Snapshot only the settings that changed (GitHub token/user removed)
po.snapshotSettingsDelta(beforeSettings);
});
...@@ -1034,6 +1034,63 @@ export class PageObject { ...@@ -1034,6 +1034,63 @@ export class PageObject {
expect(sanitizedSettingsContent).toMatchSnapshot(); expect(sanitizedSettingsContent).toMatchSnapshot();
} }
/**
* Captures the current settings state for later comparison.
* Use with `snapshotSettingsDelta()` to snapshot only what changed.
*/
captureSettings(): Record<string, unknown> {
const settingsPath = path.join(this.userDataDir, "user-settings.json");
const settingsContent = fs.readFileSync(settingsPath, "utf-8");
return JSON.parse(settingsContent);
}
/**
* Snapshots only the differences between the current settings and a previously captured state.
* Output is in git diff style for easy reading.
*/
snapshotSettingsDelta(beforeSettings: Record<string, unknown>) {
const afterSettings = this.captureSettings();
const diffLines: string[] = [];
const allKeys = new Set([
...Object.keys(beforeSettings),
...Object.keys(afterSettings),
]);
// Sort keys for deterministic output
const sortedKeys = Array.from(allKeys).sort();
for (const key of sortedKeys) {
const beforeValue = beforeSettings[key];
const afterValue = afterSettings[key];
const beforeExists = key in beforeSettings;
const afterExists = key in afterSettings;
// Format value with diff marker on each line for multiline values
const formatValue = (val: unknown, marker: "+" | "-") => {
const lines = JSON.stringify(val, null, 2).split("\n");
return lines
.map((line, i) => (i === 0 ? line : `${marker} ${line}`))
.join("\n");
};
if (!beforeExists && afterExists) {
// Added
diffLines.push(`+ "${key}": ${formatValue(afterValue, "+")}`);
} else if (beforeExists && !afterExists) {
// Removed
diffLines.push(`- "${key}": ${formatValue(beforeValue, "-")}`);
} else if (JSON.stringify(beforeValue) !== JSON.stringify(afterValue)) {
// Changed
diffLines.push(`- "${key}": ${formatValue(beforeValue, "-")}`);
diffLines.push(`+ "${key}": ${formatValue(afterValue, "+")}`);
}
}
expect(diffLines.join("\n")).toMatchSnapshot();
}
async toggleAutoUpdate() { async toggleAutoUpdate() {
await this.page.getByRole("switch", { name: "Auto-update" }).click(); await this.page.getByRole("switch", { name: "Auto-update" }).click();
} }
......
- "githubAccessToken": {
- "value": "fake_access_token_12345",
- "encryptionType": "plaintext"
- }
- "githubUser": {
- "email": "testuser@example.com"
- }
\ No newline at end of file
...@@ -13,6 +13,7 @@ export function GitHubIntegration() { ...@@ -13,6 +13,7 @@ export function GitHubIntegration() {
try { try {
const result = await updateSettings({ const result = await updateSettings({
githubAccessToken: undefined, githubAccessToken: undefined,
githubUser: undefined,
}); });
if (result) { if (result) {
showSuccess("Successfully disconnected from GitHub"); showSuccess("Successfully disconnected from GitHub");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论