Merge pull request #32850 from appsmithorg/release

Daily promotion 22/04
This commit is contained in:
Trisha Anand 2024-04-22 16:23:47 +05:30 committed by GitHub
commit 15df4e69fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
588 changed files with 8070 additions and 6443 deletions

2
.github/config.json vendored

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,10 @@
## Description
> [!TIP]
> _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content team)._
> _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team)._
>
> _Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR._
Fixes #`Issue Number`
_or_
Fixes `Issue URL`
@ -19,4 +20,10 @@ Fixes `Issue URL`
> [!CAUTION]
> If you modify the content in this section, you are likely to disrupt the CI result for your PR.
<!-- end of auto-generated comment: Cypress test results -->
<!-- end of auto-generated comment: Cypress test results -->
## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No

View File

@ -50,4 +50,4 @@ jobs:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
workingDir: ./app/client/packages/storybook
exitOnceUploaded: true
buildScriptName: "build"
buildScriptName: "build-storybook"

View File

@ -48,4 +48,4 @@ jobs:
projectToken: ${{ secrets.STORYBOOK_PROJECT_TOKEN }}
workingDir: ./app/client/packages/storybook
exitOnceUploaded: true
buildScriptName: "build"
buildScriptName: "build-storybook"

View File

@ -71,7 +71,7 @@ jobs:
mkdir -p ~/git-server/keys
mkdir -p ~/git-server/repos
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 4200:4200 -p 5000:5000 -p 3001:3000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
cd cicontainerlocal
docker run -d --name appsmith -p 80:80 \

View File

@ -147,7 +147,7 @@ jobs:
mkdir -p ~/git-server/repos
ted_tag="${{inputs.ted_tag}}"
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 -p 6001:6001 -p 8001:8000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 4200:4200 -p 5000:5000 -p 3001:3000 -p 6001:6001 -p 8001:8000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-v ~/git-server/repos:/git-server/repos "appsmith/test-event-driver:${ted_tag:-latest}"
docker run --name cloud-services -d -p 8000:80 -p 8090:8090 \
--privileged --pid=host --ipc=host --add-host=host.docker.internal:host-gateway\

View File

@ -167,7 +167,7 @@ jobs:
mkdir -p ~/git-server/keys
mkdir -p ~/git-server/repos
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 -p 6001:6001 -p 8001:8000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-p 5432:5432 -p 28017:27017 -p 25:25 -p 4200:4200 -p 5000:5000 -p 3001:3000 -p 6001:6001 -p 8001:8000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
docker run --name cloud-services -d -p 8000:80 -p 8090:8090 \
--privileged --pid=host --ipc=host --add-host=host.docker.internal:host-gateway\

View File

@ -22,8 +22,9 @@ jobs:
# Checkout the code in the current branch in case the workflow is called because of a branch push event
- name: Checkout the head commit of the branch
if: inputs.pr == 0
uses: actions/checkout@v4
with:
repository: appsmithorg/appsmith
# Checks for ok-to-test label presence in PR
- name: Check label

View File

@ -30,9 +30,9 @@ app/client/src/widgets/anvil/* @appsmithorg/anvil-team
# App viewers pod
app/client/src/widgets/* @appsmithorg/app-viewers
app/client/src/components/propertyControls/* @appsmithorg/app-viewers
app/client/src/sagas/OneClickBindingSaga.ts @sbalaji1192
app/client/src/WidgetQueryGenerators/* @sbalaji1192
app/client/src/components/editorComponents/WidgetQueryGeneratorForm/* @sbalaji1192
app/client/src/sagas/OneClickBindingSaga.ts @appsmithorg/app-viewers
app/client/src/WidgetQueryGenerators/* @appsmithorg/app-viewers
app/client/src/components/editorComponents/WidgetQueryGeneratorForm/* @appsmithorg/app-viewers
app/client/src/pages/AppViewer/* @appsmithorg/app-viewers
# New Developers Pod
@ -101,19 +101,16 @@ app/client/src/widgets/MetaHOC.tsx @appsmithorg/ui-builders
app/client/src/widgets/withWidgetProps.tsx @appsmithorg/ui-builders
# Git Pod
app/server/appsmith-git/* @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCEImpl.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCE.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/GitServiceCEImpl.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/GitServiceCE.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitCloudServicesUtils.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitDeployKeyGenerator.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java @AnaghHegde
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitUtils.java @AnaghHegde
app/client/src/pages/Editor/gitSync/* @brayn003
app/server/appsmith-git/ @appsmithorg/git-be-reviewers
app/server/**/git/** @appsmithorg/git-be-reviewers
app/server/**/import/** @appsmithorg/git-be-reviewers
app/server/**/export/** @appsmithorg/git-be-reviewers
app/server/**/*Git*.java @appsmithorg/git-be-reviewers
app/server/**/*Import*.java @appsmithorg/git-be-reviewers
app/server/**/*Export*.java @appsmithorg/git-be-reviewers
# DSL Package
app/client/packages/dsl/* @brayn003
app/client/src/pages/Editor/gitSync/ @appsmithorg/git-fe-reviewers
app/client/packages/dsl/ @appsmithorg/git-fe-reviewers
# Data Platform
@ -149,41 +146,12 @@ app/client/src/transformers/RestAPIDatasourceFormTransformer.ts @ayushpahwa
# Followed Globstar paths in combination with wildcard paths. Reference https://docs.gitlab.com/ee/user/project/codeowners/reference.html#globstar-paths
# Data Platform server - Interfaces
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Action* @nidhi-nair @sondermanish
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Datasource* @nidhi-nair @sondermanish
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/OAuth2* @nidhi-nair @sondermanish
# Data Platform server - Controllers
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Datasource* @nidhi-nair @sondermanish
# Data Platform server - Domains
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Datasource* @nidhi-nair @sondermanish
# Data Platform server - DTOs
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Datasource* @nidhi-nair @sondermanish
# Data Platform server - Repositories
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Datasource* @nidhi-nair @sondermanish
# Data Platform server - Services
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Datasource* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Authentication* @nidhi-nair @sondermanish
# Data Platform server - Solutions
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Action* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Datasource* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Authentication* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Environment* @nidhi-nair @sondermanish
# Data Platform server - Misc
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/**/Datasource* @nidhi-nair @sondermanish
app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError* @nidhi-nair @sondermanish
# Data Platform Pod
app/server/**/*Action* @nidhi-nair @sondermanish
app/server/**/*Datasource* @nidhi-nair @sondermanish
app/server/**/*OAuth2* @nidhi-nair @sondermanish
app/server/**/*Authentication* @nidhi-nair @sondermanish
app/server/**/*Environment* @nidhi-nair @sondermanish
# Team Managers pod
app/client/src/pages/Settings/**/* @ankitakinger

View File

