Skip to content

Commit

Permalink
testing post-message connection
Browse files Browse the repository at this point in the history
  • Loading branch information
robmoffat committed Jul 12, 2024
1 parent 465c126 commit 3e2c016
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 1,639 deletions.
14 changes: 0 additions & 14 deletions .release-it.json

This file was deleted.

30 changes: 8 additions & 22 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,19 @@
"dependencies": {
"@finos/fdc3": "^2.1.0-beta.6",
"@kite9/da-proxy": "workspace:*",
"@kite9/fdc3-common": "workspace:*"
"@kite9/da-server": "workspace:*",
"@kite9/fdc3-common": "workspace:*",
"@types/uuid": "^10.0.0",
"uuid": "^10.0.0"
},
"devDependencies": {
"@cucumber/cucumber": "10.3.1",
"@cucumber/html-formatter": "11.0.4",
"@cucumber/pretty-formatter": "1.0.0-alpha.0",
"@kite9/testing": "workspace:*",
"@types/expect": "24.3.0",
"@types/lodash": "4.14.167",
"@types/node": "14.14.20",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "4.12.0",
"@typescript-eslint/parser": "4.12.0",
"cucumber-console-formatter": "1.0.0",
"eslint": "7.17.0",
"eslint-config-prettier": "7.1.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-prettier": "3.3.1",
"expect": "^29.7.0",
"is-ci": "2.0.0",
"jsonpath-plus": "^7.2.0",
"jsonpath-plus": "^9.0.0",
"nyc": "15.1.0",
"prettier": "2.2.1",
"rimraf": "^5.0.7",
"ts-node": "^10.9.2",
"rimraf": "^6.0.1",
"tsx": "^4.7.1",
"typescript": "^5.3.2",
"uuid": "^9.0.1"
"typescript": "^5.3.2"
}
}
}
19 changes: 9 additions & 10 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import postMessage from './strategies/post-message'

const DEFAULT_WAIT_FOR_MS = 20000;

export const DEFAULT_OPTIONS: Options = {
setWindowGlobal: false,
fireFdc3Ready: false,
strategies: [postMessage, electronEvent],
frame: globalThis.window.opener ?? globalThis.window.parent,
waitForMs: DEFAULT_WAIT_FOR_MS,
}

