Skip to content

Commit 3182bf2

Browse files
committed
test(cat-voices): playwright plays right
1 parent 696a0fc commit 3182bf2

File tree

73 files changed

+3443
-139
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3443
-139
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
# Playwright
3+
node_modules/
4+
/test-results/
5+
/playwright-report/
6+
/blob-report/
7+
/playwright/.cache/
Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
import { Locator, Page, expect } from "@playwright/test";
2+
import { WalletConfig } from "./utils/wallets/walletUtils";
3+
import { Modal, ModalName } from "./modal";
4+
5+
export interface UTxO {
6+
tx: string;
7+
index: number;
8+
amount: number;
9+
}
10+
11+
export interface WalletCipData {
12+
balance: number;
13+
extensions: string[];
14+
networkId: string;
15+
changeAddress: string;
16+
rewardAddresses: string[];
17+
unusedAddresses: string[];
18+
usedAddresses: string[];
19+
utxos: UTxO[];
20+
publicDRepKey: string;
21+
registeredPublicStakeKeys: string;
22+
unregisteredPublicStakeKeys: string[];
23+
}
24+
25+
export class HomePage {
26+
readonly page: Page;
27+
readonly balanceLabel: Locator;
28+
readonly extensionsLabel: Locator;
29+
readonly networkIdLabel: Locator;
30+
readonly changeAddressLabel: Locator;
31+
readonly rewardAddressesLabel: Locator;
32+
readonly unusedAddressesLabel: Locator;
33+
readonly usedAddressesLabel: Locator;
34+
readonly utxosLabel: Locator;
35+
readonly publicDRepKeyLabel: Locator;
36+
readonly registeredPublicStakeKeysLabel: Locator;
37+
readonly unregisteredPublicStakeKeysLabel: Locator;
38+
readonly signDataButton: Locator;
39+
readonly signAndSubmitTxButton: Locator;
40+
readonly signAndSubmitRBACTxButton: Locator;
41+
42+
// TODO: Add keys to source app and change locators to locate based on keys
43+
constructor(page: Page) {
44+
this.page = page;
45+
this.balanceLabel = page.getByText(/^Balance: Ada \(lovelaces\):/);
46+
this.extensionsLabel = page.getByText(/^Extensions:/);
47+
this.networkIdLabel = page.getByText(/^Network ID:/);
48+
this.changeAddressLabel = page.getByText(/^Change address:/);
49+
this.rewardAddressesLabel = page.getByText(/^Reward addresses:/);
50+
this.unusedAddressesLabel = page.getByText(/^Unused addresses:/);
51+
this.usedAddressesLabel = page.getByText(/^Used addresses:/);
52+
this.utxosLabel = page.getByText(/^UTXOs:/);
53+
this.publicDRepKeyLabel = page.getByText(/^Public DRep Key:/);
54+
this.registeredPublicStakeKeysLabel = page.getByText(
55+
/^Registered Public Stake Keys:/
56+
);
57+
this.unregisteredPublicStakeKeysLabel = page.getByText(
58+
/^Unregistered Public Stake Keys:/
59+
);
60+
this.signDataButton = page.getByRole("button", { name: "Sign data" });
61+
this.signAndSubmitTxButton = page.getByRole("button", {
62+
name: "Sign & submit tx",
63+
});
64+
this.signAndSubmitRBACTxButton = page.getByRole("button", {
65+
name: "Sign & submit RBAC tx",
66+
});
67+
}
68+
69+
async getWalletCipData() {
70+
const walletCipData: WalletCipData = {
71+
balance: 0,
72+
extensions: [],
73+
networkId: "",
74+
changeAddress: "",
75+
rewardAddresses: [],
76+
unusedAddresses: [],
77+
usedAddresses: [],
78+
utxos: [],
79+
publicDRepKey: "",
80+
registeredPublicStakeKeys: "",
81+
unregisteredPublicStakeKeys: [],
82+
};
83+
await this.balanceLabel.waitFor({ state: "visible", timeout: 10000 });
84+
walletCipData.balance = await this.getBalance();
85+
walletCipData.extensions = await this.getExtensions();
86+
walletCipData.networkId = await this.getNetworkId();
87+
walletCipData.changeAddress = await this.getChangeAddress();
88+
walletCipData.rewardAddresses = await this.getRewardAddresses();
89+
walletCipData.unusedAddresses = await this.getUnusedAddresses();
90+
walletCipData.usedAddresses = await this.getUsedAddresses();
91+
walletCipData.utxos = await this.getUTXOs();
92+
walletCipData.publicDRepKey = await this.getPublicDRepKey();
93+
walletCipData.registeredPublicStakeKeys =
94+
await this.getRegisteredPublicStakeKeys();
95+
walletCipData.unregisteredPublicStakeKeys =
96+
await this.getUnregisteredPublicStakeKeys();
97+
return walletCipData;
98+
}
99+
100+
async assertModal(modalName: ModalName) {
101+
const modal = new Modal(this.page, modalName);
102+
await modal.assertModalIsVisible();
103+
}
104+
105+
async getBalance(): Promise<number> {
106+
const isVisible = await this.balanceLabel.isVisible();
107+
if (!isVisible) {
108+
throw new Error("Balance label is not visible");
109+
}
110+
const balanceText = await this.balanceLabel.textContent();
111+
const match = balanceText?.match(/^Balance: Ada \(lovelaces\): (\d+)/);
112+
if (match && match[1]) {
113+
return Number(match[1]);
114+
} else {
115+
throw new Error(`Unable to extract balance from text: ${balanceText}`);
116+
}
117+
}
118+
119+
async getExtensions(): Promise<string[]> {
120+
const isVisible = await this.extensionsLabel.isVisible();
121+
if (!isVisible) {
122+
throw new Error("Extensions label is not visible");
123+
}
124+
const extensionsText = await this.extensionsLabel.textContent();
125+
const match = extensionsText?.trim().match(/^Extensions:\s*(.+)$/);
126+
if (match && match[1]) {
127+
const trimmedText = match[1].trim();
128+
return trimmedText
129+
.split(",")
130+
.map((ext) => ext.trim())
131+
.filter((ext) => ext.length > 0);
132+
} else {
133+
throw new Error(
134+
`Unable to extract extensions from text: ${extensionsText}`
135+
);
136+
}
137+
}
138+
139+
async getNetworkId(): Promise<string> {
140+
const isVisible = await this.networkIdLabel.isVisible();
141+
if (!isVisible) {
142+
throw new Error("Network ID label is not visible");
143+
}
144+
const networkIdText = await this.networkIdLabel.textContent();
145+
const match = networkIdText?.trim().match(/^Network ID:\s*(.+)$/);
146+
if (match && match[1]) {
147+
return match[1].trim();
148+
} else {
149+
throw new Error(
150+
`Unable to extract network ID from text: ${networkIdText}`
151+
);
152+
}
153+
}
154+
155+
async getChangeAddress(): Promise<string> {
156+
const isVisible = await this.changeAddressLabel.isVisible();
157+
if (!isVisible) {
158+
throw new Error("Change address label is not visible");
159+
}
160+
const changeAddressText = await this.changeAddressLabel.textContent();
161+
const match = changeAddressText?.trim().match(/^Change address:\s*(.+)$/s);
162+
if (match && match[1]) {
163+
return match[1].trim();
164+
} else {
165+
throw new Error(
166+
`Unable to extract change address from text: ${changeAddressText}`
167+
);
168+
}
169+
}
170+
171+
async getRewardAddresses(): Promise<string[]> {
172+
const isVisible = await this.rewardAddressesLabel.isVisible();
173+
if (!isVisible) {
174+
throw new Error("Reward addresses label is not visible");
175+
}
176+
const rewardAddressesText = await this.rewardAddressesLabel.textContent();
177+
const match = rewardAddressesText?.match(/^Reward addresses:\s*(.+)$/s);
178+
if (match && match[1]) {
179+
const addresses = match[1]
180+
.trim()
181+
.split("\n")
182+
.map((addr) => addr.trim())
183+
.filter((addr) => addr.length > 0);
184+
return addresses;
185+
} else {
186+
throw new Error(
187+
`Unable to extract reward addresses from text: ${rewardAddressesText}`
188+
);
189+
}
190+
}
191+
192+
async getUnusedAddresses(): Promise<string[]> {
193+
const isVisible = await this.unusedAddressesLabel.isVisible();
194+
if (!isVisible) {
195+
throw new Error("Unused addresses label is not visible");
196+
}
197+
const unusedAddressesText = await this.unusedAddressesLabel.textContent();
198+
const match = unusedAddressesText?.match(/^Unused addresses:\s*(.+)$/s);
199+
if (match && match[1]) {
200+
const addresses = match[1]
201+
.trim()
202+
.split("\n")
203+
.map((addr) => addr.trim())
204+
.filter((addr) => addr.length > 0);
205+
return addresses;
206+
} else {
207+
throw new Error(
208+
`Unable to extract unused addresses from text: ${unusedAddressesText}`
209+
);
210+
}
211+
}
212+
213+
async getUsedAddresses(): Promise<string[]> {
214+
const isVisible = await this.usedAddressesLabel.isVisible();
215+
if (!isVisible) {
216+
throw new Error("Used addresses label is not visible");
217+
}
218+
const usedAddressesText = await this.usedAddressesLabel.textContent();
219+
const match = usedAddressesText?.match(/^Used addresses:\s*(.+)$/s);
220+
if (match && match[1]) {
221+
const addresses = match[1]
222+
.trim()
223+
.split("\n")
224+
.map((addr) => addr.trim())
225+
.filter((addr) => addr.length > 0);
226+
return addresses;
227+
} else {
228+
throw new Error(
229+
`Unable to extract used addresses from text: ${usedAddressesText}`
230+
);
231+
}
232+
}
233+
234+
async getUTXOs(): Promise<UTxO[]> {
235+
const isVisible = await this.utxosLabel.isVisible();
236+
if (!isVisible) {
237+
throw new Error("UTXOs label is not visible");
238+
}
239+
const utxosText = await this.utxosLabel.textContent();
240+
const match = utxosText?.match(/^UTXOs:\s*(.+)$/s);
241+
if (match && match[1]) {
242+
const utxosData = match[1].trim();
243+
const utxoEntries = utxosData
244+
.split(/\n\n+/)
245+
.map((entry) => entry.trim())
246+
.filter((entry) => entry.length > 0);
247+
const utxos: UTxO[] = [];
248+
for (const entry of utxoEntries) {
249+
const txMatch = entry.match(/Tx:\s*([a-fA-F0-9]+)/);
250+
const indexMatch = entry.match(/Index:\s*(\d+)/);
251+
const amountMatch = entry.match(/Amount:\s*Ada \(lovelaces\):\s*(\d+)/);
252+
if (txMatch && indexMatch && amountMatch) {
253+
utxos.push({
254+
tx: txMatch[1],
255+
index: Number(indexMatch[1]),
256+
amount: Number(amountMatch[1]),
257+
});
258+
} else {
259+
throw new Error(`Unable to parse UTXO entry: ${entry}`);
260+
}
261+
}
262+
return utxos;
263+
} else {
264+
throw new Error(`Unable to extract UTXOs from text: ${utxosText}`);
265+
}
266+
}
267+
268+
async getPublicDRepKey(): Promise<string> {
269+
await this.page.waitForTimeout(2000);
270+
const isVisible = await this.publicDRepKeyLabel.isVisible();
271+
if (!isVisible) {
272+
throw new Error("Public DRep Key label is not visible");
273+
}
274+
const publicDRepKeyText = await this.publicDRepKeyLabel.textContent();
275+
const match = publicDRepKeyText
276+
?.trim()
277+
.match(/^Public DRep Key:\s*([a-fA-F0-9]+)$/);
278+
if (match && match[1]) {
279+
return match[1];
280+
} else {
281+
throw new Error(
282+
`Unable to extract public DRep key from text: ${publicDRepKeyText}`
283+
);
284+
}
285+
}
286+
287+
async getRegisteredPublicStakeKeys(): Promise<string> {
288+
const isVisible = await this.registeredPublicStakeKeysLabel.isVisible();
289+
if (!isVisible) {
290+
throw new Error("Registered Public Stake Keys label is not visible");
291+
}
292+
const stakeKeysText =
293+
await this.registeredPublicStakeKeysLabel.textContent();
294+
const match = stakeKeysText
295+
?.trim()
296+
.match(/^Registered Public Stake Keys:\s*([a-fA-F0-9]+)$/);
297+
if (match && match[1]) {
298+
return match[1];
299+
} else {
300+
throw new Error(
301+
`Unable to extract registered public stake keys from text: ${stakeKeysText}`
302+
);
303+
}
304+
}
305+
306+
async getUnregisteredPublicStakeKeys(): Promise<string[]> {
307+
const isVisible = await this.unregisteredPublicStakeKeysLabel.isVisible();
308+
if (!isVisible) {
309+
throw new Error("Unregistered Public Stake Keys label is not visible");
310+
}
311+
const keysText = await this.unregisteredPublicStakeKeysLabel.textContent();
312+
const match = keysText
313+
?.trim()
314+
.match(/^Unregistered Public Stake Keys:\s*(.*)$/s);
315+
if (match) {
316+
const keysData = match[1].trim();
317+
if (keysData) {
318+
const keys = keysData
319+
.split("\n")
320+
.map((key) => key.trim())
321+
.filter((key) => key.length > 0);
322+
return keys;
323+
} else {
324+
return [];
325+
}
326+
} else {
327+
throw new Error(
328+
`Unable to extract unregistered public stake keys from text: ${keysText}`
329+
);
330+
}
331+
}
332+
333+
async assertBasicWalletCipData(
334+
actualWalletCipData: WalletCipData,
335+
walletConfig: WalletConfig
336+
) {
337+
expect(actualWalletCipData.balance).toBeGreaterThan(500000000);
338+
await this.assertExtensions(
339+
actualWalletCipData.extensions,
340+
walletConfig.cipBridge
341+
);
342+
expect(actualWalletCipData.networkId).not.toBeNaN();
343+
expect(actualWalletCipData.changeAddress).not.toBeNaN();
344+
expect(actualWalletCipData.rewardAddresses.length).toBeGreaterThan(0);
345+
//expect(actualWalletCipData.unusedAddresses.length).toBeGreaterThan(0);
346+
expect(actualWalletCipData.usedAddresses.length).toBeGreaterThan(0);
347+
expect(actualWalletCipData.utxos.length).toBeGreaterThan(0);
348+
expect(actualWalletCipData.publicDRepKey).not.toBeNaN();
349+
expect(actualWalletCipData.registeredPublicStakeKeys).not.toBeNaN();
350+
}
351+
352+
//Check if expected extensions are present in actual extensions
353+
async assertExtensions(
354+
actualExtensions: string[],
355+
expectedExtensions: string[]
356+
) {
357+
for (const ext of expectedExtensions) {
358+
expect(actualExtensions).toContain(ext);
359+
}
360+
}
361+
}

0 commit comments

Comments
 (0)