@ -46,14 +46,12 @@ results/
/docker/nginx.conf
/docker/nginx-root.conf
storybook-static/*
build-storybook.log
.eslintcache
.vscode
TODO
/nginx
/caddy
/public/static/wds/

View File

@ -1,7 +1,7 @@
import EditorNavigation, {
EntityType,
PageLeftPane,
} from "../../../../support/Pages/EditorNavigation";
import PageList from "../../../../support/Pages/PageList";
const widgetsPage = require("../../../../locators/Widgets.json");
const commonlocators = require("../../../../locators/commonlocators.json");
@ -32,7 +32,7 @@ describe(
it("1. Create MyPage and valdiate if its successfully created", function () {
cy.Createpage(pageid);
agHelper.AddDsl("displayWidgetDsl");
PageLeftPane.assertPresence(pageid);
PageList.assertPresence(pageid);
//Table Widget Functionality with multiple page
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
EditorNavigation.SelectEntityByName("Table1", EntityType.Widget, {}, [

View File

@ -2,6 +2,7 @@ import {
agHelper,
appSettings,
dataSources,
debuggerHelper,
deployMode,
entityExplorer,
entityItems,
@ -118,7 +119,15 @@ describe(
after(
"Verify Deletion of the datasource after all created queries are deleted",
() => {
deployMode.NavigateBacktoEditor("ran successfully"); //runAstros triggered on PageLaoad of Edit page!
deployMode.NavigateBacktoEditor();
//verify runAstros triggered on PageLaoad of Edit page!
debuggerHelper.ClickDebuggerIcon();
debuggerHelper.ClickLogsTab();
debuggerHelper.DebuggerLogsFilter("JSObject1.runAstros");
debuggerHelper.DoesConsoleLogExist("JS Function executed successfully");
debuggerHelper.CloseBottomBar();
PageLeftPane.switchSegment(PagePaneSegment.JS);
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "JSObject1",

View File

@ -50,7 +50,7 @@ describe(
_.propPane.NavigateBackToPropertyPane();
_.debuggerHelper.ClickDebuggerIcon();
_.debuggerHelper.ClicklogEntityLink();
_.agHelper.GetNAssertContains(_.propPane._paneTitle, "Menu Item 1");
_.agHelper.GetNAssertContains(_.propPane._paneTitle, "Menu Item");
_.propPane.AssertIfPropertyIsVisible("icon");
_.debuggerHelper.CloseBottomBar();
EditorNavigation.SelectEntityByName("ButtonGroup1", EntityType.Widget);

View File

@ -5,6 +5,7 @@ import EditorNavigation, {
import * as _ from "../../../../support/Objects/ObjectsCore";
import PageList from "../../../../support/Pages/PageList";
import { EntityItems } from "../../../../support/Pages/AssertHelper";
describe(
"Hide / Show page test functionality",
@ -17,6 +18,7 @@ describe(
_.entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page2",
action: "Hide",
entityType: EntityItems.Page,
});
PageLeftPane.switchToAddNew();
cy.ClearSearch();
@ -27,6 +29,7 @@ describe(
_.entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page2",
action: "Show",
entityType: EntityItems.Page,
});
cy.ClearSearch();
_.deployMode.DeployApp();

View File

@ -9,6 +9,7 @@ import EditorNavigation, {
PagePaneSegment,
} from "../../../../support/Pages/EditorNavigation";
import PageList from "../../../../support/Pages/PageList";
import { EntityItems } from "../../../../support/Pages/AssertHelper";
describe(
"Validate basic operations on Entity explorer JSEditor structure",
@ -49,13 +50,14 @@ describe(
it("2. Validate Move JSObject", function () {
const newPageId = "Page2";
PageList.AddNewPage();
PageLeftPane.assertPresence(newPageId);
PageList.assertPresence(newPageId);
EditorNavigation.SelectEntityByName(pageId, EntityType.Page);
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "RenamedJSObjectCopy",
action: "Move to page",
subAction: newPageId,
toastToValidate: "moved to page",
entityType: EntityItems.Page,
});
EditorNavigation.SelectEntityByName(newPageId, EntityType.Page);
PageLeftPane.switchSegment(PagePaneSegment.JS);

View File

@ -9,6 +9,7 @@ import {
entityExplorer,
} from "../../../../support/Objects/ObjectsCore";
import PageList from "../../../../support/Pages/PageList";
import { EntityItems } from "../../../../support/Pages/AssertHelper";
describe("Page Load tests", { tags: ["@tag.IDE"] }, () => {
afterEach(() => {
@ -86,6 +87,7 @@ describe("Page Load tests", { tags: ["@tag.IDE"] }, () => {
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page1",
action: "Hide",
entityType: EntityItems.Page,
});
deployMode.DeployApp();
// Assert active page DSL

View File

@ -97,11 +97,10 @@ describe("Git discard changes:", { tags: ["@tag.Git"] }, function () {
it("4. Delete page2 and trigger discard flow, page2 should be available again", () => {
PageList.DeletePage(page2);
// verify page is deleted
//entityExplorer.ExpandCollapseEntity("Pages");
PageLeftPane.assertAbsence(page2);
PageList.assertAbsence(page2);
gitSync.DiscardChanges();
// verify page2 is recovered back
PageLeftPane.assertPresence(page2);
PageList.assertPresence(page2);
EditorNavigation.SelectEntityByName(page2, EntityType.Page);
cy.wait("@getPage");
// verify data binding on page2
@ -161,14 +160,13 @@ describe("Git discard changes:", { tags: ["@tag.Git"] }, function () {
// discard changes
gitSync.DiscardChanges();
// verify page3 is removed
PageList.ShowList();
PageLeftPane.assertAbsence(page3);
PageList.assertAbsence(page3);
});
it(`8. Add new page i.e page3, discard changes should not throw error: "resource not found"`, () => {
cy.Createpage(page3);
gitSync.DiscardChanges();
PageLeftPane.assertAbsence(page3);
PageList.assertAbsence(page3);
});
it("9. On discard failure an error message should be show and user should be able to discard again", () => {

View File

@ -16,6 +16,7 @@ import EditorNavigation, {
PagePaneSegment,
} from "../../../../../support/Pages/EditorNavigation";
import PageList from "../../../../../support/Pages/PageList";
import { EntityItems } from "../../../../../support/Pages/AssertHelper";
const pagename = "ChildPage";
const tempBranch = "feat/tempBranch";
@ -98,6 +99,7 @@ describe("Git sync Bug #10773", { tags: ["@tag.Git"] }, function () {
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page1",
action: "Clone",
entityType: EntityItems.Page,
});
cy.wait("@clonePage").should(
"have.nested.property",
@ -151,6 +153,7 @@ describe("Git sync Bug #10773", { tags: ["@tag.Git"] }, function () {
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page1",
action: "Clone",
entityType: EntityItems.Page,
});
cy.wait("@clonePage").should(
"have.nested.property",
@ -180,6 +183,7 @@ describe("Git sync Bug #10773", { tags: ["@tag.Git"] }, function () {
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page1",
action: "Clone",
entityType: EntityItems.Page,
});
cy.wait("@clonePage").should(
"have.nested.property",

View File

@ -27,6 +27,7 @@ import {
assertHelper,
} from "../../../../../support/Objects/ObjectsCore";
import PageList from "../../../../../support/Pages/PageList";
import { EntityItems } from "../../../../../support/Pages/AssertHelper";
const newPage = "ApiCalls_1";
const pageName = "crudpage_1";
@ -102,7 +103,12 @@ describe("Git sync apps", { tags: ["@tag.Git"] }, function () {
expect(cellData).to.be.equal("New Config");
});
// rename page to crud_page
entityExplorer.RenameEntityFromExplorer("Page1", pageName);
entityExplorer.RenameEntityFromExplorer(
"Page1",
pageName,
false,
EntityItems.Page,
);
EditorNavigation.SelectEntityByName(pageName, EntityType.Page);
// create a clone of page
cy.get(`.t--entity-item:contains(${pageName})`).within(() => {

View File

@ -16,6 +16,7 @@ import EditorNavigation, {
PagePaneSegment,
} from "../../../../../support/Pages/EditorNavigation";
import PageList from "../../../../../support/Pages/PageList";
import { EntityItems } from "../../../../../support/Pages/AssertHelper";
let parentBranchKey = "ParentBranch",
childBranchKey = "ChildBranch",
@ -67,7 +68,12 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
});
PageList.AddNewPage();
entityExplorer.RenameEntityFromExplorer("Page2", "ParentPage1", true);
entityExplorer.RenameEntityFromExplorer(
"Page2",
"ParentPage1",
false,
EntityItems.Page,
);
dataSources.NavigateToDSCreateNew();
apiPage.CreateApi("ParentApi1");
jsEditor.CreateJSObject();
@ -80,7 +86,12 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
childBranchKey = branName;
});
PageList.AddNewPage();
entityExplorer.RenameEntityFromExplorer("Page2", "ChildPage1", true);
entityExplorer.RenameEntityFromExplorer(
"Page2",
"ChildPage1",
false,
EntityItems.Page,
);
dataSources.NavigateToDSCreateNew();
apiPage.CreateApi("ChildApi1");
jsEditor.CreateJSObject();
@ -92,14 +103,10 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
// A switch here should not show a 404 page
cy.switchGitBranch(parentBranchKey);
// When entity not found, takes them to the home page
cy.get(`.t--entity.page`)
.contains("Page1")
.closest(".t--entity")
.should("be.visible")
.should("have.class", "activePage");
PageList.VerifyIsCurrentPage("Page1");
EditorNavigation.SelectEntityByName("ParentPage1", EntityType.Page);
PageLeftPane.assertAbsence("ChildPage1");
PageList.assertAbsence("ChildPage1");
PageLeftPane.switchSegment(PagePaneSegment.Queries);
PageLeftPane.assertAbsence("ChildApi1");
PageLeftPane.switchSegment(PagePaneSegment.JS);
@ -113,7 +120,8 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
entityExplorer.RenameEntityFromExplorer(
"ParentPage1",
"ParentPageRenamed",
true,
false,
EntityItems.Page,
);
agHelper.RemoveUIElement("Tooltip", "Add a new query/JS Object");
PageLeftPane.switchSegment(PagePaneSegment.Queries);
@ -121,8 +129,7 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
cy.switchGitBranch(parentBranchKey);
PageList.ShowList();
PageLeftPane.assertAbsence("ParentPageRenamed");
PageList.assertAbsence("ParentPageRenamed");
PageLeftPane.switchSegment(PagePaneSegment.Queries);
PageLeftPane.assertAbsence("ParentApiRenamed");
});
@ -219,11 +226,7 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
cy.get(gitSyncLocators.branchListItem).contains("master").click();
cy.wait(4000);
PageLeftPane.switchSegment(PagePaneSegment.UI);
cy.get(`.t--entity.page`)
.contains("Page1")
.closest(".t--entity")
.should("be.visible")
.should("have.class", "activePage");
PageList.VerifyIsCurrentPage("Page1");
cy.get(".t--canvas-artboard").should("be.visible");
});
agHelper.RefreshPage();

View File

@ -10,6 +10,7 @@ import EditorNavigation, {
EntityType,
} from "../../../../../support/Pages/EditorNavigation";
import PageList from "../../../../../support/Pages/PageList";
import { EntityItems } from "../../../../../support/Pages/AssertHelper";
let parentBranchKey = "ParentBranch",
childBranchKey = "ChildBranch";
@ -58,6 +59,7 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page2",
entityType: EntityItems.Page,
});
});

View File

@ -33,11 +33,11 @@ describe("Editor Segment Context Switch", { tags: ["@tag.IDE"] }, function () {
it("will select an item when switched to it", () => {
// Check JS item is selected
PageLeftPane.switchSegment(PagePaneSegment.JS);
PageLeftPane.selectedItem().should("be.visible");
PageLeftPane.selectedItem("not.exist");
// Check Query item is selected
PageLeftPane.switchSegment(PagePaneSegment.Queries);
PageLeftPane.selectedItem().should("be.visible");
PageLeftPane.selectedItem("not.exist");
// Check UI item is selected
PageLeftPane.switchSegment(PagePaneSegment.UI);

View File

@ -67,8 +67,13 @@ describe("Linting", { tags: ["@tag.JS"] }, () => {
AppSidebar.navigate(AppSidebarButton.Editor);
});
it("1. TC 1927 - Shows correct lint error when Api is deleted or created", () => {
it("1. TC 1927 - Show correct lint errors", () => {
// For browser APIs it should give linting error
EditorNavigation.SelectEntityByName("Button1", EntityType.Widget);
propPane.EnterJSContext("onClick", `{{window}}`);
agHelper.AssertElementExist(locators._lintErrorElement);
// Shows correct lint error when Api is deleted or created
propPane.EnterJSContext(
"onClick",
`{{function(){

View File

@ -11,6 +11,7 @@ import EditorNavigation, {
EntityType,
} from "../../../../support/Pages/EditorNavigation";
import PageList from "../../../../support/Pages/PageList";
import { EntityItems } from "../../../../support/Pages/AssertHelper";
describe(
"Handle Cases while conversion",
@ -37,6 +38,7 @@ describe(
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "Page2",
entityType: EntityItems.Page,
});
});

View File

@ -7,6 +7,7 @@ import {
locators,
propPane,
} from "../../../../support/Objects/ObjectsCore";
import { EntityItems } from "../../../../support/Pages/AssertHelper";
describe("Slug URLs", () => {
let applicationName;
@ -41,7 +42,12 @@ describe("Slug URLs", () => {
expect(pathname).to.be.equal(`/app/${appName}/page1-${pageId}/edit`);
});
});
entityExplorer.RenameEntityFromExplorer("Page1", "Renamed");
entityExplorer.RenameEntityFromExplorer(
"Page1",
"Renamed",
false,
EntityItems.Page,
);
assertHelper.AssertNetworkStatus("updatePage");
// cy.location("pathname").then((pathname) => {
cy.url().then((url) => {

View File

@ -5,12 +5,15 @@ import EditorNavigation, {
const omnibar = require("../../../../locators/Omnibar.json");
import {
agHelper,
entityExplorer,
assertHelper,
deployMode,
draggableWidgets,
} from "../../../../support/Objects/ObjectsCore";
import {
createMessage,
NAV_DESCRIPTION,
ACTION_OPERATION_DESCRIPTION,
} from "../../../../../src/ce/constants/messages";
describe("Omnibar functionality test cases", () => {
const apiName = "Omnibar1";
const jsObjectName = "Omnibar2";
@ -19,17 +22,7 @@ describe("Omnibar functionality test cases", () => {
agHelper.AddDsl("omnibarDsl");
});
it("1. Bug #15104 Docs tab opens after clicking on learn more link from property pane", function () {
cy.dragAndDropToCanvas(draggableWidgets.AUDIO, { x: 300, y: 500 });
agHelper.Sleep(2000);
deployMode.StubWindowNAssert(
'//span[text()="Learn more"]',
"connect-to-a-database",
"getConsolidatedData",
);
});
it("2.Verify omnibar is present across all pages and validate its fields", function () {
it("1.Verify omnibar is present across all pages and validate its fields", function () {
cy.get(omnibar.globalSearch)
.trigger("mouseover")
.should("have.css", "background-color", "rgb(255, 255, 255)");
@ -39,19 +32,16 @@ describe("Omnibar functionality test cases", () => {
.eq(0)
.should("have.text", "Navigate")
.next()
.should(
"have.text",
"Navigate to any page, widget or file across this project.",
);
.should("have.text", createMessage(NAV_DESCRIPTION));
cy.get(omnibar.categoryTitle)
.eq(1)
.should("have.text", "Create new")
.next()
.should("have.text", "Create a new query, API or JS Object");
.should("have.text", createMessage(ACTION_OPERATION_DESCRIPTION));
cy.get("body").type("{esc}");
});
it("3. Verify Create new section and its data, also create a new api, new js object and new cURL import from omnibar ", function () {
it("2. Verify Create new section and its data, also create a new api, new js object and new cURL import from omnibar ", function () {
cy.intercept("POST", "/api/v1/actions").as("createNewApi");
cy.intercept("POST", "/api/v1/collections/actions").as(
"createNewJSCollection",
@ -90,7 +80,7 @@ describe("Omnibar functionality test cases", () => {
});
it(
"4. On an invalid search, discord link should be displayed and on clicking that link, should open discord in new tab",
"3. On an invalid search, discord link should be displayed and on clicking that link, should open discord in new tab",
{ tags: ["@tag.excludeForAirgap"] },
function () {
// typing a random string in search bar
@ -101,30 +91,11 @@ describe("Omnibar functionality test cases", () => {
cy.get(omnibar.globalSearchInput).should("have.value", "vnjkv");
// discord link should be visible
cy.get(omnibar.discordLink).should("be.visible");
// cy.window().then((win) => {
// cy.stub(win, "open", (url) => {
// win.location.href = "https://discord.com/invite/rBTTVJp";
// }).as("discordLink");
// });
// cy.url().then(($urlBeforeDiscord) => {
// // clicking on discord link should open discord
// agHelper.GetNClick(omnibar.discordLink, 0, false, 4000);
// cy.get("@discordLink").should("be.called");
// cy.wait(2000);
// //cy.go(-1);
// cy.visit($urlBeforeDiscord);
// cy.wait(4000); //for page to load
// });
deployMode.StubWindowNAssert(
omnibar.discordLink,
"https://discord.com/invite/rBTTVJp",
"getConsolidatedData",
);
cy.get(".no-data-title").should("be.visible");
},
);
it("5. Verify Navigate section shows recently opened widgets and datasources", function () {
it("4. Verify Navigate section shows recently opened widgets and datasources", function () {
EditorNavigation.SelectEntityByName("Button1", EntityType.Widget);
cy.get(omnibar.globalSearch).click({ force: true });
cy.get(omnibar.categoryTitle).contains("Navigate").click();
@ -147,12 +118,6 @@ describe("Omnibar functionality test cases", () => {
.next()
.should("have.text", "Page1");
cy.xpath(omnibar.recentlyopenItem)
.eq(3)
.should("have.text", "Audio1")
.next()
.should("have.text", "Page1");
cy.xpath(omnibar.recentlyopenItem).eq(4).should("have.text", "Page1");
cy.xpath(omnibar.recentlyopenItem).eq(3).should("have.text", "Page1");
});
});

View File

@ -59,10 +59,10 @@ describe("Page Settings", { tags: ["@tag.Settings"] }, () => {
});
_.appSettings.ClosePane();
//Page name doesn't allow special character
// Page name doesn't allow slashes and colons
_.appSettings.OpenAppSettings();
_.appSettings.GoToPageSettings("Page3");
_.pageSettings.UpdatePageNameAndVerifyTextValue("Page3!@#", "Page3 ");
_.pageSettings.UpdatePageNameAndVerifyTextValue("Page3/\\:", "Page3");
_.appSettings.ClosePane();
// Page name doesn't allow empty

View File

@ -40,11 +40,11 @@ describe(
);
cy.wait(1000);
cy.get(template.templateDialogBox).should("be.visible");
cy.xpath("//h1[text()='Slack Bot']").scrollIntoView().wait(500).click();
cy.get(template.templateCard).first().click();
cy.get(template.templateViewForkButton).first().click();
cy.waitUntil(() => cy.xpath("//span[text()='Setting up the template']"), {
errorMsg: "Setting Templates did not finish even after 75 seconds",
timeout: 950000,
timeout: 75000,
interval: 5000,
}).then(($ele) => {
cy.wrap($ele).should("have.length", 0);

View File

@ -1,5 +1,9 @@
import homePage from "../../../../locators/HomePage";
import * as _ from "../../../../support/Objects/ObjectsCore";
import {
createMessage,
LOGIN_PAGE_TITLE,
} from "../../../../../src/ce/constants/messages";
describe("Visual regression tests", { tags: ["@tag.Visual"] }, () => {
// for any changes in UI, update the screenshot in snapshot folder, to do so:
@ -47,7 +51,7 @@ describe("Visual regression tests", { tags: ["@tag.Visual"] }, () => {
cy.get(homePage.signOutIcon).click();
cy.wait(500);
// validating all the fields on login page
cy.xpath("//h1").should("have.text", "Sign in");
cy.xpath("//h1").should("have.text", createMessage(LOGIN_PAGE_TITLE));
cy.get(".bp3-label").first().should("have.text", "Email ");
cy.get(".bp3-label").last().should("have.text", "Password ");
cy.xpath('//span[text()="Sign in"]').should("be.visible");

View File

@ -35,10 +35,10 @@ describe(
// Check camera resource is properly released on navigating away
PageList.AddNewPage();
EditorNavigation.SelectEntityByName("Page2", EntityType.Widget);
EditorNavigation.SelectEntityByName("Page2", EntityType.Page);
agHelper.AssertElementAbsence(widgetLocators.cameraVideo);
EditorNavigation.SelectEntityByName("Page1", EntityType.Widget);
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
agHelper.AssertElementVisibility(widgetLocators.cameraVideo);
});

View File

@ -94,9 +94,7 @@ describe(
'SELECT * FROM public."country" LIMIT 10;',
);
// Going to HomePage where the button widget is located and opeing it's property pane.
cy.get("[data-guided-tour-id='explorer-entity-Page1']").click({
force: true,
});
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
PageLeftPane.switchSegment(PagePaneSegment.UI);
cy.openPropertyPane("selectwidget");
cy.reload();

View File

@ -38,22 +38,23 @@ describe(
() => {
before(() => {
agHelper.AddDsl("Listv2/ListV2WithNullPrimaryKey");
agHelper.Sleep(3000); //for List to load for CI flakyness
});
it("1. Widgets get displayed when PrimaryKey doesn't exist - SSP", () => {
apiPage.CreateAndFillApi(
"https://api.punkapi.com/v2/beers?page={{List1.pageNo}}&per_page={{List1.pageSize}}",
"http://host.docker.internal:5001/v1/dynamicrecords/getrecordsArray",
"",
);
agHelper.VerifyEvaluatedValue(
"https://api.punkapi.com/v2/beers?page=1&per_page=2",
);
apiPage.RunAPI(false);
EditorNavigation.SelectEntityByName("List1", EntityType.Widget);
propPane.SelectPropertiesDropDown("Data Identifier", "value");
agHelper.AssertElementAbsence(propPane._dropdownControlError);
EditorNavigation.SelectEntityByName("Text2", EntityType.Widget, {}, [
"List1",
"Container1",
]);
propPane.UpdatePropertyFieldValue("Text", "{{currentIndex}}");
agHelper.AssertText(propPane._widgetToVerifyText("Text2"), "text", "0");
table.NavigateToPageUsingButton_List("next", 2);

View File

@ -126,7 +126,6 @@ describe(
" " +
locators._widgetInDeployed(draggableWidgets.TABLE),
);
deployMode.NavigateBacktoEditor();
//Fixed height
@ -135,10 +134,6 @@ describe(
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.BUTTON));
agHelper.ClickButton("Submit");
agHelper.AssertElementVisibility(locators._modal);
//Verify that a fixed canvas size is visible when height is selected as Fixed
agHelper.AssertProperty(locators._modal, "offsetHeight", 1094);
agHelper.AssertProperty(locators._modal, "offsetWidth", 456);
agHelper.AssertElementVisibility(
locators._modal +
" " +

View File

@ -97,8 +97,7 @@ describe(
// Check if the cursor is at the end when input Type is HTML
setRTEContent(testString);
testCursorPoistion(testStringLen, tinyMceId);
setRTEContent("{selectAll}");
setRTEContent("{backspace}");
setRTEContent("{selectAll}{del}");
// Changing the input type to markdown and again testing the cursor position
cy.openPropertyPane("richtexteditorwidget");

View File

@ -46,13 +46,16 @@ describe("Rest Bugs tests", { tags: ["@tag.Datasource"] }, function () {
agHelper.PressEscape();
//Api 3
apiPage.CreateAndFillApi("http://numbersapi.com/random/math", "NumberFact");
apiPage.CreateAndFillApi(
"http://host.docker.internal:8000/a.txt",
"SampleText",
);
agHelper.PressEscape();
//Api 4
apiPage.CreateAndFillApi(
"https://www.thecocktaildb.com/api/json/v1/1/search.php?s=margarita",
"CocktailDB",
"http://host.docker.internal:5001/v1/dynamicrecords/getrecordsArray",
"dynamicRecords",
);
agHelper.PressEscape();

View File

@ -367,12 +367,12 @@ describe("JS Function Execution", { tags: ["@tag.JS"] }, function () {
isMarkedAsync ? "async" : ""
} ()=>"${functionName}",`
: i === functionsLength - 1
? `
? `
${functionName}: ${
isMarkedAsync ? "async" : ""
} ()=>"${functionName}",
}`
: `
: `
${functionName}: ${
isMarkedAsync ? "async" : ""
} ()=> "${functionName}",`;

View File

@ -1,6 +1,7 @@
import {
agHelper,
dataSources,
debuggerHelper,
deployMode,
entityExplorer,
homePage,
@ -70,44 +71,14 @@ describe(
//homePage.DeleteWorkspace("JSOnLoadTest");
});
it("6. Tc #1910 - Verify the Number of confirmation models of JS Object on page load", () => {
it("6. Tc #1910 - Verify that JSObject functions set to run on pageLoad are executed on page refresh", () => {
homePage.CreateAppInWorkspace("JSOnLoadTest");
entityExplorer.DragDropWidgetNVerify("buttonwidget", 100, 100);
dataSources.CreateDataSource("Postgres");
cy.get("@dsName").then((dsName) => {
datasourceName = dsName;
dataSources.CreateQueryAfterDSSaved(
`SELECT * FROM public."astronauts" LIMIT 1;`,
"getastronauts",
);
dataSources.CreateQueryFromOverlay(
datasourceName,
`SELECT * FROM public."category" LIMIT 1;`,
"getcategory",
);
dataSources.CreateQueryFromOverlay(
datasourceName,
`SELECT * FROM public."city" LIMIT 1;`,
"getcity",
);
dataSources.CreateQueryFromOverlay(
datasourceName,
`SELECT * FROM public."film" LIMIT 1;`,
"getfilm",
);
dataSources.CreateQueryFromOverlay(
datasourceName,
`SELECT * FROM public."hogwartsstudents" LIMIT 1;`,
"gethogwartsstudents",
);
});
jsEditor.CreateJSObject(
`export default {
astros: () => {
return getastronauts.run(); },
return "test" },
city: () => {
return getcity.run()
return "test2"
}
}`,
{
@ -119,57 +90,14 @@ describe(
);
jsEditor.EnableDisableAsyncFuncSettings("astros", true);
jsEditor.EnableDisableAsyncFuncSettings("city", true);
jsEditor.CreateJSObject(
`export default {
cat: () => {
return getcategory.run(); },
hogwartsstudents: () => {
return gethogwartsstudents.run();
}
}`,
{
paste: true,
completeReplace: true,
toRun: false,
shouldCreateNewJSObj: true,
},
);
jsEditor.EnableDisableAsyncFuncSettings("cat", true);
jsEditor.EnableDisableAsyncFuncSettings("hogwartsstudents", true);
jsEditor.CreateJSObject(
`export default {
film: async () => {
return getfilm.run();
}
}`,
{
paste: true,
completeReplace: true,
toRun: false,
shouldCreateNewJSObj: true,
},
);
jsEditor.EnableDisableAsyncFuncSettings("film", true);
});
it("7. Tc #1909 - Verify the sequence of of JS Object on page load", () => {
EditorNavigation.SelectEntityByName("JSObject1", EntityType.JSObject);
jsEditor.EnableDisableAsyncFuncSettings("astros", true);
jsEditor.EnableDisableAsyncFuncSettings("city", true);
EditorNavigation.SelectEntityByName("JSObject2", EntityType.JSObject);
jsEditor.EnableDisableAsyncFuncSettings("cat", true);
jsEditor.EnableDisableAsyncFuncSettings("hogwartsstudents", true);
EditorNavigation.SelectEntityByName("JSObject3", EntityType.JSObject);
jsEditor.EnableDisableAsyncFuncSettings("film", true);
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
agHelper.RefreshPage();
agHelper.ValidateToastMessage("ran successfully", 0, 5);
debuggerHelper.ClickDebuggerIcon();
debuggerHelper.ClickLogsTab();
debuggerHelper.DebuggerLogsFilter("JSObject1.astros");
debuggerHelper.DoesConsoleLogExist("JS Function executed successfully");
});
function AssertJSOnPageLoad(

View File

@ -288,7 +288,7 @@ describe(
entityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: "ListingAndReviews",
action: "Delete",
entityType: entityItems.Datasource,
entityType: entityItems.Page,
});
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
});

View File

@ -1,6 +1,4 @@
import EditorNavigation, {
EntityType,
} from "../../../support/Pages/EditorNavigation";
import EditorNavigation from "../../../support/Pages/EditorNavigation";
const datasource = require("../../../locators/DatasourcesEditor.json");
const queryLocators = require("../../../locators/QueryEditor.json");
@ -57,7 +55,7 @@ describe(
.eq(6)
.type("{{FilePicker.files}}", { parseSpecialCharSequences: false });
agHelper.ClickOutside(); //to close the evaluated pop-up
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
EditorNavigation.ShowCanvas();
cy.wait(2000);
});
@ -96,8 +94,7 @@ describe(
});
it("3. On canvas, fill to email, from email, subject, body, attachment and run query", function () {
EditorNavigation.SelectEntityByName("smtpquery", EntityType.Query);
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
EditorNavigation.ShowCanvas();
const noise = Math.random().toString(36).substring(0, 7);
const fromEmail = `smtp.datasource.tester.${noise}@appsmith.com`;
cy.wait(2000);

View File

@ -32,7 +32,7 @@
"topRow": 4,
"bottomRow": 36,
"parentRowSpace": 10,
"source": "https://www.example.com",
"source": "http://host.docker.internal:8000/a.txt",
"type": "IFRAME_WIDGET",
"hideCard": false,
"borderOpacity": 100,

View File

@ -60,7 +60,7 @@
"topRow": 6.0,
"bottomRow": 38.0,
"parentRowSpace": 10.0,
"source": "https://www.example.com",
"source": "http://host.docker.internal:8000/a.txt",
"type": "IFRAME_WIDGET",
"hideCard": false,
"borderOpacity": 100.0,

File diff suppressed because one or more lines are too long

View File

@ -62,7 +62,7 @@
]
},
{
"image": "https://source.unsplash.com/mGFHA_0TWnA/2048x620",
"image": "http://host.docker.internal:8000/photo-1492529029602-33e53698f407.jpeg",
"widgetName": "Image1",
"rightColumn": 64,
"widgetId": "ah4cbb9o2e",

View File

@ -62,7 +62,7 @@
]
},
{
"image": "https://source.unsplash.com/mGFHA_0TWnA/2048x620",
"image": "http://host.docker.internal:8000/photo-1503469432756-4aae2e18d881.jpeg",
"widgetName": "Image1",
"rightColumn": 64,
"widgetId": "ah4cbb9o2e",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -289,8 +289,8 @@ export class AggregateHelper {
return exists === "noVerify"
? locator // Return the locator without verification if exists is "noVerify"
: exists === "exist"
? locator.should("have.length.at.least", 1)
: locator.should("have.length", 0);
? locator.should("have.length.at.least", 1)
: locator.should("have.length", 0);
}
public GetNAssertElementText(

View File

@ -1,4 +1,5 @@
import { ObjectsRegistry } from "../Objects/Registry";
import type { EntityItemsType } from "./AssertHelper";
import { EntityItems } from "./AssertHelper";
import EditorNavigation, {
EntityType,
@ -38,8 +39,7 @@ interface EntityActionParams {
| "Export"
| "Import";
subAction?: string;
//@ts-expect-error: type mismatch
entityType?: EntityItems;
entityType?: EntityItemsType;
toAssertAction?: boolean;
toastToValidate?: string;
}
@ -82,6 +82,9 @@ export class EntityExplorer {
}: EntityActionParams) {
AppSidebar.navigate(AppSidebarButton.Editor);
this.agHelper.Sleep();
if (entityType === EntityItems.Page) {
PageList.ShowList();
}
cy.xpath(this._contextMenu(entityNameinLeftSidebar))
.scrollIntoView()
.last()
@ -98,6 +101,9 @@ export class EntityExplorer {
toastToValidate: toastToValidate,
});
}
if (entityType === EntityItems.Page) {
PageList.HideList();
}
}
public DeleteWidgetFromEntityExplorer(widgetNameinLeftSidebar: string) {
@ -168,10 +174,10 @@ export class EntityExplorer {
dropTargetId
? dropTargetId + this.locator._dropHere
: parentWidgetType
? this.locator._widgetInCanvas(parentWidgetType) +
" " +
this.locator._dropHere
: this.locator._dropHere,
? this.locator._widgetInCanvas(parentWidgetType) +
" " +
this.locator._dropHere
: this.locator._dropHere,
)
.first()
.trigger("mousemove", x, y, {
@ -256,13 +262,17 @@ export class EntityExplorer {
entityName: string,
renameVal: string,
viaMenu = false,
entityType?: EntityItemsType,
) {
AppSidebar.navigate(AppSidebarButton.Editor);
PageList.ShowList();
if (entityType === EntityItems.Page && !viaMenu) {
PageList.ShowList();
}
if (viaMenu)
this.ActionContextMenuByEntityName({
entityNameinLeftSidebar: entityName,
action: "Edit name",
entityType,
});
else cy.xpath(PageLeftPane.listItemSelector(entityName)).dblclick();
cy.xpath(this.locator._entityNameEditing(entityName))
@ -271,6 +281,10 @@ export class EntityExplorer {
.type("{enter}")
.wait(300);
this.agHelper.Sleep(); //allowing time for name change to reflect in EntityExplorer
PageLeftPane.assertPresence(renameVal);
if (entityType === EntityItems.Page) {
PageList.assertPresence(renameVal);
} else {
PageLeftPane.assertPresence(renameVal);
}
}
}

View File

@ -344,8 +344,7 @@ export class GitSync {
"Unable to import application in workspace",
),
);
this.agHelper.AssertElementExist(this.locator._btnSpinner);
this.agHelper.AssertElementAbsence(this.locator._btnSpinner, 70000); //Since page taking more time to laod in some cases
this.agHelper.WaitUntilEleAppear(this._branchName(branch + uid));
this.agHelper.AssertElementVisibility(this._branchName(branch + uid));
this.assertHelper.AssertNetworkStatus("getBranch");
cy.wrap(branch + uid).as("gitbranchName");

View File

@ -91,9 +91,12 @@ export class LeftPane {
}
});
}
public selectedItem(): Cypress.Chainable {
public selectedItem(
exists?: "exist" | "not.exist" | "noVerify",
): Cypress.Chainable {
return ObjectsRegistry.AggregateHelper.GetElement(
this.locators.activeItemSelector,
exists,
);
}

View File

@ -4,13 +4,14 @@ import EditorNavigation, {
AppSidebarButton,
EntityType,
} from "./EditorNavigation";
import { EntityItems } from "./AssertHelper";
class PageList {
private locators = {
pageListItem: (pageName: string) =>
`.t--entity.page:contains('${pageName}')`,
newButton: ".pages .t--entity-add-btn",
newPageOption: (option: string) => `//span[text()='${option}']/parent::div`,
newPageOption: ".ads-v2-menu__menu-item-children",
switcher: `.t--pages-switcher`,
};
@ -23,9 +24,9 @@ class PageList {
AppSidebar.navigate(AppSidebarButton.Editor);
this.ShowList();
ObjectsRegistry.AggregateHelper.GetNClick(this.locators.newButton);
ObjectsRegistry.AggregateHelper.GetNClick(
this.locators.newPageOption(option),
);
cy.get(this.locators.newPageOption)
.contains(option, { matchCase: false })
.click({ force: true });
if (option === "New blank page") {
ObjectsRegistry.AssertHelper.AssertNetworkStatus("@createPage", 201);
@ -40,37 +41,54 @@ class PageList {
ObjectsRegistry.AggregateHelper.GetElement(
this.locators.pageListItem(pageName),
).should("have.class", "activePage");
this.HideList();
}
public SelectedPageItem(): Cypress.Chainable {
this.ShowList();
return cy.get(".t--entity.page > .active");
this.HideList();
}
public ClonePage(pageName = "Page1") {
AppSidebar.navigate(AppSidebarButton.Editor);
this.ShowList();
EditorNavigation.SelectEntityByName(pageName, EntityType.Page);
ObjectsRegistry.EntityExplorer.ActionContextMenuByEntityName({
entityNameinLeftSidebar: pageName,
action: "Clone",
entityType: EntityItems.Page,
});
ObjectsRegistry.AssertHelper.AssertNetworkStatus("@clonePage", 201);
}
public ShowList() {
cy.get(this.locators.switcher).then(($switcher) => {
const isActive: string | undefined = $switcher.attr("data-active");
if (isActive === "false") {
const isActive: string | undefined = $switcher
.parent()
.attr("data-state");
if (isActive === "closed") {
cy.get(this.locators.switcher).click();
}
});
}
public HideList() {
cy.get(this.locators.switcher).then(($switcher) => {
const isActive: string | undefined = $switcher
.parent()
.attr("data-state");
if (isActive === "open") {
cy.get(this.locators.switcher).click({ force: true });
}
});
}
assertPresence(pageName: string) {
this.ShowList();
ObjectsRegistry.AggregateHelper.AssertElementVisibility(
this.locators.pageListItem(pageName),
);
this.HideList();
}
assertAbsence(pageName: string) {
@ -78,6 +96,7 @@ class PageList {
ObjectsRegistry.AggregateHelper.AssertElementAbsence(
this.locators.pageListItem(pageName),
);
this.HideList();
}
DeletePage(name: string) {
@ -91,6 +110,7 @@ class PageList {
cy.wait("@deletePage")
.its("response.body.responseMeta.status")
.should("eq", 200);
this.HideList();
}
}

View File

@ -172,6 +172,7 @@ export class PropertyPane {
_dataIcon = (icon: string) => `[data-icon="${icon}"]`;
_iconDropdown = "[data-test-id='virtuoso-scroller']";
_dropdownControlError = "[data-testid='t---dropdown-control-error']";
public OpenJsonFormFieldSettings(fieldName: string) {
this.agHelper.GetNClick(this._jsonFieldEdit(fieldName));

View File

@ -15,6 +15,7 @@ const dynamicInputLocators = require("../locators/DynamicInput.json");
const viewWidgetsPage = require("../locators/ViewWidgets.json");
import { ObjectsRegistry } from "../support/Objects/Registry";
import { TABLE_COLUMN_ORDER_KEY } from "./Constants";
import { EntityItems } from "./Pages/AssertHelper";
let pageidcopy = " ";
@ -934,7 +935,12 @@ Cypress.Commands.add("Createpage", (pageName, navigateToCanvasPage = true) => {
PageList.AddNewPage().then((oldPageName) => {
if (pageName) {
cy.wait(2000);
ee.RenameEntityFromExplorer(oldPageName, pageName, true);
ee.RenameEntityFromExplorer(
oldPageName,
pageName,
false,
EntityItems.Page,
);
}
cy.get("#loading").should("not.exist");
});

View File

@ -59,8 +59,12 @@ module.exports = {
"@tag.PropertyPane",
"@tag.Workspace",
"@tag.Sanity",
"@tag.Templates",
"@tag.Auditlogs",
"@tag.AccessControl",
"@tag.LicenseAndBilling",
"@tag.Authentication",
"@tag.Provisioning",
"@tag.Templates",
"@tag.MainContainer",
"@tag.Visual",
"@tag.Module",

View File

@ -111,7 +111,7 @@
"d3-geo": "^3.1.0",
"dayjs": "^1.10.6",
"deep-diff": "^1.0.2",
"design-system": "npm:@appsmithorg/design-system@2.1.37",
"design-system": "npm:@appsmithorg/design-system@2.1.38",
"design-system-old": "npm:@appsmithorg/design-system-old@1.1.16",
"downloadjs": "^1.4.7",
"echarts": "^5.4.2",

View File

@ -1,22 +0,0 @@
import { Button } from "@design-system/headless";
import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs";
<Meta
title="Design-system/Headless/Button"
component={Button}
args={{
children: "Button",
}}
/>
export const Template = (args) => <Button {...args} />;
# Button
A button is a clickable element that is used to trigger an action.
<Canvas>
<Story name="Button">{Template.bind({})}</Story>
</Canvas>
<ArgsTable story="Button" of={Button} />

View File

@ -0,0 +1,14 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "@design-system/headless";
const meta: Meta<typeof Button> = {
component: Button,
title: "Design-system/headless/Button",
render: () => <Button>Button</Button>,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Main: Story = {};

View File

@ -76,8 +76,8 @@ const _Checkbox = (props: CheckboxProps, ref: CheckboxRef) => {
const dataState = isIndeterminate
? "indeterminate"
: Boolean(inputProps.checked)
? "checked"
: "unchecked";
? "checked"
: "unchecked";
return (
<label

View File

@ -0,0 +1,22 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { Checkbox, CheckboxGroup } from "@design-system/headless";
const meta: Meta<typeof CheckboxGroup> = {
component: CheckboxGroup,
title: "Design-system/headless/CheckboxGroup",
subcomponents: {
Checkbox,
},
render: (args) => (
<CheckboxGroup {...args}>
<Checkbox value="value-1">Value 1</Checkbox>
<Checkbox value="value-2">Value 2</Checkbox>
</CheckboxGroup>
),
};
export default meta;
type Story = StoryObj<typeof Checkbox>;
export const Main: Story = {};

View File

@ -1,30 +0,0 @@
import { CheckboxGroup, Checkbox } from "@design-system/headless";
import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs";
<Meta
title="Design-system/Headless/CheckboxGroup"
component={CheckboxGroup}
args={{
label: "Checkbox group",
children: (
<>
<Checkbox value="option 1">Option 1</Checkbox>
<Checkbox value="option 2">Option 2</Checkbox>
</>
),
}}
/>
export const Template = (args) => <CheckboxGroup {...args} />;
# CheckboxGroup
A Checkbox group is a group of radio buttons that are related to each other in some way. For example, they may all represent a single question on a survey. The Checkbox group component is a headless component that provides the logic and accessibility implementation for a group of radio buttons.
Note: The `<input="checkbox" />` is visually hidden. Use the `<span data-icon />` to render a custom looking checkbox.
<Canvas>
<Story name="CheckboxGroup">{Template.bind({})}</Story>
</Canvas>
<ArgsTable story="CheckboxGroup" of={CheckboxGroup} />

View File

@ -1,109 +0,0 @@
import { Menu, Button, MenuList, Item } from "@design-system/headless";
import { Canvas, Meta, Story, ArgsTable, Source } from "@storybook/addon-docs";
<Meta title="Design-system/Headless/Menu" component={Menu} />
export const Template = (args) => {
return (
<Menu {...args}>
<Button>Menu trigger</Button>
<MenuList>
<Item>Cut</Item>
<Item>Copy</Item>
<Item>Paste</Item>
</MenuList>
</Menu>
);
};
# Menu
A menu displays a list of actions or options that a user can choose.
<Canvas>
<Story name="Menu">{Template.bind({})}</Story>
</Canvas>
## Menu props
<ArgsTable story="Menu" of={Menu} />
## MenuList props
<ArgsTable of={MenuList} />
## Item props
Item props are not pulled up in the ArgsTable, the data can be found [here](https://react-spectrum.adobe.com/react-aria/Menu.html#item).
# Placement
The placement of the menu can be changed by passing the `placement` prop.
<Story name="Menu placement">
<Menu placement="left">
<Button>Left</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="top">
<Button>Top</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="bottom">
<Button>Bottom</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="right">
<Button>Right</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
</Story>
# Menu example
<Canvas>
<Story name="Menu example">
<Menu
items={[
{ id: 1, name: "New" },
{ id: 2, name: "Open" },
]}
onAction={(key) => console.log(key)}
>
<Button>Menu trigger</Button>
<MenuList>{(item) => <Item key={item.name}>{item.name}</Item>}</MenuList>
</Menu>
</Story>
</Canvas>
<Source
dark
code={`
<Menu
items={[
{ id: 1, name: "New" },
{ id: 2, name: "Open" },
]}
onAction={(key) => console.log(key)}
>
<Button>Menu trigger</Button>
<MenuList>{(item) => <Item key={item.name}>{item.name}</Item>}</MenuList>
</Menu>
`}
/>

View File

@ -0,0 +1,75 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { Menu, Button, MenuList, Item } from "@design-system/headless";
/**
* A menu displays a list of actions or options that a user can choose.
*
* Item props are not pulled up in the ArgsTable, the data can be found [here](https://react-spectrum.adobe.com/react-aria/Menu.html#item).
*/
const meta: Meta<typeof Menu> = {
component: Menu,
title: "Design-system/headless/Menu",
subcomponents: {
//@ts-expect-error: don't need props to pass here
MenuList,
},
render: (args) => (
<Menu {...args}>
<Button>Menu trigger</Button>
<MenuList>
<Item>Cut</Item>
<Item>Copy</Item>
<Item>Paste</Item>
</MenuList>
</Menu>
),
};
export default meta;
type Story = StoryObj<typeof Menu>;
export const Main: Story = {};
/**
* The placement of the menu can be changed by passing the `placement` prop.
*/
export const Placement: Story = {
render: () => (
<>
<Menu placement="left">
<Button>Left</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="top">
<Button>Top</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="bottom">
<Button>Bottom</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
<Menu placement="right">
<Button>Right</Button>
<MenuList>
<Item key="copy">Copy</Item>
<Item key="cut">Cut</Item>
<Item key="paste">Paste</Item>
</MenuList>
</Menu>
</>
),
};

