diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22c59f033..996983f5e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,7 +15,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108))
* Specifications for getAgent() and Browser-Resident Desktop Agents. ([#1191](https://github.com/finos/FDC3/pull/1191))
* Specification for Preload Desktop Agents. This content was previously in the supported platforms section. It had been revised and amended to include recommended behavior related to the new validateAppIdentity() function. ([#1191](https://github.com/finos/FDC3/pull/1191))
-* Added optional validateAppIdentity() function to DesktopAgent interface. ([#1191](https://github.com/finos/FDC3/pull/1191))
* Typescript definitions for getAgent() and related types. ([#1191](https://github.com/finos/FDC3/pull/1191))
* Typescript definitions for Desktop Agent Communication Protocol (DACP). These constitute the internal "wire protocol" that the "@finos/fdc3" library uses to communicate with Browser-Resident DAs. ([#1191](https://github.com/finos/FDC3/pull/1191))
* Typescript definitions for Web Connection Protocol (WCP). These constitute the messages used to establish connectivity between "@finos/fdc3" and a Browser-Resident DA. ([#1191](https://github.com/finos/FDC3/pull/1191))
@@ -23,7 +22,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added utility functions `isStandardContextType(contextType: string)`, `isStandardIntent(intent: string)`,`getPossibleContextsForIntent(intent: StandardIntent)`. ([#1139](https://github.com/finos/FDC3/pull/1139))
* Added support for event listening outside of intent or context listnener. Added new function `addEventListener`, type `EventHandler`, enum `FDC3EventType` and interfaces `FDC3Event` and `FDC3ChannelChangedEvent`. ([#1207](https://github.com/finos/FDC3/pull/1207))
* Added new `CreateOrUpdateProfile` intent. ([#1359](https://github.com/finos/FDC3/pull/1359))
-* Added conformance tests into the FDC3 API documentation in the current version and backported into 2.0 and 2.1. Removed outdated 1.2 conformance tests (which are preserved in the older 2.0 and 2.1 versions). ([#1417](https://github.com/finos/FDC3/pull/1417)).
+* Added conformance tests into the FDC3 API documentation in the current version and back-ported into 2.0 and 2.1. Removed outdated 1.2 conformance tests (which are preserved in the older 2.0 and 2.1 versions). ([#1417](https://github.com/finos/FDC3/pull/1417)).
+* Added conformance tests to documentation for features introduced in FDC3 2.2 (`fdc3.addEventListener`, `PrivateChannel.addEventListener` and `getAgent`). ([#1425](https://github.com/finos/FDC3/pull/1425))
### Changed
diff --git a/docs/api/conformance/App-Channel-Tests.md b/docs/api/conformance/App-Channel-Tests.md
index 00e809723..cb85a10d5 100644
--- a/docs/api/conformance/App-Channel-Tests.md
+++ b/docs/api/conformance/App-Channel-Tests.md
@@ -55,7 +55,7 @@ hide_title: true
| B | 2. Retrieve `Channel` | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|
| B | 3. Broadcast | B broadcasts both the instrument context and a contact context, using:
`testChannel.broadcast()`
`testChannel.broadcast()` |
| A | 4. Add Context Listener | A adds a context listener to the channel _after_ B has completed all its broadcasts, via:
`await testChannel.addContextListener("fdc3.instrument", handler)`
Ensure that A does NOT receive any context via these listeners (past context is only retrieved via a `getCurrentContext()` call on App channels). |
-| A | 5. Retrieve Current Context | A is able to retrieve the most recent context of each context type from the `Channel` via:
`const instrument = await testChannel.getCurrentContext('fdc3.instrument')`
`const contact = await testChannel.getCurrentContext('fdc3.contact')`
Ensure that both contexts retrieved by A are identical to those sent by B|
+| A | 5. Retrieve Current Context | A is able to retrieve the most recent context of each context type from the `Channel` via:
`const instrument = await testChannel.getCurrentContext("fdc3.instrument")`
`const contact = await testChannel.getCurrentContext("fdc3.contact")`
Ensure that both contexts retrieved by A are identical to those sent by B|
- `ACContextHistoryTyped`: Perform above test.
- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types. Ensure that only the last version of each type is received by **A**.
diff --git a/docs/api/conformance/Basic-Tests.md b/docs/api/conformance/Basic-Tests.md
index 2d6055eb7..bfa6466ec 100644
--- a/docs/api/conformance/Basic-Tests.md
+++ b/docs/api/conformance/Basic-Tests.md
@@ -10,14 +10,27 @@ hide_title: true
_These are some basic sanity tests implemented in the FDC3 Conformance Framework. It is expected that Desktop Agent testers will run these first before commencing the much more thorough tests in section 2 onwards._
+## Connection
+
+![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface was introduced to support Browser-based FDC3 Desktop Agents, known as a 'Desktop Agent Proxy', and a new [`getAgent`](../ref/GetAgent) API call was introduced to all apps to retrieve the Desktop Agent API via that interface or the existing 'Desktop Agent Preload' interface. This test pack checks that the a connection is made correctly via `getAgent`.
+
+| App | Step | Description |
+|-----|-----------------|----------------------------------------------------------|
+| A | `getAgent` | App A calls `getAgent` and waits for the promise to resolve to a `DesktopAgent` instance. |
+| A | `getInfo` | App A can call the `getInfo()` method on the `DesktopAgent` instance to get the `ImplementationMetadata` object.
Check that fdc3Version is set to 2.2.
Check that provider and providerVersion are populated. |
+| A | `getUserChannels`| App A can call the `getUserChannels()` method on the `DesktopAgent` instance to get the `Channel` objects representing the system channels.
Check **user** channels are returned.|
+
+- `GetAgentAPI`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.
+
+## Basic API Usage
+
- `BasicCL1`: A context listener can be created for a specific context type by calling `fdc3.addContextListener("fdc3.contact",)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.
- `BasicCL2`: An **unfiltered** context listener can be created by calling `fdc3.addContextListener(null,)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.
- `BasicIL1`: An intent listener can be created for a specific intent by calling `fdc3.addIntentListener(,)`. A `Listener` object is returned and can be used to remove the listener again by calling its `unsubscribe` function.
- `BasicGI1`: An `ImplementationMetadata` object can be retrieved, to find out the version of FDC3 that is in use along with details of the provider, by calling:
- - `await fdc3.getInfo()`.w The FDC3 version should match the API version being tested for conformance.
-- `BasicAC1`: A named 'App' channel can be retrieved via the `fdc3.getOrCreateChannel()` function. The `Channel` object returned conforms to the defined interface.
-- `BasicUC1`: The list available user/system channels can be retrieved as an array of `Channel` Objects conforming to the defined interface. The API call is:
- - `await fdc3.getUserChannels()`
+ - `await fdc3.getInfo()`. The FDC3 version should match the API version being tested for conformance.
+- `BasicAC1`: A named 'App' channel can be retrieved by calling `fdc3.getOrCreateChannel()`. The `Channel` object returned conforms to the defined interface.
+- `BasicUC1`: The list available user/system channels can be retrieved, as an array of `Channel` Objects conforming to the defined interface, by calling `await fdc3.getUserChannels()`.
- `BasicJC1`: A user/system channel can be joined with the with the channel's id by calling `fdc3.joinUserChannel()`. Having done so, the current channel, retrieved by calling `fdc3.getCurrentChannel()` should NOT be null and should match _the channel id given_. After leaving the current channel by calling `fdc3.leaveCurrentChannel()`, it should go back to being `null`.
- `BasicRI1`: A specified intent can be raised by invoking `fdc3.raiseIntent(, )`. A promise should be returned.
- `BasicRI2`: An intent can be raised for some item of context by invoking: `fdc3.raiseIntentForContext()`. A promise should be returned.
diff --git a/docs/api/conformance/Intents-Tests.md b/docs/api/conformance/Intents-Tests.md
index c567cf9b7..8c951ffe0 100644
--- a/docs/api/conformance/Intents-Tests.md
+++ b/docs/api/conformance/Intents-Tests.md
@@ -27,17 +27,17 @@ You will need to pre-populate the AppDirectory with the following items (some of
| App | Usage | ListensFor `(pattern: intent([context-types…]) (=> result-type)`) | On Startup |
|-----|-------------------------------------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|
-| A | Raise Intent tests without results | `aTestingIntent(testContextX,testContextZ)`
`sharedTestingIntent1(testContextX)` | addIntentListener() for given intents |
-| B | Raise Intent tests with Context results | `bTestingIntent(testContextY)`
`sharedTestingIntent1(testContextX, testContextY) => testContextY` | addIntentListener() for given intents |
-| C | Find Intent tests (never started) | `cTestingIntent(testContextX) => testContextZ` | addIntentListener() for given intents |
-| D | Find Intent tests (never started) | `sharedTestingIntent2(testContextX) => testContextZ` | addIntentListener() for given intents |
-| E | Find Intent & Raise Intent with Channel result | `sharedTestingIntent2(testContextY) => channel` | addIntentListener() for given intents |
-| F | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel` * | addIntentListener() for given intents |
-| G | Find Intent tests (never started) | `sharedTestingIntent2(testContextY)` | addIntentListener() for given intents |
+| A | Raise Intent tests without results | `aTestingIntent(testContextX,testContextZ)`
`sharedTestingIntent1(testContextX)` | `addIntentListener()` for given intents |
+| B | Raise Intent tests with Context results | `bTestingIntent(testContextY)`
`sharedTestingIntent1(testContextX, testContextY) => testContextY` | `addIntentListener()` for given intents |
+| C | Find Intent tests (never started) | `cTestingIntent(testContextX) => testContextZ` | `addIntentListener()` for given intents |
+| D | Find Intent tests (never started) | `sharedTestingIntent2(testContextX) => testContextZ` | `addIntentListener()` for given intents |
+| E | Find Intent & Raise Intent with Channel result | `sharedTestingIntent2(testContextY) => channel` | `addIntentListener()` for given intents |
+| F | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel` * | `addIntentListener()` for given intents |
+| G | Find Intent tests (never started) | `sharedTestingIntent2(testContextY)` | `addIntentListener()` for given intents |
| H | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | - no action |
-| I | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | addIntentListener(‘MadeUpIntent’, handler) |
+| I | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | `addIntentListener("MadeUpIntent", handler)` |
| J | PrivateChannels are private | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult` | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |
-| K | PrivateChannel lifecycle events | `kTestingIntent(testContextX) => channel` | addIntentListener() for given intents |
+| K | PrivateChannel lifecycle events | `kTestingIntent(testContextX) => channel` | `addIntentListener()` for given intents |
NB:
@@ -186,26 +186,28 @@ Finally, please note that this is a larger set of apps than were required for 1.
## PrivateChannel Lifecycle Events
-| App | Step | Details |
-|------|---------------------------------------|---------------------------------------------------------------------------------------------------|
-| Test | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent(‘"kTestingIntent",testContextX,{appId:""})`
starts app K. |
-| K | 2. Receive Intent & Context | After starting up, K runs `fdc3.addIntentListener("kTestingIntent")` to register its listener.
It them receives `testContextX`, matching that sent by Test |
-| Test | 3. IntentResolution | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set. |
-| Test | 4. await results | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |
-| K | 5. Create PrivateChannel and setup event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,
it should then add listeners for the 3 events offered + a context listener via:
- `const listener1 = await privChan.onAddContextListener(handler1);`
- `const listener2 = await privChan.onUnsubscribe(handler2);`
- `const listener3 = await privChan.onDisconnect(handler3);`
- `const listener4 = await privChan.addContextListener("testContextX", handler4)`
it should then return the `PrivateChannel`. |
-| Test | 6. receive PrivateChannel | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is "private". |
-| Test | 7. addContextListener | Test should add a context listener to the PrivateChannel object via `const listener1 = privChan.addContextListener("testContextZ",handler)` |
-| K | 8. Receive event & broadcast context | The `onAddContextListener` handler (`listener1`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |
-| Test | 9. Unsubscribe listener | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `listener1.unsubscribe().` |
-| K | 10. Receive unsubscribe event | The event handler registered by K via `onUnsubscribe` should fire. If it does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|
-| Test | 11. Broadcast context | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |
-| K | 12. Receive context | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|
-| Test | 13. re-run addContextListener | Test should (again) add a context listener to the PrivateChannel object via `const listener2 = privChan.addContextListener("testContextZ",handler)` |
-| K | 14. Receive event & broadcast context | The `onAddContextListener` handler added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |
-| Test | 15. Disconnect | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |
-| K | 16. Receive events & cleanup | The `onUnsubscribe` handler added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, the `onDisconnect` handler also added in step 5 should fire. Once it has, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |
-
-- `2.0-PrivateChannelsLifecycleEvents`: Perform the above test.
+![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, the existing [`PrivateChannel`](../ref/PrivateChannel) lifecycle event functions (`onAddContextListener`, `onUnsubscribe` and `onDisconnect`) functions were deprecated in favour of a new [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener) function which supports events of all three types. Hence, the tests in this section have been updated to use [`addEventListener`](https://fdc3.finos.org/docs/next/api/ref/PrivateChannel#addeventlistener).
+
+| App | Step | Details |
+|------|--------------------------------------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent("kTestingIntent", testContextX, {appId: ""})`
starts app K. |
+| K | 2. Receive Intent & Context | After starting up, K runs `fdc3.addIntentListener("kTestingIntent")` to register its listener.
It them receives `testContextX`, matching that sent by Test |
+| Test | 3. IntentResolution | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set. |
+| Test | 4. await results | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |
+| K | 5. Create PrivateChannel & event listeners | K should create a `PrivateChannel` object via `const privChan = await fdc3.createPrivateChannel()`,
it should then add listeners for the 3 events offered + a context listener via:
- `const listener1 = await privChan.addEventListener("addContextListener", handler1);`
- `const listener2 = await privChan.addEventListener("unsubscribe", handler2);`
- `const listener3 = await privChan.addEventListener("disconnect", handler3);`
- `const listener4 = await privChan.addEventListener(null, handler4);`
- `const listener5 = await privChan.addContextListener("testContextX", handler5)`
it should then return the `PrivateChannel`. |
+| Test | 6. receive PrivateChannel | The promise received by Test from `resolution.getResult()` should resolve to a `PrivateChannel` object. Confirm that the `type` of the Channel object is "private". |
+| Test | 7. addContextListener | Test should add a context listener to the PrivateChannel object via `const testListener1 = privChan.addContextListener("testContextZ", contextHandler)` |
+| K | 8. Receive event & broadcast context | The handlers for both the "addContextListener" event (`handler1`) and all events (`handler4`) added in step 5 should fire after Test adds its listener. Once it has, K should broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 1-5). |
+| Test | 9. Unsubscribe listener | Test should confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then remove its context listener with `testListener1.unsubscribe().` |
+| K | 10. Receive unsubscribe event | The handlers for both the "unsubscribe" event (`handler2`) and all events registered by K (`handler4`) should fire. If either does not and the test moves to a subsequent step, K should indicate this to the test runner (failing the test).|
+| Test | 11. Broadcast context | Test should broadcast at least one `testContextX` object via the PrivateChannel (back to K). |
+| K | 12. Receive context | K should confirm receipt of the expected context. If it does not and the test moves to a subsequent step K should indicate this to the test runner (failing the test).|
+| Test | 13. re-run addContextListener | Test should (again) add a context listener to the PrivateChannel object via `const testListener2 = privChan.addContextListener("testContextZ", contextHandler)` |
+| K | 14. Receive event & broadcast context | Both the "addContextListener" event handler (`handler1`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test adds its listener. Once it has, K should again broadcast a short stream of `testContextZ` objects, with consecutive integer values in them (e.g. 6-10). |
+| Test | 15. Disconnect | Test should (again) confirm receipt of the expected context objects, in the expected order, broadcast by K. It should then disconnect from the channel with [`privChan.disconnect().`](https://fdc3.finos.org/docs/api/ref/PrivateChannel#disconnect) |
+| K | 16. Receive events & cleanup | Both the "unsubscribe" event handler (`handler2`) and handler for all events (`handler4`) added in step 5 should (again) fire after Test calls `privChan.disconnect()`. Subsequently, both the "disconnect" handler (`handler3`) and handler for all events (`handler4`) also added in step 5 should fire. Once they have, K can unsubscribe its listeners, indicate to the test runner that all steps were completed and close. |
+
+- `2.2-PrivateChannelsLifecycleEvents`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.
## Resolving Ambiguous Intents
diff --git a/docs/api/conformance/Metadata-Tests.md b/docs/api/conformance/Metadata-Tests.md
index 2909158cb..9bed3b937 100644
--- a/docs/api/conformance/Metadata-Tests.md
+++ b/docs/api/conformance/Metadata-Tests.md
@@ -16,54 +16,54 @@ You will need to pre-populate the AppDirectory with the following items:
## Retrieve `AppMetadata`
-| App | Step | Details |
-|--------|------------------|---------------------------------------------------------------------------------------------------|
-| Test | 1.getAppMetadata | Retrieve metadata for the configured app A with
`const metadata1 = await fdc3.getAppMetadata({appId:""})` |
-| Test | 2.Confirm | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set |
+| App | Step | Details |
+|--------|-------------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. getAppMetadata | Retrieve metadata for the configured app A with
`const metadata1 = await fdc3.getAppMetadata({appId:""})` |
+| Test | 2. Confirm | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. An `instanceId` should NOT be set |
- `GetAppMetadata`: perform the above steps.
## Instance Metadata
-| App | Step | Details |
-|------|-------------------|---------------------------------------------------------------------------------------------------|
-| Test | 1.Open1 | Open a first instance of App A using
`const appIdentifier1 = await fdc3.open({appId: ""})`
and confirm that its `AppIdentifier` contains an `instanceId`. |
-| Test | 2.Open2 | Open a second instance of App A using
`const appIdentifier2 = await fdc3.open({appId: ""})`
and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |
-| Test | 3.getAppMetadata1 | Retrieve metadata for the first instance of the app with
`const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |
-| Test | 4.Confirm1 | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |
-| Test | 5.getAppMetadata2 | Retrieve metadata for the second instance of the app with
`const metadata2 = fdc3.getAppMetadata(appIdentifier2)` |
-| Test | 6.Confirm2 | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2` |
+| App | Step | Details |
+|------|--------------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. Open1 | Open a first instance of App A using
`const appIdentifier1 = await fdc3.open({appId: ""})`
and confirm that its `AppIdentifier` contains an `instanceId`. |
+| Test | 2. Open2 | Open a second instance of App A using
`const appIdentifier2 = await fdc3.open({appId: ""})`
and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |
+| Test | 3. getAppMetadata1 | Retrieve metadata for the first instance of the app with
`const metadata1 = fdc3.getAppMetadata(appIdentifier1)` |
+| Test | 4. Confirm1 | Compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |
+| Test | 5. getAppMetadata2 | Retrieve metadata for the second instance of the app with
`const metadata2 = fdc3.getAppMetadata(appIdentifier2)` |
+| Test | 6. Confirm2 | An `instanceId` should be provided, confirm that it matches the one in `appIdentifier2` |
- `AppInstanceMetadata`: Perform the above steps.
## Finding Instances
-| App | Step | Details |
-|------|------------------|---------------------------------------------------------------------------------------------------|
-| Test | 1.Open1 | Open the first instance of App A using
`const appIdentifier1 = await fdc3.open({appId:""})`
and confirm that its `AppIdentifier` contains an `instanceId`. |
-| Test | 2.Open2 | Open a second instance of App A using
`const appIdentifier2 = await fdc3.open({appId:""})`
and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |
-| Test | 3.FindInstances | Retrieve details of open instances of app A with
`let instances = await fdc3.findInstances({appId:""})`
confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array. |
-| Test | 4.RaiseIntent | Use `appIdentifier1` to raise an intent and target that instance, with
`const resolution = fdc3.raiseIntent("aTestingIntent",{"type":"testContextX"},appIdentifier1)` |
-| Test | 5.Confirm1 | Check that `resolution.source` matches `appIdentifier1` |
-| A | 6.ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |
+| App | Step | Details |
+|------|-------------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. Open1 | Open the first instance of App A using
`const appIdentifier1 = await fdc3.open({appId:""})`
and confirm that its `AppIdentifier` contains an `instanceId`. |
+| Test | 2. Open2 | Open a second instance of App A using
`const appIdentifier2 = await fdc3.open({appId:""})`
and confirm that its `AppIdentifier` contains an `instanceId` and that its value differs from that returned for the first instance. |
+| Test | 3. FindInstances | Retrieve details of open instances of app A with
`let instances = await fdc3.findInstances({appId:""})`
confirm that both `appIdentifier1` and `appIdentifier2` are both present in the array. |
+| Test | 4. RaiseIntent | Use `appIdentifier1` to raise an intent and target that instance, with
`const resolution = fdc3.raiseIntent("aTestingIntent",{"type":"testContextX"},appIdentifier1)` |
+| Test | 5. Confirm1 | Check that `resolution.source` matches `appIdentifier1` |
+| A | 6. ConfirmReceipt | Ensure that the instance of app A represented by `appIdentifier1` received the raised intent |
- `FindInstances`: Perform the above steps.
## Getting Info For The Agent
-| App | Step | Details |
-|------|-----------------|---------------------------------------------------------------------------------------------------|
-| Test | 1.getInfo | Retrieve the `ImplementationMetadata` for the DesktopAgent with
- `fdc3.getInfo().then((implMetadata) => { subsequent steps }`
**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|
-| Test | 2.CheckVersion | Check that the `fdc3Version` variable is present and at or greater than:
- 2.0
(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):
`const isFDC3v2 = versionIsAtLeast(implMetadata, "2.0")` |
-| Test | 3.CheckProvider | Check that the `provider` variable is present and not an empty string |
-| Test | 4.CheckFeatures | Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values |
+| App | Step | Details |
+|------|------------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. getInfo | Retrieve the `ImplementationMetadata` for the DesktopAgent with
- `fdc3.getInfo().then((implMetadata) => { subsequent steps }`
**Note that the use of `then` is deliberate and intended to confirm that a promise returned (as this function switched from synchronous to asynchronous in 2.0)**|
+| Test | 2. CheckVersion | Check that the `fdc3Version` variable is present and at or greater than:
- 2.0
(which you can do with the [`versionIsAtLeast` function from FDC3's Methods.ts](https://github.com/finos/FDC3/blob/add64f8302c6dcdc8437cf0e245101e927b69ec2/src/api/Methods.ts#L207):
`const isFDC3v2 = versionIsAtLeast(implMetadata, "2.0")` |
+| Test | 3. CheckProvider | Check that the `provider` variable is present and not an empty string |
+| Test | 4. CheckFeatures | Check that the `optionalFeatures`, `optionalFeatures.OriginatingAppMetadata` and `optionalFeatures.UserChannelMembershipAPIs` variables are all present and that the latter two provide boolean values |
- `GetInfo1`: Perform the above steps.
-| App | Step | Details |
-|----------|-----------|---------------------------------------------------------------------------------------------------|
-| Test | 1.Open1 | Start an instance of App A with
`const appIdentifier1 = await fdc3.open({appId:""})`
retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |
-| A | 2.getInfo | Retrieve the `ImplementationMetadata` for the DesktopAgent with:
`fdc3.getInfo().then((implMetadata) => { ... subsequent steps ...}`
This should include `AppMetadata` for the retrieving app. |
-| A + Test | 3.Confirm | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |
+| App | Step | Details |
+|----------|------------|---------------------------------------------------------------------------------------------------|
+| Test | 1. Open1 | Start an instance of App A with
`const appIdentifier1 = await fdc3.open({appId:""})`
retrieve its `AppIdentifier` with instance details. Confirm that the `AppIdentifier` contains both an `appId` and `instanceId` |
+| A | 2 .getInfo | Retrieve the `ImplementationMetadata` for the DesktopAgent with:
`fdc3.getInfo().then((implMetadata) => { ... subsequent steps ...}`
This should include `AppMetadata` for the retrieving app. |
+| A + Test | 3. Confirm | Check that `implMetadata.appMetadata` contains an `appId` and `instanceId` matching that retrieved in the first step (will require transmission of the details from A to Test or vice-versa). Also compare the `AppMetadata` object to the expected definition for the fields provided above during setup and ensure that the metadata matches. |
- `GetInfo2`: Perform the above steps.
diff --git a/docs/api/conformance/Overview.md b/docs/api/conformance/Overview.md
index 7f2089c38..78dfb4465 100644
--- a/docs/api/conformance/Overview.md
+++ b/docs/api/conformance/Overview.md
@@ -9,15 +9,17 @@ hide_title: true
This section contains test definitions that are used to test for conformance of a Desktop Agent API implementation with FDC3.
-:::warning
+:::note
-Additions to the conformance tests for functionality introduced in FDC3 2.2 are still to be defined.
-
-Further, as FDC3 2.1 does not introduce changes to the Desktop Agent API, the conformance test set for FDC3 2.0 remains current at this time. Please see the [FDC3 2.1 Changelog entry](https://github.com/finos/FDC3/blob/main/CHANGELOG.md#fdc3-standard-21---2023-09-13) for more details.
+FDC3 2.2 introduces both a new interface to web-based FDC3 Desktop Agent, known as a "Desktop Agent Proxy", as an alternative to the injection of the FDC3 API at `window.fdc3`, which is now know as a "Desktop Agent Preload" interface `GetAgent`. 2.2 also introduces the [`getAgent`](../ref/GetAgent) function which can be used to connect to either interface and MUST be used by conformance testing apps to retrieve a interface (whichever is provided by the Desktop Agent being tested).
:::
-You can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.
+:::info
+
+Where tests were introduced in this version of FDC3, they are labelled with an in the header, like so: ![2.2](https://img.shields.io/badge/FDC3-2.2-purple)
+
+:::
There are currently 6 sections to the tests.
@@ -28,8 +30,4 @@ There are currently 6 sections to the tests.
- [Metadata Tests](Metadata-Tests.md)
- [Intents Tests](Intents-Tests.md)
-:::info
-
-Where tests were introduced in this version of FDC3, they are labelled with an in the header, like so: ![2.2](https://img.shields.io/badge/FDC3-2.2-purple)
-
-:::
+You can find the implementation of these tests in the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework) project.
diff --git a/docs/api/conformance/User-Channel-Tests.md b/docs/api/conformance/User-Channel-Tests.md
index ca2e95122..8051e24c2 100644
--- a/docs/api/conformance/User-Channel-Tests.md
+++ b/docs/api/conformance/User-Channel-Tests.md
@@ -10,13 +10,13 @@ hide_title: true
## Basic Broadcast
-| App | Step |Details |
-|-----|----------------------|----------------------------------------------------------------------------------|
-| A | 1.addContextListener | A adds an _unfiltered_ Context Listener using `addContextListener(null,handler)`.
A promise resolving to a `Listener` object is returned
Check that this has an `unsubscribe` method. |
-| A | 2.joinUserChannel | A joins the first available (non-global) user channel. The available Channels are retrieved with:
`fdc3.getUserChannels()`
The first channel (that does not have the id 'global') is joined with:
`fdc3.joinUserChannel()` |
-| B | 3.joinUserChannel | B joins the same channel as A, via the same process in 2. |
-| B | 4.Broadcast | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast()`.
Check a `void` promise is returned. |
-| A | 5.Receive Context | A receives the instrument object, matching the one broadcast by B. |
+| App | Step | Details |
+|-----|-----------------------|----------------------------------------------------------------------------------|
+| A | 1. addContextListener | A adds an _unfiltered_ Context Listener using `addContextListener(null,handler)`.
A promise resolving to a `Listener` object is returned
Check that this has an `unsubscribe` method. |
+| A | 2. joinUserChannel | A joins the first available (non-global) user channel. The available Channels are retrieved with:
`fdc3.getUserChannels()`
The first channel (that does not have the id 'global') is joined with:
`fdc3.joinUserChannel()` |
+| B | 3. joinUserChannel | B joins the same channel as A, via the same process in 2. |
+| B | 4. Broadcast | B broadcasts an `fdc3.instrument` context to the channel using `fdc3.broadcast()`.
Check a `void` promise is returned. |
+| A | 5. Receive Context | A receives the instrument object, matching the one broadcast by B. |
- `UCBasicUsage1` Perform above test.
- `UCBasicUsage2` Perform steps in order: 2,1,3,4,5 to confirm that the order of `joinUserChannel` and `addContextListener` calls doesn't matter.
@@ -25,13 +25,13 @@ hide_title: true
## Filtered Broadcast
-| App | Step |Details |
-|-----|----------------------|----------------------------------------------------------------------------------|
-| A | 1.addContextListener | A adds an `fdc3.instrument` _typed_ Context Listener using `addContextListener("fdc3.instrument",handler)`.
A promise resolving a `Listener` object is returned
Check that this has an `unsubscribe` function.|
-| A | 2.joinUserChannel | A joins the first available user channel using:
`getUserChannels()` Check **user** channels are returned.
Call `fdc3.joinChannel()` on the first non-global channel.|
-| B | 3.joinUserChannel | B joins the same channel as A, via the same process in 2. |
-| B | 4.Broadcast | B broadcasts:
1.`fdc3.broadcast()`.
2. `fdc3.broadcast()`
Check a `void` promise is returned. |
-| A | 5.Receive Context | A receives the `fdc3.instrument` object, matching the one broadcast by B.
Check that the `fdc3.contact` is NOT received. |
+| App | Step | Details |
+|-----|-----------------------|----------------------------------------------------------------------------------|
+| A | 1. addContextListener | A adds an `fdc3.instrument` _typed_ Context Listener using `addContextListener("fdc3.instrument",handler)`.
A promise resolving a `Listener` object is returned
Check that this has an `unsubscribe` function.|
+| A | 2. joinUserChannel | A joins the first available user channel using:
`getUserChannels()` Check **user** channels are returned.
Call `fdc3.joinChannel()` on the first non-global channel.|
+| B | 3. joinUserChannel | B joins the same channel as A, via the same process in 2. |
+| B | 4. Broadcast | B broadcasts:
1.`fdc3.broadcast()`.
2. `fdc3.broadcast()`
Check a `void` promise is returned. |
+| A | 5. Receive Context | A receives the `fdc3.instrument` object, matching the one broadcast by B.
Check that the `fdc3.contact` is NOT received. |
- `UCFilteredUsage1` Perform above test.
- `UCFilteredUsage2` Perform steps in order: 2,1,3,4,5.
@@ -40,13 +40,13 @@ hide_title: true
## Broadcast With Multiple Listeners
-| App | Step | Details |
-|-----|-----------------------|-------------------------------------------------------------------------------------------------------------|
-| A | 1.addContextListeners | A sets up two Context Listeners. One for `fdc3.instrument` and one for `fdc3.contact` by calling: `addContextListener ("fdc3.instrument",handler)`
`addContextListener("fdc3.contact",handler)`
A promise resolving a `Listener` object is returned for each.
Check that this has an `unsubscribe` method for each. |
-| A | 2.joinUserChannel | A joins the first available user channel using:
`getUserChannels()` Check **user** channels are returned.
Call `fdc3.joinChannel()` on the first non-global channel.|
-| B | 3.joinUserChannel | B joins the same channel as A, via the same process in 2. |
-| B | 4.Broadcast | `fdc3.broadcast()`
`fdc3.broadcast()` . |
-| A | 5.Receive Context | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.
A's `fdc3.contact` object matches the one broadcast by B, and arrives on the correct listener. |
+| App | Step | Details |
+|-----|------------------------|-------------------------------------------------------------------------------------------------------------|
+| A | 1. addContextListeners | A sets up two Context Listeners. One for `fdc3.instrument` and one for `fdc3.contact` by calling: `addContextListener ("fdc3.instrument",handler)`
`addContextListener("fdc3.contact",handler)`
A promise resolving a `Listener` object is returned for each.
Check that this has an `unsubscribe` method for each. |
+| A | 2. joinUserChannel | A joins the first available user channel using:
`getUserChannels()` Check **user** channels are returned.
Call `fdc3.joinChannel()` on the first non-global channel.|
+| B | 3. joinUserChannel | B joins the same channel as A, via the same process in 2. |
+| B | 4. Broadcast | `fdc3.broadcast()`
`fdc3.broadcast()` . |
+| A | 5. Receive Context | A's `fdc3.instrument` object matches the one broadcast by B, and arrives on the correct listener.
A's `fdc3.contact` object matches the one broadcast by B, and arrives on the correct listener. |
- `UCFilteredUsage5`: Perform above test.
- `UCFilteredUsage6`: Perform above test, except B will join a _different_ channel to A. Check that you _don't_ receive anything.
@@ -54,3 +54,19 @@ hide_title: true
- `UCFilteredUsageUnsubscribe`: Perform above test, except that after joining, **A** then `unsubscribe()`s from the channel using the `listener.unsubscribe` function. Check that **A** does NOT receive anything.
- `UCFilteredUsageLeave`: Perform above test, except that immediately after joining, **A** _leaves the channel_, and so receives nothing.
- `UCFilteredUsageNoJoin`: Perform the above test, but skip step 2 so that **A** does NOT join a channel. Confirm that the _current channel_ for **A** is NOT set before continuing with the rest of the test. **A** should receive nothing.
+
+## Event on channel changed
+
+![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) In FDC3 2.2, a new interface `addEventListener` function was added allowing an app to listen for events raised. In 2.2 only one event is supported, `userChannelChanged`.
+
+An FDC3 Desktop Agent MUST provide a method to set the current User Channel for an application. This is often accomplished by providing a control within the user interface of a window or frame, allowing the user to select the desired channel.
+
+As the method of setting the user channel is user interactive, it is either difficult or impossible to implement an automated test for this. Hence, manual tests should be performed as a final step in a conformance test. A separate manual test app should be provided to enable the test.
+
+| App | Step | Details |
+|---------------------|--------------------------------------------|---------|
+| ChannelChangedEvent | 1. Open the test application | A dedicated test application for FDC3ChannelChangedEvent should be opened. |
+| ChannelChangedEvent | 2. Register for `userChannelChanged` event | `await fdc3.addEventListener("userChannelChanged", handler);`
The `handler` function should log or render details of events received|
+| User | 3. Set User Channel | The user should set the current user channel of the app and change it a few times. Details of each change should be displayed by the test app. |
+
+- `2.2-ChannelChangedEvent`: ![2.2+](https://img.shields.io/badge/FDC3-2.2+-purple) Perform the above test.
diff --git a/docs/fdc3-compliance.md b/docs/fdc3-compliance.md
index 31798ef5a..56e144eb8 100644
--- a/docs/fdc3-compliance.md
+++ b/docs/fdc3-compliance.md
@@ -76,14 +76,6 @@ The FDC3 Standards include a set of [definitions for conformance tests](api/conf
The current set of tests focus on the Desktop Agent API and the interface to it. Tests are not yet defined for the App Directory API or Bridging API Parts of the FDC3 Standard, hence, conformance to those parts of the Standard must be determined manually.
-:::warning
-
-Additions to the conformance tests for functionality introduced in FDC3 2.2 are still to be defined.
-
-Further, as FDC3 2.1 does not introduce changes to the Desktop Agent API, the conformance test set for FDC3 2.0 remains current at this time. Please see the [FDC3 2.1 Changelog entry](https://github.com/finos/FDC3/blob/main/CHANGELOG.md#fdc3-standard-21---2023-09-13) for more details.
-
-:::
-
The FDC3 Conformance tests are implemented for JavaScript/TypeScript web applications by the [FDC3 Conformance Framework](https://github.com/finos/FDC3-conformance-framework). Desktop Agent implementors working with web interfaces (Desktop Agent Preload or Desktop Agent Proxy) can clone the conformance framework and run the tests locally to determine if their agent is compliant with the Standard.
Once a Desktop Agent has passed the conformance tests locally, its authors can [apply for a formal certification of compliance with the Standard from FINOS](https://github.com/finos/FDC3-conformance-framework/blob/main/instructions.md). Please note the [Terms and Conditions](https://github.com/finos/FDC3-conformance-framework/blob/main/terms-conditions/FDC3-Certified-Terms.md) of the Conformance Program.
diff --git a/website/versioned_docs/version-2.0/api/conformance/Intents-Tests.md b/website/versioned_docs/version-2.0/api/conformance/Intents-Tests.md
index ad7b69cfd..ab3dda31c 100644
--- a/website/versioned_docs/version-2.0/api/conformance/Intents-Tests.md
+++ b/website/versioned_docs/version-2.0/api/conformance/Intents-Tests.md
@@ -17,40 +17,40 @@ You will need to pre-populate the AppDirectory with the following items:
| App | Required Metadata |
|-----|------------------------------------------------------------------------------------------------------------------------------------------------------|
-| A | A’s AppD Record contains: `aTestingIntent` (with context type `testContextX`, `testContextZ`) and `sharedTestingIntent1` (with context type `testContextX`) |
-| B | B’s AppD Record contains `bTestingIntent` (with context type `testContextY`) and `sharedTestingIntent1` (with context types `testContextX` and `testContextY`) |
-| C | C’s AppD Record contains `cTestingIntent` (with context type `testContextX`) |
+| A | A"s AppD Record contains: `aTestingIntent` (with context type `testContextX`, `testContextZ`) and `sharedTestingIntent1` (with context type `testContextX`) |
+| B | B"s AppD Record contains `bTestingIntent` (with context type `testContextY`) and `sharedTestingIntent1` (with context types `testContextX` and `testContextY`) |
+| C | C"s AppD Record contains `cTestingIntent` (with context type `testContextX`) |
Also we assume a fourth app **D** that is going to discover the intents in the other 3.
### Find Intent From AppD
-- `IntentAppD`: Calls `fdc3.findIntent(‘aTestingIntent’)`. Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.
-- `WrongIntentAppD`: Calls `fdc3.findIntent(‘nonExistentIntent’)`. Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror
-- `IntentAppDRightContext`: Calls `fdc3.findIntent(‘aTestingIntent’, ‘testContextX’)`. Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.
-- `IntentAppDWrongContext`: Calls `fdc3.findIntent(‘aTestingIntent’, ‘testContextY’)`. Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror
-- `IntentAppDMultiple1`: Calls `fdc3.findIntent(‘sharedTestingIntent1’)`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.
-- `IntentAppDMultiple2`: Calls `fdc3.findIntent(‘sharedTestingIntent1’, 'testContextX')`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.
-- `IntentAppDMultiple3`: Calls `fdc3.findIntent(‘sharedTestingIntent1’, 'testContextY')`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **B** app metadata.
+- `IntentAppD`: Calls `fdc3.findIntent("aTestingIntent")`. Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.
+- `WrongIntentAppD`: Calls `fdc3.findIntent("nonExistentIntent")`. Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror
+- `IntentAppDRightContext`: Calls `fdc3.findIntent("aTestingIntent", "testContextX")`. Receives promise containing an appIntent with metadata containing `aTestingIntent` and only **A** app metadata.
+- `IntentAppDWrongContext`: Calls `fdc3.findIntent("aTestingIntent", "testContextY")`. Rejects with no apps found error https://fdc3.finos.org/docs/api/ref/Errors#resolveerror
+- `IntentAppDMultiple1`: Calls `fdc3.findIntent("sharedTestingIntent1")`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.
+- `IntentAppDMultiple2`: Calls `fdc3.findIntent("sharedTestingIntent1", 'testContextX')`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **A** and **B** app metadata.
+- `IntentAppDMultiple3`: Calls `fdc3.findIntent("sharedTestingIntent1", 'testContextY')`. Receives promise containing an appIntent with metadata containing `sharedTestingIntent` and only **B** app metadata.
### Find Intents By Context
-- `SingleContext`: Call `fdc3.findIntentsByContext(‘testContextX’)`. Should return `aTestingIntent` (app **A**), `sharedTestingIntent1` (**A**, **B**) and `cTestingIntent` (**C**) AND nothing else.
+- `SingleContext`: Call `fdc3.findIntentsByContext("testContextX")`. Should return `aTestingIntent` (app **A**), `sharedTestingIntent1` (**A**, **B**) and `cTestingIntent` (**C**) AND nothing else.
- `NoContext`: Call `fdc3.findIntentsByContext()`. Throws error of `NoAppsFound`
### Raise Intent
| App | Step | Details |
|-----|----------------|---------------------------------------------------------------------------------------------------|
-| D | 1. Raise | `fdc3.raiseIntent(‘sharedTestingIntent1’, {testContextY})`
starts app B. |
-| B | 2. Gather Context | `fdc.addIntentListener(‘sharedTestingIntent1’)`
Receives testContextY, matching that sent by D |
+| D | 1. Raise | `fdc3.raiseIntent("sharedTestingIntent1", {testContextY})`
starts app B. |
+| B | 2. Gather Context | `fdc.addIntentListener("sharedTestingIntent1")`
Receives testContextY, matching that sent by D |
- `SingleResolve1`: Perform above test
-- `TargetedResolve1`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, )` to start app A, otherwise, as above
-- `TargetedResolve2`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: ""})` to start app A, otherwise, as above
-- `TargetedResolve3`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: “”, appId: “”})` to start app B, otherwise, as above
-- `FailedResolve1-3` As with `TargetedResolve1-3`, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextY}, )` and variations. You will receive `NoAppsFound` Error
-- `FailedResolve4` As above, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, )`. You will receive `NoAppsFound` Error
+- `TargetedResolve1`: Use `fdc3.raiseIntent("aTestingIntent", {testContextX}, )` to start app A, otherwise, as above
+- `TargetedResolve2`: Use `fdc3.raiseIntent("aTestingIntent", {testContextX}, {name: ""})` to start app A, otherwise, as above
+- `TargetedResolve3`: Use `fdc3.raiseIntent("aTestingIntent", {testContextX}, {name: "", appId: ""})` to start app B, otherwise, as above
+- `FailedResolve1-3` As with `TargetedResolve1-3`, but use `fdc3.raiseIntent("aTestingIntent", {testContextY}, )` and variations. You will receive `NoAppsFound` Error
+- `FailedResolve4` As above, but use `fdc3.raiseIntent("aTestingIntent", {testContextX}, )`. You will receive `NoAppsFound` Error
## Current Intents Tests ![2.0](https://img.shields.io/badge/FDC3-2.0-blue)
@@ -81,7 +81,7 @@ You will need to pre-populate the AppDirectory with the following items (some of
| F | Find Intent & Raise Intent with PrivateChannel result | `sharedTestingIntent2(testContextY) => channel` * | addIntentListener() for given intents |
| G | Find Intent tests (never started) | `sharedTestingIntent2(testContextY)` | addIntentListener() for given intents |
| H | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | - no action |
-| I | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | addIntentListener(‘MadeUpIntent’, handler) |
+| I | Raise Intent (bad config/behavior) | `sharedTestingIntent2(testContextY) => testContextZ` | addIntentListener("MadeUpIntent", handler) |
| J | PrivateChannels are private | `privateChannelIsPrivate(privateChannelDetails) => privateChannelIsPrivateResult` | Tries to retrieve privateChannel sent in the privateChannelDetails context, fails |
| K | PrivateChannel lifecycle events | `kTestingIntent(testContextX) => channel` | addIntentListener() for given intents |
@@ -130,7 +130,7 @@ Finally, please note that this is a larger set of apps than were required for 1.
- `2.0-RaiseIntentSingleResolve`: Perform above test
- `2.0-RaiseIntentTargetedAppResolve`: Repeat the above test, but:
- - In the first step use `fdc3.raiseIntent("sharedTestingIntent1", testContextX, {"appID": ""})` to start app B,
+ - In the first step use `fdc3.raiseIntent("sharedTestingIntent1", testContextX, {"appID": ""})` to start app B,
- Otherwise, as above.
- `2.0-RaiseIntentTargetedInstanceResolveOpen`: Repeat the above test, but:
- Before the first step, use `let appIdentifier = await fdc3.open({appId: ""})` to start A and retrieve its `AppIdentifier` with instance details.
@@ -234,7 +234,7 @@ Finally, please note that this is a larger set of apps than were required for 1.
| App | Step | Details |
|-------|-----------------|---------------------------------------------------------------------------------------------------|
-| Test | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent(‘"kTestingIntent", testContextX, {appId: ""})`
starts app K. |
+| Test | 1. Raise intent | Test raises an intent with `fdc3.raiseIntent(""kTestingIntent", testContextX, {appId: ""})`
starts app K. |
| K | 2. Receive Intent & Context | After starting up, K runs `fdc3.addIntentListener("kTestingIntent")` to register its listener.
It them receives `testContextX`, matching that sent by Test |
| Test | 3. IntentResolution | The `raiseIntent` call returns an `IntentResolution` Object with an `AppIdentifier` as the `source field` with App K's `appId` and `instanceId` set. |
| Test | 4. await results | Test should `await resolution.getResult()` on the `IntentResolution` object returned in the previous step. A promise should be returned quickly. |
diff --git a/website/versioned_docs/version-2.0/api/conformance/Open-Tests.md b/website/versioned_docs/version-2.0/api/conformance/Open-Tests.md
index 85e8f0aa6..7e58228b0 100644
--- a/website/versioned_docs/version-2.0/api/conformance/Open-Tests.md
+++ b/website/versioned_docs/version-2.0/api/conformance/Open-Tests.md
@@ -14,41 +14,41 @@ hide_title: true
| A | 1. Opening App | App A calls a function (see below) to open a second app, B |
| A | 2. Check Metadata | Ensure that the correct app was opened |
-- `AOpensB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name’)`
-- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “”})`
+- `AOpensB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open("app B Name")`
+- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: ""})`
- `AOpensB3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “”, appId: “”})`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”})`
-- `AOpensB4`: ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: “”})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "", appId: ""})`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""})`
+- `AOpensB4`: ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: ""})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.
## A Fails To Open Another App
| App | Step | Description |
|-----|-----------------|----------------------------------------------------------|
| A | 1. Opening App | App A calls a function (see below) to try and open a non-existent app |
-| A | 2. Check Error Response | ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open` throws an Error with the message "App Not Found"
![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open` returns a promise that rejects with an Error with the message "App Not Found" |
+| A | 2. Check Error Response | ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open` throws an Error with the message "App Not Found"
![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open` returns a promise that rejects with an Error with the message "App Not Found" |
-- `AFailsToOpenB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘non existent app’)`
-- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “non existent app”})`
+- `AFailsToOpenB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open("non existent app")`
+- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: "non existent app"})`
- `AFailsToOpenB3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “non existent app”, appId: “non existent app”})`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”})`
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "non existent app", appId: "non existent app"})`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""})`
## A Opens B With Context
| App | Step | Description |
|-----|-----------------|----------------------------------------------------------|
| A | 1. Opening App |App A opens app B with an `fdc3.instrument` Context Object by calling a function (see below) |
-| B | 2. Receive Context | Add an untyped context listener via:
`fdc3.addContextListener(null, handler)`
B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open() call made by A |
+| B | 2. Receive Context | Add an untyped context listener via:
`fdc3.addContextListener(null, handler)`
B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open() call made by A |
-- `AOpensBWithContext1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name', )`
-- `AOpensBWithContext2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “”}, )`
+- `AOpensBWithContext1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open("app B Name", )`
+- `AOpensBWithContext2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: ""}, )`
- `AOpensBWithContext3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “”, appId: “”}, )`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”}, )`
-- `AOpensBWithSpecificContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener('fdc3.instrument', handler)`
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "", appId: ""}, )`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""}, )`
+- `AOpensBWithSpecificContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener('fdc3.instrument', handler)`
- `AOpensBMultipleListen`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener('fdc3.contact', handler)` prior to the existing `addContextListener` for `fdc3.instrument`. The correct context listener should receive the context, and the promise completes successfully.
- `AOpensBWithWrongContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.
- - Confirm that NO context is received.
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) the `fdc3.open` call throws an Error with message `AppTimeout`
+ - Confirm that NO context is received.
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) the `fdc3.open` call throws an Error with message `AppTimeout`
- ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) The promise returned to **A** by `fdc3.open` rejects with an Error with message `AppTimeout`
diff --git a/website/versioned_docs/version-2.1/api/conformance/Intents-Tests.md b/website/versioned_docs/version-2.1/api/conformance/Intents-Tests.md
index ad7b69cfd..fcecdb770 100644
--- a/website/versioned_docs/version-2.1/api/conformance/Intents-Tests.md
+++ b/website/versioned_docs/version-2.1/api/conformance/Intents-Tests.md
@@ -48,7 +48,7 @@ Also we assume a fourth app **D** that is going to discover the intents in the o
- `SingleResolve1`: Perform above test
- `TargetedResolve1`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, )` to start app A, otherwise, as above
- `TargetedResolve2`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: ""})` to start app A, otherwise, as above
-- `TargetedResolve3`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: “”, appId: “”})` to start app B, otherwise, as above
+- `TargetedResolve3`: Use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, {name: "", appId: ""})` to start app B, otherwise, as above
- `FailedResolve1-3` As with `TargetedResolve1-3`, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextY}, )` and variations. You will receive `NoAppsFound` Error
- `FailedResolve4` As above, but use `fdc3.raiseIntent(‘aTestingIntent’, {testContextX}, )`. You will receive `NoAppsFound` Error
diff --git a/website/versioned_docs/version-2.1/api/conformance/Open-Tests.md b/website/versioned_docs/version-2.1/api/conformance/Open-Tests.md
index 85e8f0aa6..bc4b87d7a 100644
--- a/website/versioned_docs/version-2.1/api/conformance/Open-Tests.md
+++ b/website/versioned_docs/version-2.1/api/conformance/Open-Tests.md
@@ -15,11 +15,11 @@ hide_title: true
| A | 2. Check Metadata | Ensure that the correct app was opened |
- `AOpensB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name’)`
-- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “”})`
+- `AOpensB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: ""})`
- `AOpensB3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “”, appId: “”})`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”})`
-- `AOpensB4`: ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: “”})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "", appId: ""})`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""})`
+- `AOpensB4`: ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) **A** uses an `AppIdentifier` to open B and retrieves an updated `AppIdentifier` with an `instanceId` set via `const instanceIdentifier = await fdc3.open({appId: ""})`. Ensure that the `appId` matches that requested and that an `instanceId` property has been set.
## A Fails To Open Another App
@@ -29,10 +29,10 @@ hide_title: true
| A | 2. Check Error Response | ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open` throws an Error with the message "App Not Found"
![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open` returns a promise that rejects with an Error with the message "App Not Found" |
- `AFailsToOpenB1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘non existent app’)`
-- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “non existent app”})`
+- `AFailsToOpenB2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: "non existent app"})`
- `AFailsToOpenB3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “non existent app”, appId: “non existent app”})`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”})`
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "non existent app", appId: "non existent app"})`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""})`
## A Opens B With Context
@@ -42,10 +42,10 @@ hide_title: true
| B | 2. Receive Context | Add an untyped context listener via:
`fdc3.addContextListener(null, handler)`
B receives an `fdc3.instrument` Context Object matching that passed to the `fdc3.open() call made by A |
- `AOpensBWithContext1`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open(‘app B Name', )`
-- `AOpensBWithContext2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: “”}, )`
+- `AOpensBWithContext2`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) **A** uses `fdc3.open({name: ""}, )`
- `AOpensBWithContext3`: **A** uses an `AppMetadata` or `AppIdentifier` to open B, via:
- - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: “”, appId: “”}, )`
- - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: “”}, )`
+ - ![1.2](https://img.shields.io/badge/FDC3-1.2-green) `fdc3.open({name: "", appId: ""}, )`
+ - ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) `fdc3.open({appId: ""}, )`
- `AOpensBWithSpecificContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform AOpensBWithContext3 but replace **B**s call with `fdc3.addContextListener('fdc3.instrument', handler)`
- `AOpensBMultipleListen`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should perform an additional `fdc3.addContextListener('fdc3.contact', handler)` prior to the existing `addContextListener` for `fdc3.instrument`. The correct context listener should receive the context, and the promise completes successfully.
- `AOpensBWithWrongContext`: ![1.2](https://img.shields.io/badge/FDC3-1.2-green) ![2.0](https://img.shields.io/badge/FDC3-2.0-blue) Perform `AOpensBWithSpecificContext` but **B** should add a context listener for the wrong context type (e.g. `fdc3.dummyType`) instead of the expected type in step 2.