/**
* This return an FDC3 API. Should be called by application code.
*
* @param optionsOverride - options to override the default options
*/
export function getAgentAPI(optionsOverride: Options = DEFAULT_OPTIONS): Promise<DesktopAgent> {
export function getAgentAPI(optionsOverride?: Options): Promise<DesktopAgent> {

const DEFAULT_OPTIONS: Options = {
setWindowGlobal: false,
fireFdc3Ready: false,
strategies: [postMessage, electronEvent],
frame: globalThis.window.opener ?? globalThis.window.parent,
waitForMs: DEFAULT_WAIT_FOR_MS,
}

const options = {
...DEFAULT_OPTIONS,
Expand Down Expand Up @@ -65,7 +65,6 @@ export function getAgentAPI(optionsOverride: Options = DEFAULT_OPTIONS): Promise
*/
export function fdc3Ready(waitForMs = DEFAULT_WAIT_FOR_MS): Promise<DesktopAgent> {
return getAgentAPI({
...DEFAULT_OPTIONS,
waitForMs,
setWindowGlobal: true,
fireFdc3Ready: true
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/strategies/post-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const loader: Loader = (options: Options) => {

const out = new Promise<DesktopAgent>((resolve, reject) => {
// setup listener for message and retrieve JS URL from it
window.addEventListener("message", (event) => {
globalThis.window.addEventListener("message", (event) => {
const data: APIResponseMessage = event.data;
if ((data.type == FDC3_API_RESPONSE_MESSAGE_TYPE) && (data.method == 'message-port')) {
return resolve(messagePortInit(event, options));
Expand Down
49 changes: 22 additions & 27 deletions packages/client/test/features/desktop-agent-strategy.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,31 @@ Feature: Different Strategies for Accessing the Desktop Agent
Given A Dummy Desktop Agent in "dummy-api"
And "dummyFailover" is a function which returns "{dummy-api}"

Scenario: Running inside an Electron Container
In this scenario, window.fdc3 is set by the electron container and returned by getAgentAPI

Given I call getAgentAPI for a promise result
And I refer to "result" as "theAPIPromise"
And we wait for a period of "200" ms
And `window.fdc3` is injected into the runtime with the value in "{dummy-api}"
Then the promise "{theAPIPromise}" should resolve
And I call "{result}" with "getInfo"
Then "{result}" is an object with the following contents
| fdc3Version | appMetadata.appId | provider |
| 2.0 | Test App Id | None |

Scenario: Running inside a Browser and using post message
Given I call "getAgentAPI"
Given Parent Window listens for postMessage events
Given I call getAgentAPI for a promise result
And I refer to "{result}" as "theAPIPromise"
Then postMessage is sent with the following contents
And I receive a postMessage message with the following contents
| blah | blah |
| thing | thang |
And we wait for a period of "200" ms
Then the promise "{theAPIPromise}" should resolve
And "{result.getInfo()}" should be an object with the following fields
| blah | blah |
| thing | thang |

Scenario: Failover desktop agent
Given I call "getAgentAPI" with the following options
| failover | waitTimeMs |
| {dummyFailover} | 1000 |
Then the promise "{theAPIPromise}" should resolve
And "{result.getInfo()}" should be an object with the following fields
| blah | blah |
| dummy | thang |
# Scenario: Running inside an Electron Container
# In this scenario, window.fdc3 is set by the electron container and returned by getAgentAPI
# Given I call getAgentAPI for a promise result
# And I refer to "result" as "theAPIPromise"
# And we wait for a period of "200" ms
# And `window.fdc3` is injected into the runtime with the value in "{dummy-api}"
# Then the promise "{theAPIPromise}" should resolve
# And I call "{result}" with "getInfo"
# Then "{result}" is an object with the following contents
# | fdc3Version | appMetadata.appId | provider |
# | 2.0 | Test App Id | None |
# Scenario: Failover desktop agent
# Given I call "getAgentAPI" with the following options
# | failover | waitTimeMs |
# | {dummyFailover} | 1000 |
# Then the promise "{theAPIPromise}" should resolve
# And "{result.getInfo()}" should be an object with the following fields
# | blah | blah |
# | dummy | thang |
53 changes: 52 additions & 1 deletion packages/client/test/step-definitions/desktop-agent.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { CustomWorld } from '../world';
import { TestMessaging } from '../support/TestMessaging';
import { handleResolve, setupGenericSteps, SimpleIntentResolver } from '@kite9/testing';
import { BasicDesktopAgent, DefaultChannelSupport, DefaultIntentSupport, NoopAppSupport, NoopHandshakeSupport } from '@kite9/da-proxy';
import { desktopAgentSupplier } from '@kite9/da-server';


type EventHandler = {
type: string,
Expand All @@ -11,8 +13,16 @@ type EventHandler = {

class MockWindow {

name: string

constructor(name: string) {
this.name = name
}

eventHandlers: EventHandler[] = []

parent: MockWindow | null = null

addEventListener(type: string, callback: (e: Event) => void): void {
this.eventHandlers.push({ type, callback })
}
Expand All @@ -24,21 +34,62 @@ class MockWindow {
}
})
}

postMessage(msg: object, targetOrigin: string | undefined, ports: MessagePort[] | undefined): void {
this.dispatchEvent({
type: 'message',
data: msg,
origin: targetOrigin,
ports,
source: this.parent ?? this // when posting from client, set source to self
} as any)
}
}

/**
* This allows us to handle fdc3.ready events
*/
globalThis.window = new MockWindow() as any
globalThis.window = new MockWindow("client") as any

/**
* Need to do this after we've set up window
*/
import { getAgentAPI } from '../../src';
import { AppChecker } from '@kite9/fdc3-common';


setupGenericSteps()

Given('Parent Window listens for postMessage events', async function (this: CustomWorld) {

const parent = new MockWindow("parent")
// sets the parent window
globalThis.window.parent = parent as any

const appChecker: AppChecker = _o => { return { appId: "app1" } }

const detailsResolver = (_o: Window, _a: any) => {
return {
apiKey: "ABC",
uri: "http://localhost:8080/static/da/embed.html",
desktopAgentId: "123",
intentResolver: null,
channelSelector: null
}
}

const portResolver = (_o: Window, _a: any) => {
const channel = new MessageChannel()
channel.port2.start()

return channel.port1
}

desktopAgentSupplier(appChecker, detailsResolver, portResolver, parent as any)


})

Given('A Dummy Desktop Agent in {string}', async function (this: CustomWorld, field: string) {

if (!this.messaging) {
Expand Down
3 changes: 3 additions & 0 deletions packages/client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
},
{
"path": "../testing"
},
{
"path": "../da-server"
}
]
}
2 changes: 1 addition & 1 deletion packages/da-proxy/test/world/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class CustomWorld extends PropsWorld {

messaging: TestMessaging | null = null

log(s: string) {
log: (s: string) => void = (s: string) => {
console.log(s)
}

Expand Down
6 changes: 3 additions & 3 deletions packages/da-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"scripts": {
"clean": "rimraf dist; rimraf generated; rimraf node_modules; rumraf coverage; rimraf .nyc_output; rimraf cucumber-report.html",
"clean": "rimraf dist; rimraf generated; rimraf node_modules; rimraf coverage; rimraf .nyc_output; rimraf cucumber-report.html",
"directory-openapi": "npx openapi-typescript https://fdc3.finos.org/schemas/2.1/appd.schema.json --output generated/directory-schema.ts",
"test": "nyc --reporter=lcov --reporter=text cucumber-js",
"test": "run directory-openapi; tsc; nyc --reporter=lcov --reporter=text cucumber-js",
"build": "run directory-openapi; tsc --module es2022"
},
"dependencies": {
Expand Down Expand Up @@ -39,7 +39,7 @@
"nyc": "15.1.0",
"openapi-typescript": "^6.7.4",
"prettier": "2.2.1",
"rimraf": "^5.0.7",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.2",
"uuid": "^9.0.1"
Expand Down
4 changes: 3 additions & 1 deletion packages/da-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BasicFDC3Server, DefaultFDC3Server } from "./BasicFDC3Server"
import { FDC3Server } from "./FDC3Server"
import { Directory, DirectoryApp, DirectoryIntent } from "./directory/DirectoryInterface"
import { BasicDirectory } from "./directory/BasicDirectory"
import { desktopAgentSupplier } from "./supply/post-message"

export {
type ServerContext,
Expand All @@ -12,5 +13,6 @@ export {
type Directory,
BasicDirectory,
type DirectoryApp,
type DirectoryIntent
type DirectoryIntent,
desktopAgentSupplier
}
7 changes: 4 additions & 3 deletions packages/da-server/src/supply/post-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { APIResponseMessage, AppChecker, DesktopAgentDetailResolver, Supplier, F
* This configures the postMessage listener to respond to requests for desktop agent APIs.
* Called by the server-side desktop agent.
*/
export const supply: Supplier = (
export const desktopAgentSupplier: Supplier = (
checker: AppChecker,
detailsResolver: DesktopAgentDetailResolver,
portResolver: DesktopAgentPortResolver = () => null) => {
portResolver: DesktopAgentPortResolver = () => null,
on: Window = globalThis.window) => {

function createResponseMessage(source: Window, appId: AppIdentifier): APIResponseMessage {
return {
Expand All @@ -34,7 +35,7 @@ export const supply: Supplier = (
}
}

window.addEventListener(
on.addEventListener(
"message",
(event) => {
const data = event.data;
Expand Down
4 changes: 2 additions & 2 deletions packages/demo/src/client/da/dummy-desktop-agent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { supply } from "@kite9/da-server/src/supply/post-message";
import { desktopAgentSupplier } from "@kite9/da-server";
import { io } from "socket.io-client"
import { v4 as uuid } from 'uuid'
import { APP_GOODBYE, DA_HELLO, FDC3_APP_EVENT } from "../../message-types";
Expand Down Expand Up @@ -60,7 +60,7 @@ window.addEventListener("load", () => {
})

// set up desktop agent handler here using FDC3 Web Loader (or whatever we call it)
supply(sc.appChecker, sc.detailsResolver, sc.portResolver)
desktopAgentSupplier(sc.appChecker, sc.detailsResolver, sc.portResolver)
})
})

3 changes: 2 additions & 1 deletion packages/fdc3-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export type AppChecker = (o: Window) => AppIdentifier | undefined;
export type Supplier = (
checker: AppChecker,
detailsResolver: DesktopAgentDetailResolver,
portResolver?: DesktopAgentPortResolver) => void;
portResolver?: DesktopAgentPortResolver,
on?: Window) => void;

export type Loader = (options: Options) => Promise<DesktopAgent>

Expand Down
Loading

0 comments on commit 3e2c016

Please sign in to comment.