View File

@ -1,132 +0,0 @@
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverModalContent,
Button,
} from "@design-system/headless";
import { ControlledPopover } from "./ControlledPopover";
import { Canvas, Meta, Story, ArgsTable, Source } from "@storybook/addon-docs";
<Meta title="Design-system/Headless/Popover" component={Popover} />
export const Template = (args) => {
return (
<Popover {...args}>
<PopoverTrigger>
<Button>My trigger</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
);
};
# Popover
A popover is an interactive mini-dialog floating element that displays information related to an anchor element when the element is clicked.
Based on the [headless Popover component](/?path=/docs/design-system-headless-popover--docs).
<Canvas>
<Story name="Popover">{Template.bind({})}</Story>
</Canvas>
## Popover props
<ArgsTable story="Popover" of={Popover} />
## PopoverTrigger props
<ArgsTable of={PopoverTrigger} />
## PopoverContent props
<ArgsTable of={PopoverContent} />
# Modal
A modal is a floating element that displays information that requires immediate attention, appearing over the page content and blocking interactions with the page until it is dismissed.
## PopoverModalContent props
<ArgsTable of={PopoverModalContent} />
<Source
dark
code={`
export const Modal = () => {
const [isOpen, setIsOpen] = useState(false);
const ref = useRef(null);
return (
<>
<Button onPress={() => setIsOpen(!isOpen)} ref={ref}>
Controlled popover
</Button>
<Popover isOpen={isOpen} setOpen={setIsOpen} triggerRef={ref}>
<PopoverContent>Controlled popover content</PopoverContent>
</Popover>
</>
);
};
`}
/>
# Placement
The placement of the popover can be changed by passing the `placement` prop.
<Canvas>
<Story name="Popover placement">
<Popover placement="left">
<PopoverTrigger>
<Button>Left</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="top">
<PopoverTrigger>
<Button>Top</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="bottom">
<PopoverTrigger>
<Button>Bottom</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="right">
<PopoverTrigger>
<Button>Right</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
</Story>
</Canvas>
# Controlled popover
<Canvas>
<Story name="Controlled popover">
<ControlledPopover />
</Story>
</Canvas>
<Source
dark
code={`
export const ControlledPopover = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<Popover isOpen={isOpen} setOpen={setIsOpen}>
<PopoverTrigger>
<Button onPress={() => setIsOpen(!isOpen)}>Controlled popover</Button>
</PopoverTrigger>
<PopoverContent>Controlled popover content</PopoverContent>
</Popover>
);
};
`}
/>

