Skip to content

Commit 98ab29e

Browse files
authored
test: Rewrite e2e test for upgrade flow (dfinity#3660)
Rewrite e2e test for upgrade flow since existing test relied upon the legacy frontend that no longer exists. # Changes - Remove `migration.spec.ts`. - Add `upgrade.spec.ts` with e2e test that no longer relies upon legacy frontend.
1 parent 4758ae3 commit 98ab29e

3 files changed

Lines changed: 194 additions & 191 deletions

File tree

src/frontend/tests/e2e-playwright/routes/manage/migration.spec.ts

Lines changed: 0 additions & 191 deletions
This file was deleted.
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { test } from "../fixtures";
2+
import { expect } from "@playwright/test";
3+
import {
4+
addVirtualAuthenticator,
5+
virtualAuthenticatorPrivKeyToPubKey,
6+
dummyAuth,
7+
fromBase64URL,
8+
getCredentialsFromVirtualAuthenticator,
9+
II_URL,
10+
LEGACY_II_URL,
11+
} from "../utils";
12+
import { toSeed } from "../fixtures/identity";
13+
import { Ed25519KeyIdentity } from "@icp-sdk/core/identity";
14+
15+
const LEGACY_PASSKEY_NAME = "pre-upgrade-passkey";
16+
17+
test("Can upgrade identity", async ({
18+
page,
19+
managePage,
20+
identities,
21+
actorForIdentity,
22+
}) => {
23+
// Navigate to legacy page that doesn't redirect
24+
await page.goto(LEGACY_II_URL + "/self-service");
25+
26+
// Add virtual authenticator and create a passkey in page context
27+
const authenticatorId = await addVirtualAuthenticator(page);
28+
await page.evaluate(
29+
async (rpId) => {
30+
await navigator.credentials.create({
31+
publicKey: {
32+
challenge: Uint8Array.from("<ic0.app>", (c) => c.charCodeAt(0)),
33+
attestation: "direct",
34+
pubKeyCredParams: [{ type: "public-key", alg: -7 }], // ES256
35+
rp: {
36+
name: "Internet Identity Service",
37+
id: rpId,
38+
},
39+
user: {
40+
id: window.crypto.getRandomValues(new Uint8Array(16)),
41+
displayName: "Internet Identity User",
42+
name: "Internet Identity User",
43+
},
44+
},
45+
});
46+
},
47+
LEGACY_II_URL.replace(/^https?:\/\//, ""),
48+
);
49+
50+
// Get the created credential from the virtual authenticator
51+
const [credential] = await getCredentialsFromVirtualAuthenticator(
52+
page,
53+
authenticatorId,
54+
);
55+
const publicKey = await virtualAuthenticatorPrivKeyToPubKey(
56+
credential!.privateKey,
57+
);
58+
const credentialId = fromBase64URL(credential!.credentialId);
59+
60+
// Use an actor to create a legacy passkey (not id.ai)
61+
// since this functionality is no longer available.
62+
const actor = await actorForIdentity(identities[0].identityNumber);
63+
64+
// Add the legacy passkey to the identity
65+
await actor.authn_method_add(identities[0].identityNumber, {
66+
metadata: [
67+
["alias", { String: LEGACY_PASSKEY_NAME }],
68+
["origin", { String: LEGACY_II_URL }],
69+
],
70+
authn_method: {
71+
WebAuthn: {
72+
pubkey: publicKey,
73+
credential_id: credentialId,
74+
aaguid: [],
75+
},
76+
},
77+
security_settings: {
78+
protection: { Unprotected: null },
79+
purpose: { Authentication: null },
80+
},
81+
last_authentication: [],
82+
});
83+
84+
// Remove the dummy auth so the identity is only accessible via the legacy passkey,
85+
// which simulates the state of an identity that hasn't been upgraded yet.
86+
await actor.authn_method_remove(
87+
identities[0].identityNumber,
88+
new Uint8Array(
89+
Ed25519KeyIdentity.generate(toSeed(identities[0].dummyAuthIndex))
90+
.getPublicKey()
91+
.toDer(),
92+
),
93+
);
94+
95+
// Verify identity can be upgraded multiple times
96+
for (let attempt = 0; attempt < 3; attempt++) {
97+
// Navigate to the new II_URL to trigger the upgrade flow
98+
await page.goto(II_URL);
99+
100+
// Open the sign-in dialog
101+
if (attempt > 0) {
102+
await page.getByRole("button", { name: "Switch identity" }).click();
103+
await page.getByRole("button", { name: "Add another identity" }).click();
104+
} else {
105+
await page.getByRole("button", { name: "Sign in" }).click();
106+
}
107+
108+
// Select the passkey authentication method
109+
await page.getByRole("button", { name: "Continue with passkey" }).click();
110+
await page.getByRole("button", { name: "Upgrade" }).click();
111+
112+
// Enter the identity number
113+
await page
114+
.getByPlaceholder("Internet Identity number")
115+
.fill(identities[0].identityNumber.toString());
116+
await page.getByRole("button", { name: "Continue" }).click();
117+
118+
// On subsequent attempts, we expect a message that the identity is already upgraded
119+
if (attempt > 0) {
120+
await expect(
121+
page.getByRole("heading", { name: "Identity already upgraded" }),
122+
).toBeVisible();
123+
await page.getByRole("button", { name: "Upgrade again" }).click();
124+
}
125+
126+
// Set the identity name and register new dummy auth
127+
const newAuth = dummyAuth();
128+
await page.getByLabel("Identity name").fill(identities[0].name);
129+
newAuth(page);
130+
131+
// Complete the upgrade process
132+
await page.getByRole("button", { name: "Upgrade identity" }).click();
133+
await managePage.assertVisible();
134+
}
135+
});

0 commit comments

Comments
 (0)