Skip to content

Commit bb09052

Browse files
chore: renable kernel playwright test (#1104)
* chore: renable kernel playwright test Signed-off-by: Alex Matson <alex.matson@digitalasset.com> * cleanup Signed-off-by: Alex Matson <alex.matson@digitalasset.com> * refactor window manager Signed-off-by: Alex Matson <alex.matson@digitalasset.com> * generalize popup locator Signed-off-by: Alex Matson <alex.matson@digitalasset.com> * clean Signed-off-by: Alex Matson <alex.matson@digitalasset.com> --------- Signed-off-by: Alex Matson <alex.matson@digitalasset.com>
1 parent f25af3d commit bb09052

File tree

12 files changed

+251
-254
lines changed

12 files changed

+251
-254
lines changed

.github/workflows/build.yml

Lines changed: 98 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -105,104 +105,110 @@ jobs:
105105
- name: Run unit tests
106106
run: yarn test:all
107107

108-
## TODO: Re-enable kernel-e2e later
109108
test-kernel-e2e:
110109
runs-on: ubuntu-latest
111110
needs: build
112111
steps:
113112
- name: Checkout
114113
uses: actions/checkout@v4
115-
# - uses: ./.github/actions/setup_yarn
116-
117-
# - name: Download Canton
118-
# run: yarn script:fetch:canton
119-
120-
# - name: Start Canton
121-
# run: |
122-
# set -e
123-
# timeout 5m bash -c '
124-
# LOGFILE=canton_start.log
125-
# yarn start:canton > "$LOGFILE" 2>&1 &
126-
# pid=$!
127-
# for i in {1..60}; do
128-
# if grep -q "Bootstrap script successfully executed." "$LOGFILE"; then
129-
# echo "Canton started successfully."
130-
# exit 0
131-
# fi
132-
# if ! kill -0 $pid 2>/dev/null; then
133-
# echo "Canton process exited unexpectedly."
134-
# cat "$LOGFILE"
135-
# exit 1
136-
# fi
137-
# sleep 5
138-
# done
139-
# echo "Timeout: 'Bootstrap script successfully executed.' not found in 5 minutes."
140-
# cat "$LOGFILE"
141-
# exit 1
142-
# '
143-
144-
# - name: Start remote WK
145-
# run: yarn nx run @canton-network/wallet-gateway-remote:start &
146-
147-
# - run: yarn nx run @canton-network/example-ping:dev &
148-
149-
# - run: yarn nx run @canton-network/mock-oauth2:start &
150-
151-
# # Figures out the version of playwright that's installed.
152-
# # 1. Because we don't know what version yarn will resolve it to, we have
153-
# # to use `yarn why` to get the actually installed version.
154-
# # 2. Because we're in a workspace, we need to make sure we get the version
155-
# # for the root and not any children, hence the `grep`. If not using
156-
# # workspaces, this can be skipped.
157-
# # 3. jq comes pre-installed in the Ubuntu runner, so we use that to get
158-
# # the correct version string.
159-
# # 4. Finally, we use sed to extract just the version number (eg; '1.22.0')
160-
# # The result is stored in steps.playwright-version.outputs.version
161-
# - name: Get installed Playwright version
162-
# id: playwright-version
163-
# run: echo "::set-output name=version::$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')"
164-
165-
# # Attempt to restore the correct Playwright browser binaries based on the
166-
# # currently installed version of Playwright (The browser binary versions
167-
# # may change with Playwright versions).
168-
# # Note: Playwright's cache directory is hard coded because that's what it
169-
# # says to do in the docs. There doesn't appear to be a command that prints
170-
# # it out for us.
171-
# - name: Load Playwright browser cache
172-
# uses: actions/cache@v4
173-
# id: playwright-cache
174-
# with:
175-
# path: '~/.cache/ms-playwright'
176-
# key: '${{ runner.os }}-0-playwright-${{ steps.playwright-version.outputs.version }}'
177-
# # As a fallback, if the Playwright version has changed, try use the
178-
# # most recently cached version. There's a good chance that at least one
179-
# # of the browser binary versions haven't been updated, so Playwright can
180-
# # skip installing that in the next step.
181-
# # Note: When falling back to an old cache, `cache-hit` (used below)
182-
# # will be `false`. This allows us to restore the potentially out of
183-
# # date cache, but still let Playwright decide if it needs to download
184-
# # new binaries or not.
185-
# restore-keys: |
186-
# ${{ runner.os }}-0-playwright-
187-
188-
# # If the Playwright browser binaries weren't able to be restored, we tell
189-
# # playwright to install everything for us.
190-
# - name: Install Playwright's dependencies
191-
# if: steps.playwright-cache.outputs.cache-hit != 'true'
192-
# run: yarn workspace @canton-network/example-ping run playwright install --with-deps
193-
194-
# - name: Build project
195-
# run: yarn build:all
196-
197-
# - name: Run example e2e
198-
# run: yarn nx playwright:e2e @canton-network/example-ping
199-
200-
# - uses: actions/upload-artifact@v4
201-
# if: ${{ !cancelled() }}
202-
# with:
203-
# name: playwright-report
204-
# path: examples/ping/playwright-report/
205-
# retention-days: 30
114+
- uses: ./.github/actions/setup_yarn
115+
116+
- name: Download Canton
117+
run: yarn script:fetch:canton
118+
119+
- name: Start Canton
120+
run: |
121+
set -e
122+
timeout 5m bash -c '
123+
LOGFILE=canton_start.log
124+
yarn start:canton > "$LOGFILE" 2>&1 &
125+
pid=$!
126+
for i in {1..60}; do
127+
if grep -q "Bootstrap script successfully executed." "$LOGFILE"; then
128+
echo "Canton started successfully."
129+
exit 0
130+
fi
131+
if ! kill -0 $pid 2>/dev/null; then
132+
echo "Canton process exited unexpectedly."
133+
cat "$LOGFILE"
134+
exit 1
135+
fi
136+
sleep 5
137+
done
138+
echo "Timeout: 'Bootstrap script successfully executed.' not found in 5 minutes."
139+
cat "$LOGFILE"
140+
exit 1
141+
'
142+
143+
- name: Start remote WK
144+
run: yarn nx run @canton-network/wallet-gateway-remote:start &
145+
146+
- run: yarn nx run @canton-network/example-ping:dev > "example-ping.log" 2>&1 &
147+
148+
- run: yarn nx run @canton-network/mock-oauth2:start &
149+
150+
# Figures out the version of playwright that's installed.
151+
# 1. Because we don't know what version yarn will resolve it to, we have
152+
# to use `yarn why` to get the actually installed version.
153+
# 2. Because we're in a workspace, we need to make sure we get the version
154+
# for the root and not any children, hence the `grep`. If not using
155+
# workspaces, this can be skipped.
156+
# 3. jq comes pre-installed in the Ubuntu runner, so we use that to get
157+
# the correct version string.
158+
# 4. Finally, we use sed to extract just the version number (eg; '1.22.0')
159+
# The result is stored in steps.playwright-version.outputs.version
160+
- name: Get installed Playwright version
161+
id: playwright-version
162+
run: echo "::set-output name=version::$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')"
163+
164+
# Attempt to restore the correct Playwright browser binaries based on the
165+
# currently installed version of Playwright (The browser binary versions
166+
# may change with Playwright versions).
167+
# Note: Playwright's cache directory is hard coded because that's what it
168+
# says to do in the docs. There doesn't appear to be a command that prints
169+
# it out for us.
170+
- name: Load Playwright browser cache
171+
uses: actions/cache@v4
172+
id: playwright-cache
173+
with:
174+
path: '~/.cache/ms-playwright'
175+
key: '${{ runner.os }}-0-playwright-${{ steps.playwright-version.outputs.version }}'
176+
# As a fallback, if the Playwright version has changed, try use the
177+
# most recently cached version. There's a good chance that at least one
178+
# of the browser binary versions haven't been updated, so Playwright can
179+
# skip installing that in the next step.
180+
# Note: When falling back to an old cache, `cache-hit` (used below)
181+
# will be `false`. This allows us to restore the potentially out of
182+
# date cache, but still let Playwright decide if it needs to download
183+
# new binaries or not.
184+
restore-keys: |
185+
${{ runner.os }}-0-playwright-
186+
187+
# If the Playwright browser binaries weren't able to be restored, we tell
188+
# playwright to install everything for us.
189+
- name: Install Playwright's dependencies
190+
if: steps.playwright-cache.outputs.cache-hit != 'true'
191+
run: yarn workspace @canton-network/example-ping run playwright install --with-deps
192+
193+
- name: Build project
194+
run: yarn build:all
195+
196+
- name: Run example e2e
197+
run: yarn nx playwright:e2e @canton-network/example-ping
198+
199+
- uses: actions/upload-artifact@v4
200+
if: ${{ !cancelled() }}
201+
with:
202+
name: playwright-report
203+
path: examples/ping/playwright-report/
204+
retention-days: 5
205+
206+
- uses: actions/upload-artifact@v4
207+
if: ${{ failure() }}
208+
with:
209+
name: example-ping-logs
210+
path: example-ping.log
211+
retention-days: 5
206212

207213
sdk-e2e:
208214
name: sdk-e2e (${{ matrix.network }})

core/wallet-ui-components/src/components/Discovery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ export class Discovery extends HTMLElement {
259259

260260
private selectKernel(kernel: DiscoverResult) {
261261
if (window.opener) {
262+
console.debug('Posting selected kernel to opener', kernel)
262263
window.opener.postMessage(kernel, '*')
263264
} else {
264265
console.warn('no window opener...')

core/wallet-ui-components/src/windows/discovery.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,12 @@ import { DiscoverResult, GatewaysConfig } from '@canton-network/core-types'
55
import { Discovery } from '../components/Discovery.js'
66
import { popup } from './popup.js'
77

8-
export class WindowState {
9-
private static instance: WindowProxy | undefined
10-
11-
private constructor() {}
12-
static getInstance() {
13-
if (!this.instance || this.instance.closed) {
14-
const win = window.open(
15-
'',
16-
'wallet-popup',
17-
`width=400,height=500,screenX=200,screenY=200`
18-
)
19-
if (!win) throw new Error('Failed to open popup window')
20-
this.instance = win
21-
}
22-
return this.instance
23-
}
24-
}
25-
268
export async function discover(
279
verifiedGateways: GatewaysConfig[]
2810
): Promise<DiscoverResult> {
29-
const win = await popup(Discovery, { title: 'Connect to a Wallet Gateway' })
11+
const win = popup.open(Discovery, {
12+
title: 'Connect to a Wallet Gateway',
13+
})
3014

3115
localStorage.setItem(
3216
'splice_wallet_verified_gateways',
Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { WindowState } from './discovery'
5-
64
interface PopupOptions {
75
title?: string
86
target?: string
@@ -17,22 +15,77 @@ interface StyledElement {
1715
styles: string
1816
}
1917

20-
export function popup(
21-
component: StyledElement,
22-
options?: PopupOptions
23-
): Promise<Window> {
24-
const { title = 'Custom Popup' } = options || {}
18+
let globalPopupInstance: WindowProxy | undefined
19+
20+
class PopupInstance {
21+
static getInstance() {
22+
if (!globalPopupInstance || globalPopupInstance.closed) {
23+
console.log('[PopupInstance] Creating new global popup instance')
24+
const win = window.open(
25+
'',
26+
'wallet-popup',
27+
`width=400,height=500,screenX=200,screenY=200`
28+
)
29+
if (!win) throw new Error('Failed to open popup window')
30+
globalPopupInstance = win
31+
}
32+
return globalPopupInstance
33+
}
34+
35+
constructor() {
36+
window.addEventListener('beforeunload', () => {
37+
if (globalPopupInstance) {
38+
console.log('[PopupInstance] Closing popup instance on unload')
39+
globalPopupInstance.close()
40+
globalPopupInstance = undefined
41+
}
42+
})
43+
}
44+
45+
open(url: string | URL): WindowProxy
46+
open(component: StyledElement, options?: PopupOptions): WindowProxy
47+
open(
48+
urlOrComponent: string | URL | StyledElement,
49+
options?: PopupOptions
50+
): WindowProxy {
51+
if (
52+
typeof urlOrComponent === 'string' ||
53+
urlOrComponent instanceof URL
54+
) {
55+
const win = PopupInstance.getInstance()
56+
win.location.href = urlOrComponent.toString()
57+
win.focus()
58+
return win
59+
} else {
60+
const componentUrl = this.getComponentUrl(urlOrComponent, options)
61+
const win = PopupInstance.getInstance()
62+
win.location.href = componentUrl
63+
win.focus()
64+
return win
65+
}
66+
}
67+
68+
close() {
69+
console.log('[PopupInstance] Closing popup instance')
70+
if (globalPopupInstance) globalPopupInstance.close()
71+
}
72+
73+
private getComponentUrl(
74+
component: StyledElement,
75+
options?: PopupOptions
76+
): string {
77+
const { title = 'Custom Popup' } = options || {}
2578

26-
const sanitizedStyles = component.styles
27-
.replaceAll('\n', ' ')
28-
.replaceAll("'", "\\'")
29-
.replaceAll('"', '\\"')
79+
const sanitizedStyles = component.styles
80+
.replaceAll('\n', ' ')
81+
.replaceAll("'", "\\'")
82+
.replaceAll('"', '\\"')
3083

31-
const elementSource = component
32-
.toString()
33-
.replace('SUBSTITUTABLE_CSS', `''`)
84+
const elementSource = component
85+
.toString()
86+
.replace('SUBSTITUTABLE_CSS', `''`)
3487

35-
const html = `<!DOCTYPE html>
88+
const html = `<!DOCTYPE html>
3689
<html>
3790
<head>
3891
<title>${title}</title>
@@ -63,30 +116,13 @@ export function popup(
63116
content.style.height = '100%';
64117
65118
document.body.appendChild(content)
119+
120+
URL.revokeObjectURL(window.location.href)
66121
</script>
67122
</html>`
68123

69-
const url = URL.createObjectURL(new Blob([html], { type: 'text/html' }))
70-
71-
return new Promise((resolve) => {
72-
const win = WindowState.getInstance()
73-
win.location.href = url
74-
win.focus()
75-
76-
resolve(win)
77-
})
124+
return URL.createObjectURL(new Blob([html], { type: 'text/html' }))
125+
}
78126
}
79127

80-
export function popupHref(url: URL | string): Promise<Window> {
81-
return new Promise((resolve, reject) => {
82-
const win = WindowState.getInstance()
83-
win.location.href = url.toString()
84-
85-
if (win) {
86-
win.focus()
87-
resolve(win)
88-
} else {
89-
reject(new Error('Failed to open popup window.'))
90-
}
91-
})
92-
}
128+
export const popup = new PopupInstance()

0 commit comments

Comments
 (0)