View File

@ -0,0 +1,82 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverModalContent,
Button,
} from "@design-system/headless";
import { ControlledPopover as ControlledPopoverExample } from "./ControlledPopover";
/**
* A popover is an interactive mini-dialog floating element that displays information related to an anchor element when the element is clicked.
*
* Based on the [headless Popover component](/?path=/docs/design-system-headless-popover--docs).
*
* A popover is a floating element that displays information that requires immediate attention, appearing over the page content and blocking interactions with the page until it is dismissed.
*/
const meta: Meta<typeof Popover> = {
component: Popover,
title: "Design-system/headless/Popover",
subcomponents: {
//@ts-expect-error: don't need props to pass here
PopoverTrigger,
//@ts-expect-error: don't need props to pass here
PopoverContent,
//@ts-expect-error: don't need props to pass here
PopoverModalContent,
},
render: (args) => (
<Popover {...args}>
<PopoverTrigger>
<Button>My trigger</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
),
};
export default meta;
type Story = StoryObj<typeof Popover>;
export const Main: Story = {};
/**
* The placement of the menu can be changed by passing the `placement` prop.
*/
export const Placement: Story = {
render: () => (
<>
<Popover placement="left">
<PopoverTrigger>
<Button>Left</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="top">
<PopoverTrigger>
<Button>Top</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="bottom">
<PopoverTrigger>
<Button>Bottom</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
<Popover placement="right">
<PopoverTrigger>
<Button>Right</Button>
</PopoverTrigger>
<PopoverContent>My popover</PopoverContent>
</Popover>
</>
),
};
export const ControlledPopover: Story = {
render: () => <ControlledPopoverExample />,
};

