From c539c17c2308e169e9ef5a8c89dd917260b71caf Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 16 Jan 2025 20:58:29 +0530 Subject: [PATCH 1/4] test: git commit dialog integ tests --- test/spec/Extn-Git-integ-test.js | 83 +++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/test/spec/Extn-Git-integ-test.js b/test/spec/Extn-Git-integ-test.js index d485fde179..572f3d997c 100644 --- a/test/spec/Extn-Git-integ-test.js +++ b/test/spec/Extn-Git-integ-test.js @@ -27,7 +27,7 @@ define(function (require, exports, module) { return; } - let $, __PR, testWindow, ExtensionLoader, Menus, Commands, CommandManager, + let $, __PR, testWindow, ExtensionLoader, Menus, Commands, CommandManager, EditorManager, SpecRunnerUtils = require("spec/SpecRunnerUtils"), anotherTestFolder = SpecRunnerUtils.getTestPath("/spec/LowLevelFileIO-test-files"); @@ -60,6 +60,7 @@ define(function (require, exports, module) { ExtensionLoader = testWindow.brackets.test.ExtensionLoader; Commands = testWindow.brackets.test.Commands; CommandManager = testWindow.brackets.test.CommandManager; + EditorManager = testWindow.brackets.test.EditorManager; testPathGit = await SpecRunnerUtils.getTempTestDirectory("/spec/EditorCommandHandlers-test-files"); await SpecRunnerUtils.loadProjectInTestWindow(testPathGit); @@ -69,7 +70,8 @@ define(function (require, exports, module) { }, "Git menus to be present", 10000); }, 30000); - describe("Init repo and do all tests", function () { + describe("Init repo and do all tests in order", function () { + // ordering of tests in this matters and it may not run as individual tests. let $gitPanel, $gitIcon; beforeAll(async function () { $gitPanel = $("#git-panel"); @@ -116,15 +118,80 @@ define(function (require, exports, module) { expect($(".check-all").prop("checked")).toBeFalse(); }); - it("Should be able to stage and commit initialized git repo", async function () { + function clickOpenFile(elementNumber) { + const $elements = $gitPanel.find(".modified-file"); // Get all .modified-file elements + if (elementNumber >= 0 && elementNumber < $elements.length) { + $($elements[elementNumber]).trigger("mousedown"); // Trigger mousedown on the specified element + } else { + console.error("Invalid element number:", elementNumber); // Handle invalid index + } + } + + + it("Should clicking on file in git panel should open it", async function () { await showGitPanel(); - expect($(".check-all").prop("checked")).toBeFalse(); - $(".check-all").click(); + clickOpenFile(0); await awaitsFor(()=>{ - const checkboxes = document.querySelectorAll(".check-one"); - return Array.from(checkboxes).every(checkbox => checkbox.checked); - }, "All files to be staged for commit", 10000); + const editor = EditorManager.getActiveEditor(); + if(!editor){ + return false; + } + return editor.document.file.fullPath.endsWith(".gitignore"); + }, "first file to open"); + }); + + async function commitAllBtnClick() { + await showGitPanel(); + if(!$(".check-all").prop("checked")) { + $(".check-all").click(); + await awaitsFor(()=>{ + const checkboxes = document.querySelectorAll(".check-one"); + return Array.from(checkboxes).every(checkbox => checkbox.checked); + }, "All files to be staged for commit", 10000); + } $(".git-commit").click(); + await __PR.waitForModalDialog("#git-commit-dialog"); + } + + function expectTextToContain(srcText, list) { + const nonEmptyLines = srcText + .split("\n") // Split the text into lines + .map(line => line.trim()) // Trim each line + .filter(line => line !== "").join("\n"); // Remove empty lines + for(const text of list) { + expect(nonEmptyLines).toContain(text); + } + } + + it("Should be able to stage, show commit dialog and cancel dialog on initialized git repo", async function () { + await commitAllBtnClick(); + __PR.clickDialogButtonID(__PR.Dialogs.DIALOG_BTN_CANCEL); + await __PR.waitForModalDialogClosed("#git-commit-dialog"); + }); + + it("Should git dialog show commit diff and lint errors", async function () { + await commitAllBtnClick(); + + // check lint errors + await awaitsFor(()=>{ + return $(".lint-errors").text().includes("test.html"); + }, "lint errors to be shown", 10000); + expect($(".lint-errors").text()).toContain(" is missing required \"lang\" attribute"); + expect($(".lint-errors").is(":visible")).toBeTrue(); + + // check commit diff + await awaitsFor(()=>{ + return $(".commit-diff").text().includes("test.html"); + }, "commit-diff to be shown", 10000); + expectTextToContain($(".commit-diff").text(), [ + ".gitignore", "test.css", "test.html", "test.js", + "/node_modules/", "color:", ``, + `console.log` + ]); + + // dismiss dialog + __PR.clickDialogButtonID(__PR.Dialogs.DIALOG_BTN_CANCEL); + await __PR.waitForModalDialogClosed("#git-commit-dialog"); }); }); From 63eedbd65b3173335a9d09760f13be07af437cae Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 16 Jan 2025 21:39:07 +0530 Subject: [PATCH 2/4] test: git change navigation integ tests --- .../default/DebugCommands/MacroRunner.js | 9 +++ test/spec/Extn-Git-integ-test.js | 64 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/extensions/default/DebugCommands/MacroRunner.js b/src/extensions/default/DebugCommands/MacroRunner.js index 020b5012d4..60ef9361cf 100644 --- a/src/extensions/default/DebugCommands/MacroRunner.js +++ b/src/extensions/default/DebugCommands/MacroRunner.js @@ -758,10 +758,19 @@ define(function (require, exports, module) { _clickDialogButtonWithSelector(buttonSelector, dialogClass, false); } + /** + * Saves the currently active file + * @returns {Promise} A promise that resolves when file is saved to disc + */ + function saveActiveFile() { + return jsPromise(CommandManager.execute(Commands.FILE_SAVE)); + } + const __PR= { readTextFile, writeTextFile, deletePath, openFile, setCursors, expectCursorsToBe, keydown, typeAtCursor, validateText, validateAllMarks, validateMarks, closeFile, closeAll, undo, redo, setPreference, getPreference, validateEqual, validateNotEqual, execCommand, + saveActiveFile, awaitsFor, waitForModalDialog, waitForModalDialogClosed, clickDialogButtonID, clickDialogButton, EDITING, $, Commands, Dialogs }; diff --git a/test/spec/Extn-Git-integ-test.js b/test/spec/Extn-Git-integ-test.js index 572f3d997c..0919e3a34a 100644 --- a/test/spec/Extn-Git-integ-test.js +++ b/test/spec/Extn-Git-integ-test.js @@ -146,13 +146,20 @@ define(function (require, exports, module) { $(".check-all").click(); await awaitsFor(()=>{ const checkboxes = document.querySelectorAll(".check-one"); - return Array.from(checkboxes).every(checkbox => checkbox.checked); + const commitIsDisabled = $(".git-commit").prop("disabled"); + return Array.from(checkboxes).every(checkbox => checkbox.checked) && !commitIsDisabled; }, "All files to be staged for commit", 10000); } $(".git-commit").click(); await __PR.waitForModalDialog("#git-commit-dialog"); } + async function commmitDlgWithMessage(message) { + $("input[name='commit-message']").val(message); + __PR.clickDialogButtonID(__PR.Dialogs.DIALOG_BTN_OK); + await __PR.waitForModalDialogClosed("#git-commit-dialog"); + } + function expectTextToContain(srcText, list) { const nonEmptyLines = srcText .split("\n") // Split the text into lines @@ -193,6 +200,61 @@ define(function (require, exports, module) { __PR.clickDialogButtonID(__PR.Dialogs.DIALOG_BTN_CANCEL); await __PR.waitForModalDialogClosed("#git-commit-dialog"); }); + + it("Should be able to commit the files", async function () { + await commitAllBtnClick(); + await commmitDlgWithMessage("first commit"); + await awaitsFor(()=>{ + return $(".git-edited-list tr").length === 0; + }, "no files to be commited", 10000); + }); + + it("Should editing new file and saving add it to changed files list", async function () { + __PR.setCursors(["5:15"]); + __PR.typeAtCursor("\nhelloIG"); + await __PR.saveActiveFile(); + await awaitsFor(()=>{ + return $(".git-edited-list tr").length === 1; + }, "new edited file to come up in status", 10000); + + // now commit + await commitAllBtnClick(); + await commmitDlgWithMessage("second commit"); + await awaitsFor(()=>{ + return $(".git-edited-list tr").length === 0; + }, "no files to be commited", 10000); + }); + + async function gotoChange(line, direction) { + await awaitsFor(()=>{ + $(`.git-${direction}-gutter`).click(); + const editor = EditorManager.getActiveEditor(); + return editor.getCursorPos().line === line; + }, `should go to previous change ${line}`, 10000, 100); + } + + it("Should be able to navigate to next and previous changes and then discard changes", async function () { + __PR.setCursors(["1:1"]); + __PR.typeAtCursor("changeLine1\n"); + __PR.setCursors(["4:1"]); + __PR.typeAtCursor("changeLine2\n"); + await __PR.saveActiveFile(); + await awaitsFor(()=>{ + return $(".git-edited-list tr").length === 1; + }, "new edited file to come up in status", 10000); + + // next previous buttons tests + await gotoChange(3, "prev"); + await gotoChange(0, "prev"); + await gotoChange(3, "next"); + + // discard all changes with panel button + $(".btn-git-undo").click(); + __PR.clickDialogButtonID(__PR.Dialogs.DIALOG_BTN_OK); + await awaitsFor(()=>{ + return $(".git-edited-list tr").length === 0; + }, "no files to be commited", 10000); + }); }); }); From 0f20441b33209f0cee16773e18aad079aefb399a Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 16 Jan 2025 23:46:40 +0530 Subject: [PATCH 3/4] test: git history viewer and username/email config integ tests --- src/extensions/default/Git/main.js | 4 +- test/spec/Extn-Git-integ-test.js | 93 ++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/extensions/default/Git/main.js b/src/extensions/default/Git/main.js index 0213af7bc1..e1921ca047 100644 --- a/src/extensions/default/Git/main.js +++ b/src/extensions/default/Git/main.js @@ -18,6 +18,7 @@ define(function (require, exports, module) { Events = require("src/Events"), Main = require("src/Main"), Preferences = require("src/Preferences"), + Git = require("src/git/Git"), BracketsEvents = require("src/BracketsEvents"); // Load extension modules that are not included by core @@ -49,7 +50,8 @@ define(function (require, exports, module) { if (typeof window === "object") { window.phoenixGitEvents = { EventEmitter: EventEmitter, - Events: Events + Events: Events, + Git }; } }); diff --git a/test/spec/Extn-Git-integ-test.js b/test/spec/Extn-Git-integ-test.js index 0919e3a34a..ab04bb953b 100644 --- a/test/spec/Extn-Git-integ-test.js +++ b/test/spec/Extn-Git-integ-test.js @@ -78,6 +78,29 @@ define(function (require, exports, module) { $gitIcon = $("#git-toolbar-icon"); }); + it("should git username and email be valid", async function () { + const tempUser = "phcodeTestGitUser"; + const tempEmail = "phcodeTestGitUser@gmail.com"; + // username validate + let currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); + if(!currentVal) { + await testWindow.phoenixGitEvents.Git.setConfig("user.name", tempUser, true); + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); + expect(currentVal).toBe(tempUser); + } else { + expect(currentVal).toBeDefined(); + } + // email validate + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); + if(!currentVal) { + await testWindow.phoenixGitEvents.Git.setConfig("user.email", tempEmail, true); + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); + expect(currentVal).toBe(tempEmail); + } else { + expect(currentVal).toBeDefined(); + } + }); + it("should only git settings, init and clone commands be enabled in non-git repos", async function () { await forCommandEnabled(Commands.CMD_GIT_INIT); await forCommandEnabled(Commands.CMD_GIT_CLONE); @@ -255,6 +278,76 @@ define(function (require, exports, module) { return $(".git-edited-list tr").length === 0; }, "no files to be commited", 10000); }); + + async function waitForHistoryVisible(visible) { + await awaitsFor(() => { + return $gitPanel.find("#git-history-list").is(":visible") === visible; + }, `History list to be visible: ${visible}`); + } + + async function testHistoryToggle(whichHistory) { + const $historyToggleButton = $gitPanel.find(whichHistory); + + $historyToggleButton.trigger("click"); + await waitForHistoryVisible(true); + + const $historyList = $gitPanel.find("#git-history-list"); + + // Check if the first and second commits are displayed + const $historyCommits = $historyList.find(".commit-subject"); + expect($historyCommits.length).toBeGreaterThanOrEqual(2); + + // Verify the content of the first and second commits + expect($historyCommits.eq(0).text().trim()).toBe("second commit"); + expect($historyCommits.eq(1).text().trim()).toBe("first commit"); + + $historyToggleButton.trigger("click"); + await waitForHistoryVisible(false); + } + + it("should show history with first and second commit on clicking global history", async () => { + await testHistoryToggle(".git-history-toggle"); + }); + + it("should show history with first and second commit on clicking global history", async () => { + await testHistoryToggle(".git-file-history"); + }); + + async function waitForHistoryViewerVisible(visible) { + await awaitsFor(() => { + return $("#history-viewer").is(":visible") === visible; + }, `History viewer to be visible: ${visible}`); + } + + async function testHistoryViewerToggle(commitIndex) { + const $historyList = $gitPanel.find("#git-history-list"); + const $commitRow = $historyList.find(".history-commit").eq(commitIndex); + + // Ensure the commit row exists + expect($commitRow.length).toBe(1); + + // Click the row to show the history viewer + $commitRow.trigger("click"); + await waitForHistoryViewerVisible(true); + + // Verify that the history viewer shows the correct commit + const $historyViewer = $("#editor-holder .git"); + await awaitsFor(() => { + return $historyViewer.find(".commit-title").text().trim().includes("first commit"); + }, `History viewer to have commit detail`); + + // Click the row again to dismiss the history viewer + $commitRow.trigger("click"); + await waitForHistoryViewerVisible(false); + } + + it("should show the history viewer when clicking the first commit row and dismiss it on clicking again", async () => { + const $historyToggleButton = $gitPanel.find(".git-history-toggle"); + $historyToggleButton.trigger("click"); + await waitForHistoryVisible(true); // Ensure the history list is visible + await testHistoryViewerToggle(1); // Test for the first commit row + }); + }); }); From 7f6ef6579df243675093740348fba15c2b4d01d3 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 17 Jan 2025 00:19:15 +0530 Subject: [PATCH 4/4] test: git username test fix --- test/spec/Extn-Git-integ-test.js | 47 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/test/spec/Extn-Git-integ-test.js b/test/spec/Extn-Git-integ-test.js index ab04bb953b..2d40c4b030 100644 --- a/test/spec/Extn-Git-integ-test.js +++ b/test/spec/Extn-Git-integ-test.js @@ -78,29 +78,6 @@ define(function (require, exports, module) { $gitIcon = $("#git-toolbar-icon"); }); - it("should git username and email be valid", async function () { - const tempUser = "phcodeTestGitUser"; - const tempEmail = "phcodeTestGitUser@gmail.com"; - // username validate - let currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); - if(!currentVal) { - await testWindow.phoenixGitEvents.Git.setConfig("user.name", tempUser, true); - currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); - expect(currentVal).toBe(tempUser); - } else { - expect(currentVal).toBeDefined(); - } - // email validate - currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); - if(!currentVal) { - await testWindow.phoenixGitEvents.Git.setConfig("user.email", tempEmail, true); - currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); - expect(currentVal).toBe(tempEmail); - } else { - expect(currentVal).toBeDefined(); - } - }); - it("should only git settings, init and clone commands be enabled in non-git repos", async function () { await forCommandEnabled(Commands.CMD_GIT_INIT); await forCommandEnabled(Commands.CMD_GIT_CLONE); @@ -150,7 +127,6 @@ define(function (require, exports, module) { } } - it("Should clicking on file in git panel should open it", async function () { await showGitPanel(); clickOpenFile(0); @@ -163,6 +139,29 @@ define(function (require, exports, module) { }, "first file to open"); }); + it("should git username and email be valid", async function () { + const tempUser = "phcodeTestGitUser"; + const tempEmail = "phcodeTestGitUser@gmail.com"; + // username validate + let currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); + if(!currentVal) { + await testWindow.phoenixGitEvents.Git.setConfig("user.name", tempUser, true); + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.name"); + expect(currentVal).toBe(tempUser); + } else { + expect(currentVal).toBeDefined(); + } + // email validate + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); + if(!currentVal) { + await testWindow.phoenixGitEvents.Git.setConfig("user.email", tempEmail, true); + currentVal = await testWindow.phoenixGitEvents.Git.getConfig("user.email"); + expect(currentVal).toBe(tempEmail); + } else { + expect(currentVal).toBeDefined(); + } + }); + async function commitAllBtnClick() { await showGitPanel(); if(!$(".check-all").prop("checked")) {