Skip to content

Commit

Permalink
Tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
guillemcordoba committed Oct 28, 2024
1 parent b82bcc7 commit e665129
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 129 deletions.
2 changes: 1 addition & 1 deletion docs/link-device-process.md → docs/design.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

# Link Devices process

```mermaid
sequenceDiagram
Expand Down
39 changes: 0 additions & 39 deletions tests/src/agent-to-linked-devices.test.ts

This file was deleted.

58 changes: 58 additions & 0 deletions tests/src/link-devices.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { toPromise } from '@holochain-open-dev/signals';
import { EntryRecord } from '@holochain-open-dev/utils';
import { ActionHash, Record, encodeHashToBase64 } from '@holochain/client';
import { dhtSync, runScenario } from '@holochain/tryorama';
import { decode } from '@msgpack/msgpack';
import { assert, test } from 'vitest';

import { setup } from './setup.js';

test('link devices', async () => {
await runScenario(async scenario => {
const { alice, bob } = await setup(scenario);

// Bob gets the links, should be empty
let linksOutput = await toPromise(
bob.store.linkedDevicesForAgent.get(bob.player.agentPubKey),
);
assert.equal(linksOutput.length, 0);

const alicePasscode = [1, 3, 7, 2];
const bobPasscode = [9, 3, 8, 4];

await alice.store.client.prepareLinkDevices(alicePasscode);
await bob.store.client.prepareLinkDevices(bobPasscode);

await alice.store.client.initLinkDevices(
bob.player.agentPubKey,
bobPasscode,
);
await bob.store.client.requestLinkDevices(
alice.player.agentPubKey,
alicePasscode,
);

// Wait for the created entry to be propagated to the other node.
await dhtSync([alice.player, bob.player], alice.player.cells[0].cell_id[0]);

// Bob gets the links again
linksOutput = await toPromise(
bob.store.linkedDevicesForAgent.get(bob.player.agentPubKey),
);
assert.equal(linksOutput.length, 1);
assert.deepEqual(
encodeHashToBase64(alice.player.agentPubKey),
encodeHashToBase64(linksOutput[0]),
);

// Alice gets the links again
linksOutput = await toPromise(
alice.store.linkedDevicesForAgent.get(alice.player.agentPubKey),
);
assert.equal(linksOutput.length, 1);
assert.deepEqual(
encodeHashToBase64(bob.player.agentPubKey),
encodeHashToBase64(linksOutput[0]),
);
});
});
135 changes: 79 additions & 56 deletions tests/src/setup.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,83 @@
import { EntryRecord } from "@holochain-open-dev/utils";
import { EntryRecord } from '@holochain-open-dev/utils';
import {
ActionHash,
AgentPubKey,
AppBundleSource,
AppCallZomeRequest,
AppWebsocket,
encodeHashToBase64,
EntryHash,
fakeActionHash,
fakeAgentPubKey,
fakeDnaHash,
fakeEntryHash,
NewEntryAction,
Record,
} from "@holochain/client";
import { Scenario } from "@holochain/tryorama";
import { encode } from "@msgpack/msgpack";
import { dirname } from "path";
import { fileURLToPath } from "url";
import { LinkedDevicesClient } from "../../ui/src/linked-devices-client.js";
import { LinkedDevicesStore } from "../../ui/src/linked-devices-store.js";
ActionHash,
AgentPubKey,
AppBundleSource,
AppCallZomeRequest,
AppWebsocket,
EntryHash,
NewEntryAction,
Record,
encodeHashToBase64,
fakeActionHash,
fakeAgentPubKey,
fakeDnaHash,
fakeEntryHash,
} from '@holochain/client';
import { Scenario } from '@holochain/tryorama';
import { encode } from '@msgpack/msgpack';
import { dirname } from 'path';
import { fileURLToPath } from 'url';

import { LinkedDevicesClient } from '../../ui/src/linked-devices-client.js';
import { LinkedDevicesStore } from '../../ui/src/linked-devices-store.js';

export async function setup(scenario: Scenario) {
const testHappUrl = dirname(fileURLToPath(import.meta.url)) + "/../../workdir/linked-devices_test.happ";

// Add 2 players with the test hApp to the Scenario. The returned players
// can be destructured.
const [alice, bob] = await scenario.addPlayersWithApps([
{ appBundleSource: { path: testHappUrl } },
{ appBundleSource: { path: testHappUrl } },
]);

// Shortcut peer discovery through gossip and register all agents in every
// conductor of the scenario.
await scenario.shareAllAgents();

const aliceStore = new LinkedDevicesStore(
new LinkedDevicesClient(alice.appWs as any, "linked_devices_test", "linked_devices"),
);

const bobStore = new LinkedDevicesStore(
new LinkedDevicesClient(bob.appWs as any, "linked_devices_test", "linked_devices"),
);

// Shortcut peer discovery through gossip and register all agents in every
// conductor of the scenario.
await scenario.shareAllAgents();

return {
alice: {
player: alice,
store: aliceStore,
},
bob: {
player: bob,
store: bobStore,
},
};
const testHappUrl =
dirname(fileURLToPath(import.meta.url)) +
'/../../workdir/linked-devices_test.happ';

// Add 2 players with the test hApp to the Scenario. The returned players
// can be destructured.
const [alice, bob] = await scenario.addPlayersWithApps([
{ appBundleSource: { path: testHappUrl } },
{ appBundleSource: { path: testHappUrl } },
]);

await alice.conductor
.adminWs()
.authorizeSigningCredentials(alice.cells[0].cell_id);

await bob.conductor
.adminWs()
.authorizeSigningCredentials(bob.cells[0].cell_id);

// Shortcut peer discovery through gossip and register all agents in every
// conductor of the scenario.
await scenario.shareAllAgents();

const aliceStore = new LinkedDevicesStore(
new LinkedDevicesClient(
alice.appWs as any,
'linked_devices_test',
'linked_devices',
),
);

const bobStore = new LinkedDevicesStore(
new LinkedDevicesClient(
bob.appWs as any,
'linked_devices_test',
'linked_devices',
),
);

// Shortcut peer discovery through gossip and register all agents in every
// conductor of the scenario.
await scenario.shareAllAgents();

// Prevent race condition when two zome calls are made instantly at the beginning of the lifecycle that cause a ChainHeadMoved error because they trigger 2 parallel init workflows
await aliceStore.client.getLinkingAgents();
await bobStore.client.getLinkingAgents();

return {
alice: {
player: alice,
store: aliceStore,
},
bob: {
player: bob,
store: bobStore,
},
};
}
25 changes: 18 additions & 7 deletions ui/src/linked-devices-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ZomeClient } from '@holochain-open-dev/utils';
import { AgentPubKey, AppClient, Link } from '@holochain/client';
import {
AgentPubKey,
AppCallZomeRequest,
AppClient,
Link,
} from '@holochain/client';

import { LinkedDevicesProof, LinkedDevicesSignal } from './types.js';

Expand Down Expand Up @@ -28,8 +33,8 @@ export class LinkedDevicesClient extends ZomeClient<LinkedDevicesSignal> {
});
}

async prepareLinkDevices(passcode: number[]) {
await this.callZome('prepare_link_devices', passcode);
async prepareLinkDevices(myPasscode: number[]) {
await this.callZome('prepare_link_devices', myPasscode);
}
async getLinkingAgents(): Promise<Array<Link>> {
return this.callZome('get_linking_agents', null);
Expand All @@ -39,10 +44,16 @@ export class LinkedDevicesClient extends ZomeClient<LinkedDevicesSignal> {
}

async initLinkDevices(recipient: AgentPubKey, recipient_passcode: number[]) {
await this.callZome('init_link_devices', {
recipient,
recipient_passcode,
});
const req: AppCallZomeRequest = {
role_name: this.roleName,
zome_name: this.zomeName,
fn_name: 'init_link_devices',
payload: {
recipient,
recipient_passcode,
},
};
await this.client.callZome(req, 2_000);
}

async requestLinkDevices(
Expand Down
5 changes: 3 additions & 2 deletions ui/src/linked-devices-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
collectionSignal,
liveLinksSignal,
pipe,
uniquify,
} from '@holochain-open-dev/signals';
import { HashType, LazyHoloHashMap, retype } from '@holochain-open-dev/utils';
import { AgentPubKey } from '@holochain/client';
Expand All @@ -11,7 +12,7 @@ import { LinkedDevicesClient } from './linked-devices-client.js';
export class LinkedDevicesStore {
constructor(public client: LinkedDevicesClient) {
// At startup, clear all the cap grants that might have been left over from an unfinished link agent process
this.client.clearLinkAgent();
this.client.clearLinkDevices();
}

/** Linked Devices for Agent */
Expand All @@ -24,7 +25,7 @@ export class LinkedDevicesStore {
() => this.client.getLinkedDevicesForAgent(agent),
'AgentToLinkedDevices',
),
links => links.map(l => retype(l.target, HashType.AGENT)),
links => uniquify(links.map(l => retype(l.target, HashType.AGENT))),
),
);

Expand Down
Loading

0 comments on commit e665129

Please sign in to comment.