View File

@ -0,0 +1,28 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { RadioGroup, Radio } from "@design-system/headless";
/**
* A Radio group is a group of radio buttons that are related to each other in some way. For example, they may all represent a single question on a survey. The Radio group component is a headless component that provides the logic and accessibility implementation for a group of radio buttons.
*
* Note: The `<input="radio" />` is visually hidden by default. Use the `<span data-icon />` to render custom looking radio.
*/
const meta: Meta<typeof RadioGroup> = {
component: RadioGroup,
title: "Design-system/headless/RadioGroup",
subcomponents: {
//@ts-expect-error: don't need props to pass here
Radio,
},
render: (args) => (
<RadioGroup label="Radio group" {...args}>
<Radio value="option 1">Option 1</Radio>
<Radio value="option 2">Option 2</Radio>
</RadioGroup>
),
};
export default meta;
type Story = StoryObj<typeof RadioGroup>;
export const Main: Story = {};

View File

@ -1,30 +0,0 @@
import { RadioGroup, Radio } from "@design-system/headless";
import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs";
<Meta
title="Design-system/Headless/RadioGroup"
component={RadioGroup}
args={{
label: "Radio group",
children: (
<>
<Radio value="option 1">Option 1</Radio>
<Radio value="option 2">Option 2</Radio>
</>
),
}}
/>
export const Template = (args) => <RadioGroup {...args} />;
# RadioGroup
A Radio group is a group of radio buttons that are related to each other in some way. For example, they may all represent a single question on a survey. The Radio group component is a headless component that provides the logic and accessibility implementation for a group of radio buttons.
Note: The `<input="radio" />` is visually hidden by default. Use the `<span data-icon />` to render custom looking radio.
<Canvas>
<Story name="RadioGroup">{Template.bind({})}</Story>
</Canvas>
<ArgsTable story="RadioGroup" of={RadioGroup} />

