diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Comments/AddComments_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Comments/AddComments_spec.js new file mode 100644 index 0000000000..64f473c472 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Comments/AddComments_spec.js @@ -0,0 +1,132 @@ +const commentsLocators = require("../../../../locators/commentsLocators.json"); +const commonLocators = require("../../../../locators/commonlocators.json"); +const homePage = require("../../../../locators/HomePage.json"); +const dsl = require("../../../../fixtures/basicDsl.json"); + +function setFlagForTour() { + return new Promise((resolve) => { + const request = indexedDB.open("Appsmith", 2); // had to use version: 2 here, TODO: check why + request.onerror = function(event) { + console.log("Error loading database", event); + }; + request.onsuccess = function(event) { + const db = request.result; + const transaction = db.transaction("keyvaluepairs", "readwrite"); + const objectStore = transaction.objectStore("keyvaluepairs"); + objectStore.put(true, "CommentsIntroSeen"); + resolve(); + }; + }); +} + +function typeIntoDraftEditor(selector, text) { + cy.get(selector).then((input) => { + var textarea = input.get(0); + textarea.dispatchEvent(new Event("focus")); + + var textEvent = document.createEvent("TextEvent"); + textEvent.initTextEvent("textInput", true, true, null, text); + textarea.dispatchEvent(textEvent); + + textarea.dispatchEvent(new Event("blur")); + }); +} + +const newCommentText1 = "new comment text 1"; +let commentThreadId; +let appName; + +describe("Comments", function() { + before(() => { + return cy.wrap(null).then(async () => { + cy.addDsl(dsl); + appName = localStorage.getItem("AppName"); + await setFlagForTour(); + }); + }); + + /** + * create new comment thread + * share app with an admin user + * - check if he can view the comments on edit mode + * - check the unread indicator shows due to unread comments + * publish and check if the comment shows up on view mode + */ + + it("new comments can be created after switching to comment mode", () => { + return cy.wrap(null).then(async () => { + // wait for the page to load + cy.get(commonLocators.canvas); + cy.get(commentsLocators.switchToCommentModeBtn).click({ force: true }); + cy.get(commonLocators.canvas).click(50, 50); + typeIntoDraftEditor(commentsLocators.mentionsInput, newCommentText1); + cy.get(commentsLocators.mentionsInput).type("{enter}"); + await cy.wait("@createNewThread"); + }); + }); + + // create another comment since the first one is a private bot thread + it("another comment can be created after dismissing the first one", () => { + cy.get(commonLocators.canvas).click(10, 10); + // wait for transition to be completed + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(300); + typeIntoDraftEditor(commentsLocators.mentionsInput, newCommentText1); + cy.get(commentsLocators.mentionsInput).type("{enter}"); + cy.wait("@createNewThread").then((response) => { + commentThreadId = response.response.body.data.id; + }); + }); + + it("unread indicator is visible for another app user when a new comment is added", () => { + // share app with TESTUSERNAME2 + cy.get(homePage.shareApp).click({ force: true }); + cy.shareApp(Cypress.env("TESTUSERNAME2"), homePage.adminRole); + cy.LogintoApp(Cypress.env("TESTUSERNAME2"), Cypress.env("TESTPASSWORD2")); + + // launch the editor + cy.get(homePage.searchInput).type(appName); + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(2000); + cy.get(homePage.applicationCard) + .first() + .trigger("mouseover"); + cy.get(homePage.appEditIcon) + .first() + .click({ force: true }); + cy.get("#loading").should("not.exist"); + + // unread indicator should be visible since a new comment was added + cy.get(commentsLocators.toggleCommentModeOnUnread).should("exist"); + cy.get(commentsLocators.toggleCommentModeOn).should("not.exist"); + }); + + it("is visible for the other app users in edit mode", () => { + cy.get(commentsLocators.switchToCommentModeBtn).click({ + force: true, + }); + cy.get( + `${commentsLocators.inlineCommentThreadPin}${commentThreadId}`, + ).click({ force: true }); + cy.contains(newCommentText1); + }); + + it("unread indicator should be hidden once all comment threads are marked as read", () => { + // thread should be marked as read by clicking before, unread indicator should not be visible + cy.get(commentsLocators.toggleCommentModeOnUnread).should("not.exist"); + cy.get(commentsLocators.toggleCommentModeOn).should("exist"); + }); + + it("is visible in the published mode", () => { + cy.PublishtheApp(); + // wait for the published page to load + cy.get(commonLocators.viewerPage); + cy.get(commentsLocators.switchToCommentModeBtn).click({ + force: true, + }); + cy.get( + `${commentsLocators.inlineCommentThreadPin}${commentThreadId}`, + ).click({ force: true }); + cy.contains(newCommentText1); + }); +}); diff --git a/app/client/cypress/locators/commentsLocators.json b/app/client/cypress/locators/commentsLocators.json new file mode 100644 index 0000000000..de72ea0d8b --- /dev/null +++ b/app/client/cypress/locators/commentsLocators.json @@ -0,0 +1,8 @@ +{ + "switchToCommentModeBtn": ".t--switch-comment-mode-on", + "mentionsInput": "[data-testid='mentions-input']", + "postButtonAddComment": "[data-cy='add-comment-submit']", + "inlineCommentThreadPin": ".t--inline-comment-pin-trigger-", + "toggleCommentModeOnUnread": ".t--toggle-comment-mode-on--unread", + "toggleCommentModeOn": ".t--toggle-comment-mode-on" +} diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index 73095cc9fa..f999beb8b8 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -115,5 +115,6 @@ "currencyType": ".t--property-control-currency .bp3-popover-target", "decimalType": ".t--property-control-decimals .bp3-popover-target", "allowCurrencyChange": ".t--property-control-allowcurrencychange input[type='checkbox']", - "inputCurrencyChangeType": ".t--input-currency-change" + "inputCurrencyChangeType": ".t--input-currency-change", + "viewerPage": ".t--app-viewer-page" } diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index 2f8d8b4e6f..b06628c311 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -2454,6 +2454,9 @@ Cypress.Commands.add("startServerAndRoutes", () => { cy.route("DELETE", "/api/v1/organizations/*/logo").as("deleteLogo"); cy.route("POST", "/api/v1/applications/*/fork/*").as("postForkAppOrg"); cy.route("PUT", "/api/v1/users/leaveOrganization/*").as("leaveOrgApiCall"); + + cy.route("POST", "/api/v1/comments/threads").as("createNewThread"); + cy.route("POST", "/api/v1/comments?threadId=*").as("createNewComment"); }); Cypress.Commands.add("alertValidate", (text) => { diff --git a/app/client/src/comments/inlineComments/InlineCommentPin.tsx b/app/client/src/comments/inlineComments/InlineCommentPin.tsx index 576a62305d..b66070ed1b 100644 --- a/app/client/src/comments/inlineComments/InlineCommentPin.tsx +++ b/app/client/src/comments/inlineComments/InlineCommentPin.tsx @@ -78,7 +78,7 @@ function Pin({ return ( + {props.dsl.widgetId && WidgetFactory.createWidget(props.dsl, RenderModes.PAGE)} diff --git a/app/client/src/pages/Editor/ToggleModeButton.tsx b/app/client/src/pages/Editor/ToggleModeButton.tsx index 9afd697a79..60dcc3e159 100644 --- a/app/client/src/pages/Editor/ToggleModeButton.tsx +++ b/app/client/src/pages/Editor/ToggleModeButton.tsx @@ -269,11 +269,14 @@ function CommentModeBtn({ showSelectedMode: boolean; }) { const CommentModeIcon = showUnreadIndicator ? CommentModeUnread : CommentMode; + const commentModeClassName = showUnreadIndicator + ? `t--toggle-comment-mode-on--unread` + : `t--toggle-comment-mode-on`; return ( setCommentModeInUrl(false)} showSelectedMode={showSelectedMode} type="fill"