diff --git a/README.md b/README.md index e399fafe..103c9edb 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,14 @@ [![FINOS - Incubating](https://cdn.jsdelivr.net/gh/finos/contrib-toolbox@master/images/badge-incubating.svg)](https://finosfoundation.atlassian.net/wiki/display/FINOS/Incubating) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6456/badge)](https://bestpractices.coreinfrastructure.org/projects/6456) -|Version | Release | Specification | -|-----------|---------|--------| -|[FDC3 1.2](https://fdc3.finos.org/docs/1.2/fdc3-intro) | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/finos/FDC3-Conformance-Framework) | [1.2 Tests Specification](https://github.com/finos/FDC3/blob/master/toolbox/fdc3-conformance/FDC3-1.2-Conformance-Test-Cases.md) | -|[FDC3 2.0](https://fdc3.finos.org/docs/fdc3-intro) | _in development_ | [2.0 Tests Specification](https://github.com/finos/FDC3/blob/8166c0e6aa872b2fc7b755384e5b2eeeaf88c732/toolbox/fdc3-conformance/FDC3-2.0-Conformance-Test-Cases.md) | - # FDC3 Conformance Framework A framework for testing whether desktop containers implement the [FDC3 standard](https://fdc3.finos.org/). +The tests implemented for each FDC3 version are based on the FDC3 Conformance tests specifications defined by the FDC3 maintainers and provided in the main FDC3 repository. Please see [the README file in that repository](https://github.com/finos/FDC3/blob/master/toolbox/fdc3-conformance/README.md) for further details. + +Tests are currently implemented for version [1.2](https://fdc3.finos.org/docs/1.2/fdc3-intro) and [2.0](https://fdc3.finos.org/docs/fdc3-intro) of the FDC3 Standard. + ## What Is It? - There are many vendors implementing Desktop Agents for the FDC3 standard. diff --git a/directories/local-conformance-2_0.v2.json b/directories/local-conformance-2_0.v2.json index de89611d..4d4105b5 100644 --- a/directories/local-conformance-2_0.v2.json +++ b/directories/local-conformance-2_0.v2.json @@ -1,5 +1,6 @@ { - "applications": [{ + "applications": [ + { "appId": "Conformance1", "name": "Conformance1", "title": "FDC3 2.0 Conformance Framework", @@ -42,7 +43,16 @@ "publisher": "FINOS", "icons": [{ "src": "http://localhost:3001/finos-icon-256.png" - }] + }], + "interop": { + "intents": { + "listensFor": { + "ConformanceListener": { + "contexts": ["fdc3.nothing"] + } + } + } + } }, { "appId": "ChannelsAppId", @@ -130,7 +140,7 @@ "contexts": ["testContextX", "testContextZ"] }, "sharedTestingIntent1": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 1", "contexts": ["testContextX"] } } @@ -180,12 +190,8 @@ "interop": { "intents": { "listensFor": { - "bTestingIntent": { - "displayName": "B Testing Intent", - "contexts": ["testContextY"] - }, "sharedTestingIntent1": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 1", "contexts": ["testContextX", "testContextY"], "resultType": "testContextY" } @@ -289,7 +295,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextX"], "resultType": "testContextZ" } @@ -341,7 +347,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextY"], "resultType": "channel" } @@ -393,7 +399,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextY"], "resultType": "channel" } @@ -445,7 +451,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextY"] } } @@ -496,7 +502,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextY"], "resultType": "testContextZ" } @@ -548,7 +554,7 @@ "intents": { "listensFor": { "sharedTestingIntent2": { - "displayName": "Shared Testing Intent", + "displayName": "Shared Testing Intent 2", "contexts": ["testContextY"], "resultType": "testContextZ" } diff --git a/options/README.md b/options/README.md index 1aae60ee..86f32c5e 100644 --- a/options/README.md +++ b/options/README.md @@ -2,4 +2,8 @@ For maintainers: Please add any vendor-specific code only in this directory. -For users: Please note that this directory contains vendor-specific extensions to aid in the testing of the conformance of different Desktop Agents. It doesn't form part of the Conformance Framework proper. +For users: + + - Please note that this directory contains vendor-specific extensions to aid in the testing of the conformance of different Desktop Agents. It doesn't form part of the Conformance Framework proper. + - If you wish to test glue42 core-plus, you'll need to supply a license key. + diff --git a/options/glue/v2.0/glue42/core-plus/startCorePlusRunner.js b/options/glue/v2.0/glue42/core-plus/startCorePlusRunner.js index b23ca860..1984526e 100644 --- a/options/glue/v2.0/glue42/core-plus/startCorePlusRunner.js +++ b/options/glue/v2.0/glue42/core-plus/startCorePlusRunner.js @@ -1,6 +1,6 @@ const init = async () => { const config = { - licenseKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmF0aW9uIjoxNjkzNTE1NjAwLCJ0eXBlIjoidHJpYWwifQ.VOHEfGyNlgTfLexfDWfqUMLgH5pCjLqYjW3mON2J8Ec", + licenseKey: "<", applications: { local: [ { @@ -53,11 +53,6 @@ const init = async () => { height: 600, }, intents: [ - { - name: "bTestingIntent", - displayName: "B Testing Intent", - contexts: ["testContextY"], - }, { name: "sharedTestingIntent1", displayName: "Shared Testing Intent", diff --git a/options/glue/v2.0/glue42/startRunner.js b/options/glue/v2.0/glue42/startRunner.js index 3d12c171..184c4b5d 100644 --- a/options/glue/v2.0/glue42/startRunner.js +++ b/options/glue/v2.0/glue42/startRunner.js @@ -52,11 +52,6 @@ const init = async () => { height: 600, }, intents: [ - { - name: "bTestingIntent", - displayName: "B Testing Intent", - contexts: ["testContextY"], - }, { name: "sharedTestingIntent1", displayName: "Shared Testing Intent", diff --git a/src/constants.ts b/src/constants.ts index 7dc0857d..537b3123 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,9 +4,9 @@ const constants = { ShortWait: 1000, Fdc3Timeout: 500, // The amount of time to wait for the FDC3Ready event during initialisation - TestTimeout: 15000, // Tests that take longer than this (in milliseconds) will fail - WaitTime: 3000, // The amount of time to wait for mock apps to finish processing - WindowCloseWaitTime: 3000, // The amount of time to allow for clean-up of closed windows + TestTimeout: 20000, // Tests that take longer than this (in milliseconds) will fail + WaitTime: 5000, // The amount of time to wait for mock apps to finish processing + WindowCloseWaitTime: 1000, // The amount of time to allow for clean-up of closed windows NoListenerTimeout: 120000, // the amount of time to allow for a DA to timeout waiting on a context or intent listener // FDC3 does not define this timeout so this should be extended if the DA uses a longer timeout ControlChannel: "app-control", //app channel used for passing messages between mock apps and tests diff --git a/src/mock/v2.0/basic.ts b/src/mock/v2.0/basic.ts index 5cd7debf..9a03f5d3 100644 --- a/src/mock/v2.0/basic.ts +++ b/src/mock/v2.0/basic.ts @@ -2,7 +2,7 @@ import { closeWindowOnCompletion, onFdc3Ready } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0/dist/api/DesktopAgent"; import { sendContextToTests } from "./mock-functions"; import { AppControlContext } from "../../context-types"; -import { Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; onFdc3Ready().then(async () => { await closeWindowOnCompletion(); @@ -12,14 +12,14 @@ onFdc3Ready().then(async () => { // broadcast that this app has received context if (context.type === "fdc3.instrument") { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, context: context, } as AppControlContext); } }); } catch (ex) { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, errorMessage: `${ex.message ?? ex}`, } as AppControlContext); } diff --git a/src/mock/v2.0/intent-a.ts b/src/mock/v2.0/intent-a.ts index 3a1f7546..7c56f3f3 100644 --- a/src/mock/v2.0/intent-a.ts +++ b/src/mock/v2.0/intent-a.ts @@ -3,7 +3,7 @@ import { sendContextToTests } from "../v2.0/mock-functions"; import { wait } from "../../utils"; import { IntentUtilityContext } from "../../context-types"; import { IntentResult, DesktopAgent } from "fdc3_2_0"; -import { ContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; onFdc3Ready().then(async () => { @@ -17,7 +17,7 @@ onFdc3Ready().then(async () => { const { appMetadata } = await fdc3.getInfo(); await sendContextToTests({ - type: "aTestingIntent-listener-triggered", + type: ControlContextType.aTestingIntentListenerTriggered, instanceId: appMetadata.instanceId, }); @@ -29,14 +29,14 @@ onFdc3Ready().then(async () => { await delayExecution(context.delayBeforeReturn); await sendContextToTests({ - type: "sharedTestingIntent1-listener-triggered", + type: ControlContextType.sharedTestingIntent1ListenerTriggered, }); return context; }); await sendContextToTests({ - type: "intent-app-a-opened", + type: ControlContextType.intentAppAOpened, }); }); diff --git a/src/mock/v2.0/intent-b.ts b/src/mock/v2.0/intent-b.ts index b178cfdd..c123efdd 100644 --- a/src/mock/v2.0/intent-b.ts +++ b/src/mock/v2.0/intent-b.ts @@ -3,7 +3,7 @@ import { DesktopAgent } from "fdc3_2_0/dist/api/DesktopAgent"; import { sendContextToTests } from "../v2.0/mock-functions"; import { wait } from "../../utils"; import { AppControlContext, IntentUtilityContext } from "../../context-types"; -import { Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; onFdc3Ready().then(async () => { await closeWindowOnCompletion(); @@ -14,14 +14,14 @@ onFdc3Ready().then(async () => { // broadcast that this app has received context if (context.type === "fdc3.instrument") { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, context: context, } as AppControlContext); } }); } catch (ex) { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, errorMessage: `${ex.message ?? ex}`, } as AppControlContext); } @@ -33,7 +33,7 @@ onFdc3Ready().then(async () => { } await sendContextToTests({ - type: "sharedTestingIntent1-listener-triggered", + type: ControlContextType.sharedTestingIntent1ListenerTriggered, }); return context; diff --git a/src/mock/v2.0/intent-c.ts b/src/mock/v2.0/intent-c.ts index a41d6a4e..f9629b2b 100644 --- a/src/mock/v2.0/intent-c.ts +++ b/src/mock/v2.0/intent-c.ts @@ -2,7 +2,7 @@ import { closeWindowOnCompletion, onFdc3Ready } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0/dist/api/DesktopAgent"; import { sendContextToTests } from "../v2.0/mock-functions"; import { AppControlContext } from "../../context-types"; -import { Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; onFdc3Ready().then(async () => { await closeWindowOnCompletion(); @@ -12,14 +12,14 @@ onFdc3Ready().then(async () => { // broadcast that this app has received context if (context.type === "fdc3.instrument") { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, context: context, } as AppControlContext); } }); } catch (ex) { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, errorMessage: `${ex.message ?? ex}`, } as AppControlContext); } diff --git a/src/mock/v2.0/intent-e.ts b/src/mock/v2.0/intent-e.ts index fdcb1aa6..beacd09d 100644 --- a/src/mock/v2.0/intent-e.ts +++ b/src/mock/v2.0/intent-e.ts @@ -1,21 +1,25 @@ import { closeWindowOnCompletion, onFdc3Ready, sendContextToTests, validateContext } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0"; import { wait } from "../../utils"; -import { ContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import constants from "../../constants"; declare let fdc3: DesktopAgent; //used in '2.0-RaiseIntentChannelResult' onFdc3Ready().then(async () => { await closeWindowOnCompletion(); + const { appMetadata } = await fdc3.getInfo(); + fdc3.addIntentListener(Intent.sharedTestingIntent2, async (context) => { validateContext(context.type, ContextType.testContextY); const channel = await fdc3.getOrCreateChannel("test-channel"); + + //set-up alert to test framework that the task was completed after a short delay + setTimeout(async () => { + await sendContextToTests({ type: ControlContextType.sharedTestingIntent2ResultSent, id: { key: "uniqueId" }, instanceId: appMetadata.instanceId }); + }, constants.ShortWait) + return channel; }); - - const { appMetadata } = await fdc3.getInfo(); - - await wait(); // send context after short delay - await sendContextToTests({ type: ContextType.testContextZ, id: { key: "uniqueId" }, instanceId: appMetadata.instanceId }); }); diff --git a/src/mock/v2.0/intent-f.ts b/src/mock/v2.0/intent-f.ts index 56e249a4..df225509 100644 --- a/src/mock/v2.0/intent-f.ts +++ b/src/mock/v2.0/intent-f.ts @@ -1,20 +1,24 @@ import { closeWindowOnCompletion, onFdc3Ready, sendContextToTests, validateContext } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0"; import { wait } from "../../utils"; -import { ContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import constants from "../../constants"; declare let fdc3: DesktopAgent; //used in '2.0-RaiseIntentPrivateChannelResult' onFdc3Ready().then(async () => { await closeWindowOnCompletion(); + const { appMetadata } = await fdc3.getInfo(); + fdc3.addIntentListener(Intent.sharedTestingIntent2, async (context) => { validateContext(context.type, ContextType.testContextY); const privateChannel = await fdc3.createPrivateChannel(); + + //set-up alert to test framework that the task was completed after a short delay + setTimeout(async () => { + await sendContextToTests({ type: ControlContextType.sharedTestingIntent2ResultSent, id: { key: "uniqueId" }, instanceId: appMetadata.instanceId }); + }, constants.ShortWait) + return privateChannel; }); - - const { appMetadata } = await fdc3.getInfo(); - - await wait(); // send context after short delay - await sendContextToTests({ type: ContextType.testContextZ, id: { key: "uniqueId" }, instanceId: appMetadata.instanceId }); }); diff --git a/src/mock/v2.0/intent-j.ts b/src/mock/v2.0/intent-j.ts index b7ae2952..c5000d1f 100644 --- a/src/mock/v2.0/intent-j.ts +++ b/src/mock/v2.0/intent-j.ts @@ -1,6 +1,6 @@ import { closeWindowOnCompletion, onFdc3Ready, sendContextToTests, validateContext } from "./mock-functions"; import { ChannelError, DesktopAgent } from "fdc3_2_0"; -import { ContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; @@ -13,10 +13,10 @@ onFdc3Ready().then(async () => { try { await fdc3.getOrCreateChannel(context.id.key); - await sendContextToTests({ type: "error", errorMessage: "No error thrown when calling fdc3.getOrCreateChannel('') from the mock app" }); + await sendContextToTests({ type: ControlContextType.error, errorMessage: "No error thrown when calling fdc3.getOrCreateChannel('') from the mock app" }); } catch (ex) { if (ex.message !== ChannelError.AccessDenied) { - await sendContextToTests({ type: "error", errorMessage: `Incorrect error received when calling fdc3.getOrCreateChannel(''). Expected AccessDenied, got ${ex.message}` }); + await sendContextToTests({ type: ControlContextType.error, errorMessage: `Incorrect error received when calling fdc3.getOrCreateChannel(''). Expected AccessDenied, got ${ex.message}` }); } } diff --git a/src/mock/v2.0/intent-k.ts b/src/mock/v2.0/intent-k.ts index 30b3cfce..73ef49f6 100644 --- a/src/mock/v2.0/intent-k.ts +++ b/src/mock/v2.0/intent-k.ts @@ -3,7 +3,7 @@ import { DesktopAgent } from "fdc3_2_0"; import { wait } from "../../utils"; import { IntentUtilityContext } from "../../context-types"; import constants from "../../constants"; -import { ContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; //used in '2.0-PrivateChannelsLifecycleEvents' @@ -38,13 +38,13 @@ onFdc3Ready().then(async () => { }); await privChan.onUnsubscribe(async (contextType) => { - //let test know onUnsubscribe was triggered - await sendContextToTests({ type: "onUnsubscribeTriggered" }); + //let test know onUnsubscribe was triggered + await sendContextToTests({ type: ControlContextType.onUnsubscribeTriggered }); }); await privChan.onDisconnect(async () => { - //let test know onUnsubscribe was triggered - await sendContextToTests({ type: "onDisconnectTriggered" }); + //let test know onUnsubscribe was triggered + await sendContextToTests({ type: ControlContextType.onDisconnectTriggered }); }); return privChan; diff --git a/src/mock/v2.0/metadata.ts b/src/mock/v2.0/metadata.ts index 0ac6e90b..76bf0575 100644 --- a/src/mock/v2.0/metadata.ts +++ b/src/mock/v2.0/metadata.ts @@ -1,7 +1,7 @@ import { closeWindowOnCompletion, onFdc3Ready, sendContextToTests } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0"; import { AppControlContext } from "../../context-types"; -import { Intent } from "../../test/v2.0/support/intent-support-2.0"; +import { ControlContextType, Intent } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; @@ -13,22 +13,10 @@ onFdc3Ready().then(async () => { //execute command from test app and send back metadata const implMetadata = await fdc3.getInfo(); const metadataContext = { - type: "context-listener-triggered", + type: ControlContextType.ContextListenerTriggered, implMetadata: implMetadata, }; sendContextToTests(metadataContext); }); - - // used in 'FindInstances' - await fdc3.addIntentListener(Intent.aTestingIntent, async (context) => { - const implMetadata = await fdc3.getInfo(); - const metadataAppContext: AppControlContext = { - type: "intent-listener-triggered", - instanceId: implMetadata.appMetadata.instanceId, - }; - - sendContextToTests(metadataAppContext); - return context; - }); }); diff --git a/src/mock/v2.0/open-a.ts b/src/mock/v2.0/open-a.ts index 67355492..51922eec 100644 --- a/src/mock/v2.0/open-a.ts +++ b/src/mock/v2.0/open-a.ts @@ -2,6 +2,7 @@ import { closeWindowOnCompletion, onFdc3Ready } from "./mock-functions"; import { DesktopAgent } from "fdc3_2_0/dist/api/DesktopAgent"; import { sendContextToTests } from "../v2.0/mock-functions"; import { AppControlContext } from "../../context-types"; +import { ControlContextType } from "../../test/v2.0/support/intent-support-2.0"; declare let fdc3: DesktopAgent; onFdc3Ready().then(async () => { @@ -10,7 +11,7 @@ onFdc3Ready().then(async () => { // broadcast that this app has received context if (context.type !== "shouldNotReceiveThisContext") { await sendContextToTests({ - type: "context-received", + type: ControlContextType.contextReceived, errorMessage: `Listener received incorrect context type. Listener listening for 'shouldNotReceiveThisContext' type received '${context.type}' type`, } as AppControlContext); } diff --git a/src/test/common/fdc3.app-channels.ts b/src/test/common/fdc3.app-channels.ts index 622f48e5..5cd6a739 100644 --- a/src/test/common/fdc3.app-channels.ts +++ b/src/test/common/fdc3.app-channels.ts @@ -1,5 +1,6 @@ import { assert, expect } from "chai"; import { wait } from "../../utils"; +import constants from "../../constants"; import { APP_CHANNEL_AND_BROADCAST, APP_CHANNEL_AND_BROADCAST_TWICE, ChannelControl, JOIN_AND_BROADCAST_TWICE } from "./control/channel-control"; export function createAppChannelTests(cc: ChannelControl, documentation: string, prefix: string): Mocha.Suite { @@ -22,9 +23,16 @@ export function createAppChannelTests(cc: ChannelControl, documen }); await cc.openChannelApp(acTestId, testChannel.id, APP_CHANNEL_AND_BROADCAST); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener1]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener1]); } }); @@ -40,7 +48,11 @@ export function createAppChannelTests(cc: ChannelControl, documen await cc.setupContextChecker(testChannel, null, "fdc3.instrument", errorMessage, () => (receivedContext = true)); if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } } }); @@ -56,9 +68,16 @@ export function createAppChannelTests(cc: ChannelControl, documen }); await cc.openChannelApp(acTestId4, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener1]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener1]); } }); @@ -109,9 +128,16 @@ export function createAppChannelTests(cc: ChannelControl, documen }); await cc.openChannelApp(acTestId8, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener, listener2]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener, listener2]); } }); @@ -132,9 +158,16 @@ export function createAppChannelTests(cc: ChannelControl, documen }); await cc.openChannelApp(acTestId9, testChannel.id, APP_CHANNEL_AND_BROADCAST_TWICE); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener, listener2]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener,listener2]); } }); diff --git a/src/test/common/fdc3.basic.ts b/src/test/common/fdc3.basic.ts index 101e0bd0..e699efec 100644 --- a/src/test/common/fdc3.basic.ts +++ b/src/test/common/fdc3.basic.ts @@ -41,7 +41,7 @@ export let basicCL2 = (fdc3: any, documentation: string, listener: any) => { export let basicIL1 = (fdc3: any, documentation: string, listener: any) => { it("(BasicIL1) Method is callable", async () => { - const intentName = "fdc3.conformanceListener"; + const intentName = "ConformanceListener"; try { listener = await fdc3.addIntentListener(intentName, (info: any) => { console.log(`Intent listener for intent ${intentName} triggered with result ${info}`); diff --git a/src/test/common/fdc3.open.ts b/src/test/common/fdc3.open.ts index 964cb974..4055bd04 100644 --- a/src/test/common/fdc3.open.ts +++ b/src/test/common/fdc3.open.ts @@ -1,6 +1,7 @@ import { assert } from "chai"; import constants from "../../constants"; import { openApp, OpenCommonConfig, OpenControl } from "./control/open-control"; +import { ControlContextType } from "../v2.0/support/intent-support-2.0"; export function getCommonOpenTests(control: OpenControl, documentation: string, config: OpenCommonConfig) { @@ -31,7 +32,7 @@ export function getCommonOpenTests(control: OpenControl, documentation: str let context: any, targetApp: any; context = { type: "fdc3.instrument", name: "context" }; targetApp = control.createTargetApp(openApp.b.name,openApp.b.id); - const receiver = control.contextReceiver("context-received"); + const receiver = control.contextReceiver(ControlContextType.contextReceived); await control.openMockApp(targetApp, context); await control.validateReceivedContext(await receiver, "fdc3.instrument"); await control.closeMockApp(AOpensBWithContext3); @@ -42,7 +43,7 @@ export function getCommonOpenTests(control: OpenControl, documentation: str let context: any, targetApp: any; context = { type: "fdc3.instrument", name: "context" }; targetApp = control.createTargetApp(openApp.b.name,openApp.b.id); - const receiver = control.contextReceiver("context-received"); + const receiver = control.contextReceiver(ControlContextType.contextReceived); await control.openMockApp(targetApp, context); await control.validateReceivedContext(await receiver, "fdc3.instrument"); await control.closeMockApp(AOpensBWithSpecificContext); @@ -53,7 +54,7 @@ export function getCommonOpenTests(control: OpenControl, documentation: str let context: any, targetApp: any; context = { type: "fdc3.instrument", name: "context" }; targetApp = control.createTargetApp(openApp.b.name,openApp.b.id); - const receiver = control.contextReceiver("context-received"); + const receiver = control.contextReceiver(ControlContextType.contextReceived); await control.openMockApp(targetApp, context); await receiver; await control.validateReceivedContext(await receiver, "fdc3.instrument"); diff --git a/src/test/common/fdc3.user-channels.ts b/src/test/common/fdc3.user-channels.ts index 214b5648..85e79fff 100644 --- a/src/test/common/fdc3.user-channels.ts +++ b/src/test/common/fdc3.user-channels.ts @@ -2,6 +2,7 @@ import { assert, expect } from "chai"; import { failOnTimeout, wait, wrapPromise } from "../../utils"; import { JOIN_AND_BROADCAST, JOIN_AND_BROADCAST_TWICE } from "./control/channel-control"; import { ChannelControl } from "./control/channel-control"; +import constants from "../../constants"; export function createUserChannelTests(cc: ChannelControl, documentation: string, prefix: string): Mocha.Suite { const channelName = prefix === "" ? "System channels" : "User channels"; @@ -23,9 +24,16 @@ export function createUserChannelTests(cc: ChannelControl, docume await cc.joinChannel(channel); await cc.openChannelApp(scTestId1, channel.id, JOIN_AND_BROADCAST); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail("No context received" + errorMessage); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -40,9 +48,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let listener = await cc.setupAndValidateListener(null, null, "fdc3.instrument", errorMessage, () => (receivedContext = true)); await cc.openChannelApp(scTestId2, channel.id, JOIN_AND_BROADCAST); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -57,9 +72,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let listener = await cc.setupAndValidateListener(null, null, "fdc3.instrument", errorMessage, () => (receivedContext = true)); await cc.joinChannel(channel); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -74,9 +96,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let receivedContext = false; let listener = await cc.setupAndValidateListener(null, null, "fdc3.instrument", errorMessage, () => (receivedContext = true)); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -91,9 +120,16 @@ export function createUserChannelTests(cc: ChannelControl, docume await cc.joinChannel(channel); await cc.openChannelApp(scTestId4, channel.id, JOIN_AND_BROADCAST_TWICE); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -108,9 +144,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let listener = await cc.setupAndValidateListener(null, "fdc3.instrument", "fdc3.instrument", errorMessage, () => (receivedContext = true)); await cc.openChannelApp(UCFilteredUsage2, channel.id, JOIN_AND_BROADCAST_TWICE); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -125,9 +168,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let listener = await cc.setupAndValidateListener(null, "fdc3.instrument", "fdc3.instrument", errorMessage, () => (receivedContext = true)); await cc.joinChannel(userChannel); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -142,9 +192,16 @@ export function createUserChannelTests(cc: ChannelControl, docume let receivedContext = false; let listener = await cc.setupAndValidateListener(undefined, "fdc3.instrument", "fdc3.instrument", errorMessage, () => (receivedContext = true)); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener]); - if (!receivedContext) { - assert.fail(`No context received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener]); } }); @@ -181,9 +238,16 @@ export function createUserChannelTests(cc: ChannelControl, docume await cc.joinChannel(channel); await cc.openChannelApp(scTestId5, channel.id, JOIN_AND_BROADCAST_TWICE, undefined, true, contextId); await resolveExecutionCompleteListener; - cc.unsubscribeListeners([listener, listener2]); - if (!receivedContext) { - assert.fail(`At least one context was not received!\n${errorMessage}`); + try { + if (!receivedContext) { + //allow upto a second for the context to arrive + await wait(constants.ShortWait); + if (!receivedContext) { + assert.fail(`No context received!\n${errorMessage}`); + } + } + } finally { + cc.unsubscribeListeners([listener, listener2]); } }); diff --git a/src/test/v2.0/advanced/fdc3.findInstances.ts b/src/test/v2.0/advanced/fdc3.findInstances.ts index defa8cae..b4260be9 100644 --- a/src/test/v2.0/advanced/fdc3.findInstances.ts +++ b/src/test/v2.0/advanced/fdc3.findInstances.ts @@ -4,7 +4,8 @@ import { failOnTimeout, wait, wrapPromise } from "../../../utils"; import { closeMockAppWindow } from "../fdc3-2_0-utils"; import { IntentUtilityContext } from "../../../context-types"; import { MetadataFdc3Api } from "../support/metadata-support-2.0"; -import { ContextType, Intent, IntentApp, RaiseIntentControl2_0 } from "../support/intent-support-2.0"; +import { ContextType, ControlContextType, Intent, IntentApp, RaiseIntentControl2_0 } from "../support/intent-support-2.0"; +import { AppIdentifier, IntentResolution } from "fdc3_2_0"; const findInstancesDocs = "\r\nDocumentation: " + APIDocumentation2_0.findInstances + "\r\nCause: "; @@ -30,12 +31,12 @@ export default () => let instances = await control.findInstances(IntentApp.IntentAppA); validateInstances(instances, appIdentifier, appIdentifier2); - const timeout = failOnTimeout("'aTestingIntent-listener-triggered' context not received from mock app"); // fail if expected context not received + const timeout = failOnTimeout(`'${ControlContextType.aTestingIntentListenerTriggered}' context not received from mock app`); // fail if expected context not received const wrapper = wrapPromise(); const appControlChannel = await api.retrieveAppControlChannel(); //ensure appIdentifier received the raised intent - listener = await appControlChannel.addContextListener("aTestingIntent-listener-triggered", (context: IntentUtilityContext) => { + listener = await appControlChannel.addContextListener(ControlContextType.aTestingIntentListenerTriggered, (context: IntentUtilityContext) => { expect(context['instanceId'], "the raised intent was received by a different instance of the mock app than expected").to.be.equals(appIdentifier.instanceId); clearTimeout(timeout); wrapper.resolve(); @@ -54,15 +55,18 @@ export default () => }); }); -function validateResolutionSource(resolution, appIdentifier) { +function validateResolutionSource(resolution: IntentResolution, appIdentifier: AppIdentifier) { // check that resolution.source matches the appIdentifier expect(resolution.source.appId, "IntentResolution.source.appId did not match the mock app's AppIdentifier's appId").to.be.equal(appIdentifier.appId); expect(resolution.source.instanceId, "IntentResolution.source.instanceId did not match the mock app's AppIdentifier's instanceId").to.be.equal(appIdentifier.instanceId); } -function validateInstances(instances, appIdentifier, appIdentifier2) { - // check that the retrieved instances match the retrieved appIdentifiers - if (!instances.some((instance) => JSON.stringify(instance) === JSON.stringify(appIdentifier) || JSON.stringify(instance) === JSON.stringify(appIdentifier2))) { +function validateInstances(instances: AppIdentifier[], appIdentifier: AppIdentifier, appIdentifier2: AppIdentifier) { + // check that the retrieved instances match both the retrieved appIdentifiers + const compareAppIdentifiers = (a: AppIdentifier, b: AppIdentifier) => a.appId === b.appId && a.instanceId === b.instanceId; + + if (!(instances.some((instance) => compareAppIdentifiers(instance, appIdentifier)) && + instances.some((instance) => compareAppIdentifiers(instance, appIdentifier2)))) { assert.fail(`At least one AppIdentifier object is missing from the AppIdentifier array returned after calling fdc3.findInstances(app: AppIdentifier)${findInstancesDocs}`); } } diff --git a/src/test/v2.0/advanced/fdc3.getInfo.ts b/src/test/v2.0/advanced/fdc3.getInfo.ts index a92948b1..7ac1ad09 100644 --- a/src/test/v2.0/advanced/fdc3.getInfo.ts +++ b/src/test/v2.0/advanced/fdc3.getInfo.ts @@ -4,6 +4,7 @@ import { closeMockAppWindow } from "../fdc3-2_0-utils"; import { ImplementationMetadata, Listener } from "fdc3_2_0"; import { MetadataValidator, MetadataContext, MetadataFdc3Api } from "../support/metadata-support-2.0"; import { APIDocumentation2_0 } from "../apiDocuments-2.0"; +import { ControlContextType } from "../support/intent-support-2.0"; const getInfoDocs = "\r\nDocumentation: " + APIDocumentation2_0.getInfo + "\r\nCause"; const validator = new MetadataValidator(); @@ -46,7 +47,7 @@ export default () => const timeout = failOnTimeout("did not receive MetadataContext from metadata app"); // fail if no metadataContext received const wrapper = wrapPromise(); - listener = await appControlChannel.addContextListener("context-listener-triggered", async (context: MetadataContext) => { + listener = await appControlChannel.addContextListener(ControlContextType.ContextListenerTriggered, async (context: MetadataContext) => { implMetadata = context.implMetadata; wrapper.resolve(); clearTimeout(timeout); diff --git a/src/test/v2.0/advanced/fdc3.raiseIntent-Result.ts b/src/test/v2.0/advanced/fdc3.raiseIntent-Result.ts index 71059b3e..fb3c4c9e 100644 --- a/src/test/v2.0/advanced/fdc3.raiseIntent-Result.ts +++ b/src/test/v2.0/advanced/fdc3.raiseIntent-Result.ts @@ -1,15 +1,16 @@ import { Listener } from "fdc3_2_0"; import { closeMockAppWindow } from "../fdc3-2_0-utils"; -import { RaiseIntentControl2_0, IntentResultType, IntentApp, ContextType, Intent } from "../support/intent-support-2.0"; +import { RaiseIntentControl2_0, IntentResultType, IntentApp, ContextType, Intent, ControlContextType } from "../support/intent-support-2.0"; import { wait } from "../../../utils"; +import constants from "../../../constants"; const control = new RaiseIntentControl2_0(); export default () => -describe("fdc3.raiseIntent (Result)", () => { + describe("fdc3.raiseIntent (Result)", () => { let errorListener: Listener = undefined; - + afterEach(async function afterEach() { await closeMockAppWindow(this.currentTest.title); @@ -31,7 +32,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentVoidResult5secs = "(2.0-RaiseIntentVoidResult5secs) App A receives a void IntentResult after a 5 second delay"; it(RaiseIntentVoidResult5secs, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext("aTestingIntent-listener-triggered", 8000); + let receiver = control.receiveContext(ControlContextType.aTestingIntentListenerTriggered, 8000); const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, undefined, 5000); control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); let intentResultPromise = control.getIntentResult(intentResolution); @@ -55,7 +56,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentContextResult5secs = "(2.0-RaiseIntentContextResult5secs) IntentResult resolves to testContextY instance after a 5 second delay"; it(RaiseIntentContextResult5secs, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext("sharedTestingIntent1-listener-triggered", 8000); + let receiver = control.receiveContext(ControlContextType.sharedTestingIntent1ListenerTriggered, 8000); const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextY, undefined, 5000); control.validateIntentResolution(IntentApp.IntentAppB, intentResolution); const intentResultPromise = control.getIntentResult(intentResolution); @@ -70,7 +71,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentChannelResult = "(2.0-RaiseIntentChannelResult) IntentResult resolves to a Channel object"; it(RaiseIntentChannelResult, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext(ContextType.testContextZ, 5000); + let receiver = control.receiveContext(ControlContextType.sharedTestingIntent2ResultSent, constants.WaitTime); const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, { appId: IntentApp.IntentAppE, }); @@ -87,7 +88,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentPrivateChannelResult = "(2.0-RaiseIntentPrivateChannelResult) IntentResult resolves to a private Channel object"; it(RaiseIntentPrivateChannelResult, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext(ContextType.testContextZ, 5000); + let receiver = control.receiveContext(ControlContextType.sharedTestingIntent2ResultSent, constants.WaitTime); const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent2, ContextType.testContextY, { appId: IntentApp.IntentAppF, }); @@ -104,7 +105,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentVoidResult61secs = "(2.0-RaiseIntentVoidResult61secs) App A receives a void IntentResult after a 61 second delay"; it(RaiseIntentVoidResult61secs, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext("aTestingIntent-listener-triggered", 64000); + let receiver = control.receiveContext(ControlContextType.aTestingIntentListenerTriggered, 64000); const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, undefined, 61000); control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); let intentResultPromise = control.getIntentResult(intentResolution); @@ -119,7 +120,7 @@ describe("fdc3.raiseIntent (Result)", () => { const RaiseIntentContextResult61secs = "(2.0-RaiseIntentContextResult61secs) IntentResult resolves to testContextY instance after a 61 second delay"; it(RaiseIntentContextResult61secs, async () => { errorListener = await control.listenForError(); - const { listenerPromise : receiver } = await control.receiveContext("sharedTestingIntent1-listener-triggered", 64000); + let receiver = control.receiveContext(ControlContextType.sharedTestingIntent1ListenerTriggered, 64000); const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextY, undefined, 61000); control.validateIntentResolution(IntentApp.IntentAppB, intentResolution); let intentResultPromise = control.getIntentResult(intentResolution); diff --git a/src/test/v2.0/advanced/fdc3.raiseIntent.ts b/src/test/v2.0/advanced/fdc3.raiseIntent.ts index c804c28d..d265d02b 100644 --- a/src/test/v2.0/advanced/fdc3.raiseIntent.ts +++ b/src/test/v2.0/advanced/fdc3.raiseIntent.ts @@ -1,6 +1,6 @@ import { ChannelError, PrivateChannel, Listener } from "fdc3_2_0"; import { assert, expect } from "chai"; -import { RaiseIntentControl2_0, IntentResultType, IntentApp, ContextType, Intent } from "../support/intent-support-2.0"; +import { RaiseIntentControl2_0, IntentResultType, IntentApp, ContextType, Intent, ControlContextType } from "../support/intent-support-2.0"; import { closeMockAppWindow } from "../fdc3-2_0-utils"; const control = new RaiseIntentControl2_0(); @@ -9,121 +9,121 @@ const control = new RaiseIntentControl2_0(); * Details on the mock apps used in these tests can be found in /mock/README.md */ export default () => - describe("fdc3.raiseIntent", () => { - let errorListener: Listener = undefined; - - afterEach(async function afterEach() { - await closeMockAppWindow(this.currentTest.title); - - if (errorListener) { - errorListener.unsubscribe(); - errorListener = undefined; - } - }); - - const RaiseIntentSingleResolve = "(2.0-RaiseIntentSingleResolve) Should start app intent-a when raising intent 'aTestingIntent1' with context 'testContextX'"; - it(RaiseIntentSingleResolve, async () => { - errorListener = await control.listenForError(); - const { listenerPromise : result } = await control.receiveContext("aTestingIntent-listener-triggered"); - const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX); - control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); - await result; - }); - - const RaiseIntentTargetedAppResolve = "(2.0-RaiseIntentTargetedAppResolve) Should start app intent-b when raising intent 'sharedTestingIntent1' with context 'testContextX'"; - it(RaiseIntentTargetedAppResolve, async () => { - errorListener = await control.listenForError(); - const { listenerPromise : result } = await control.receiveContext("sharedTestingIntent1-listener-triggered"); - const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextX, { - appId: IntentApp.IntentAppB, + describe("fdc3.raiseIntent", () => { + let errorListener: Listener = undefined; + + afterEach(async function afterEach() { + await closeMockAppWindow(this.currentTest.title); + + if (errorListener) { + errorListener.unsubscribe(); + errorListener = undefined; + } + }); + + const RaiseIntentSingleResolve = "(2.0-RaiseIntentSingleResolve) Should start app intent-a when raising intent 'aTestingIntent1' with context 'testContextX'"; + it(RaiseIntentSingleResolve, async () => { + errorListener = await control.listenForError(); + const { listenerPromise: result } = await control.receiveContext("aTestingIntent-listener-triggered"); + const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX); + control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); + await result; + }); + + const RaiseIntentTargetedAppResolve = "(2.0-RaiseIntentTargetedAppResolve) Should start app intent-b when raising intent 'sharedTestingIntent1' with context 'testContextX'"; + it(RaiseIntentTargetedAppResolve, async () => { + errorListener = await control.listenForError(); + const { listenerPromise: result } = await control.receiveContext("sharedTestingIntent1-listener-triggered"); + const intentResolution = await control.raiseIntent(Intent.sharedTestingIntent1, ContextType.testContextX, { + appId: IntentApp.IntentAppB, + }); + control.validateIntentResolution(IntentApp.IntentAppB, intentResolution); + await result; + }); + + const RaiseIntentTargetedInstanceResolveOpen = "(2.0-RaiseIntentTargetedInstanceResolveOpen) Should target running instance of intent-a app when raising intent 'aTestingIntent1' with context 'testContextX' after opening intent-a app"; + it(RaiseIntentTargetedInstanceResolveOpen, async () => { + // add app control listeners + errorListener = await control.listenForError(); + const { listenerPromise: confirmAppOpened } = await control.receiveContext("intent-app-a-opened"); + const { listenerPromise: result } = await control.receiveContext("aTestingIntent-listener-triggered"); + + const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA); + await confirmAppOpened; + + const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, appIdentifier); + await result; + control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); + const instances = await control.findInstances(IntentApp.IntentAppA); + control.validateInstances(instances, 1, appIdentifier.instanceId, (await result).instanceId); + }); + + const RaiseIntentTargetedInstanceResolveFindInstances = "(2.0-RaiseIntentTargetedInstanceResolveFindInstances) Should start app intent-a when targeted by raising intent 'aTestingIntent1' with context 'testContextX'"; + it(RaiseIntentTargetedInstanceResolveFindInstances, async () => { + // add app control listeners + errorListener = await control.listenForError(); + const { listenerPromise: confirmAppOpened } = await control.receiveContext("intent-app-a-opened"); + const { listenerPromise: result } = await control.receiveContext("aTestingIntent-listener-triggered"); + + const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA); + const instances = await control.findInstances(IntentApp.IntentAppA); + control.validateInstances(instances, 1, appIdentifier.instanceId); + await confirmAppOpened; + + const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, instances[0]); + await result; + control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); + + const instances2 = await control.findInstances(IntentApp.IntentAppA); + expect(instances2.length).to.be.equal(1); //make sure no other instance is started + }); + + const PrivateChannelsAreNotAppChannels = "(2.0-PrivateChannelsAreNotAppChannels) Cannot create an app channel using a private channel id"; + it(PrivateChannelsAreNotAppChannels, async () => { + errorListener = await control.listenForError(); + const privChan = await control.createPrivateChannel(); + control.validatePrivateChannel(privChan); + const privChan2 = await control.createPrivateChannel(); + control.validatePrivateChannel(privChan2); + + expect(privChan.id).to.not.be.equal(privChan2.id); //check that the ids of both private channels are different + try { + await control.createAppChannel(privChan.id); + assert.fail("No error was not thrown when calling fdc3.getOrCreateChannel(privateChannel.id)"); + } catch (ex) { + expect(ex).to.have.property("message", ChannelError.AccessDenied, `Incorrect error received when calling fdc3.getOrCreateChannel(privateChannel.id). Expected AccessDenied, got ${ex.message}`); + } + + const intentResolution = await control.raiseIntent(Intent.privateChannelIsPrivate, ContextType.privateChannelDetails, undefined, undefined, { key: privChan2.id }); + control.validateIntentResolution(IntentApp.IntentAppJ, intentResolution); + let result = await control.getIntentResult(intentResolution); + control.validateIntentResult(result, IntentResultType.Context, ContextType.privateChannelDetails); + }); + + const PrivateChannelsLifecycleEvents = "(2.0-PrivateChannelsLifecycleEvents) PrivateChannel lifecycle events are triggered when expected"; + it(PrivateChannelsLifecycleEvents, async () => { + errorListener = await control.listenForError(); + const { listenerPromise: onUnsubscribeReceiver } = await control.receiveContext("onUnsubscribeTriggered"); + const intentResolution = await control.raiseIntent(Intent.kTestingIntent, ContextType.testContextX, { + appId: IntentApp.IntentAppK, + }); + control.validateIntentResolution(IntentApp.IntentAppK, intentResolution); + let result = await control.getIntentResult(intentResolution); + control.validateIntentResult(result, IntentResultType.PrivateChannel); + let listener = await control.receiveContextStreamFromMockApp(result, 1, 5); + control.unsubscribeListener(listener); + await onUnsubscribeReceiver; //should receive context from privChannel.onUnsubscribe in mock app + const { listenerPromise: textContextXReceiver } = await control.receiveContext(ContextType.testContextX); + control.privateChannelBroadcast(result, ContextType.testContextX); + await textContextXReceiver; + const { listenerPromise: onUnsubscribeReceiver2 } = await control.receiveContext("onUnsubscribeTriggered"); + const { listenerPromise: onDisconnectReceiver } = await control.receiveContext("onDisconnectTriggered"); + let listener2 = await control.receiveContextStreamFromMockApp(result, 6, 10); + control.disconnectPrivateChannel(result); + + //confirm that onUnsubscribe and onDisconnect were triggered in intent-k + await onUnsubscribeReceiver2; + await onDisconnectReceiver; + control.unsubscribeListener(listener2); + }); }); - control.validateIntentResolution(IntentApp.IntentAppB, intentResolution); - await result; - }); - - const RaiseIntentTargetedInstanceResolveOpen = "(2.0-RaiseIntentTargetedInstanceResolveOpen) Should target running instance of intent-a app when raising intent 'aTestingIntent1' with context 'testContextX' after opening intent-a app"; - it(RaiseIntentTargetedInstanceResolveOpen, async () => { - // add app control listeners - errorListener = await control.listenForError(); - const { listenerPromise : confirmAppOpened } = await control.receiveContext("intent-app-a-opened"); - const { listenerPromise : result } = await control.receiveContext("aTestingIntent-listener-triggered"); - - const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA); - await confirmAppOpened; - - const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, appIdentifier); - await result; - control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); - const instances = await control.findInstances(IntentApp.IntentAppA); - control.validateInstances(instances, 1, appIdentifier.instanceId, (await result).instanceId); - }); - - const RaiseIntentTargetedInstanceResolveFindInstances = "(2.0-RaiseIntentTargetedInstanceResolveFindInstances) Should start app intent-a when targeted by raising intent 'aTestingIntent1' with context 'testContextX'"; - it(RaiseIntentTargetedInstanceResolveFindInstances, async () => { - // add app control listeners - errorListener = await control.listenForError(); - const { listenerPromise : confirmAppOpened } = await control.receiveContext("intent-app-a-opened"); - const { listenerPromise : result } = await control.receiveContext("aTestingIntent-listener-triggered"); - - const appIdentifier = await control.openIntentApp(IntentApp.IntentAppA); - const instances = await control.findInstances(IntentApp.IntentAppA); - control.validateInstances(instances, 1, appIdentifier.instanceId); - await confirmAppOpened; - - const intentResolution = await control.raiseIntent(Intent.aTestingIntent, ContextType.testContextX, instances[0]); - await result; - control.validateIntentResolution(IntentApp.IntentAppA, intentResolution); - - const instances2 = await control.findInstances(IntentApp.IntentAppA); - expect(instances2.length).to.be.equal(1); //make sure no other instance is started - }); - - const PrivateChannelsAreNotAppChannels = "(2.0-PrivateChannelsAreNotAppChannels) Cannot create an app channel using a private channel id"; - it(PrivateChannelsAreNotAppChannels, async () => { - errorListener = await control.listenForError(); - const privChan = await control.createPrivateChannel(); - control.validatePrivateChannel(privChan); - const privChan2 = await control.createPrivateChannel(); - control.validatePrivateChannel(privChan2); - - expect(privChan.id).to.not.be.equal(privChan2.id); //check that the ids of both private channels are different - try { - await control.createAppChannel(privChan.id); - assert.fail("No error was not thrown when calling fdc3.getOrCreateChannel(privateChannel.id)"); - } catch (ex) { - expect(ex).to.have.property("message", ChannelError.AccessDenied, `Incorrect error received when calling fdc3.getOrCreateChannel(privateChannel.id). Expected AccessDenied, got ${ex.message}`); - } - - const intentResolution = await control.raiseIntent(Intent.privateChannelIsPrivate, ContextType.privateChannelDetails, undefined, undefined, { key: privChan2.id }); - control.validateIntentResolution(IntentApp.IntentAppJ, intentResolution); - let result = await control.getIntentResult(intentResolution); - control.validateIntentResult(result, IntentResultType.Context, ContextType.privateChannelDetails); - }); - - const PrivateChannelsLifecycleEvents = "(2.0-PrivateChannelsLifecycleEvents) PrivateChannel lifecycle events are triggered when expected"; - it(PrivateChannelsLifecycleEvents, async () => { - errorListener = await control.listenForError(); - const {listenerPromise: onUnsubscribeReceiver } = await control.receiveContext("onUnsubscribeTriggered"); - const intentResolution = await control.raiseIntent(Intent.kTestingIntent, ContextType.testContextX, { - appId: IntentApp.IntentAppK, - }); - control.validateIntentResolution(IntentApp.IntentAppK, intentResolution); - let result = await control.getIntentResult(intentResolution); - control.validateIntentResult(result, IntentResultType.PrivateChannel); - let listener = await control.receiveContextStreamFromMockApp(result, 1, 5); - control.unsubscribeListener(listener); - await onUnsubscribeReceiver; //should receive context from privChannel.onUnsubscribe in mock app - const { listenerPromise : textContextXReceiver } = await control.receiveContext(ContextType.testContextX); - control.privateChannelBroadcast(result, ContextType.testContextX); - await textContextXReceiver; - const { listenerPromise: onUnsubscribeReceiver2 } = await control.receiveContext("onUnsubscribeTriggered"); - const { listenerPromise: onDisconnectReceiver } = await control.receiveContext("onDisconnectTriggered"); - let listener2 = await control.receiveContextStreamFromMockApp(result, 6, 10); - control.disconnectPrivateChannel(result); - - //confirm that onUnsubscribe and onDisconnect were triggered in intent-k - await onUnsubscribeReceiver2; - await onDisconnectReceiver; - control.unsubscribeListener(listener2); - }); - }); diff --git a/src/test/v2.0/support/intent-support-2.0.ts b/src/test/v2.0/support/intent-support-2.0.ts index 5e82d22b..c90313cb 100644 --- a/src/test/v2.0/support/intent-support-2.0.ts +++ b/src/test/v2.0/support/intent-support-2.0.ts @@ -13,19 +13,21 @@ export class RaiseIntentControl2_0 { let timeout; const appControlChannel = await getOrCreateChannel(constants.ControlChannel); //wrap promise so we can await this function without it having to be resolved - return { listenerPromise: new Promise(async (resolve, reject) => { - const listener = await appControlChannel.addContextListener(contextType, (context: AppControlContext) => { - resolve(context); - clearTimeout(timeout); - listener.unsubscribe(); - }); - - //if no context received reject promise - const { promise: sleepPromise, timeout: theTimeout } = sleep(waitTime ?? constants.WaitTime); - timeout = theTimeout; - await sleepPromise; - reject(new Error("No context received. Listener expected to receive context of type " + contextType + " from mock app")); - })}; + return { + listenerPromise: new Promise(async (resolve, reject) => { + const listener = await appControlChannel.addContextListener(contextType, (context: AppControlContext) => { + resolve(context); + clearTimeout(timeout); + listener.unsubscribe(); + }); + + //if no context received reject promise + const { promise: sleepPromise, timeout: theTimeout } = sleep(waitTime ?? constants.WaitTime); + timeout = theTimeout; + await sleepPromise; + reject(new Error("No context received. Listener expected to receive context of type " + contextType + " from mock app")); + }) + }; } async openIntentApp(appId): Promise { @@ -83,7 +85,7 @@ export class RaiseIntentControl2_0 { const intentResult = intentResolution.getResult(); if (typeof intentResult.then !== "function") { assert.fail(`intentResolution.getResult() did not return a Promise: ${JSON.stringify(intentResult, null, 2)}`); - } + } clearTimeout(timeout); return intentResult; } @@ -222,6 +224,20 @@ export enum ContextType { privateChannelDetails = "privateChannelDetails", } +export enum ControlContextType { + contextReceived = "context-received", + error = "error", + aTestingIntentListenerTriggered = "aTestingIntent-listener-triggered", + intentAppAOpened = "intent-app-a-opened", + sharedTestingIntent1ListenerTriggered = "sharedTestingIntent1-listener-triggered", + sharedTestingIntent2ResultSent = "sharedTestingIntent2-result-sent", + onUnsubscribeTriggered = "onUnsubscribeTriggered", + onDisconnectTriggered = "onDisconnectTriggered", + ContextListenerTriggered = "context-listener-triggered", + IntentListenerTriggered = "intent-listener-triggered", + +} + export enum Intent { aTestingIntent = "aTestingIntent", bTestingIntent = "bTestingIntent", diff --git a/src/test/v2.0/support/open-support-2.0.ts b/src/test/v2.0/support/open-support-2.0.ts index c5316b29..b8426957 100644 --- a/src/test/v2.0/support/open-support-2.0.ts +++ b/src/test/v2.0/support/open-support-2.0.ts @@ -7,6 +7,7 @@ import { AppControlContext } from "../../../context-types"; import { OpenControl } from "../../common/control/open-control"; import { APIDocumentation2_0 } from "../apiDocuments-2.0"; import { closeMockAppWindow } from "../fdc3-2_0-utils"; +import { ControlContextType } from "./intent-support-2.0"; declare let fdc3: DesktopAgent; const openDocs = "\r\nDocumentation: " + APIDocumentation2_0.open + "\r\nCause:"; @@ -58,7 +59,7 @@ export class OpenControl2_0 implements OpenControl { } addListenerAndFailIfReceived = async () => { const appControlChannel = await fdc3.getOrCreateChannel(constants.ControlChannel); - await appControlChannel.addContextListener("context-received", (context: AppControlContext) => { + await appControlChannel.addContextListener(ControlContextType.contextReceived, (context: AppControlContext) => { assert.fail(context.errorMessage); }); }; diff --git a/src/test/v2.1/advanced/fdc3.open.ts b/src/test/v2.1/advanced/fdc3.open.ts index 2d09c9d2..1ebf0b4c 100644 --- a/src/test/v2.1/advanced/fdc3.open.ts +++ b/src/test/v2.1/advanced/fdc3.open.ts @@ -5,6 +5,7 @@ import { APIDocumentation2_1 } from "../apiDocuments-2.1"; import { OpenControl2_1 } from "../support/open-support-2.1"; import { DesktopAgent } from "fdc3_2_0"; import { assert, expect } from "chai"; +import { ControlContextType } from "../../v2.0/support/intent-support-2.0"; const openDocs = "\r\nDocumentation: " + APIDocumentation2_1 + "\r\nCause:"; const control = new OpenControl2_1(); @@ -24,7 +25,7 @@ export default () => //run v2.0-only open tests const AOpensBMalformedContext = `(AOpensBMalformedContext) App B listeners receive nothing when passing a malformed context`; it(AOpensBMalformedContext, async () => { - const receiver = control.contextReceiver("context-received"); + const receiver = control.contextReceiver(ControlContextType.contextReceived); await control.openMockApp(openApp.f.name); await receiver; await control.closeMockApp(AOpensBMalformedContext);