View File

@ -1,26 +0,0 @@
import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs";
import { TextInput } from "../";
<Meta
title="Design-system/headless/TextInput"
component={TextInput}
args={{
label: "Label",
placeholder: "Placeholder",
}}
/>
export const Template = (args) => <TextInput {...args} />;
# TextInput
TextInput component allows users to input text. It is mostly used in forms.
<Canvas>
<Story name="TextInput">{Template.bind({})}</Story>
</Canvas>
# Props
<ArgsTable of={TextInput} />

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from "@storybook/react";
import { TextInput } from "@design-system/headless";
/**
* TextInput component allows users to input text. It is mostly used in forms.
*/
const meta: Meta<typeof TextInput> = {
component: TextInput,
title: "Design-system/headless/TextInput",
args: {
label: "Label",
placeholder: "Placeholder",
},
};
export default meta;
type Story = StoryObj<typeof TextInput>;
export const Main: Story = {};

View File

@ -1,85 +0,0 @@
import {
TooltipRoot,
TooltipTrigger,
TooltipContent,
Button,
} from "@design-system/headless";
import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs";
<Meta
title="Design-system/Headless/Tooltip"
component={TooltipRoot}
args={{
open: undefined,
onOpenChange: undefined,
}}
/>
export const Template = (args) => {
return (
<TooltipRoot {...args}>
<TooltipTrigger>
<Button>My trigger</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
);
};
# Tooltip
A tooltip is a small pop-up that appears when a user places their cursor over an element such as a link or button. Tooltips can be used to provide users with additional information about an element without having to clutter up the UI with additional text.
<Canvas>
<Story name="Tooltip">{Template.bind({})}</Story>
</Canvas>
<ArgsTable story="Tooltip" of={TooltipRoot} />
# Placement
The placement of the tooltip can be changed by passing the `placement` prop.
<Canvas>
<Story name="Tooltip placement">
<TooltipRoot placement="left">
<TooltipTrigger>
<Button>Left</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="top">
<TooltipTrigger>
<Button>Top</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="bottom">
<TooltipTrigger>
<Button>Bottom</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="right">
<TooltipTrigger>
<Button>Right</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
</Story>
</Canvas>
# Disabled
If the trigger is disabled, the tooltip will not be displayed.
<Canvas>
<Story name="Tooltip disabled">
<TooltipRoot>
<TooltipTrigger>
<Button isDisabled>Disabled</Button>
</TooltipTrigger>
<TooltipContent disabled>My tooltip</TooltipContent>
</TooltipRoot>
</Story>
</Canvas>

