pinokiod 8.0.79 → 8.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "8.0.79",
3
+ "version": "8.0.80",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -1870,8 +1870,10 @@ class Server {
1870
1870
  }
1871
1871
  return ""
1872
1872
  }
1873
+ const launcherPath = this.kernel.path("api", name)
1874
+ const launcherDisplayPath = this.formatLogsDisplayPath(launcherPath)
1873
1875
  const launcherRemote = this.kernel.api && typeof this.kernel.api.parentGitURI === "function"
1874
- ? (this.kernel.api.parentGitURI(this.kernel.path("api", name)) || "")
1876
+ ? (this.kernel.api.parentGitURI(launcherPath) || "")
1875
1877
  : ""
1876
1878
  const launcherRemoteUrl = buildGitRemoteWebUrl(launcherRemote)
1877
1879
 
@@ -1926,7 +1928,8 @@ class Server {
1926
1928
  dev_link,
1927
1929
  // repos,
1928
1930
  current_urls,
1929
- path: this.kernel.path("api", name),
1931
+ path: launcherPath,
1932
+ launcher_path_display: launcherDisplayPath,
1930
1933
  log_path: this.kernel.path("api", name, "logs"),
1931
1934
  plugin_menu: null,
1932
1935
  portal: this.portal,
@@ -202,52 +202,148 @@ body.dark .app-header-info-popover-title {
202
202
  body.dark .app-header-info-popover-description {
203
203
  color: rgba(203, 213, 225, 0.78);
204
204
  }
205
- .app-header-info-popover-link,
206
- .app-header-info-popover-link--muted {
205
+ .app-header-info-popover-meta {
207
206
  margin-top: 12px;
208
- min-height: 32px;
209
- display: flex;
210
- align-items: center;
211
- justify-content: space-between;
212
- gap: 10px;
213
- padding: 0 10px;
214
- border-radius: 7px;
207
+ overflow: hidden;
215
208
  border: 1px solid rgba(15, 23, 42, 0.1);
209
+ border-radius: 7px;
216
210
  background: rgba(15, 23, 42, 0.035);
211
+ }
212
+ body.dark .app-header-info-popover-meta {
213
+ border-color: rgba(255, 255, 255, 0.1);
214
+ background: rgba(255, 255, 255, 0.06);
215
+ }
216
+ .app-header-info-popover-row {
217
+ min-height: 48px;
218
+ display: grid;
219
+ grid-template-columns: 26px minmax(0, 1fr) auto;
220
+ align-items: center;
221
+ gap: 10px;
222
+ padding: 7px 9px;
217
223
  color: rgba(15, 23, 42, 0.88);
218
- font-size: 12px;
219
- font-weight: 650;
220
- line-height: 1.2;
221
- text-decoration: none;
222
224
  box-sizing: border-box;
223
225
  }
224
- .app-header-info-popover-link:hover {
226
+ .app-header-info-popover-row + .app-header-info-popover-row {
227
+ border-top: 1px solid rgba(15, 23, 42, 0.1);
228
+ }
229
+ body.dark .app-header-info-popover-row {
230
+ color: rgba(248, 250, 252, 0.9);
231
+ }
232
+ body.dark .app-header-info-popover-row + .app-header-info-popover-row {
233
+ border-top-color: rgba(255, 255, 255, 0.1);
234
+ }
235
+ .app-header-info-popover-row--link {
236
+ text-decoration: none;
237
+ }
238
+ .app-header-info-popover-row--link:hover {
225
239
  background: rgba(15, 23, 42, 0.07);
226
240
  }
227
- .app-header-info-popover-link span {
241
+ body.dark .app-header-info-popover-row--link:hover {
242
+ background: rgba(255, 255, 255, 0.09);
243
+ }
244
+ .app-header-info-popover-row--link:focus-visible {
245
+ outline: 2px solid rgba(10, 132, 255, 0.55);
246
+ outline-offset: -2px;
247
+ }
248
+ .app-header-info-popover-row-icon {
249
+ width: 26px;
250
+ display: inline-flex;
251
+ align-items: center;
252
+ justify-content: center;
253
+ color: rgba(71, 85, 105, 0.78);
254
+ font-size: 18px;
255
+ }
256
+ body.dark .app-header-info-popover-row-icon {
257
+ color: rgba(226, 232, 240, 0.82);
258
+ }
259
+ .app-header-info-popover-row-copy {
228
260
  min-width: 0;
261
+ }
262
+ .app-header-info-popover-row-label {
263
+ display: block;
264
+ color: rgba(15, 23, 42, 0.9);
265
+ font-size: 12px;
266
+ font-weight: 700;
267
+ line-height: 1.2;
268
+ }
269
+ body.dark .app-header-info-popover-row-label {
270
+ color: rgba(248, 250, 252, 0.92);
271
+ }
272
+ .app-header-info-popover-row-value {
273
+ display: block;
274
+ margin-top: 3px;
275
+ color: rgba(71, 85, 105, 0.8);
276
+ font-size: 11px;
277
+ font-weight: 500;
278
+ line-height: 1.2;
229
279
  overflow: hidden;
230
280
  text-overflow: ellipsis;
231
281
  white-space: nowrap;
232
282
  }
233
- .app-header-info-popover-link:focus-visible {
283
+ body.dark .app-header-info-popover-row-value {
284
+ color: rgba(203, 213, 225, 0.76);
285
+ }
286
+ .app-header-info-popover-row-actions {
287
+ display: inline-flex;
288
+ align-items: center;
289
+ gap: 4px;
290
+ }
291
+ .app-header-info-popover-row-action {
292
+ appearance: none;
293
+ width: 28px;
294
+ height: 28px;
295
+ display: inline-flex;
296
+ align-items: center;
297
+ justify-content: center;
298
+ margin: 0;
299
+ padding: 0;
300
+ border: 1px solid rgba(15, 23, 42, 0.1);
301
+ border-radius: 6px;
302
+ background: rgba(255, 255, 255, 0.5);
303
+ color: rgba(71, 85, 105, 0.82);
304
+ font: inherit;
305
+ cursor: pointer;
306
+ }
307
+ .app-header-info-popover-row-action:hover {
308
+ border-color: rgba(15, 23, 42, 0.16);
309
+ background: rgba(15, 23, 42, 0.065);
310
+ color: rgba(15, 23, 42, 0.9);
311
+ }
312
+ .app-header-info-popover-row-action:focus-visible {
234
313
  outline: 2px solid rgba(10, 132, 255, 0.55);
235
314
  outline-offset: 2px;
236
315
  }
237
- body.dark .app-header-info-popover-link,
238
- body.dark .app-header-info-popover-link--muted {
316
+ .app-header-info-popover-row-action.is-copied {
317
+ color: #15803d;
318
+ }
319
+ body.dark .app-header-info-popover-row-action {
239
320
  border-color: rgba(255, 255, 255, 0.1);
240
- background: rgba(255, 255, 255, 0.06);
241
- color: rgba(248, 250, 252, 0.9);
321
+ background: rgba(255, 255, 255, 0.035);
322
+ color: rgba(226, 232, 240, 0.8);
242
323
  }
243
- body.dark .app-header-info-popover-link:hover {
324
+ body.dark .app-header-info-popover-row-action:hover {
325
+ border-color: rgba(255, 255, 255, 0.16);
244
326
  background: rgba(255, 255, 255, 0.09);
327
+ color: rgba(248, 250, 252, 0.94);
245
328
  }
246
- .app-header-info-popover-link--muted {
247
- justify-content: flex-start;
329
+ body.dark .app-header-info-popover-row-action.is-copied {
330
+ color: #86efac;
331
+ }
332
+ .app-header-info-popover-row-trailing {
333
+ width: 28px;
334
+ height: 28px;
335
+ display: inline-flex;
336
+ align-items: center;
337
+ justify-content: center;
338
+ color: rgba(71, 85, 105, 0.72);
339
+ }
340
+ body.dark .app-header-info-popover-row-trailing {
341
+ color: rgba(226, 232, 240, 0.76);
342
+ }
343
+ .app-header-info-popover-row--muted .app-header-info-popover-row-value {
248
344
  color: rgba(100, 116, 139, 0.78);
249
345
  }
250
- body.dark .app-header-info-popover-link--muted {
346
+ body.dark .app-header-info-popover-row--muted .app-header-info-popover-row-value {
251
347
  color: rgba(148, 163, 184, 0.86);
252
348
  }
253
349
  .app-header-identity-icon {
@@ -8281,6 +8377,10 @@ body.dark .pinokio-custom-terminal-header {
8281
8377
  <%
8282
8378
  const appInfoRemoteUrl = typeof launcher_remote_url === "string" ? launcher_remote_url : ""
8283
8379
  const appInfoRemoteDisplayUrl = appInfoRemoteUrl.replace(/^https?:\/\//i, "")
8380
+ const appInfoFolderPath = typeof path === "string" ? path : ""
8381
+ const appInfoFolderDisplayPath = typeof launcher_path_display === "string" && launcher_path_display
8382
+ ? launcher_path_display
8383
+ : appInfoFolderPath
8284
8384
  %>
8285
8385
  <body class='<%= [theme, "app-page"].filter(Boolean).join(" ") %>' data-platform="<%=platform%>" data-agent="<%=agent%>" data-view="<%=type%>">
8286
8386
  <header class='navheader grabbable'>
@@ -8327,14 +8427,43 @@ body.dark .pinokio-custom-terminal-header {
8327
8427
  <div class="app-header-info-popover-description"><%=config.description || 'No description provided.'%></div>
8328
8428
  </div>
8329
8429
  </div>
8330
- <% if (appInfoRemoteUrl) { %>
8331
- <a class="app-header-info-popover-link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
8332
- <span><%=appInfoRemoteDisplayUrl%></span>
8333
- <i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i>
8334
- </a>
8335
- <% } else { %>
8336
- <div class="app-header-info-popover-link--muted">No browser-openable remote detected</div>
8337
- <% } %>
8430
+ <div class="app-header-info-popover-meta">
8431
+ <% if (appInfoFolderPath) { %>
8432
+ <div class="app-header-info-popover-row">
8433
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-regular fa-folder"></i></span>
8434
+ <span class="app-header-info-popover-row-copy">
8435
+ <span class="app-header-info-popover-row-label">App folder</span>
8436
+ <span class="app-header-info-popover-row-value" title="<%=appInfoFolderPath%>"><%=appInfoFolderDisplayPath%></span>
8437
+ </span>
8438
+ <span class="app-header-info-popover-row-actions">
8439
+ <button type="button" class="app-header-info-popover-row-action" title="Copy app folder" aria-label="Copy app folder" data-app-info-copy-path="<%=appInfoFolderPath%>">
8440
+ <i class="fa-regular fa-copy" aria-hidden="true"></i>
8441
+ </button>
8442
+ <button type="button" class="app-header-info-popover-row-action" title="Reveal app folder" aria-label="Reveal app folder" data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path>
8443
+ <i class="fa-regular fa-folder-open" aria-hidden="true"></i>
8444
+ </button>
8445
+ </span>
8446
+ </div>
8447
+ <% } %>
8448
+ <% if (appInfoRemoteUrl) { %>
8449
+ <a class="app-header-info-popover-row app-header-info-popover-row--link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
8450
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
8451
+ <span class="app-header-info-popover-row-copy">
8452
+ <span class="app-header-info-popover-row-label">Source</span>
8453
+ <span class="app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%></span>
8454
+ </span>
8455
+ <span class="app-header-info-popover-row-trailing" aria-hidden="true"><i class="fa-solid fa-arrow-up-right-from-square"></i></span>
8456
+ </a>
8457
+ <% } else { %>
8458
+ <div class="app-header-info-popover-row app-header-info-popover-row--muted">
8459
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
8460
+ <span class="app-header-info-popover-row-copy">
8461
+ <span class="app-header-info-popover-row-label">Source</span>
8462
+ <span class="app-header-info-popover-row-value">No browser-openable remote detected</span>
8463
+ </span>
8464
+ </div>
8465
+ <% } %>
8466
+ </div>
8338
8467
  </div>
8339
8468
  </div>
8340
8469
  <span class='app-header-identity-separator' aria-hidden="true"></span>
@@ -8913,14 +9042,43 @@ body.dark .pinokio-custom-terminal-header {
8913
9042
  <div class="app-header-info-popover-description"><%=config.description || 'No description provided.'%></div>
8914
9043
  </div>
8915
9044
  </div>
8916
- <% if (appInfoRemoteUrl) { %>
8917
- <a class="app-header-info-popover-link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
8918
- <span><%=appInfoRemoteDisplayUrl%></span>
8919
- <i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i>
8920
- </a>
8921
- <% } else { %>
8922
- <div class="app-header-info-popover-link--muted">No browser-openable remote detected</div>
8923
- <% } %>
9045
+ <div class="app-header-info-popover-meta">
9046
+ <% if (appInfoFolderPath) { %>
9047
+ <div class="app-header-info-popover-row">
9048
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-regular fa-folder"></i></span>
9049
+ <span class="app-header-info-popover-row-copy">
9050
+ <span class="app-header-info-popover-row-label">App folder</span>
9051
+ <span class="app-header-info-popover-row-value" title="<%=appInfoFolderPath%>"><%=appInfoFolderDisplayPath%></span>
9052
+ </span>
9053
+ <span class="app-header-info-popover-row-actions">
9054
+ <button type="button" class="app-header-info-popover-row-action" title="Copy app folder" aria-label="Copy app folder" data-app-info-copy-path="<%=appInfoFolderPath%>">
9055
+ <i class="fa-regular fa-copy" aria-hidden="true"></i>
9056
+ </button>
9057
+ <button type="button" class="app-header-info-popover-row-action" title="Reveal app folder" aria-label="Reveal app folder" data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path>
9058
+ <i class="fa-regular fa-folder-open" aria-hidden="true"></i>
9059
+ </button>
9060
+ </span>
9061
+ </div>
9062
+ <% } %>
9063
+ <% if (appInfoRemoteUrl) { %>
9064
+ <a class="app-header-info-popover-row app-header-info-popover-row--link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
9065
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
9066
+ <span class="app-header-info-popover-row-copy">
9067
+ <span class="app-header-info-popover-row-label">Source</span>
9068
+ <span class="app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%></span>
9069
+ </span>
9070
+ <span class="app-header-info-popover-row-trailing" aria-hidden="true"><i class="fa-solid fa-arrow-up-right-from-square"></i></span>
9071
+ </a>
9072
+ <% } else { %>
9073
+ <div class="app-header-info-popover-row app-header-info-popover-row--muted">
9074
+ <span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
9075
+ <span class="app-header-info-popover-row-copy">
9076
+ <span class="app-header-info-popover-row-label">Source</span>
9077
+ <span class="app-header-info-popover-row-value">No browser-openable remote detected</span>
9078
+ </span>
9079
+ </div>
9080
+ <% } %>
9081
+ </div>
8924
9082
  </div>
8925
9083
  </div>
8926
9084
  <span class='mobile-bottom-nav__identity-separator' aria-hidden="true"></span>
@@ -16638,6 +16796,48 @@ const rerenderMenuSection = (container, html) => {
16638
16796
  popover.classList.toggle("hidden", isOpen)
16639
16797
  trigger.setAttribute("aria-expanded", isOpen ? "false" : "true")
16640
16798
  })
16799
+ root.querySelectorAll("[data-app-info-copy-path]").forEach((button) => {
16800
+ button.addEventListener("click", async (event) => {
16801
+ event.preventDefault()
16802
+ event.stopPropagation()
16803
+ const value = button.getAttribute("data-app-info-copy-path") || ""
16804
+ if (!value) {
16805
+ return
16806
+ }
16807
+ try {
16808
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
16809
+ await navigator.clipboard.writeText(value)
16810
+ } else {
16811
+ const input = document.createElement("textarea")
16812
+ input.value = value
16813
+ input.setAttribute("readonly", "")
16814
+ input.style.position = "fixed"
16815
+ input.style.opacity = "0"
16816
+ document.body.appendChild(input)
16817
+ input.select()
16818
+ document.execCommand("copy")
16819
+ input.remove()
16820
+ }
16821
+ const icon = button.querySelector("i")
16822
+ const originalIconClass = icon ? icon.className : ""
16823
+ button.classList.add("is-copied")
16824
+ button.setAttribute("title", "Copied")
16825
+ button.setAttribute("aria-label", "App folder copied")
16826
+ if (icon) icon.className = "fa-solid fa-check"
16827
+ window.setTimeout(() => {
16828
+ button.classList.remove("is-copied")
16829
+ button.setAttribute("title", "Copy app folder")
16830
+ button.setAttribute("aria-label", "Copy app folder")
16831
+ if (icon) icon.className = originalIconClass
16832
+ }, 1400)
16833
+ } catch (_) {}
16834
+ })
16835
+ })
16836
+ root.querySelectorAll("[data-app-info-reveal-path]").forEach((button) => {
16837
+ button.addEventListener("click", () => {
16838
+ closeAppInfoPopovers()
16839
+ })
16840
+ })
16641
16841
  root.querySelectorAll("[data-app-info-external-link]").forEach((link) => {
16642
16842
  link.addEventListener("click", (event) => {
16643
16843
  const href = link.getAttribute("href") || ""
@@ -998,9 +998,12 @@ test("app identity popover exposes launcher metadata and remote browser link", a
998
998
  assert.ok(helperIndex > existingCommunityGitConfigIndex)
999
999
  assert.ok(helperIndex < launcherRemoteIndex)
1000
1000
  assert.ok(renderPropIndex > launcherRemoteIndex)
1001
- assert.match(server, /kernel\.api\.parentGitURI\(this\.kernel\.path\("api", name\)\)/)
1001
+ assert.match(server, /const launcherPath = this\.kernel\.path\("api", name\)/)
1002
+ assert.match(server, /const launcherDisplayPath = this\.formatLogsDisplayPath\(launcherPath\)/)
1003
+ assert.match(server, /kernel\.api\.parentGitURI\(launcherPath\)/)
1002
1004
  assert.match(server, /launcherRemoteUrl = buildGitRemoteWebUrl\(launcherRemote\)/)
1003
1005
  assert.match(server, /launcher_remote_url: launcherRemoteUrl/)
1006
+ assert.match(server, /launcher_path_display: launcherDisplayPath/)
1004
1007
  assert.match(server, /const buildGitRemoteWebUrl = \(value\) =>/)
1005
1008
  assert.match(server, /return `https:\/\/\$\{sshUrlMatch\[1\]\}\/\$\{sshUrlMatch\[2\]\}`/)
1006
1009
  assert.match(server, /return `https:\/\/\$\{scpMatch\[1\]\}\/\$\{scpMatch\[2\]\}`/)
@@ -1011,8 +1014,17 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1011
1014
  assert.match(appView, /class="app-header-info-popover-icon" src="<%=config\.icon \|\| '\/pinokio-black\.png'%>"/)
1012
1015
  assert.match(appView, /const appInfoRemoteUrl = typeof launcher_remote_url === "string" \? launcher_remote_url : ""/)
1013
1016
  assert.ok(appView.includes('const appInfoRemoteDisplayUrl = appInfoRemoteUrl.replace(/^https?:\\/\\//i, "")'))
1017
+ assert.match(appView, /const appInfoFolderPath = typeof path === "string" \? path : ""/)
1018
+ assert.match(appView, /const appInfoFolderDisplayPath = typeof launcher_path_display === "string"/)
1019
+ assert.match(appView, /data-app-info-copy-path="<%=appInfoFolderPath%>"/)
1020
+ assert.match(appView, /data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path/)
1021
+ assert.match(appView, /fa-regular fa-folder/)
1022
+ assert.match(appView, /fa-brands fa-github/)
1023
+ assert.match(appView, /app-header-info-popover-row-label">App folder</)
1024
+ assert.match(appView, /app-header-info-popover-row-label">Source</)
1014
1025
  assert.match(appView, /href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link/)
1015
- assert.match(appView, /<span><%=appInfoRemoteDisplayUrl%><\/span>/)
1026
+ assert.match(appView, /app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%><\/span>/)
1027
+ assert.match(appView, /grid-template-columns: 26px minmax\(0, 1fr\) auto/)
1016
1028
  assert.match(appView, /text-overflow: ellipsis/)
1017
1029
  assert.match(appView, /white-space: nowrap/)
1018
1030
  assert.match(appView, /window\.open\(href, "_blank"\)/)
@@ -1046,7 +1058,7 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1046
1058
  assert.match(appView, /\.mobile-bottom-nav \.resource-usage-popover \{[\s\S]*bottom: calc\(100% \+ 9px\);/)
1047
1059
  assert.doesNotMatch(appView, /Open launcher remote/)
1048
1060
  assert.doesNotMatch(appView, /fetch\("\/go"/)
1049
- assert.doesNotMatch(appView, /app-header-info-popover-link"[^>]*features="browser"/)
1061
+ assert.doesNotMatch(appView, /data-app-info-external-link[^>]*features="browser"/)
1050
1062
  assert.doesNotMatch(appView, /appInfoGitHistoryUrl|hydrateAppInfoGithubUrl|buildAppInfoGithubUrl|launcher_github_url|Open launcher on GitHub|No GitHub remote detected/)
1051
1063
 
1052
1064
  const start = appView.indexOf('<script>\n(() => {\n const appInfoRoots = Array.from(document.querySelectorAll("[data-app-info-root]"))')
@@ -1059,7 +1071,9 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1059
1071
  <div data-app-info-root>
1060
1072
  <button type="button" data-app-header-info-trigger aria-expanded="false">Demo</button>
1061
1073
  <div class="hidden" data-app-header-info-popover>
1062
- <a class="app-header-info-popover-link" href="https://gitlab.com/octocat/demo" title="https://gitlab.com/octocat/demo" data-app-info-external-link>gitlab.com/octocat/demo</a>
1074
+ <button type="button" data-app-info-copy-path="/tmp/demo"><i class="fa-regular fa-copy"></i></button>
1075
+ <button type="button" data-filepath="/tmp/demo" data-app-info-reveal-path>Reveal</button>
1076
+ <a class="app-header-info-popover-row app-header-info-popover-row--link" href="https://gitlab.com/octocat/demo" title="https://gitlab.com/octocat/demo" data-app-info-external-link>gitlab.com/octocat/demo</a>
1063
1077
  </div>
1064
1078
  </div>
1065
1079
  <iframe></iframe>
@@ -1069,6 +1083,13 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1069
1083
  pretendToBeVisual: true
1070
1084
  })
1071
1085
  const openedUrls = []
1086
+ const copiedPaths = []
1087
+ Object.defineProperty(dom.window.navigator, "clipboard", {
1088
+ configurable: true,
1089
+ value: {
1090
+ writeText: async (value) => copiedPaths.push(value)
1091
+ }
1092
+ })
1072
1093
  dom.window.open = (url, target, features) => {
1073
1094
  openedUrls.push({ url, target, features })
1074
1095
  }
@@ -1080,7 +1101,7 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1080
1101
 
1081
1102
  assert.equal(popover.classList.contains("hidden"), true)
1082
1103
  assert.equal(trigger.getAttribute("aria-expanded"), "false")
1083
- const remoteLink = dom.window.document.querySelector(".app-header-info-popover-link")
1104
+ const remoteLink = dom.window.document.querySelector(".app-header-info-popover-row--link")
1084
1105
  assert.ok(remoteLink)
1085
1106
  assert.equal(remoteLink.getAttribute("href"), "https://gitlab.com/octocat/demo")
1086
1107
  assert.equal(remoteLink.getAttribute("title"), "https://gitlab.com/octocat/demo")
@@ -1088,6 +1109,17 @@ test("app identity popover exposes launcher metadata and remote browser link", a
1088
1109
  assert.equal(remoteLink.hasAttribute("features"), false)
1089
1110
  assert.equal(remoteLink.textContent.trim(), "gitlab.com/octocat/demo")
1090
1111
 
1112
+ click()
1113
+ const copyButton = dom.window.document.querySelector("[data-app-info-copy-path]")
1114
+ copyButton.dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true, cancelable: true }))
1115
+ await new Promise((resolve) => setImmediate(resolve))
1116
+ assert.deepEqual(copiedPaths, ["/tmp/demo"])
1117
+ assert.equal(copyButton.classList.contains("is-copied"), true)
1118
+ assert.equal(copyButton.getAttribute("aria-label"), "App folder copied")
1119
+ assert.equal(popover.classList.contains("hidden"), false)
1120
+ dom.window.document.querySelector("[data-app-info-reveal-path]").click()
1121
+ assert.equal(popover.classList.contains("hidden"), true)
1122
+
1091
1123
  click()
1092
1124
  assert.equal(popover.classList.contains("hidden"), false)
1093
1125
  assert.equal(trigger.getAttribute("aria-expanded"), "true")