Skip to content

Commit

Permalink
Improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lmuntaner committed Dec 17, 2024
1 parent 9debab8 commit 6b8f069
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 120 deletions.
316 changes: 202 additions & 114 deletions src/frontend/src/utils/iiConnection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import { CredentialData, convertToCredentialData } from "./credential-devices";
import { AuthenticatedConnection, Connection } from "./iiConnection";
import { MultiWebAuthnIdentity } from "./multiWebAuthnIdentity";

const mockDevice: DeviceData = {
const createMockDevice = (origin?: string): DeviceData => ({
alias: "mockDevice",
metadata: [],
origin: [],
origin: origin !== undefined ? [origin] : [],
protection: { protected: null },
pubkey: new Uint8Array(),
key_type: { platform: null },
purpose: { authentication: null },
credential_id: [],
};
});
const mockDevice = createMockDevice();

const mockDelegationIdentity = {
getDelegation() {
Expand Down Expand Up @@ -116,6 +117,7 @@ test("commits changes on identity metadata", async () => {
describe("Connection.login", () => {
let failSign = false;
beforeEach(() => {
failSign = false;
vi.spyOn(MultiWebAuthnIdentity, "fromCredentials").mockImplementation(
() => {
const mockIdentity = {
Expand Down Expand Up @@ -148,141 +150,227 @@ describe("Connection.login", () => {
);
});

it("login returns authenticated connection with expected rpID", async () => {
DOMAIN_COMPATIBILITY.set(true);
vi.stubGlobal("navigator", {
// Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
describe("domains compatibility flag enabled and browser support", () => {
beforeEach(() => {
DOMAIN_COMPATIBILITY.set(true);
vi.stubGlobal("navigator", {
// Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
});
});
const connection = new Connection("aaaaa-aa", mockActor);

const loginResult = await connection.login(BigInt(12345));
it("login returns authenticated connection with expected rpID", async () => {
const connection = new Connection("aaaaa-aa", mockActor);

expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
"identity.ic0.app"
);
}
});
const loginResult = await connection.login(BigInt(12345));

it("login returns authenticated connection without rpID if flag is not enabled", async () => {
DOMAIN_COMPATIBILITY.set(false);
vi.stubGlobal("navigator", {
// Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
"identity.ic0.app"
);
}
});
const connection = new Connection("aaaaa-aa", mockActor);

const loginResult = await connection.login(BigInt(12345));
it("connection exludes rpId when user cancels", async () => {
// This one would fail because it's not the device the user is using at the moment.
const currentOriginDevice: DeviceData = createMockDevice(currentOrigin);
const currentOriginCredentialData =
convertToCredentialData(currentOriginDevice);
const currentDevice: DeviceData = createMockDevice();
const currentDeviceCredentialData =
convertToCredentialData(currentDevice);
const mockActor = {
identity_info: vi.fn().mockResolvedValue({ Ok: { metadata: [] } }),
lookup: vi.fn().mockResolvedValue([currentOriginDevice, currentDevice]),
} as unknown as ActorSubclass<_SERVICE>;
const connection = new Connection("aaaaa-aa", mockActor);

failSign = true;
const firstLoginResult = await connection.login(BigInt(12345));

expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(firstLoginResult.kind).toBe("webAuthnFailed");
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
expect.arrayContaining([
currentOriginCredentialData,
currentDeviceCredentialData,
]),
undefined
);
}
});

it("login returns authenticated connection without rpID if browser doesn't support it", async () => {
DOMAIN_COMPATIBILITY.set(true);
vi.stubGlobal("navigator", {
// Does NOT Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
failSign = false;
const secondLoginResult = await connection.login(BigInt(12345));

expect(secondLoginResult.kind).toBe("loginSuccess");
if (secondLoginResult.kind === "loginSuccess") {
expect(secondLoginResult.connection).toBeInstanceOf(
AuthenticatedConnection
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(2);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.arrayContaining([currentDeviceCredentialData]),
"identity.ic0.app"
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.not.arrayContaining([currentOriginCredentialData]),
"identity.ic0.app"
);
}
});
const connection = new Connection("aaaaa-aa", mockActor);

const loginResult = await connection.login(BigInt(12345));
it("connection doesn't exclude rpId if user has only one domain", async () => {
const currentOriginDevice: DeviceData = createMockDevice(currentOrigin);
const currentOriginCredentialData =
convertToCredentialData(currentOriginDevice);
const currentOriginDevice2: DeviceData = createMockDevice(currentOrigin);
const currentOriginCredentialData2 =
convertToCredentialData(currentOriginDevice2);
const mockActor = {
identity_info: vi.fn().mockResolvedValue({ Ok: { metadata: [] } }),
lookup: vi
.fn()
.mockResolvedValue([currentOriginDevice, currentOriginDevice2]),
} as unknown as ActorSubclass<_SERVICE>;
const connection = new Connection("aaaaa-aa", mockActor);

failSign = true;
const firstLoginResult = await connection.login(BigInt(12345));

expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(firstLoginResult.kind).toBe("webAuthnFailed");
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
expect.arrayContaining([
currentOriginCredentialData,
currentOriginCredentialData2,
]),
undefined
);
}

failSign = false;
const secondLoginResult = await connection.login(BigInt(12345));

expect(secondLoginResult.kind).toBe("loginSuccess");
if (secondLoginResult.kind === "loginSuccess") {
expect(secondLoginResult.connection).toBeInstanceOf(
AuthenticatedConnection
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(2);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.arrayContaining([
currentOriginCredentialData,
currentOriginCredentialData2,
]),
undefined
);
}
});
});

it("connection exludes rpId when user cancels", async () => {
// This one will fail because it's not the device the user is using at the moment.
const currentOriginDevice: DeviceData = {
alias: "mockDevice",
metadata: [],
origin: [currentOrigin],
protection: { protected: null },
pubkey: new Uint8Array(),
key_type: { platform: null },
purpose: { authentication: null },
credential_id: [],
};
const currentOriginCredentialData =
convertToCredentialData(currentOriginDevice);
const currentDevice: DeviceData = {
alias: "mockDevice",
metadata: [],
origin: [],
protection: { protected: null },
pubkey: new Uint8Array(),
key_type: { platform: null },
purpose: { authentication: null },
credential_id: [],
};
const currentDeviceCredentialData = convertToCredentialData(currentDevice);
const mockActor = {
identity_info: vi.fn().mockResolvedValue({ Ok: { metadata: [] } }),
lookup: vi.fn().mockResolvedValue([currentOriginDevice, currentDevice]),
} as unknown as ActorSubclass<_SERVICE>;
DOMAIN_COMPATIBILITY.set(true);
vi.stubGlobal("navigator", {
// Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
describe("domains compatibility flag enabled and browser doesn't support", () => {
beforeEach(() => {
DOMAIN_COMPATIBILITY.set(true);
vi.stubGlobal("navigator", {
// Does NOT Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
});
});
const connection = new Connection("aaaaa-aa", mockActor);

failSign = true;
const firstLoginResult = await connection.login(BigInt(12345));

expect(firstLoginResult.kind).toBe("webAuthnFailed");
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
expect.arrayContaining([
currentOriginCredentialData,
currentDeviceCredentialData,
]),
undefined
);

failSign = false;
const secondLoginResult = await connection.login(BigInt(12345));
it("login returns authenticated connection without rpID if browser doesn't support it", async () => {
const connection = new Connection("aaaaa-aa", mockActor);

expect(secondLoginResult.kind).toBe("loginSuccess");
if (secondLoginResult.kind === "loginSuccess") {
expect(secondLoginResult.connection).toBeInstanceOf(
AuthenticatedConnection
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(2);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.arrayContaining([currentDeviceCredentialData]),
"identity.ic0.app"
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.not.arrayContaining([currentOriginCredentialData]),
"identity.ic0.app"
const loginResult = await connection.login(BigInt(12345));

expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
undefined
);
}
});
});

describe("domains compatibility flag disabled", () => {
beforeEach(() => {
DOMAIN_COMPATIBILITY.set(false);
vi.stubGlobal("navigator", {
// Supports RoR
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
});
});

it("login returns authenticated connection without rpID if flag is not enabled", async () => {
const connection = new Connection("aaaaa-aa", mockActor);

const loginResult = await connection.login(BigInt(12345));

expect(loginResult.kind).toBe("loginSuccess");
if (loginResult.kind === "loginSuccess") {
expect(loginResult.connection).toBeInstanceOf(AuthenticatedConnection);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
[convertToCredentialData(mockDevice)],
undefined
);
}
});

it("connection does not exlud rpId when user cancels", async () => {
const currentOriginDevice: DeviceData = createMockDevice(currentOrigin);
const currentOriginCredentialData =
convertToCredentialData(currentOriginDevice);
const currentDevice: DeviceData = createMockDevice();
const currentDeviceCredentialData =
convertToCredentialData(currentDevice);
const mockActor = {
identity_info: vi.fn().mockResolvedValue({ Ok: { metadata: [] } }),
lookup: vi.fn().mockResolvedValue([currentOriginDevice, currentDevice]),
} as unknown as ActorSubclass<_SERVICE>;
const connection = new Connection("aaaaa-aa", mockActor);

failSign = true;
const firstLoginResult = await connection.login(BigInt(12345));

expect(firstLoginResult.kind).toBe("webAuthnFailed");
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(1);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledWith(
expect.arrayContaining([
currentOriginCredentialData,
currentDeviceCredentialData,
]),
undefined
);
}

failSign = false;
const secondLoginResult = await connection.login(BigInt(12345));

expect(secondLoginResult.kind).toBe("loginSuccess");
if (secondLoginResult.kind === "loginSuccess") {
expect(secondLoginResult.connection).toBeInstanceOf(
AuthenticatedConnection
);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenCalledTimes(2);
expect(MultiWebAuthnIdentity.fromCredentials).toHaveBeenNthCalledWith(
2,
expect.arrayContaining([
currentDeviceCredentialData,
currentOriginCredentialData,
]),
undefined
);
}
});
});
});
Loading

0 comments on commit 6b8f069

Please sign in to comment.