Skip to content

Commit 2af8e36

Browse files
authored
chore: test cases for static url flow (#41363)
## Description Added cypress test cases to validate page slug and application slug persistence flows. We are also validating the deployed application to ascertain if the static url work after being enabled and routes deleted after it has being disabled. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Settings" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/19159763732> > Commit: c6771d6 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=19159763732&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Settings` > Spec: > <hr>Fri, 07 Nov 2025 06:29:12 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Static URL is enabled by default: apps and pages get auto-generated, editable slugs with live validation, URL preview, persistence across reloads, and deploy-time routing. * **Tests** * Added end-to-end coverage for slug generation, editing, validation, persistence, cancellation, disable/reenable flows, and deployed-route behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 4583e46 commit 2af8e36

File tree

6 files changed

+717
-2
lines changed

6 files changed

+717
-2
lines changed
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import * as _ from "../../../../support/Objects/ObjectsCore";
2+
import AdminsSettings from "../../../../locators/AdminsSettings";
3+
4+
describe("Static URL - Slug Persistence", { tags: ["@tag.Settings"] }, () => {
5+
it("1. Should auto-generate slug from application name when Static URL toggle is enabled", () => {
6+
// Navigate to General Settings
7+
_.appSettings.OpenAppSettings();
8+
_.appSettings.GoToGeneralSettings();
9+
10+
// Get the current application name
11+
_.agHelper
12+
.GetText(AdminsSettings.generalSettingsAppName, "val")
13+
.then((appName) => {
14+
const appNameStr = appName as string;
15+
// Convert app name to expected slug format (lowercase, spaces replaced with hyphens)
16+
const expectedSlug = appNameStr
17+
.toLowerCase()
18+
.trim()
19+
.replace(/\s+/g, "-")
20+
.replace(/[^a-z0-9-]/g, ""); // Remove any special characters except hyphens
21+
22+
// Toggle on Static URL
23+
_.agHelper.GetNClick(AdminsSettings.generalSettingsStaticUrl);
24+
25+
// Wait for the API call to complete
26+
_.assertHelper.AssertNetworkStatus("@fetchAppSlugSuggestion", 200);
27+
cy.get("@fetchAppSlugSuggestion").then((interception: any) => {
28+
const suggestedSlug = interception.response.body.data;
29+
30+
// Verify the slug input field is visible and contains the suggested slug
31+
_.agHelper.AssertElementVisibility(
32+
AdminsSettings.generalSettingsStaticAppSlug,
33+
);
34+
_.agHelper.AssertText(
35+
AdminsSettings.generalSettingsStaticAppSlug,
36+
"val",
37+
suggestedSlug,
38+
);
39+
40+
// Verify the suggested slug starts with the expected slug derived from the application name
41+
// Backend appends a random hash after a hyphen for uniqueness
42+
expect(suggestedSlug).to.satisfy((slug: string) =>
43+
slug.startsWith(`${expectedSlug}`),
44+
);
45+
});
46+
});
47+
});
48+
49+
it("2. Should allow editing slug and show available status with updated URL preview", () => {
50+
// Continue from test 1 - static URL is already enabled and slug is already set
51+
// Get the current slug from the input field
52+
_.agHelper
53+
.GetText(AdminsSettings.generalSettingsStaticAppSlug, "val")
54+
.then((initialSlug) => {
55+
const initialSlugStr = initialSlug as string;
56+
57+
// Verify the slug input field is visible and contains the suggested slug
58+
_.agHelper.AssertElementVisibility(
59+
AdminsSettings.generalSettingsStaticAppSlug,
60+
);
61+
_.agHelper.AssertText(
62+
AdminsSettings.generalSettingsStaticAppSlug,
63+
"val",
64+
initialSlugStr,
65+
);
66+
67+
// Modify the slug by appending "1"
68+
const modifiedSlug = initialSlugStr + "1";
69+
_.agHelper.ClearNType(
70+
AdminsSettings.generalSettingsStaticAppSlug,
71+
modifiedSlug,
72+
);
73+
74+
// Wait for the validation API call to complete
75+
_.assertHelper.AssertNetworkStatus("@validateAppSlug", 200);
76+
77+
// Verify the "Available" message appears
78+
_.agHelper.AssertContains("Available", "be.visible");
79+
80+
// Verify the URL preview shows the modified slug
81+
// The URL preview should contain the full URL ending with the modified slug
82+
_.agHelper.AssertContains(`/app/${modifiedSlug}`, "be.visible");
83+
});
84+
});
85+
86+
it("3. Should persist slug after confirmation and reflect on page reload", () => {
87+
// Continue from test 2 - slug is already modified and available
88+
// Get the modified slug from the input field
89+
_.agHelper
90+
.GetText(AdminsSettings.generalSettingsStaticAppSlug, "val")
91+
.then((modifiedSlug) => {
92+
const modifiedSlugStr = modifiedSlug as string;
93+
94+
// Verify the "Available" message is still visible
95+
_.agHelper.AssertContains("Available", "be.visible");
96+
97+
// Click on "Apply" button to open confirmation modal
98+
// The Apply button is in the settings pane, not in the modal
99+
_.agHelper.AssertElementEnabledDisabled(
100+
AdminsSettings.staticUrlConfirmationConfirm,
101+
0,
102+
false,
103+
);
104+
_.agHelper.GetNClickByContains(
105+
AdminsSettings.staticUrlConfirmationConfirm,
106+
"Apply",
107+
);
108+
109+
// Verify the modal appears with title "Change App Slug"
110+
_.agHelper.AssertElementVisibility(
111+
AdminsSettings.staticUrlConfirmationModal,
112+
);
113+
_.agHelper.AssertContains("Change App Slug", "be.visible");
114+
115+
// Verify the modal shows the "To" URL with the modified slug
116+
_.agHelper.AssertContains("To", "be.visible");
117+
_.agHelper.AssertContains(`/app/${modifiedSlugStr}`, "be.visible");
118+
119+
// Click on "Change App Slug" button in the modal to confirm
120+
_.agHelper.GetNClickByContains(
121+
AdminsSettings.staticUrlConfirmationConfirm,
122+
"Change App Slug",
123+
);
124+
125+
// Verify the success toast notification appears
126+
_.agHelper.ValidateToastMessage("App slug updated");
127+
128+
// Reload the page
129+
_.agHelper.CypressReload();
130+
131+
// Verify the slug persists after reload
132+
_.agHelper.AssertElementVisibility(
133+
AdminsSettings.generalSettingsStaticAppSlug,
134+
);
135+
_.agHelper.AssertText(
136+
AdminsSettings.generalSettingsStaticAppSlug,
137+
"val",
138+
modifiedSlugStr,
139+
);
140+
});
141+
});
142+
143+
it("4. Should not persist slug when modal is cancelled", () => {
144+
// Continue from test 3 - slug is already persisted from previous test
145+
// Get the current persisted slug from the input field
146+
_.agHelper
147+
.GetText(AdminsSettings.generalSettingsStaticAppSlug, "val")
148+
.then((persistedSlug) => {
149+
const persistedSlugStr = persistedSlug as string;
150+
151+
// Modify the slug by appending "2" to create a new modified slug
152+
const modifiedSlug = persistedSlugStr + "2";
153+
_.agHelper.ClearNType(
154+
AdminsSettings.generalSettingsStaticAppSlug,
155+
modifiedSlug,
156+
);
157+
158+
// Wait for the validation API call to complete
159+
_.assertHelper.AssertNetworkStatus("@validateAppSlug", 200);
160+
161+
// Verify the "Available" message appears
162+
_.agHelper.AssertContains("Available", "be.visible");
163+
164+
// Click on "Apply" button to open confirmation modal
165+
_.agHelper.AssertElementEnabledDisabled(
166+
AdminsSettings.staticUrlConfirmationConfirm,
167+
0,
168+
false,
169+
);
170+
_.agHelper.GetNClickByContains(
171+
AdminsSettings.staticUrlConfirmationConfirm,
172+
"Apply",
173+
);
174+
175+
// Verify the modal appears with title "Change App Slug"
176+
_.agHelper.AssertElementVisibility(
177+
AdminsSettings.staticUrlConfirmationModal,
178+
);
179+
_.agHelper.AssertContains("Change App Slug", "be.visible");
180+
181+
// Verify the modal shows the "To" URL with the modified slug
182+
_.agHelper.AssertContains("To", "be.visible");
183+
_.agHelper.AssertContains(`/app/${modifiedSlug}`, "be.visible");
184+
185+
// Click on "Cancel" button in the modal instead of confirming
186+
// This should close the modal without persisting the slug
187+
_.agHelper.GetNClickByContains(
188+
AdminsSettings.staticUrlConfirmationCancel,
189+
"Cancel",
190+
);
191+
192+
// Verify the modal is closed
193+
_.agHelper.AssertElementAbsence(
194+
AdminsSettings.staticUrlConfirmationModal,
195+
);
196+
197+
// Reload the page
198+
_.agHelper.CypressReload();
199+
200+
// Wait for the page to load
201+
_.appSettings.OpenAppSettings();
202+
_.appSettings.GoToGeneralSettings();
203+
204+
// Verify the modified slug does NOT persist after reload
205+
// The slug should revert to the previously persisted slug (from test 3)
206+
_.agHelper.AssertElementVisibility(
207+
AdminsSettings.generalSettingsStaticAppSlug,
208+
);
209+
_.agHelper.AssertText(
210+
AdminsSettings.generalSettingsStaticAppSlug,
211+
"val",
212+
persistedSlugStr,
213+
);
214+
// Note: AssertText doesn't support "not.have.value", so keeping the original assertion
215+
cy.get(AdminsSettings.generalSettingsStaticAppSlug).should(
216+
"not.have.value",
217+
modifiedSlug,
218+
);
219+
});
220+
});
221+
222+
it("5. Should delete persisted slug and generate new slug when Static URL is disabled and re-enabled", () => {
223+
// Continue from test 4 - slug is already persisted from previous test
224+
// Get the current persisted slug and application name
225+
let appNameStr: string;
226+
let persistedSlugStr: string;
227+
228+
_.agHelper
229+
.GetText(AdminsSettings.generalSettingsAppName, "val")
230+
.then((appName) => {
231+
appNameStr = appName as string;
232+
});
233+
234+
_.agHelper
235+
.GetText(AdminsSettings.generalSettingsStaticAppSlug, "val")
236+
.then((persistedSlug) => {
237+
persistedSlugStr = persistedSlug as string;
238+
});
239+
240+
cy.then(() => {
241+
// Convert app name to expected slug format (lowercase, spaces replaced with hyphens)
242+
const expectedSlug = appNameStr
243+
.toLowerCase()
244+
.trim()
245+
.replace(/\s+/g, "-")
246+
.replace(/[^a-z0-9-]/g, ""); // Remove any special characters except hyphens
247+
248+
// Disable Static URL toggle
249+
_.agHelper.GetNClick(AdminsSettings.generalSettingsStaticUrl);
250+
251+
// Verify the confirmation modal appears for disabling
252+
_.agHelper.AssertElementVisibility(
253+
AdminsSettings.staticUrlConfirmationModal,
254+
);
255+
_.agHelper.AssertContains("Disable App Static URL", "be.visible");
256+
257+
// Confirm disabling in the modal
258+
_.agHelper.GetNClickByContains(
259+
AdminsSettings.staticUrlConfirmationConfirm,
260+
"Disable Static URL",
261+
);
262+
263+
// Wait for the snackbar notification
264+
_.agHelper.ValidateToastMessage(
265+
"Static URL disabled. The app has reverted to default Appsmith URLs.",
266+
);
267+
268+
// Verify the slug input field is no longer visible (toggle is off)
269+
_.agHelper.AssertElementAbsence(
270+
AdminsSettings.generalSettingsStaticAppSlug,
271+
);
272+
273+
// Re-enable Static URL toggle
274+
_.agHelper.GetNClick(AdminsSettings.generalSettingsStaticUrl);
275+
276+
// Wait for the API call to fetch new slug suggestion
277+
_.assertHelper
278+
.WaitForNetworkCall("@fetchAppSlugSuggestion")
279+
.then((response: any) => {
280+
const newSuggestedSlug = response.body.data;
281+
282+
// Verify the slug input field is visible again
283+
_.agHelper.AssertElementVisibility(
284+
AdminsSettings.generalSettingsStaticAppSlug,
285+
);
286+
_.agHelper.AssertText(
287+
AdminsSettings.generalSettingsStaticAppSlug,
288+
"val",
289+
newSuggestedSlug,
290+
);
291+
292+
// Verify the new slug is different from the previously persisted slug
293+
expect(newSuggestedSlug).to.not.eq(persistedSlugStr);
294+
295+
// Verify the new slug starts with the expected slug derived from the application name
296+
// Backend appends a random hash after a hyphen for uniqueness
297+
expect(newSuggestedSlug).to.satisfy((slug: string) =>
298+
slug.startsWith(expectedSlug),
299+
);
300+
});
301+
});
302+
});
303+
});

0 commit comments

Comments
 (0)