From 2869d5f7eaea0cf613d139b3a7d9e1da9d312419 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 1 Sep 2025 23:56:02 +0530 Subject: [PATCH 1/7] feat: add delete and duplicate button tests --- test/spec/LiveDevelopmentMultiBrowser-test.js | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index 0b5b59c68..d6cfafbec 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -2126,6 +2126,115 @@ define(function (require, exports, module) { await endEditModePreviewSession(); }, 30000); + + it("should delete element from source code when delete button is clicked", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain('id="testId"'); // Ensure test element exists + + // Click on the test element to show more options box + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Click the delete button in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let deleteButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + deleteButton = host.shadowRoot.querySelector('span[data-action="delete"]'); + } + }); + + if (deleteButton) { + deleteButton.click(); + } + `); + + // Wait for the operation to complete + await awaits(1000); + + // Verify the element is removed from source code + const updatedContent = DocumentManager.getCurrentDocument().getText(); + expect(updatedContent).not.toContain('id="testId"'); + expect(updatedContent.length).toBeLessThan(originalContent.length); + + // Verify the element is also removed from DOM + await forRemoteExec(`!!document.getElementById('testId')`, (result) => { + return result === false; + }); + + await endEditModePreviewSession(); + }, 30000); + + it("should duplicate element in source code when duplicate button is clicked", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain('id="testId"'); // Ensure test element exists + + // Count initial occurrences of the test element + const originalTestIdCount = (originalContent.match(/id="testId"/g) || []).length; + expect(originalTestIdCount).toBe(1); // Should have exactly one initially + + // Click on the test element to show more options box + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Click the duplicate button in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let duplicateButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + duplicateButton = host.shadowRoot.querySelector('span[data-action="duplicate"]'); + } + }); + + if (duplicateButton) { + duplicateButton.click(); + } + `); + + // Wait for the operation to complete + await awaits(1000); + + // Verify the element is duplicated in source code + const updatedContent = DocumentManager.getCurrentDocument().getText(); + const newTestIdCount = (updatedContent.match(/id="testId"/g) || []).length; + expect(newTestIdCount).toBe(2); // Should now have two instances + expect(updatedContent.length).toBeGreaterThan(originalContent.length); + + // Verify both elements exist in the DOM + await forRemoteExec(`document.querySelectorAll('[id="testId"]').length`, (result) => { + return result === 2; + }); + + // Verify both elements have the same text content + await forRemoteExec(` + const elements = document.querySelectorAll('[id="testId"]'); + elements.length === 2 && elements[0].textContent === elements[1].textContent + `, (result) => { + return result === true; + }); + + await endEditModePreviewSession(); + }, 30000); }); }); }); From 674cdd331f70f6ad4c03e87863425f5d8625331b Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 2 Sep 2025 00:34:28 +0530 Subject: [PATCH 2/7] feat: add tests for edit mode --- test/spec/LiveDevelopmentMultiBrowser-test.js | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index d6cfafbec..a1eee4fea 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -2235,6 +2235,275 @@ define(function (require, exports, module) { await endEditModePreviewSession(); }, 30000); + + it("should edit text content via double-click and sync to source", async function () { + await awaitsForDone( + SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html" + ); + + await waitsForLiveDevelopmentToOpenWithEditMode("hover"); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain("Brackets is awesome!"); // Original text + + const newText = "Phoenix is fantastic!"; + + // Double-click the element to start editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new MouseEvent('dblclick', { + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + // Wait a moment for edit mode to activate + await awaits(500); + + // Verify element is in edit mode (contenteditable) + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === true; + }); + + // Modify the text content + await forRemoteExec(` + const element = document.getElementById('testId'); + element.textContent = '${newText}'; + // Trigger input event to simulate user typing + element.dispatchEvent(new Event('input', { bubbles: true })); + `); + + // Press Enter to finish editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new KeyboardEvent('keydown', { + key: 'Enter', + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + // Wait for the operation to complete + await awaits(1000); + + // Verify the text is updated in source code + const updatedContent = DocumentManager.getCurrentDocument().getText(); + expect(updatedContent).toContain(newText); + expect(updatedContent).not.toContain("Brackets is awesome!"); + + // Verify the text is updated in DOM + await forRemoteExec(`document.getElementById('testId').textContent.trim()`, (result) => { + return result === newText; + }); + + await endEditModePreviewSession(); + }, 30000); + + it("should edit text content via edit button and sync to source", async function () { + await awaitsForDone( + SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html" + ); + + await waitsForLiveDevelopmentToOpenWithEditMode("hover"); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain("Brackets is awesome!"); // Original text + + const newText = "Edited via button!"; + + // Click on the test element to show more options box + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Click the edit-text button in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let editButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + editButton = host.shadowRoot.querySelector('span[data-action="edit-text"]'); + } + }); + + if (editButton) { + editButton.click(); + } + `); + + // Wait for edit mode to activate + await awaits(500); + + // Verify element is in edit mode + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === true; + }); + + // Modify the text content + await forRemoteExec(` + const element = document.getElementById('testId'); + element.textContent = '${newText}'; + element.dispatchEvent(new Event('input', { bubbles: true })); + `); + + // Press Enter to finish editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new KeyboardEvent('keydown', { + key: 'Enter', + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + // Wait for operation to complete + await awaits(1000); + + // Verify changes in source code + const updatedContent = DocumentManager.getCurrentDocument().getText(); + expect(updatedContent).toContain(newText); + expect(updatedContent).not.toContain("Brackets is awesome!"); + + // Verify changes in DOM + await forRemoteExec(`document.getElementById('testId').textContent.trim()`, (result) => { + return result === newText; + }); + + await endEditModePreviewSession(); + }, 30000); + + it("should cancel text edit when Escape key is pressed", async function () { + await awaitsForDone( + SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html" + ); + + await waitsForLiveDevelopmentToOpenWithEditMode("hover"); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain("Brackets is awesome!"); // Original text + + const temporaryText = "This should be cancelled!"; + + // Double-click to start editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new MouseEvent('dblclick', { + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + await awaits(500); + + // Modify the text content + await forRemoteExec(` + const element = document.getElementById('testId'); + element.textContent = '${temporaryText}'; + element.dispatchEvent(new Event('input', { bubbles: true })); + `); + + // Press Escape to cancel editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new KeyboardEvent('keydown', { + key: 'Escape', + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + // Wait for operation to complete + await awaits(1000); + + // Verify source code is unchanged (edit was cancelled) + const finalContent = DocumentManager.getCurrentDocument().getText(); + expect(finalContent).toContain("Brackets is awesome!"); // Original text preserved + expect(finalContent).not.toContain(temporaryText); // Temporary text not saved + + // Verify DOM reverted to original text + await forRemoteExec(`document.getElementById('testId').textContent.trim()`, (result) => { + return result === "Brackets is awesome!"; + }); + + // Verify element is no longer in edit mode + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === false; + }); + + await endEditModePreviewSession(); + }, 30000); + + it("should finish text edit when element loses focus (blur)", async function () { + await awaitsForDone( + SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html" + ); + + await waitsForLiveDevelopmentToOpenWithEditMode("hover"); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain("Brackets is awesome!"); // Original text + + const newText = "Edited via blur event!"; + + // Double-click to start editing + await forRemoteExec(` + const element = document.getElementById('testId'); + const event = new MouseEvent('dblclick', { + bubbles: true, + cancelable: true + }); + element.dispatchEvent(event); + `); + + await awaits(500); + + // Modify the text content + await forRemoteExec(` + const element = document.getElementById('testId'); + element.textContent = '${newText}'; + element.dispatchEvent(new Event('input', { bubbles: true })); + `); + + // Click outside the element to trigger blur + await forRemoteExec(` + document.body.click(); // Click on body to lose focus + `); + + // Wait for operation to complete + await awaits(1000); + + // Verify changes were saved in source code + const updatedContent = DocumentManager.getCurrentDocument().getText(); + expect(updatedContent).toContain(newText); + expect(updatedContent).not.toContain("Brackets is awesome!"); + + // Verify changes in DOM + await forRemoteExec(`document.getElementById('testId').textContent.trim()`, (result) => { + return result === newText; + }); + + // Verify element is no longer in edit mode + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === false; + }); + + await endEditModePreviewSession(); + }, 30000); }); }); }); From a27d954f939c6cd5b944d87ffa5acee6e1da9fd2 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 2 Sep 2025 16:42:54 +0530 Subject: [PATCH 3/7] feat: add tests for undo after delete/duplicate operations --- test/spec/LiveDevelopmentMultiBrowser-test.js | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index a1eee4fea..6bdc29310 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -2504,6 +2504,171 @@ define(function (require, exports, module) { await endEditModePreviewSession(); }, 30000); + + it("should restore deleted element when undo is pressed after delete operation", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain('id="testId"'); // Ensure test element exists + + // Store original element text for verification + const originalElementText = await forRemoteExec(`document.getElementById('testId').textContent.trim()`); + + // Click on the test element to show more options box + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Click the delete button in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let deleteButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + deleteButton = host.shadowRoot.querySelector('span[data-action="delete"]'); + } + }); + + if (deleteButton) { + deleteButton.click(); + } + `); + + // Wait for the delete operation to complete + await awaits(1000); + + // Verify the element is removed from source code + const deletedContent = DocumentManager.getCurrentDocument().getText(); + expect(deletedContent).not.toContain('id="testId"'); + expect(deletedContent.length).toBeLessThan(originalContent.length); + + // Verify the element is also removed from DOM + await forRemoteExec(`!!document.getElementById('testId')`, (result) => { + return result === false; + }); + + // Now perform undo operation using Ctrl+Z + await forRemoteExec(` + const event = new KeyboardEvent('keydown', { + key: 'z', + ctrlKey: true, + metaKey: false, // Use false for Windows/Linux, true for Mac + bubbles: true, + cancelable: true + }); + document.dispatchEvent(event); + `); + + // Wait for the undo operation to complete + await awaits(1500); + + // Verify the element is restored in source code + const restoredContent = DocumentManager.getCurrentDocument().getText(); + expect(restoredContent).toContain('id="testId"'); + expect(restoredContent.length).toBe(originalContent.length); + + // Verify the element is restored in DOM + await forRemoteExec(`!!document.getElementById('testId')`, (result) => { + return result === true; + }); + + // Verify the restored element has the same text content + await forRemoteExec(`document.getElementById('testId').textContent.trim()`, (result) => { + return result === originalElementText; + }); + + await endEditModePreviewSession(); + }, 30000); + + it("should restore original state when undo is pressed after duplicate operation", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Get original source code content + const originalContent = DocumentManager.getCurrentDocument().getText(); + expect(originalContent).toContain('id="testId"'); // Ensure test element exists + + // Count initial occurrences of the test element + const originalTestIdCount = (originalContent.match(/id="testId"/g) || []).length; + expect(originalTestIdCount).toBe(1); // Should have exactly one initially + + // Click on the test element to show more options box + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Click the duplicate button in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let duplicateButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + duplicateButton = host.shadowRoot.querySelector('span[data-action="duplicate"]'); + } + }); + + if (duplicateButton) { + duplicateButton.click(); + } + `); + + // Wait for the duplicate operation to complete + await awaits(1000); + + // Verify the element is duplicated in source code + const duplicatedContent = DocumentManager.getCurrentDocument().getText(); + const newTestIdCount = (duplicatedContent.match(/id="testId"/g) || []).length; + expect(newTestIdCount).toBe(2); // Should now have two instances + expect(duplicatedContent.length).toBeGreaterThan(originalContent.length); + + // Verify both elements exist in the DOM + await forRemoteExec(`document.querySelectorAll('[id="testId"]').length`, (result) => { + return result === 2; + }); + + // Now perform undo operation using Ctrl+Z + await forRemoteExec(` + const event = new KeyboardEvent('keydown', { + key: 'z', + ctrlKey: true, + metaKey: false, // Use false for Windows/Linux, true for Mac + bubbles: true, + cancelable: true + }); + document.dispatchEvent(event); + `); + + // Wait for the undo operation to complete + await awaits(1500); + + // Verify the duplicate is removed and we're back to original state + const restoredContent = DocumentManager.getCurrentDocument().getText(); + const restoredTestIdCount = (restoredContent.match(/id="testId"/g) || []).length; + expect(restoredTestIdCount).toBe(1); // Should be back to one instance + expect(restoredContent.length).toBe(originalContent.length); + + // Verify only one element exists in DOM + await forRemoteExec(`document.querySelectorAll('[id="testId"]').length`, (result) => { + return result === 1; + }); + + // Verify the remaining element still has correct content + await forRemoteExec(`!!document.getElementById('testId')`, (result) => { + return result === true; + }); + + await endEditModePreviewSession(); + }, 30000); }); }); }); From bf06d15d2cfbde44b329a3ed757ec03386ddd556 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 2 Sep 2025 16:58:23 +0530 Subject: [PATCH 4/7] feat: shouldn't show select parent when elements parent is body tag test --- test/spec/LiveDevelopmentMultiBrowser-test.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index 6bdc29310..3493bc237 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -2669,6 +2669,37 @@ define(function (require, exports, module) { await endEditModePreviewSession(); }, 30000); + + it("should not show select parent option when element's direct parent is body", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Click on the test element (which has body as direct parent in simple1.html) + await forRemoteExec(`document.getElementById('testId').click()`); + + // Wait for more options box to appear + await waitForMoreOptionsBox(true); + + // Check that select-parent option is NOT present in the shadow DOM + await forRemoteExec(` + const shadowHosts = Array.from(document.body.children).filter(el => el.shadowRoot); + let selectParentButton = null; + + shadowHosts.forEach(host => { + if (host.shadowRoot && host.shadowRoot.innerHTML.includes('phoenix-more-options-box')) { + selectParentButton = host.shadowRoot.querySelector('span[data-action="select-parent"]'); + } + }); + + selectParentButton === null; + `, (result) => { + return result === true; + }); + + await endEditModePreviewSession(); + }, 30000); }); }); }); From d56e1781d47fc332a82ad92997ba5c86f9b17fa6 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 2 Sep 2025 17:38:14 +0530 Subject: [PATCH 5/7] feat: add tests for preview mode/play button --- test/spec/LiveDevelopmentMultiBrowser-test.js | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index 3493bc237..e4ec99cc8 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -1968,6 +1968,26 @@ define(function (require, exports, module) { await waitForClickedElement(false); } + async function switchToPreviewMode() { + if (LiveDevMultiBrowser && LiveDevMultiBrowser.config) { + LiveDevMultiBrowser.config.isProUser = false; + if (LiveDevMultiBrowser.updateConfig) { + LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); + } + } + await awaits(500); + } + + async function switchToEditMode() { + if (LiveDevMultiBrowser && LiveDevMultiBrowser.config) { + LiveDevMultiBrowser.config.isProUser = true; + if (LiveDevMultiBrowser.updateConfig) { + LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); + } + } + await awaits(500); + } + it("should show info box on hover when elemHighlights is 'hover'", async function () { await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), "SpecRunnerUtils.openProjectFiles simple1.html"); @@ -2700,6 +2720,86 @@ define(function (require, exports, module) { await endEditModePreviewSession(); }, 30000); + + it("should hide UI boxes when switching to preview mode and show them when switching back to edit mode", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Step 1: Click element to show UI boxes in edit mode + await forRemoteExec(`document.getElementById('testId').click()`); + + // Step 2: Verify boxes are visible + await waitForMoreOptionsBox(true); + await waitForClickedElement(true); + + // Step 3: Switch to preview mode + await switchToPreviewMode(); + + // Step 4: Verify boxes are hidden after mode switch + await waitForMoreOptionsBox(false); + await waitForClickedElement(false); + + // Step 5: Verify clicking element in preview mode doesn't show boxes + await forRemoteExec(`document.getElementById('testId').click()`); + await awaits(300); // Brief wait to ensure no boxes appear + await waitForMoreOptionsBox(false); + await waitForClickedElement(false); + + // Step 6: Switch back to edit mode + await switchToEditMode(); + + // Step 7: Click element again to show boxes in edit mode + await forRemoteExec(`document.getElementById('testId').click()`); + + // Step 8: Verify boxes are visible again + await waitForMoreOptionsBox(true); + await waitForClickedElement(true); + + await endEditModePreviewSession(); + }, 30000); + + it("should switch to preview mode when preview (play icon) button is clicked", async function () { + await awaitsForDone(SpecRunnerUtils.openProjectFiles(["simple1.html"]), + "SpecRunnerUtils.openProjectFiles simple1.html"); + + await waitsForLiveDevelopmentToOpenWithEditMode('hover'); + + // Step 1: Click element to show UI boxes in edit mode + await forRemoteExec(`document.getElementById('testId').click()`); + + // Step 2: Verify boxes are visible in edit mode + await waitForMoreOptionsBox(true); + await waitForClickedElement(true); + + // Step 3: Click the preview (play icon) button in the toolbar + testWindow.$("#previewModeLivePreviewButton").click(); + await awaits(1000); // Wait for mode switch and preference update + + // Step 4: Verify boxes are hidden after clicking preview button + await waitForMoreOptionsBox(false); + await waitForClickedElement(false); + + // Step 5: Verify clicking element in preview mode doesn't show boxes + await forRemoteExec(`document.getElementById('testId').click()`); + await awaits(300); + await waitForMoreOptionsBox(false); + await waitForClickedElement(false); + + // Step 6: Click preview button again to toggle back to edit mode + testWindow.$("#previewModeLivePreviewButton").click(); + await awaits(1000); // Wait for mode switch and preference update + + // Step 7: Click element to verify boxes work again in edit mode + await forRemoteExec(`document.getElementById('testId').click()`); + + // Step 8: Verify boxes are visible again + await waitForMoreOptionsBox(true); + await waitForClickedElement(true); + + await endEditModePreviewSession(); + }, 30000); }); }); }); From dea2e0560897d918ea4263c6aecefc0d3af0880a Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 2 Sep 2025 18:09:31 +0530 Subject: [PATCH 6/7] refactor: replace await awaits(..) with awaitsFor --- test/spec/LiveDevelopmentMultiBrowser-test.js | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index e4ec99cc8..7569c004c 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -1975,7 +1975,6 @@ define(function (require, exports, module) { LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); } } - await awaits(500); } async function switchToEditMode() { @@ -1985,7 +1984,6 @@ define(function (require, exports, module) { LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); } } - await awaits(500); } it("should show info box on hover when elemHighlights is 'hover'", async function () { @@ -2179,10 +2177,12 @@ define(function (require, exports, module) { } `); - // Wait for the operation to complete - await awaits(1000); - // Verify the element is removed from source code + await awaitsFor(function () { + const updatedContent = DocumentManager.getCurrentDocument().getText(); + return !updatedContent.includes('id="testId"'); + }, "element to be removed from source code"); + const updatedContent = DocumentManager.getCurrentDocument().getText(); expect(updatedContent).not.toContain('id="testId"'); expect(updatedContent.length).toBeLessThan(originalContent.length); @@ -2232,7 +2232,11 @@ define(function (require, exports, module) { `); // Wait for the operation to complete - await awaits(1000); + await awaitsFor(function () { + const updatedContent = DocumentManager.getCurrentDocument().getText(); + const newTestIdCount = (updatedContent.match(/id="testId"/g) || []).length; + return newTestIdCount === 2; + }, "element to be duplicated in source code"); // Verify the element is duplicated in source code const updatedContent = DocumentManager.getCurrentDocument().getText(); @@ -2280,8 +2284,10 @@ define(function (require, exports, module) { element.dispatchEvent(event); `); - // Wait a moment for edit mode to activate - await awaits(500); + // Wait for edit mode to activate + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === true; + }); // Verify element is in edit mode (contenteditable) await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { @@ -2308,7 +2314,10 @@ define(function (require, exports, module) { `); // Wait for the operation to complete - await awaits(1000); + await awaitsFor(function () { + const updatedContent = DocumentManager.getCurrentDocument().getText(); + return updatedContent.includes(newText); + }, "text to be updated in source code"); // Verify the text is updated in source code const updatedContent = DocumentManager.getCurrentDocument().getText(); @@ -2360,7 +2369,9 @@ define(function (require, exports, module) { `); // Wait for edit mode to activate - await awaits(500); + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + return result === true; + }); // Verify element is in edit mode await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { @@ -2386,7 +2397,10 @@ define(function (require, exports, module) { `); // Wait for operation to complete - await awaits(1000); + await awaitsFor(function () { + const updatedContent = DocumentManager.getCurrentDocument().getText(); + return updatedContent.includes(newText); + }, "text changes to be saved in source code"); // Verify changes in source code const updatedContent = DocumentManager.getCurrentDocument().getText(); @@ -2425,8 +2439,6 @@ define(function (require, exports, module) { element.dispatchEvent(event); `); - await awaits(500); - // Modify the text content await forRemoteExec(` const element = document.getElementById('testId'); @@ -2446,7 +2458,10 @@ define(function (require, exports, module) { `); // Wait for operation to complete - await awaits(1000); + await awaitsFor(function () { + const finalContent = DocumentManager.getCurrentDocument().getText(); + return finalContent === originalContent; + }, "edit to be cancelled and source unchanged"); // Verify source code is unchanged (edit was cancelled) const finalContent = DocumentManager.getCurrentDocument().getText(); @@ -2490,8 +2505,6 @@ define(function (require, exports, module) { element.dispatchEvent(event); `); - await awaits(500); - // Modify the text content await forRemoteExec(` const element = document.getElementById('testId'); @@ -2505,7 +2518,10 @@ define(function (require, exports, module) { `); // Wait for operation to complete - await awaits(1000); + await awaitsFor(function () { + const updatedContent = DocumentManager.getCurrentDocument().getText(); + return updatedContent.includes(newText); + }, "blur event to save changes to source code"); // Verify changes were saved in source code const updatedContent = DocumentManager.getCurrentDocument().getText(); @@ -2561,7 +2577,10 @@ define(function (require, exports, module) { `); // Wait for the delete operation to complete - await awaits(1000); + await awaitsFor(function () { + const deletedContent = DocumentManager.getCurrentDocument().getText(); + return !deletedContent.includes('id="testId"'); + }, "delete operation to complete"); // Verify the element is removed from source code const deletedContent = DocumentManager.getCurrentDocument().getText(); @@ -2586,7 +2605,10 @@ define(function (require, exports, module) { `); // Wait for the undo operation to complete - await awaits(1500); + await awaitsFor(function () { + const restoredContent = DocumentManager.getCurrentDocument().getText(); + return restoredContent.includes('id="testId"'); + }, "undo operation to restore deleted element"); // Verify the element is restored in source code const restoredContent = DocumentManager.getCurrentDocument().getText(); @@ -2643,7 +2665,11 @@ define(function (require, exports, module) { `); // Wait for the duplicate operation to complete - await awaits(1000); + await awaitsFor(function () { + const duplicatedContent = DocumentManager.getCurrentDocument().getText(); + const newTestIdCount = (duplicatedContent.match(/id="testId"/g) || []).length; + return newTestIdCount === 2; + }, "duplicate operation to complete"); // Verify the element is duplicated in source code const duplicatedContent = DocumentManager.getCurrentDocument().getText(); @@ -2669,7 +2695,11 @@ define(function (require, exports, module) { `); // Wait for the undo operation to complete - await awaits(1500); + await awaitsFor(function () { + const restoredContent = DocumentManager.getCurrentDocument().getText(); + const restoredTestIdCount = (restoredContent.match(/id="testId"/g) || []).length; + return restoredTestIdCount === 1; + }, "undo operation to remove duplicate"); // Verify the duplicate is removed and we're back to original state const restoredContent = DocumentManager.getCurrentDocument().getText(); @@ -2743,7 +2773,6 @@ define(function (require, exports, module) { // Step 5: Verify clicking element in preview mode doesn't show boxes await forRemoteExec(`document.getElementById('testId').click()`); - await awaits(300); // Brief wait to ensure no boxes appear await waitForMoreOptionsBox(false); await waitForClickedElement(false); @@ -2775,7 +2804,6 @@ define(function (require, exports, module) { // Step 3: Click the preview (play icon) button in the toolbar testWindow.$("#previewModeLivePreviewButton").click(); - await awaits(1000); // Wait for mode switch and preference update // Step 4: Verify boxes are hidden after clicking preview button await waitForMoreOptionsBox(false); @@ -2783,13 +2811,11 @@ define(function (require, exports, module) { // Step 5: Verify clicking element in preview mode doesn't show boxes await forRemoteExec(`document.getElementById('testId').click()`); - await awaits(300); await waitForMoreOptionsBox(false); await waitForClickedElement(false); // Step 6: Click preview button again to toggle back to edit mode testWindow.$("#previewModeLivePreviewButton").click(); - await awaits(1000); // Wait for mode switch and preference update // Step 7: Click element to verify boxes work again in edit mode await forRemoteExec(`document.getElementById('testId').click()`); From f5a677bcf31c52273ae97aa667d1584d64d00858 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 8 Sep 2025 14:38:12 +0530 Subject: [PATCH 7/7] fix: tests failing on desktop timing issues --- test/spec/LiveDevelopmentMultiBrowser-test.js | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/spec/LiveDevelopmentMultiBrowser-test.js b/test/spec/LiveDevelopmentMultiBrowser-test.js index 7569c004c..81f9292ef 100644 --- a/test/spec/LiveDevelopmentMultiBrowser-test.js +++ b/test/spec/LiveDevelopmentMultiBrowser-test.js @@ -1974,6 +1974,7 @@ define(function (require, exports, module) { if (LiveDevMultiBrowser.updateConfig) { LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); } + await awaits(200); } } @@ -1983,6 +1984,7 @@ define(function (require, exports, module) { if (LiveDevMultiBrowser.updateConfig) { LiveDevMultiBrowser.updateConfig(JSON.stringify(LiveDevMultiBrowser.config)); } + await awaits(200); } } @@ -2285,12 +2287,7 @@ define(function (require, exports, module) { `); // Wait for edit mode to activate - await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { - return result === true; - }); - - // Verify element is in edit mode (contenteditable) - await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable') && document.getElementById('testId').getAttribute('contenteditable') === 'true'`, (result) => { return result === true; }); @@ -2369,12 +2366,7 @@ define(function (require, exports, module) { `); // Wait for edit mode to activate - await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { - return result === true; - }); - - // Verify element is in edit mode - await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable')`, (result) => { + await forRemoteExec(`document.getElementById('testId').hasAttribute('contenteditable') && document.getElementById('testId').getAttribute('contenteditable') === 'true'`, (result) => { return result === true; }); @@ -2594,10 +2586,11 @@ define(function (require, exports, module) { // Now perform undo operation using Ctrl+Z await forRemoteExec(` + const isMac = ${brackets.platform === "mac"}; const event = new KeyboardEvent('keydown', { key: 'z', - ctrlKey: true, - metaKey: false, // Use false for Windows/Linux, true for Mac + ctrlKey: !isMac, + metaKey: isMac, bubbles: true, cancelable: true }); @@ -2684,10 +2677,11 @@ define(function (require, exports, module) { // Now perform undo operation using Ctrl+Z await forRemoteExec(` + const isMac = ${brackets.platform === "mac"}; const event = new KeyboardEvent('keydown', { key: 'z', - ctrlKey: true, - metaKey: false, // Use false for Windows/Linux, true for Mac + ctrlKey: !isMac, + metaKey: isMac, bubbles: true, cancelable: true }); @@ -2804,6 +2798,7 @@ define(function (require, exports, module) { // Step 3: Click the preview (play icon) button in the toolbar testWindow.$("#previewModeLivePreviewButton").click(); + await awaits(200); // Step 4: Verify boxes are hidden after clicking preview button await waitForMoreOptionsBox(false); @@ -2816,6 +2811,7 @@ define(function (require, exports, module) { // Step 6: Click preview button again to toggle back to edit mode testWindow.$("#previewModeLivePreviewButton").click(); + await awaits(200); // Step 7: Click element to verify boxes work again in edit mode await forRemoteExec(`document.getElementById('testId').click()`);