Skip to content

Commit 5d7df64

Browse files
committed
Fixing issue with intent metadata in agent-proxy and a leak in conformance test execution
1 parent b767b19 commit 5d7df64

9 files changed

Lines changed: 115 additions & 26 deletions

File tree

packages/fdc3-agent-proxy/src/intents/DefaultIntentSupport.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ export class DefaultIntentSupport implements IntentSupport {
147147
app: app || undefined,
148148
metadata: {
149149
traceId: metadata?.traceId ?? v4(),
150+
...(metadata?.signature !== undefined && { signature: metadata.signature }),
151+
...(metadata?.custom !== undefined && { custom: metadata.custom }),
150152
},
151153
},
152154
meta,
@@ -197,6 +199,8 @@ export class DefaultIntentSupport implements IntentSupport {
197199
app,
198200
metadata: {
199201
traceId: metadata?.traceId ?? v4(),
202+
...(metadata?.signature !== undefined && { signature: metadata.signature }),
203+
...(metadata?.custom !== undefined && { custom: metadata.custom }),
200204
},
201205
},
202206
meta,

packages/fdc3-agent-proxy/test/features/raise-intents.feature

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,19 @@ Feature: Basic Intents Support
7171
And messaging will have posts
7272
| payload.context.type | matches_type |
7373
| fdc3.cancel-me | raiseIntentForContextRequest |
74+
75+
Scenario: Raising an intent with metadata forwards traceId, signature and custom
76+
Given "intentMetadata" is metadata with traceId "trace-123" and signature "sig-abc"
77+
When I call "{api}" with "raiseIntent" with parameters "Buy" and "{instrumentContext}" and "{null}" and "{intentMetadata}"
78+
Then "{result}" is an object with the following contents
79+
| source.appId | source.instanceId |
80+
| bank | b1 |
81+
And messaging will have posts
82+
| payload.intent | payload.context.type | payload.metadata.traceId | payload.metadata.signature | payload.metadata.custom.priority | matches_type |
83+
| Buy | fdc3.instrument | trace-123 | sig-abc | high | raiseIntentRequest |
84+
85+
Scenario: Raising an intent without metadata generates a traceId but omits signature and custom
86+
When I call "{api}" with "raiseIntent" with parameters "Buy" and "{instrumentContext}"
87+
And messaging will have posts
88+
| payload.intent | payload.context.type | payload.metadata.signature | payload.metadata.custom | matches_type |
89+
| Buy | fdc3.instrument | {null} | {null} | raiseIntentRequest |

packages/fdc3-agent-proxy/test/step-definitions/intents.steps.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,14 @@ Given('{string} returns a void promise', (world: CustomWorld, intentHandlerName:
202202
return null;
203203
};
204204
});
205+
206+
Given(
207+
'{string} is metadata with traceId {string} and signature {string}',
208+
(world: CustomWorld, field: string, traceId: string, signature: string) => {
209+
world.props[field] = {
210+
traceId,
211+
signature,
212+
custom: { priority: 'high' },
213+
};
214+
}
215+
);

packages/testing/src/steps/generic.impl.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,31 @@ export async function callWithMethodAndThreeParams(
100100
}
101101
}
102102

103+
export async function callWithMethodAndFourParams(
104+
world: PropsWorldLike,
105+
field: string,
106+
fnName: string,
107+
param1: string,
108+
param2: string,
109+
param3: string,
110+
param4: string
111+
): Promise<void> {
112+
try {
113+
const object = handleResolve(field, world) as Record<string, (...args: unknown[]) => unknown>;
114+
const fn = object[fnName];
115+
const result = await fn.call(
116+
object,
117+
handleResolve(param1, world),
118+
handleResolve(param2, world),
119+
handleResolve(param3, world),
120+
handleResolve(param4, world)
121+
);
122+
world.props['result'] = result;
123+
} catch (error) {
124+
world.props['result'] = error;
125+
}
126+
}
127+
103128
export function referToAs(world: PropsWorldLike, from: string, to: string): void {
104129
world.props[to] = handleResolve(from, world);
105130
}

packages/testing/src/steps/generic.steps.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ export function setupGenericSteps(schemaBasePath: string): void {
3737
}
3838
);
3939

40+
When(
41+
'I call {string} with {string} with parameters {string} and {string} and {string} and {string}',
42+
async (
43+
world: PropsWorldLike,
44+
field: string,
45+
fnName: string,
46+
param1: string,
47+
param2: string,
48+
param3: string,
49+
param4: string
50+
) => {
51+
await impl.callWithMethodAndFourParams(world, field, fnName, param1, param2, param3, param4);
52+
}
53+
);
54+
4055
When('I refer to {string} as {string}', (world: PropsWorldLike, from: string, to: string) => {
4156
impl.referToAs(world, from, to);
4257
});

