4411c9ffb45c18af78f627ca5fd61435603c7d87
[arvados.git] / services / workbench2 / cypress / e2e / search.cy.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 describe("Search tests", function () {
6     let activeUser;
7     let adminUser;
8
9     before(function () {
10         // Only set up common users once. These aren't set up as aliases because
11         // aliases are cleaned up after every test. Also it doesn't make sense
12         // to set the same users on beforeEach() over and over again, so we
13         // separate a little from Cypress' 'Best Practices' here.
14         cy.getUser("admin", "Admin", "User", true, true)
15             .as("adminUser")
16             .then(function () {
17                 adminUser = this.adminUser;
18             });
19         cy.getUser("collectionuser1", "Collection", "User", false, true)
20             .as("activeUser")
21             .then(function () {
22                 activeUser = this.activeUser;
23             });
24     });
25
26     it("can search for old collection versions", function () {
27         const colName = `Versioned Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
28         let colUuid = "";
29         let oldVersionUuid = "";
30         // Make sure no other collections with this name exist
31         cy.doRequest("GET", "/arvados/v1/collections", null, {
32             filters: `[["name", "=", "${colName}"]]`,
33             include_old_versions: true,
34         })
35             .its("body.items")
36             .as("collections")
37             .then(function () {
38                 expect(this.collections).to.be.empty;
39             });
40         // Creates the collection using the admin token so we can set up
41         // a bogus manifest text without block signatures.
42         cy.createCollection(adminUser.token, {
43             name: colName,
44             owner_uuid: activeUser.user.uuid,
45             preserve_version: true,
46             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
47         })
48             .as("originalVersion")
49             .then(function () {
50                 // Change the file name to create a new version.
51                 cy.updateCollection(adminUser.token, this.originalVersion.uuid, {
52                     manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo\n",
53                 });
54                 colUuid = this.originalVersion.uuid;
55             });
56         // Confirm that there are 2 versions of the collection
57         cy.doRequest("GET", "/arvados/v1/collections", null, {
58             filters: `[["name", "=", "${colName}"]]`,
59             include_old_versions: true,
60         })
61             .its("body.items")
62             .as("collections")
63             .then(function () {
64                 expect(this.collections).to.have.lengthOf(2);
65                 this.collections.map(function (aCollection) {
66                     expect(aCollection.current_version_uuid).to.equal(colUuid);
67                     if (aCollection.uuid !== aCollection.current_version_uuid) {
68                         oldVersionUuid = aCollection.uuid;
69                     }
70                 });
71                 cy.loginAs(activeUser);
72                 const searchQuery = `${colName} type:arvados#collection`;
73                 // Search for only collection's current version
74                 cy.doSearch(`${searchQuery}`);
75                 cy.get("[data-cy=search-results]").should("contain", "head version");
76                 cy.get("[data-cy=search-results]").should("not.contain", "version 1");
77                 // ...and then, include old versions.
78                 cy.doSearch(`${searchQuery} is:pastVersion`);
79                 cy.get("[data-cy=search-results]").should("contain", "head version");
80                 cy.get("[data-cy=search-results]").should("contain", "version 1");
81             });
82     });
83
84     it("can display path of the selected item", function () {
85         const colName = `Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
86
87         // Creates the collection using the admin token so we can set up
88         // a bogus manifest text without block signatures.
89         cy.createCollection(adminUser.token, {
90             name: colName,
91             owner_uuid: activeUser.user.uuid,
92             preserve_version: true,
93             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
94         }).then(function () {
95             cy.loginAs(activeUser);
96
97             cy.doSearch(colName);
98
99             cy.get("[data-cy=search-results]").should("contain", colName);
100
101             cy.get("[data-cy=search-results]").contains(colName).closest("tr").click();
102
103             cy.get("[data-cy=element-path]").should("contain", `/ Projects / ${colName}`);
104         });
105     });
106
107     it("can search items using quotes", function () {
108         const random = Math.floor(Math.random() * Math.floor(999999));
109         const colName = `Collection ${random}`;
110         const colName2 = `Collection test ${random}`;
111
112         // Creates the collection using the admin token so we can set up
113         // a bogus manifest text without block signatures.
114         cy.createCollection(adminUser.token, {
115             name: colName,
116             owner_uuid: activeUser.user.uuid,
117             preserve_version: true,
118             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
119         }).as("collection1");
120
121         cy.createCollection(adminUser.token, {
122             name: colName2,
123             owner_uuid: activeUser.user.uuid,
124             preserve_version: true,
125             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
126         }).as("collection2");
127
128         cy.getAll("@collection1", "@collection2").then(function () {
129             cy.loginAs(activeUser);
130
131             cy.doSearch(colName);
132             cy.get("[data-cy=search-results] table tbody tr").should("have.length", 2);
133
134             cy.doSearch(`"${colName}"`);
135             cy.get("[data-cy=search-results] table tbody tr").should("have.length", 1);
136         });
137     });
138
139     it("can display owner of the item", function () {
140         const colName = `Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
141
142         cy.createCollection(adminUser.token, {
143             name: colName,
144             owner_uuid: activeUser.user.uuid,
145             preserve_version: true,
146             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
147         }).then(function () {
148             cy.loginAs(activeUser);
149
150             cy.doSearch(colName);
151
152             cy.get("[data-cy=search-results]").should("contain", colName);
153
154             cy.get("[data-cy=search-results]")
155                 .contains(colName)
156                 .closest("tr")
157                 .within(() => {
158                     cy.get("p").contains(activeUser.user.uuid).should("contain", activeUser.user.full_name);
159                 });
160         });
161     });
162
163     it("shows search context menu", function () {
164         const colName = `Home Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
165         const federatedColName = `Federated Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
166         const federatedColUuid = "xxxxx-4zz18-000000000000000";
167
168         // Intercept config to insert remote cluster
169         cy.intercept({ method: "GET", hostname: "127.0.0.1", url: "**/arvados/v1/config?nocache=*" }, req => {
170             req.reply(res => {
171                 res.body.RemoteClusters = {
172                     "*": res.body.RemoteClusters["*"],
173                     xxxxx: {
174                         ActivateUsers: true,
175                         Host: "xxxxx.fakecluster.tld",
176                         Insecure: false,
177                         Proxy: true,
178                         Scheme: "",
179                     },
180                 };
181             });
182         });
183
184         // Fake remote cluster config
185         cy.intercept(
186             {
187                 method: "GET",
188                 hostname: "xxxxx.fakecluster.tld",
189                 url: "**/arvados/v1/config",
190             },
191             {
192                 statusCode: 200,
193                 body: {
194                     API: {},
195                     ClusterID: "xxxxx",
196                     Collections: {},
197                     Containers: {},
198                     InstanceTypes: {},
199                     Login: {},
200                     Mail: { SupportEmailAddress: "arvados@example.com" },
201                     RemoteClusters: {
202                         "*": {
203                             ActivateUsers: false,
204                             Host: "",
205                             Insecure: false,
206                             Proxy: false,
207                             Scheme: "https",
208                         },
209                     },
210                     Services: {
211                         Composer: { ExternalURL: "" },
212                         Controller: { ExternalURL: "https://xxxxx.fakecluster.tld:34763/" },
213                         DispatchCloud: { ExternalURL: "" },
214                         DispatchLSF: { ExternalURL: "" },
215                         DispatchSLURM: { ExternalURL: "" },
216                         GitHTTP: { ExternalURL: "https://xxxxx.fakecluster.tld:39105/" },
217                         GitSSH: { ExternalURL: "" },
218                         Health: { ExternalURL: "https://xxxxx.fakecluster.tld:42915/" },
219                         Keepbalance: { ExternalURL: "" },
220                         Keepproxy: { ExternalURL: "https://xxxxx.fakecluster.tld:46773/" },
221                         Keepstore: { ExternalURL: "" },
222                         RailsAPI: { ExternalURL: "" },
223                         WebDAV: { ExternalURL: "https://xxxxx.fakecluster.tld:36041/" },
224                         WebDAVDownload: { ExternalURL: "https://xxxxx.fakecluster.tld:42957/" },
225                         WebShell: { ExternalURL: "" },
226                         Websocket: { ExternalURL: "wss://xxxxx.fakecluster.tld:37121/websocket" },
227                         Workbench1: { ExternalURL: "https://wb1.xxxxx.fakecluster.tld/" },
228                         Workbench2: { ExternalURL: "https://wb2.xxxxx.fakecluster.tld/" },
229                     },
230                     StorageClasses: {
231                         default: { Default: true, Priority: 0 },
232                     },
233                     Users: {},
234                     Volumes: {},
235                     Workbench: {},
236                 },
237             }
238         );
239
240         cy.createCollection(adminUser.token, {
241             name: colName,
242             owner_uuid: activeUser.user.uuid,
243             preserve_version: true,
244             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n",
245         }).then(function (testCollection) {
246             cy.loginAs(activeUser);
247
248             // Intercept search results to add federated result
249             cy.intercept({ method: "GET", url: "**/arvados/v1/groups/contents?*" }, req => {
250                 req.reply(res => {
251                     res.body.items = [
252                         res.body.items[0],
253                         {
254                             ...res.body.items[0],
255                             uuid: federatedColUuid,
256                             portable_data_hash: "00000000000000000000000000000000+0",
257                             name: federatedColName,
258                             href: res.body.items[0].href.replace(testCollection.uuid, federatedColUuid),
259                         },
260                     ];
261                     res.body.items_available += 1;
262                 });
263             });
264
265             cy.doSearch(colName);
266
267             // Stub new window
268             cy.window().then(win => {
269                 cy.stub(win, "open").as("Open");
270             });
271
272             // Check copy to clipboard
273             cy.get("[data-cy=search-results]").contains(colName).rightclick();
274             cy.get("[data-cy=context-menu]").within(ctx => {
275                 // Check that there are 4 items in the menu
276                 cy.get(ctx).children().should("have.length", 4);
277                 cy.contains("API Details");
278                 cy.contains("Copy to clipboard");
279                 cy.contains("Open in new tab");
280                 cy.contains("View details");
281
282                 cy.contains("Copy to clipboard").click();
283                 cy.waitForDom();
284                 cy.window().then(win =>
285                     win.navigator.clipboard.readText().then(text => {
286                         expect(text).to.match(new RegExp(`/collections/${testCollection.uuid}$`));
287                     })
288                 );
289             });
290
291             // Check open in new tab
292             cy.get("[data-cy=search-results]").contains(colName).rightclick();
293             cy.get("[data-cy=context-menu]").within(() => {
294                 cy.contains("Open in new tab").click();
295                 cy.waitForDom();
296                 cy.get("@Open").should("have.been.calledOnceWith", `${window.location.origin}/collections/${testCollection.uuid}`);
297             });
298
299             // Check federated result copy to clipboard
300             cy.get("[data-cy=search-results]").contains(federatedColName).rightclick();
301             cy.get("[data-cy=context-menu]").within(() => {
302                 cy.contains("Copy to clipboard").click();
303                 cy.waitForDom();
304                 cy.window().then(win =>
305                     win.navigator.clipboard.readText().then(text => {
306                         expect(text).to.equal(`https://wb2.xxxxx.fakecluster.tld/collections/${federatedColUuid}`);
307                     })
308                 );
309             });
310             // Check open in new tab
311             cy.get("[data-cy=search-results]").contains(federatedColName).rightclick();
312             cy.get("[data-cy=context-menu]").within(() => {
313                 cy.contains("Open in new tab").click();
314                 cy.waitForDom();
315                 cy.get("@Open").should("have.been.calledWith", `https://wb2.xxxxx.fakecluster.tld/collections/${federatedColUuid}`);
316             });
317         });
318     });
319 });