View File

@ -0,0 +1,81 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import {
TooltipRoot,
TooltipTrigger,
TooltipContent,
Button,
} from "@design-system/headless";
/**
* A tooltip is a small pop-up that appears when a user places their cursor over an element such as a link or button. Tooltips can be used to provide users with additional information about an element without having to clutter up the UI with additional text.
*/
const meta: Meta<typeof TooltipRoot> = {
component: TooltipRoot,
title: "Design-system/headless/Tooltip",
subcomponents: {
TooltipTrigger,
TooltipContent,
},
render: (args) => (
<TooltipRoot {...args}>
<TooltipTrigger>
<Button>My trigger</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
),
};
export default meta;
type Story = StoryObj<typeof TooltipRoot>;
export const Main: Story = {};
/**
* The placement of the tooltip can be changed by passing the `placement` prop.
*/
export const Placement: Story = {
render: () => (
<>
<TooltipRoot placement="left">
<TooltipTrigger>
<Button>Left</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="top">
<TooltipTrigger>
<Button>Top</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="bottom">
<TooltipTrigger>
<Button>Bottom</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
<TooltipRoot placement="right">
<TooltipTrigger>
<Button>Right</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
</>
),
};
/**
* If the trigger is disabled, the tooltip will not be displayed.
*/
export const Disabled: Story = {
render: () => (
<TooltipRoot>
<TooltipTrigger>
<Button isDisabled>Disabled</Button>
</TooltipTrigger>
<TooltipContent>My tooltip</TooltipContent>
</TooltipRoot>
),
};

