Skip to content

Commit

Permalink
Working to close resources
Browse files Browse the repository at this point in the history
  • Loading branch information
robmoffat committed Jul 17, 2024
1 parent f390843 commit 39279cf
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 65 deletions.
2 changes: 1 addition & 1 deletion packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function getAgentAPI(optionsOverride?: Options): Promise<DesktopAgent> {
const DEFAULT_OPTIONS: Options = {
setWindowGlobal: false,
fireFdc3Ready: false,
strategies: [postMessage, electronEvent],
strategies: [electronEvent, postMessage],
frame: globalThis.window.opener ?? globalThis.window.parent,
waitForMs: DEFAULT_WAIT_FOR_MS,
}
Expand Down
101 changes: 54 additions & 47 deletions packages/client/test/features/desktop-agent-strategy.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +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 a promise of "{dummy-api}"
And a browser document in "document" and window in "window"
# Scenario: Running inside a Browser and using post message with direct message ports
# Given Parent Window desktop "da" listens for postMessage events in "{window}", returns direct message response
# And we wait for a period of "200" ms
# And I call getAgentAPI for a promise result with the following options
# | setWindowGlobal | fireFdc3Ready |
# | true | true |
# And I refer to "{result}" as "theAPIPromise"
# 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 | cucumber-provider |
# And I refer to "{document.body.children[0]}" as "channel-selector"
# And I refer to "{channel-selector.children[0]}" as "iframe"
# Then "{iframe}" is an object with the following contents
# | tag | atts.name | atts.src | style.width | style.height |
# | iframe | FDC3 Channel Selector | http://localhost:4000/channel_selector.html | 100% | 100% |
# And "{window.fdc3}" is not null
# And "{window.events}" is an array of objects with the following contents
# | type | data.type | data.methods | data.method |
# | message | FDC3-API-Request | post-message | {null} |
# | message | FDC3-API-Response | {null} | message-port |
# | fdc3Ready | {null} | {null} | {null} |
# Then I close "{document}"

Scenario: Running inside a Browser and using post message with direct message ports
Given Parent Window desktop "da" listens for postMessage events in "{window}", returns direct message response
And we wait for a period of "200" ms
And I call getAgentAPI for a promise result with the following options
| setWindowGlobal | fireFdc3Ready |
| true | true |
And I refer to "{result}" as "theAPIPromise"
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 | cucumber-provider |
And I refer to "{document.body.children[0]}" as "channel-selector"
And I refer to "{channel-selector.children[0]}" as "iframe"
Then "{iframe}" is an object with the following contents
| tag | atts.name | atts.src | style.width | style.height |
| iframe | FDC3 Channel Selector | http://localhost:4000/channel_selector.html | 100% | 100% |
And "{window.fdc3}" is not null
And "{window.events}" is an array of objects with the following contents
| type | data.type | data.methods | data.method |
| message | FDC3-API-Request | post-message | {null} |
| message | FDC3-API-Response | {null} | message-port |
| fdc3Ready | {null} | {null} | {null} |
Then I call "{document}" with "shutdown"

Scenario: Running inside a Browser using the embedded iframe strategy
Given Parent Window desktop "da" listens for postMessage events in "{window}", returns iframe response
Expand Down Expand Up @@ -58,26 +59,32 @@ Feature: Different Strategies for Accessing the Desktop Agent
| message | FDC3-Port-Transfer-Response | {null} | {null} | {null} |
| fdc3Ready | {null} | {null} | {null} | {null} |
Then I call "{document}" with "shutdown"
# 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 "500" 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 Strategy.
# In this case, neither the window.fdc3 object nor the postMessage API is available, so the fallback strategy is used.
# This results in a da-proxy which has the provider name "None"
# Given I call getAgentAPI for a promise result with the following options
# | fallbackStrategy | waitForMs |
# | {dummyFailover} | 1000 |
# And I refer to "{result}" as "theAPIPromise"
# 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 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 "500" 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 |
Then I call "{document}" with "shutdown"

Scenario: Failover Strategy.
In this case, neither the window.fdc3 object nor the postMessage API is available, so the fallback strategy is used.
This results in a da-proxy which has the provider name "None"

Given I call getAgentAPI for a promise result with the following options
| fallbackStrategy | waitForMs |
| {dummyFailover} | 1000 |
And I refer to "{result}" as "theAPIPromise"
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 |
Then I call "{document}" with "shutdown"
21 changes: 8 additions & 13 deletions packages/client/test/support/MockDocument.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FDC3_PORT_TRANSFER_RESPONSE_TYPE } from "@kite9/fdc3-common"
import { EMBED_URL, ServerDetails, buildFDC3ServerInstance } from "./MockFDC3Server"
import { EMBED_URL, MockFDC3Server, buildConnection } from "./MockFDC3Server"
import { CustomWorld } from "../world"
import { DesktopAgent } from "@finos/fdc3"

