Skip to content

Commit 04c564b

Browse files
committed
feat: Add test for Nextcloud 30 and update docker-compose file
1 parent 556e41a commit 04c564b

File tree

2 files changed

+286
-3
lines changed

2 files changed

+286
-3
lines changed

e2e/linkeditor.30.spec.ts

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
import { test, expect, type Page } from "@playwright/test";
2+
3+
const adminLogin = async (page: Page) => {
4+
await page.getByPlaceholder("Account name or email").fill(process.env.NEXTCLOUD_ADMIN_USER!);
5+
await page.getByPlaceholder("Account name or email").press("Tab");
6+
await page.getByPlaceholder("Password").fill(process.env.NEXTCLOUD_ADMIN_PASSWORD!);
7+
await page.getByPlaceholder("Password").press("Enter");
8+
};
9+
10+
const testUserLogin = async (page: Page) => {
11+
// Log in as other user
12+
await page.getByPlaceholder("Account name or email").fill("testuser-1");
13+
await page.getByPlaceholder("Account name or email").press("Tab");
14+
await page.getByPlaceholder("Password").fill("testuser-1-password");
15+
await page.getByPlaceholder("Password").press("Enter");
16+
};
17+
18+
const testFileViewer = async (
19+
page: Page,
20+
{ fileName, url, _blank, close }: { fileName: string; url: string; _blank: boolean; close?: boolean },
21+
) => {
22+
await page.locator("h3").filter({ hasText: fileName }).isVisible();
23+
24+
await page.getByText(`You are about to visit: ${url}`).isVisible();
25+
26+
if (_blank) {
27+
const page1Promise = page.waitForEvent("popup");
28+
await page.getByRole("link", { name: url }).click();
29+
const page1 = await page1Promise;
30+
expect(page1.url()).toBe(`${url}/`);
31+
page1.close();
32+
}
33+
34+
await page.getByRole("link", { name: "Visit link" }).isVisible();
35+
expect(await page.getByRole("link", { name: "Visit link" }).getAttribute("href")).toBe(url);
36+
37+
if (_blank) {
38+
expect(await page.getByRole("link", { name: "Visit link" }).getAttribute("target")).toBe("_blank");
39+
}
40+
41+
if (close === false) {
42+
return;
43+
}
44+
45+
await page.getByRole("link", { name: "Cancel" }).click();
46+
await expect(page.getByRole("heading", { name: "Test File.URL" })).not.toBeVisible();
47+
};
48+
49+
test.beforeEach(async ({ page, context }) => {
50+
// Grant clipboard permissions to browser context
51+
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
52+
53+
await page.goto("http://localhost:8000");
54+
});
55+
56+
test.describe("Preparation", () => {
57+
test("create test user", async ({ page }) => {
58+
await adminLogin(page);
59+
60+
await page.getByLabel("Settings menu").click();
61+
await page.getByRole("link", { name: "Accounts" }).click();
62+
await page.getByRole("button", { name: "New account" }).click();
63+
await page.locator('[data-test="username"]').fill("testuser-1");
64+
await page.locator('[data-test="password"]').fill("testuser-1-password");
65+
await page.locator('[data-test="submit"]').click();
66+
await page.getByRole("cell", { name: "testuser-1 testuser-" }).getByRole("strong").isVisible();
67+
});
68+
});
69+
70+
test.describe("Link File Creation", () => {
71+
test("create a .URL link file", async ({ page }) => {
72+
await adminLogin(page);
73+
74+
await page.getByLabel("Files", { exact: true }).click();
75+
await page.getByRole("button", { name: "New" }).click();
76+
await page.getByRole("menuitem", { name: "New link (.URL)" }).click();
77+
await page.getByLabel("File name").fill("Test File.URL");
78+
await page.getByRole("button", { name: "Create" }).click();
79+
await page.getByPlaceholder("e.g. https://example.org").fill("https://example.org");
80+
await page.getByRole("link", { name: "Save" }).click();
81+
// Space is produced by two <span> around filename and suffix and accessibility text is "View link"
82+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).scrollIntoViewIfNeeded();
83+
await expect(page.getByRole("button").filter({ hasText: "Test File .URL" })).toBeVisible();
84+
});
85+
86+
test("create a .webloc link file", async ({ page }) => {
87+
await adminLogin(page);
88+
89+
await page.getByLabel("Files", { exact: true }).click();
90+
await page.getByRole("button", { name: "New" }).click();
91+
await page.getByRole("menuitem", { name: "New link (.webloc)" }).click();
92+
await page.getByLabel("File name").fill("Test File.webloc");
93+
await page.getByRole("button", { name: "Create" }).click();
94+
await page.getByPlaceholder("e.g. https://example.org").fill("https://example.org");
95+
await page.getByRole("link", { name: "Save" }).click();
96+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
97+
await expect(page.getByRole("button").filter({ hasText: "Test File .webloc" })).toBeVisible();
98+
});
99+
100+
test("create a .webloc link file in a subdirectory", async ({ page }) => {
101+
await adminLogin(page);
102+
103+
await page.getByLabel("Files", { exact: true }).click();
104+
105+
await page.getByRole("button", { name: "Documents" }).click();
106+
107+
await page.getByRole("button", { name: "New" }).click();
108+
await page.getByRole("menuitem", { name: "New link (.webloc)" }).click();
109+
await page.getByLabel("File name").fill("Test File.webloc");
110+
await page.getByRole("button", { name: "Create" }).click();
111+
await page.getByPlaceholder("e.g. https://example.org").fill("https://example.org");
112+
await page.getByRole("link", { name: "Save" }).click();
113+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
114+
await expect(page.getByRole("button").filter({ hasText: "Test File .webloc" })).toBeVisible();
115+
});
116+
117+
test("open an existing .URL link file", async ({ page }) => {
118+
await adminLogin(page);
119+
120+
await page.getByLabel("Files", { exact: true }).click();
121+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).scrollIntoViewIfNeeded();
122+
await expect(page.getByRole("button").filter({ hasText: "Test File .URL" })).toBeVisible();
123+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).click();
124+
125+
await testFileViewer(page, { fileName: "Test File.URL", url: "https://example.org", _blank: true });
126+
});
127+
128+
test("open an existing .webloc link file", async ({ page }) => {
129+
await adminLogin(page);
130+
131+
await page.getByLabel("Files", { exact: true }).click();
132+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
133+
await expect(page.getByRole("button").filter({ hasText: "Test File .webloc" })).toBeVisible();
134+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).click();
135+
136+
await testFileViewer(page, { fileName: "Test File.webloc", url: "https://example.org", _blank: true });
137+
});
138+
139+
test("open link in same tab", async ({ page }) => {
140+
await adminLogin(page);
141+
142+
await page.getByLabel("Files", { exact: true }).click();
143+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).scrollIntoViewIfNeeded();
144+
await page.getByRole("row", { name: 'Toggle selection for file "Test File.URL"' }).getByLabel("Actions").click();
145+
await page.getByRole("menuitem", { name: "Edit link" }).click();
146+
await page.getByText("Open in same window", { exact: true }).click();
147+
await page.getByRole("link", { name: "Save" }).click();
148+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).click();
149+
150+
await testFileViewer(page, { fileName: "Test File.URL", url: "https://example.org", _blank: false, close: false });
151+
152+
await page.getByRole("link", { name: "Visit link" }).click();
153+
expect(page.url()).toBe("https://example.org/");
154+
});
155+
156+
test("open link in same tab without confirmation", async ({ page }) => {
157+
await adminLogin(page);
158+
159+
await page.getByLabel("Files", { exact: true }).click();
160+
161+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).scrollIntoViewIfNeeded();
162+
await page.getByRole("row", { name: 'Toggle selection for file "Test File.URL"' }).getByLabel("Actions").click();
163+
await page.getByRole("menuitem", { name: "Edit link" }).click();
164+
await page.getByText("Skip confirmation dialog").click();
165+
await page.getByRole("link", { name: "Save" }).click();
166+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).click();
167+
168+
await page.waitForURL("https://example.org/");
169+
});
170+
});
171+
172+
test.describe("Link File Sharing", () => {
173+
test("open shared link file", async ({ page }) => {
174+
await adminLogin(page);
175+
176+
await page.getByLabel("Files", { exact: true }).click();
177+
178+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
179+
await page
180+
.getByRole("row", { name: 'Toggle selection for file "Test File.webloc" View link Show sharing options' })
181+
.getByLabel("Show sharing options")
182+
.click();
183+
184+
await page.getByPlaceholder("Name, email, or Federated").click();
185+
await page.getByPlaceholder("Name, email, or Federated").fill("testuser");
186+
await page.getByRole("option", { name: "testuser-" }).click();
187+
await page.getByRole("button", { name: "Save share" }).click();
188+
await page.getByLabel("Copy internal link to").click();
189+
await expect(page.getByText("Link copied✖")).toBeVisible();
190+
191+
// Log out
192+
await page.getByLabel("Settings menu").click();
193+
await page.getByRole("link", { name: "Log out" }).click();
194+
195+
await testUserLogin(page);
196+
197+
// Go to link copied to clipboard
198+
const handle = await page.evaluateHandle(() => navigator.clipboard.readText());
199+
const copiedUrl = await handle.jsonValue();
200+
await page.goto(copiedUrl);
201+
202+
await testFileViewer(page, { fileName: "Test File.webloc", url: "https://example.org", _blank: true });
203+
});
204+
205+
test("edit a shared link file", async ({ page }) => {
206+
await testUserLogin(page);
207+
208+
await page.getByLabel("Files", { exact: true }).click();
209+
210+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
211+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).click();
212+
213+
await testFileViewer(page, {
214+
fileName: "Test File.webloc",
215+
url: "https://example.org",
216+
_blank: true,
217+
close: false,
218+
});
219+
220+
await page.getByRole("link", { name: "Edit link" }).click();
221+
await page.getByPlaceholder("e.g. https://example.org").click();
222+
await page.getByPlaceholder("e.g. https://example.org").fill("https://nextcloud.com");
223+
await page.getByPlaceholder("e.g. https://example.org").press("Enter");
224+
225+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).click();
226+
227+
await testFileViewer(page, { fileName: "Test File.webloc", url: "https://nextcloud.com", _blank: true });
228+
});
229+
});
230+
231+
test.describe("Public Link File Sharing", () => {
232+
test("open publicly shared link file", async ({ page }) => {
233+
await adminLogin(page);
234+
await page.getByLabel("Files", { exact: true }).click();
235+
236+
// Share the file
237+
await page.getByRole("button").filter({ hasText: "Test File .URL" }).scrollIntoViewIfNeeded();
238+
await page
239+
.getByRole("row", { name: 'Toggle selection for file "Test File.URL" View link Show sharing options' })
240+
.getByLabel("Show sharing options")
241+
.click();
242+
243+
// Create and copy the public link
244+
await page.getByLabel("Create a new share link").click();
245+
await expect(page.getByText("Link copied✖")).toBeVisible();
246+
247+
// Go to link copied to clipboard
248+
const handle = await page.evaluateHandle(() => navigator.clipboard.readText());
249+
const copiedUrl = await handle.jsonValue();
250+
await page.goto(copiedUrl);
251+
252+
await page.getByRole("link", { name: "View link" }).click();
253+
254+
await page.waitForURL("https://example.org/");
255+
});
256+
257+
test("cannot edit publicly shared link file", async ({ page }) => {
258+
await adminLogin(page);
259+
await page.getByLabel("Files", { exact: true }).click();
260+
261+
// Share the file
262+
await page.getByRole("button").filter({ hasText: "Test File .webloc" }).scrollIntoViewIfNeeded();
263+
await page.getByLabel("Shared with testuser-").click();
264+
265+
// Create and copy the public link
266+
await page.getByLabel("Create a new share link").click();
267+
await expect(page.getByText("Link copied✖")).toBeVisible();
268+
269+
// Go to link copied to clipboard
270+
const handle = await page.evaluateHandle(() => navigator.clipboard.readText());
271+
const copiedUrl = await handle.jsonValue();
272+
await page.goto(copiedUrl);
273+
274+
await page.getByRole("link", { name: "View link" }).click();
275+
276+
await testFileViewer(page, {
277+
fileName: "Test File.webloc",
278+
url: "https://nextcloud.com",
279+
_blank: true,
280+
close: false,
281+
});
282+
283+
await expect(page.getByRole("link", { name: "Edit link" })).not.toBeVisible();
284+
});
285+
});

tests/docker-compose.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: "3.4"
2-
31
x-restart-policy: &restart_policy
42
restart: unless-stopped
53

@@ -44,7 +42,7 @@ services:
4442

4543
app:
4644
<<: *restart_policy
47-
image: nextcloud:28-fpm-alpine
45+
image: nextcloud:30-fpm-alpine
4846
ports:
4947
- 9000:9000
5048
links:

0 commit comments

Comments
 (0)