toolbox/fdc3-conformance/src/test/advanced/fdc3.context-metadata.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ const validator = new ContextMetadataValidator();
1919
export default async () => {
2020
const fdc3 = await getAgent();
2121
const cc = new ChannelControlImpl(fdc3);
22+
let mockAppOpened = false;
2223

2324
return describe('fdc3.contextMetadata', () => {
24-
beforeEach(cc.leaveChannel);
25+
beforeEach(async function beforeEach() {
26+
mockAppOpened = false;
27+
await cc.leaveChannel();
28+
});
2529

2630
afterEach(async function afterEach() {
27-
await cc.closeMockApp(this.currentTest?.title ?? 'Some-Test-Title');
31+
if (mockAppOpened) {
32+
await cc.closeMockApp(this.currentTest?.title ?? 'Some-Test-Title');
33+
}
2834
});
2935

3036
// --- User Channel Tests ---
@@ -51,6 +57,7 @@ export default async () => {
5157

5258
const channel = await cc.getNonGlobalUserChannel();
5359
await cc.joinChannel(channel);
60+
mockAppOpened = true;
5461
await cc.openChannelApp(ucMetadataBroadcast, channel.id, JOIN_AND_BROADCAST);
5562
await resolveExecutionCompleteListener;
5663

@@ -88,6 +95,7 @@ export default async () => {
8895

8996
const channel = await cc.getNonGlobalUserChannel();
9097
await cc.joinChannel(channel);
98+
mockAppOpened = true;
9199
await cc.openChannelApp(ucMetadataTraceId, channel.id, JOIN_AND_BROADCAST_WITH_TRACE_ID);
92100
await resolveExecutionCompleteListener;
93101

@@ -126,6 +134,7 @@ export default async () => {
126134

127135
const channel = await cc.getNonGlobalUserChannel();
128136
await cc.joinChannel(channel);
137+
mockAppOpened = true;
129138
await cc.openChannelApp(ucMetadataSignatureCustom, channel.id, JOIN_AND_BROADCAST_WITH_SIGNATURE_CUSTOM);
130139
await resolveExecutionCompleteListener;
131140

@@ -164,6 +173,7 @@ export default async () => {
164173
}
165174
);
166175

176+
mockAppOpened = true;
167177
await cc.openChannelApp(acMetadataBroadcast, 'test-channel', APP_CHANNEL_AND_BROADCAST);
168178
await resolveExecutionCompleteListener;
169179

@@ -189,6 +199,7 @@ export default async () => {
189199
const resolveExecutionCompleteListener = cc.initCompleteListener(acGetCurrentContextWithMetadata);
190200
const testChannel = await fdc3.getOrCreateChannel('test-channel');
191201

202+
mockAppOpened = true;
192203
await cc.openChannelApp(acGetCurrentContextWithMetadata, 'test-channel', APP_CHANNEL_AND_BROADCAST);
193204
await resolveExecutionCompleteListener;
194205

toolbox/fdc3-conformance/src/test/basic/fdc3.basic.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ const basicIL1 = (fdc3: DesktopAgent, documentation: string) => {
7070
};
7171

7272
const basicGI1 = (fdc3: DesktopAgent, documentation: string) => {
73-
console.log('coming here in');
7473
it('(BasicGI1) Returns ImplementationMetadata object', async () => {
7574
try {
7675
const info = await fdc3.getInfo();
Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Channel, Context, DesktopAgent } from '@finos/fdc3';
1+
import { Channel, Context, DesktopAgent, Listener } from '@finos/fdc3';
22
import { AppControlContext, AppControlContextListener } from '../context-types';
33
import constants from '../constants';
44
import { wait } from '../utils';
@@ -7,9 +7,18 @@ declare let fdc3: DesktopAgent;
77

88
export async function closeMockAppWindow(testId: string, count: number = 1) {
99
const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel);
10-
const { listenerPromise: contextPromise } = await waitForContext('windowClosed', testId, appControlChannel, count);
10+
const { listenerPromise: contextPromise, listener } = await waitForContext(
11+
'windowClosed',
12+
testId,
13+
appControlChannel,
14+
count
15+
);
1116
await broadcastCloseWindow(testId);
12-
await contextPromise;
17+
try {
18+
await contextPromise;
19+
} finally {
20+
listener.unsubscribe();
21+
}
1322
await wait(constants.WindowCloseWaitTime); // wait for window to close
1423
}
1524

@@ -26,7 +35,7 @@ export const waitForContext = async (
2635
testId: string,
2736
channel: Channel,
2837
count = 1
29-
): Promise<AppControlContextListener> => {
38+
): Promise<AppControlContextListener & { listener: Listener }> => {
3039
let promiseResolve: (c: Context) => void;
3140
let promiseReject: (x: unknown) => void;
3241

@@ -41,23 +50,22 @@ export const waitForContext = async (
4150
}
4251
}, 1000);
4352

44-
return channel
45-
.addContextListener(contextType, ctx => {
46-
if (ctx['testId'] == testId) {
47-
console.log(`Received ${contextType}`);
48-
count--;
49-
if (count == 0) {
50-
promiseResolve(ctx);
51-
} else {
52-
console.log(`Waiting for ${count} more ${contextType}`);
53-
}
53+
const listener = await channel.addContextListener(contextType, ctx => {
54+
if (ctx['testId'] == testId) {
55+
console.log(`Received ${contextType}`);
56+
count--;
57+
if (count == 0) {
58+
promiseResolve(ctx);
5459
} else {
55-
console.log(`Wrong test id expected: ${testId} got: ${ctx['testId']}`);
60+
console.log(`Waiting for ${count} more ${contextType}`);
5661
}
57-
})
58-
.then(() => {
59-
return {
60-
listenerPromise,
61-
};
62-
});
62+
} else {
63+
console.log(`Wrong test id expected: ${testId} got: ${ctx['testId']}`);
64+
}
65+
});
66+
67+
return {
68+
listenerPromise,
69+
listener,
70+
};
6371
};

toolbox/fdc3-conformance/src/test/support/channels-support.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ export class ChannelControlImpl implements ChannelControl {
5353
};
5454

5555
initCompleteListener = async (testId: string) => {
56-
const { listenerPromise } = await waitForContext(
56+
const { listenerPromise, listener } = await waitForContext(
5757
'executionComplete',
5858
testId,
5959
await this.fdc3.getOrCreateChannel(constants.ControlChannel)
6060
);
61-
return listenerPromise;
61+
return listenerPromise.finally(() => listener.unsubscribe());
6262
};
6363

6464
openChannelApp = async (

0 commit comments

Comments
 (0)