View File

@ -6,6 +6,8 @@ import {
StyledSquarePreview,
} from "@design-system/storybook";
import { Icon } from "@design-system/widgets";
<Meta title="Design-system/Theme/Tokens/Dimension" />
# Dimension
@ -114,10 +116,14 @@ Border radii on various elements are fluid and additionally adjusted by theme co
export const BorderRadius = () => {
const { theme } = useTheme();
const { borderRadius } = theme;
console.log(theme);
const { borderRadiusElevation } = theme;
return (
<ThemeProvider theme={theme}>
<TokenTable prefix="border-radius" tokens={borderRadius}>
<TokenTable
prefix="border-radius-elevation"
tokens={borderRadiusElevation}
>
{(cssVar) => (
<StyledSquarePreview
style={{
@ -134,11 +140,37 @@ export const BorderRadius = () => {
### Icon Sizing
--
export const IconSizing = () => {
const { theme } = useTheme();
const { iconSize } = theme;
return (
<ThemeProvider theme={theme}>
<TokenTable prefix="icon-size" tokens={iconSize}>
{(cssVar) => (
<Icon name="star" style={{ width: cssVar, height: cssVar }} />
)}
</TokenTable>
</ThemeProvider>
);
};
<IconSizing />
### Icon Stroke
--
export const IconStroke = () => {
const { theme } = useTheme();
const { strokeWidth } = theme;
return (
<ThemeProvider theme={theme}>
<TokenTable prefix="stroke-width" tokens={strokeWidth}>
{(cssVar) => <Icon name="star" style={{ strokeWidth: cssVar }} />}
</TokenTable>
</ThemeProvider>
);
};
<IconStroke />
[Table will be here once scale is implemented]

Some files were not shown because too many files have changed in this diff Show More