Expand Down Expand Up @@ -61,6 +61,7 @@ export class MockWindow extends MockElement {

eventHandlers: EventHandler[] = []
events: any[] = []
serverInstance: MockFDC3Server | null = null

parent: MockWindow | null = null

Expand Down Expand Up @@ -102,13 +103,14 @@ export class MockWindow extends MockElement {
shutdown() {
this.eventHandlers = []
this.fdc3 = undefined
if (this.serverInstance) {
this.serverInstance.shutdown()
}
}
}

class MockIFrame extends MockWindow {

serverInstance: ServerDetails | null = null

constructor(tag: string, cw: CustomWorld, window: MockWindow) {
super(tag, cw)
this.parent = window
Expand All @@ -119,19 +121,12 @@ class MockIFrame extends MockWindow {
const parent = this.parent as MockWindow

if ((name == 'src') && (value.startsWith(EMBED_URL))) {
this.serverInstance = buildFDC3ServerInstance(this.cw)
const connection = buildConnection(this.cw)
parent.serverInstance?.instances.push(connection)

parent.postMessage({
type: FDC3_PORT_TRANSFER_RESPONSE_TYPE,
}, parent.location.origin, [this.serverInstance.externalPort!!])
}
}

shutdown(): void {
super.shutdown()
if (this.serverInstance) {
this.serverInstance.channel.port1.close()
this.serverInstance.channel.port2.close()
}, parent.location.origin, [connection.externalPort!!])
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions packages/client/test/support/MockFDC3Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ const appChecker: AppChecker = _o => { return dummyInstanceId }

export const EMBED_URL = "http://localhost:8080/static/da/embed.html"

export type ServerDetails = {
export type ConnectionDetails = {
externalPort: MessagePort,
channel: MessageChannel,
server: DefaultFDC3Server
}

export function buildFDC3ServerInstance(world: CustomWorld): ServerDetails {
export function buildConnection(world: CustomWorld): ConnectionDetails {
const channel = new MessageChannel()
channel.port2.start()

Expand All @@ -35,7 +35,7 @@ export function buildFDC3ServerInstance(world: CustomWorld): ServerDetails {

export class MockFDC3Server {

private instances: ServerDetails[] = []
instances: ConnectionDetails[] = []
private useIframe: boolean
private window: MockWindow
private world: CustomWorld
Expand All @@ -45,6 +45,7 @@ export class MockFDC3Server {
this.window = window
this.world = world
this.init()
this.window.serverInstance = this
}

shutdown() {
Expand All @@ -67,7 +68,7 @@ export class MockFDC3Server {

portResolver = (_o: Window, _a: any) => {
if (!this.useIframe) {
const details = buildFDC3ServerInstance(this.world)
const details = buildConnection(this.world)
this.instances.push(details)
return details.externalPort
} else {
Expand Down

0 comments on commit 39279cf

Please sign in to comment.