@dxos/react-ui 0.1.35 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/lib/browser/chunk-5VRACIDE.mjs +10 -0
  2. package/dist/lib/browser/chunk-5VRACIDE.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +231 -181
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +45 -0
  7. package/dist/lib/browser/testing/index.mjs.map +7 -0
  8. package/dist/types/src/components/InvitationList/InvitationListContainer.d.ts.map +1 -1
  9. package/dist/types/src/components/InvitationList/InvitationListItem.d.ts.map +1 -1
  10. package/dist/types/src/composites/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
  11. package/dist/types/src/composites/Shell/ShellContext.d.ts.map +1 -1
  12. package/dist/types/src/panels/DevicesPanel/DevicesPanel.d.ts.map +1 -1
  13. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts +5 -5
  14. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  15. package/dist/types/src/panels/JoinPanel/view-states/InvitationAccepted.d.ts +1 -1
  16. package/dist/types/src/panels/JoinPanel/view-states/InvitationAccepted.d.ts.map +1 -1
  17. package/dist/types/src/panels/JoinPanel/view-states/InvitationAuthenticator.d.ts +2 -2
  18. package/dist/types/src/panels/JoinPanel/view-states/InvitationAuthenticator.d.ts.map +1 -1
  19. package/dist/types/src/panels/JoinPanel/view-states/InvitationInput.d.ts +2 -2
  20. package/dist/types/src/panels/JoinPanel/view-states/InvitationInput.d.ts.map +1 -1
  21. package/dist/types/src/panels/JoinPanel/view-states/InvitationRescuer.d.ts +2 -2
  22. package/dist/types/src/panels/JoinPanel/view-states/InvitationRescuer.d.ts.map +1 -1
  23. package/dist/types/src/panels/SpacePanel/SpacePanel.d.ts.map +1 -1
  24. package/dist/types/src/playwright/invitations-manager.d.ts +8 -17
  25. package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
  26. package/dist/types/src/testing/index.d.ts +2 -0
  27. package/dist/types/src/testing/index.d.ts.map +1 -0
  28. package/dist/types/src/testing/shell-manager.d.ts +16 -0
  29. package/dist/types/src/testing/shell-manager.d.ts.map +1 -0
  30. package/dist/types/src/util/invitationStatusValue.d.ts.map +1 -1
  31. package/package.json +25 -14
  32. package/src/components/InvitationList/InvitationList.tsx +2 -2
  33. package/src/components/InvitationList/InvitationListContainer.tsx +3 -2
  34. package/src/components/InvitationList/InvitationListItem.tsx +4 -8
  35. package/src/composites/JoinDialog/JoinDialog.stories.tsx +3 -12
  36. package/src/composites/Shell/Shell.tsx +4 -4
  37. package/src/composites/Shell/ShellContext.tsx +11 -8
  38. package/src/panels/DevicesPanel/DevicesPanel.tsx +3 -1
  39. package/src/panels/JoinPanel/JoinPanel.tsx +8 -8
  40. package/src/panels/JoinPanel/joinMachine.ts +108 -98
  41. package/src/panels/JoinPanel/view-states/InvitationAccepted.tsx +7 -7
  42. package/src/panels/JoinPanel/view-states/InvitationAuthenticator.tsx +14 -14
  43. package/src/panels/JoinPanel/view-states/InvitationInput.tsx +9 -9
  44. package/src/panels/JoinPanel/view-states/InvitationRescuer.tsx +10 -10
  45. package/src/panels/SpacePanel/SpacePanel.tsx +19 -4
  46. package/src/playwright/invitations-manager.ts +23 -78
  47. package/src/playwright/invitations.spec.ts +147 -139
  48. package/src/testing/index.ts +5 -0
  49. package/src/testing/shell-manager.ts +61 -0
  50. package/src/util/invitationStatusValue.ts +3 -2
@@ -3,28 +3,29 @@
3
3
  //
4
4
 
5
5
  import { expect } from 'chai';
6
- import type { Browser, ConsoleMessage, Page } from 'playwright';
6
+ import type { Browser, ConsoleMessage } from 'playwright';
7
7
  import waitForExpect from 'wait-for-expect';
8
8
 
9
9
  import { Trigger } from '@dxos/async';
10
- import type { InvitationsOptions } from '@dxos/client';
11
- import { ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
10
+ import { ConnectionState, Invitation } from '@dxos/protocols/proto/dxos/client/services';
12
11
  import { setupPage } from '@dxos/test/playwright';
13
12
 
13
+ import { ShellManager } from '../testing';
14
+
14
15
  // TODO(wittjosiah): Factor out.
15
16
  // TODO(burdon): No hard-coding of ports; reconcile all DXOS tools ports.
16
17
  const storybookUrl = (storyId: string) => `http://localhost:9009/iframe.html?id=${storyId}&viewMode=story`;
17
18
 
18
19
  export type PanelType = number | 'identity' | 'devices' | 'spaces' | 'join';
19
20
 
20
- export class InvitationsManager {
21
- page!: Page;
22
-
21
+ export class InvitationsManager extends ShellManager {
23
22
  private _initialized = false;
24
23
  private _invitationCode = new Trigger<string>();
25
- private _authenticationCode = new Trigger<string>();
24
+ private _authCode = new Trigger<string>();
26
25
 
27
- constructor(private readonly _browser: Browser) {}
26
+ constructor(private readonly _browser: Browser) {
27
+ super();
28
+ }
28
29
 
29
30
  async init() {
30
31
  if (this._initialized) {
@@ -45,24 +46,12 @@ export class InvitationsManager {
45
46
 
46
47
  async getDisplayName(id: number) {
47
48
  // TODO(wittjosiah): Update id.
48
- return this._peer(id).getByTestId('identity-list-item').nth(0).textContent();
49
+ return this.peer(id).getByTestId('identity-list-item').nth(0).textContent();
49
50
  }
50
51
 
51
52
  async getSpaceName(id: number, nth: number) {
52
53
  // TODO(wittjosiah): Update id.
53
- return this._peer(id).getByTestId('space-list-item').nth(nth).textContent();
54
- }
55
-
56
- authenticatorIsVisible(id: number, type: 'device' | 'space') {
57
- // TODO(wittjosiah): Update id.
58
- return this._peer(id)
59
- .getByTestId(`${type === 'device' ? 'halo' : 'space'}-auth-code-input`)
60
- .isVisible();
61
- }
62
-
63
- invitationFailed(id: number) {
64
- // TODO(wittjosiah): Update id.
65
- return this._peer(id).getByTestId('invitation-rescuer-reset').isVisible();
54
+ return this.peer(id).getByTestId('space-list-item').nth(nth).textContent();
66
55
  }
67
56
 
68
57
  // Actions
@@ -77,7 +66,7 @@ export class InvitationsManager {
77
66
  }
78
67
 
79
68
  async openPanel(id: number, panel: PanelType) {
80
- const peer = this._peer(id);
69
+ const peer = this.peer(id);
81
70
 
82
71
  if (typeof panel === 'number') {
83
72
  // TODO(wittjosiah): Update id.
@@ -104,7 +93,7 @@ export class InvitationsManager {
104
93
  }
105
94
 
106
95
  async createIdentity(id: number) {
107
- const createIdentity = this._peer(id).getByTestId('invitations.create-identity');
96
+ const createIdentity = this.peer(id).getByTestId('invitations.create-identity');
108
97
  // TODO(wittjosiah): Clicking on buttons wrapped in tooltips is flaky in webkit playwright.
109
98
  await createIdentity.click();
110
99
  await waitForExpect(async () => {
@@ -113,12 +102,12 @@ export class InvitationsManager {
113
102
  }
114
103
 
115
104
  async createSpace(id: number) {
116
- await this._peer(id).getByTestId('invitations.create-space').click();
105
+ await this.peer(id).getByTestId('invitations.create-space').click();
117
106
  }
118
107
 
119
- async createInvitation(id: number, type: 'device' | 'space', options?: InvitationsOptions): Promise<string> {
108
+ async createInvitation(id: number, type: 'device' | 'space', options?: Partial<Invitation>): Promise<string> {
120
109
  if (!options) {
121
- const peer = this._peer(id);
110
+ const peer = this.peer(id);
122
111
  this._invitationCode = new Trigger<string>();
123
112
  await peer.getByTestId(`${type}s-panel.create-invitation`).click();
124
113
  return this._invitationCode.wait();
@@ -139,7 +128,7 @@ export class InvitationsManager {
139
128
  }
140
129
 
141
130
  async acceptInvitation(id: number, type: 'device' | 'space', invitation: string) {
142
- const peer = this._peer(id);
131
+ const peer = this.peer(id);
143
132
  // TODO(wittjosiah): Update ids.
144
133
  if (type === 'device') {
145
134
  await peer.getByTestId('join-identity').click();
@@ -148,56 +137,12 @@ export class InvitationsManager {
148
137
  await this.page.keyboard.press('Enter');
149
138
  }
150
139
 
151
- async cancelInvitation(id: number, type: 'device' | 'space', kind: 'host' | 'guest') {
152
- const peer = this._peer(id);
153
- if (kind === 'guest') {
154
- await peer.getByTestId(`${type === 'device' ? 'halo' : 'space'}-invitation-authenticator-cancel`).click();
155
- }
156
- }
157
-
158
- async invitationInputContinue(id: number, type: 'device' | 'space') {
159
- // TODO(wittjosiah): Update ids.
160
- await this._peer(id)
161
- .getByTestId(`${type === 'device' ? 'halo' : 'space'}-invitation-input-continue`)
162
- .click();
163
- }
164
-
165
- async getAuthenticationCode(): Promise<string> {
166
- this._authenticationCode = new Trigger<string>();
167
- return await this._authenticationCode.wait();
168
- }
169
-
170
- async authenticateInvitation(id: number, type: 'device' | 'space', authenticationCode: string) {
171
- const peer = this._peer(id);
172
- // TODO(wittjosiah): Update ids.
173
- await peer.getByTestId(`${type === 'device' ? 'halo' : 'space'}-auth-code-input`).type(authenticationCode);
174
- await peer.getByTestId(`${type === 'device' ? 'halo' : 'space'}-invitation-authenticator-next`).click();
175
- }
176
-
177
- async clearAuthenticationCode(id: number, type: 'device' | 'space') {
178
- const peer = this._peer(id);
179
- // TODO(wittjosiah): Update ids.
180
- await peer.getByTestId(`${type === 'device' ? 'halo' : 'space'}-auth-code-input`).fill('');
181
- await peer.getByTestId(`${type === 'device' ? 'halo' : 'space'}-auth-code-input`).focus();
182
- }
183
-
184
- async resetInvitation(id: number) {
185
- const peer = this._peer(id);
186
- // TODO(wittjosiah): Update ids.
187
- await peer.getByTestId('invitation-rescuer-reset').click();
188
- }
189
-
190
- // TODO(wittjosiah): Remove.
191
- async doneInvitation(id: number, type: 'device' | 'space') {
192
- const peer = this._peer(id);
193
- // TODO(wittjosiah): Update ids.
194
- await peer
195
- .getByTestId(type === 'device' ? 'halo-invitation-accepted-done' : 'space-invitation-accepted-done')
196
- .click();
140
+ async getAuthCode(): Promise<string> {
141
+ this._authCode = new Trigger<string>();
142
+ return await this._authCode.wait();
197
143
  }
198
144
 
199
- // TODO(wittjosiah): Peer manager?
200
- private _peer(id: number) {
145
+ peer(id: number) {
201
146
  return this.page.getByTestId(`peer-${id}`);
202
147
  }
203
148
 
@@ -206,8 +151,8 @@ export class InvitationsManager {
206
151
  const json = JSON.parse(message.text());
207
152
  if (json.invitationCode) {
208
153
  this._invitationCode.wake(json.invitationCode);
209
- } else if (json.authenticationCode) {
210
- this._authenticationCode.wake(json.authenticationCode);
154
+ } else if (json.authCode) {
155
+ this._authCode.wake(json.authCode);
211
156
  }
212
157
  } catch {}
213
158
  }
@@ -4,10 +4,10 @@
4
4
 
5
5
  import { test } from '@playwright/test';
6
6
  import { expect } from 'chai';
7
+ import waitForExpect from 'wait-for-expect';
7
8
 
8
9
  import { sleep } from '@dxos/async';
9
- import { ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
10
- import { AuthMethod } from '@dxos/protocols/proto/dxos/halo/invitations';
10
+ import { ConnectionState, Invitation } from '@dxos/protocols/proto/dxos/client/services';
11
11
 
12
12
  import { InvitationsManager } from './invitations-manager';
13
13
 
@@ -26,74 +26,97 @@ test.describe('Invitations', () => {
26
26
  const invitation = await manager.createInvitation(0, 'device');
27
27
 
28
28
  await manager.openPanel(1, 'identity');
29
- const [authenticationCode] = await Promise.all([
30
- manager.getAuthenticationCode(),
31
- manager.acceptInvitation(1, 'device', invitation)
32
- ]);
33
- await manager.authenticateInvitation(1, 'device', authenticationCode);
34
- await manager.doneInvitation(1, 'device');
29
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(1, 'device', invitation)]);
30
+ await manager.authenticateInvitation('device', authCode, manager.peer(1));
31
+ await manager.doneInvitation('device', manager.peer(1));
35
32
 
36
33
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
37
34
  });
38
35
 
39
- // TODO(wittjosiah): Auth method not hooked up?
40
- test.skip('no auth method', async () => {
36
+ test('no auth method', async () => {
41
37
  await manager.createIdentity(0);
42
38
  await manager.openPanel(0, 'devices');
43
- const invitation = await manager.createInvitation(0, 'device', { authMethod: AuthMethod.NONE });
39
+ const invitation = await manager.createInvitation(0, 'device', { authMethod: Invitation.AuthMethod.NONE });
44
40
 
45
41
  await manager.openPanel(1, 'identity');
46
42
  await manager.acceptInvitation(1, 'device', invitation);
47
- await manager.doneInvitation(1, 'device');
43
+ await manager.doneInvitation('device', manager.peer(1));
48
44
 
49
45
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
50
46
  });
51
47
 
52
- // TODO(wittjosiah): Invalid auth code cannot retry.
53
- test.skip('invalid & retry auth code', async () => {
48
+ test('invalid & retry auth code', async () => {
54
49
  await manager.createIdentity(0);
55
50
  await manager.openPanel(0, 'devices');
56
51
  const invitation = await manager.createInvitation(0, 'device');
57
52
 
58
53
  await manager.openPanel(1, 'identity');
59
- const [authenticationCode] = await Promise.all([
60
- manager.getAuthenticationCode(),
61
- manager.acceptInvitation(1, 'device', invitation)
62
- ]);
63
- await manager.authenticateInvitation(1, 'device', '000000');
64
- await manager.clearAuthenticationCode(1, 'device');
65
- await manager.authenticateInvitation(1, 'device', authenticationCode);
66
- await manager.doneInvitation(1, 'device');
54
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(1, 'device', invitation)]);
55
+ await manager.authenticateInvitation('device', '000000', manager.peer(1));
56
+ await manager.clearAuthCode('device', manager.peer(1));
57
+ await manager.authenticateInvitation('device', authCode, manager.peer(1));
58
+ await manager.doneInvitation('device', manager.peer(1));
67
59
 
68
60
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
69
61
  });
70
62
 
71
- // TODO(wittjosiah): Invalid auth code cannot retry.
72
- test.skip('invalid & max auth code retries reached, retry invitation', async () => {});
73
-
74
- // TODO(wittjosiah): Trigger timeout.
75
- test.skip('invitation timeout & retry', async () => {
63
+ test('invalid & max auth code retries reached, retry invitation', async () => {
76
64
  await manager.createIdentity(0);
77
65
  await manager.openPanel(0, 'devices');
78
- const invitation = await manager.createInvitation(0, 'device', { timeout: 100 });
66
+ const invitation = await manager.createInvitation(0, 'device');
79
67
 
80
68
  await manager.openPanel(1, 'identity');
81
- await sleep(100);
69
+ await manager.acceptInvitation(1, 'device', invitation);
82
70
 
83
- // TODO(wittjosiah): Retry here.
71
+ await manager.authenticateInvitation('device', '000001', manager.peer(1));
72
+ await manager.clearAuthCode('device', manager.peer(1));
73
+ await manager.authenticateInvitation('device', '000002', manager.peer(1));
74
+ await manager.clearAuthCode('device', manager.peer(1));
75
+ await manager.authenticateInvitation('device', '000003', manager.peer(1));
84
76
 
85
- const [authenticationCode] = await Promise.all([
86
- manager.getAuthenticationCode(),
87
- manager.acceptInvitation(1, 'device', invitation)
88
- ]);
89
- await manager.authenticateInvitation(1, 'device', authenticationCode);
90
- await manager.doneInvitation(1, 'device');
77
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
78
+
79
+ await manager.resetInvitation(manager.peer(1));
80
+ await manager.invitationInputContinue('device', manager.peer(1));
81
+
82
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('device', manager.peer(1))]);
83
+
84
+ await manager.authenticateInvitation('device', authCode, manager.peer(1));
85
+ await manager.doneInvitation('device', manager.peer(1));
91
86
 
92
87
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
93
88
  });
94
89
 
95
- // TODO(wittjosiah): Propagate cancel to guest.
96
- test.skip('invitation cancelled by host', async () => {});
90
+ test('invitation timeout', async () => {
91
+ await manager.createIdentity(0);
92
+ await manager.openPanel(0, 'devices');
93
+ const invitation = await manager.createInvitation(0, 'device', { timeout: 10 });
94
+
95
+ await manager.openPanel(1, 'identity');
96
+ await manager.acceptInvitation(1, 'device', invitation);
97
+
98
+ // Wait for timeout to fire.
99
+ await waitForExpect(async () => {
100
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
101
+ }, 100);
102
+ });
103
+
104
+ test('invitation cancelled by host', async () => {
105
+ await manager.createIdentity(0);
106
+ await manager.openPanel(0, 'devices');
107
+ const invitation = await manager.createInvitation(0, 'device');
108
+
109
+ await manager.openPanel(1, 'identity');
110
+ await manager.acceptInvitation(1, 'device', invitation);
111
+ // Wait for invitation to connect before cancelling it.
112
+ await sleep(100);
113
+ await manager.cancelInvitation('device', 'host', manager.peer(0));
114
+
115
+ // Wait for cancellation to propagate.
116
+ await waitForExpect(async () => {
117
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
118
+ }, 100);
119
+ });
97
120
 
98
121
  test('invitation cancelled by guest & retry', async () => {
99
122
  await manager.createIdentity(0);
@@ -102,15 +125,12 @@ test.describe('Invitations', () => {
102
125
 
103
126
  await manager.openPanel(1, 'identity');
104
127
  await manager.acceptInvitation(1, 'device', invitation);
105
- await manager.cancelInvitation(1, 'device', 'guest');
106
- await manager.resetInvitation(1);
107
- await manager.invitationInputContinue(1, 'device');
108
- const [authenticationCode] = await Promise.all([
109
- manager.getAuthenticationCode(),
110
- manager.clearAuthenticationCode(1, 'device')
111
- ]);
112
- await manager.authenticateInvitation(1, 'device', authenticationCode);
113
- await manager.doneInvitation(1, 'device');
128
+ await manager.cancelInvitation('device', 'guest', manager.peer(1));
129
+ await manager.resetInvitation(manager.peer(1));
130
+ await manager.invitationInputContinue('device', manager.peer(1));
131
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('device', manager.peer(1))]);
132
+ await manager.authenticateInvitation('device', authCode, manager.peer(1));
133
+ await manager.doneInvitation('device', manager.peer(1));
114
134
 
115
135
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
116
136
  });
@@ -126,14 +146,13 @@ test.describe('Invitations', () => {
126
146
  await manager.setConnectionState(0, ConnectionState.OFFLINE);
127
147
  await sleep(100);
128
148
  await manager.setConnectionState(0, ConnectionState.ONLINE);
129
- await manager.resetInvitation(1);
130
- await manager.invitationInputContinue(1, 'device');
131
- const [authenticationCode] = await Promise.all([
132
- manager.getAuthenticationCode(),
133
- manager.clearAuthenticationCode(1, 'device')
134
- ]);
135
- await manager.authenticateInvitation(1, 'device', authenticationCode);
136
- await manager.doneInvitation(1, 'device');
149
+ // TODO(wittjosiah): Requires attempting an action to discover the network failure.
150
+ await manager.authenticateInvitation('device', '00000', manager.peer(1));
151
+ await manager.resetInvitation(manager.peer(1));
152
+ await manager.invitationInputContinue('device', manager.peer(1));
153
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('device', manager.peer(1))]);
154
+ await manager.authenticateInvitation('device', authCode, manager.peer(1));
155
+ await manager.doneInvitation('device', manager.peer(1));
137
156
 
138
157
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
139
158
  });
@@ -146,20 +165,20 @@ test.describe('Invitations', () => {
146
165
 
147
166
  await manager.openPanel(1, 'identity');
148
167
  await manager.openPanel(2, 'identity');
149
- const [authenticationCode1] = await Promise.all([
150
- manager.getAuthenticationCode(),
168
+ const [authCode1] = await Promise.all([
169
+ manager.getAuthCode(),
151
170
  manager.acceptInvitation(1, 'device', invitation1)
152
171
  ]);
153
172
  // Prevent auth code from being reused.
154
173
  await sleep(100);
155
- const [authenticationCode2] = await Promise.all([
156
- manager.getAuthenticationCode(),
174
+ const [authCode2] = await Promise.all([
175
+ manager.getAuthCode(),
157
176
  manager.acceptInvitation(2, 'device', invitation2)
158
177
  ]);
159
- await manager.authenticateInvitation(1, 'device', authenticationCode1);
160
- await manager.authenticateInvitation(2, 'device', authenticationCode2);
161
- await manager.doneInvitation(1, 'device');
162
- await manager.doneInvitation(2, 'device');
178
+ await manager.authenticateInvitation('device', authCode1, manager.peer(1));
179
+ await manager.authenticateInvitation('device', authCode2, manager.peer(2));
180
+ await manager.doneInvitation('device', manager.peer(1));
181
+ await manager.doneInvitation('device', manager.peer(2));
163
182
 
164
183
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
165
184
  expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(2));
@@ -176,12 +195,9 @@ test.describe('Invitations', () => {
176
195
 
177
196
  await manager.createIdentity(1);
178
197
  await manager.openPanel(1, 'join');
179
- const [authenticationCode] = await Promise.all([
180
- manager.getAuthenticationCode(),
181
- manager.acceptInvitation(1, 'space', invitation)
182
- ]);
183
- await manager.authenticateInvitation(1, 'space', authenticationCode);
184
- await manager.doneInvitation(1, 'space');
198
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(1, 'space', invitation)]);
199
+ await manager.authenticateInvitation('space', authCode, manager.peer(1));
200
+ await manager.doneInvitation('space', manager.peer(1));
185
201
 
186
202
  await manager.openPanel(0, 'spaces');
187
203
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -191,12 +207,12 @@ test.describe('Invitations', () => {
191
207
  await manager.createIdentity(0);
192
208
  await manager.createSpace(0);
193
209
  await manager.openPanel(0, 0);
194
- const invitation = await manager.createInvitation(0, 'space', { authMethod: AuthMethod.NONE });
210
+ const invitation = await manager.createInvitation(0, 'space', { authMethod: Invitation.AuthMethod.NONE });
195
211
 
196
212
  await manager.createIdentity(1);
197
213
  await manager.openPanel(1, 'join');
198
214
  await manager.acceptInvitation(1, 'space', invitation);
199
- await manager.doneInvitation(1, 'space');
215
+ await manager.doneInvitation('space', manager.peer(1));
200
216
 
201
217
  await manager.openPanel(0, 'spaces');
202
218
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -210,17 +226,14 @@ test.describe('Invitations', () => {
210
226
 
211
227
  await manager.createIdentity(1);
212
228
  await manager.openPanel(1, 'join');
213
- const [authenticationCode] = await Promise.all([
214
- manager.getAuthenticationCode(),
215
- manager.acceptInvitation(1, 'space', invitation)
216
- ]);
217
- await manager.authenticateInvitation(1, 'space', '000000');
229
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(1, 'space', invitation)]);
230
+ await manager.authenticateInvitation('space', '000000', manager.peer(1));
218
231
 
219
- expect(await manager.authenticatorIsVisible(1, 'space')).to.be.true;
232
+ expect(await manager.authenticatorIsVisible('space', manager.peer(1))).to.be.true;
220
233
 
221
- await manager.clearAuthenticationCode(1, 'space');
222
- await manager.authenticateInvitation(1, 'space', authenticationCode);
223
- await manager.doneInvitation(1, 'space');
234
+ await manager.clearAuthCode('space', manager.peer(1));
235
+ await manager.authenticateInvitation('space', authCode, manager.peer(1));
236
+ await manager.doneInvitation('space', manager.peer(1));
224
237
 
225
238
  await manager.openPanel(0, 'spaces');
226
239
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -236,55 +249,60 @@ test.describe('Invitations', () => {
236
249
  await manager.openPanel(1, 'join');
237
250
  await manager.acceptInvitation(1, 'space', invitation);
238
251
 
239
- await manager.authenticateInvitation(1, 'space', '000001');
240
- await manager.clearAuthenticationCode(1, 'space');
241
- await manager.authenticateInvitation(1, 'space', '000002');
242
- await manager.clearAuthenticationCode(1, 'space');
243
- await manager.authenticateInvitation(1, 'space', '000003');
252
+ await manager.authenticateInvitation('space', '000001', manager.peer(1));
253
+ await manager.clearAuthCode('space', manager.peer(1));
254
+ await manager.authenticateInvitation('space', '000002', manager.peer(1));
255
+ await manager.clearAuthCode('space', manager.peer(1));
256
+ await manager.authenticateInvitation('space', '000003', manager.peer(1));
244
257
 
245
- expect(await manager.invitationFailed(1)).to.be.true;
258
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
246
259
 
247
- await manager.resetInvitation(1);
248
- await manager.invitationInputContinue(1, 'space');
260
+ await manager.resetInvitation(manager.peer(1));
261
+ await manager.invitationInputContinue('space', manager.peer(1));
249
262
 
250
- const [authenticationCode] = await Promise.all([
251
- manager.getAuthenticationCode(),
252
- manager.clearAuthenticationCode(1, 'space')
253
- ]);
263
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('space', manager.peer(1))]);
254
264
 
255
- await manager.authenticateInvitation(1, 'space', authenticationCode);
256
- await manager.doneInvitation(1, 'space');
265
+ await manager.authenticateInvitation('space', authCode, manager.peer(1));
266
+ await manager.doneInvitation('space', manager.peer(1));
257
267
 
258
268
  await manager.openPanel(0, 'spaces');
259
269
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
260
270
  });
261
271
 
262
- // TODO(wittjosiah): Trigger timeout.
263
- test.skip('invitation timeout & retry', async () => {
272
+ test('invitation timeout', async () => {
264
273
  await manager.createIdentity(0);
265
274
  await manager.createSpace(0);
266
275
  await manager.openPanel(0, 0);
267
- const invitation = await manager.createInvitation(0, 'space', { timeout: 100 });
276
+ const invitation = await manager.createInvitation(0, 'space', { timeout: 10 });
268
277
 
269
278
  await manager.createIdentity(1);
270
279
  await manager.openPanel(1, 'join');
271
- await sleep(100);
280
+ await manager.acceptInvitation(1, 'space', invitation);
272
281
 
273
- // TODO(wittjosiah): Retry here.
282
+ // Wait for timeout to fire.
283
+ await waitForExpect(async () => {
284
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
285
+ }, 100);
286
+ });
274
287
 
275
- const [authenticationCode] = await Promise.all([
276
- manager.getAuthenticationCode(),
277
- manager.acceptInvitation(1, 'space', invitation)
278
- ]);
279
- await manager.authenticateInvitation(1, 'space', authenticationCode);
280
- await manager.doneInvitation(1, 'space');
288
+ test('invitation cancelled by host', async () => {
289
+ await manager.createIdentity(0);
290
+ await manager.createSpace(0);
291
+ await manager.openPanel(0, 0);
292
+ const invitation = await manager.createInvitation(0, 'space');
281
293
 
282
- await manager.openPanel(0, 'spaces');
283
- expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
284
- });
294
+ await manager.createIdentity(1);
295
+ await manager.openPanel(1, 'join');
296
+ await manager.acceptInvitation(1, 'space', invitation);
297
+ // Wait for invitation to connect before cancelling it.
298
+ await sleep(100);
299
+ await manager.cancelInvitation('space', 'host', manager.peer(0));
285
300
 
286
- // TODO(wittjosiah): Propagate cancel to guest.
287
- test.skip('invitation cancelled by host', async () => {});
301
+ // Wait for cancellation to propagate.
302
+ await waitForExpect(async () => {
303
+ expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
304
+ }, 100);
305
+ });
288
306
 
289
307
  test('invitation cancelled by guest & retry', async () => {
290
308
  await manager.createIdentity(0);
@@ -295,17 +313,14 @@ test.describe('Invitations', () => {
295
313
  await manager.createIdentity(1);
296
314
  await manager.openPanel(1, 'join');
297
315
  await manager.acceptInvitation(1, 'space', invitation);
298
- await manager.cancelInvitation(1, 'space', 'guest');
299
- await manager.resetInvitation(1);
300
- await manager.invitationInputContinue(1, 'space');
316
+ await manager.cancelInvitation('space', 'guest', manager.peer(1));
317
+ await manager.resetInvitation(manager.peer(1));
318
+ await manager.invitationInputContinue('space', manager.peer(1));
301
319
 
302
- const [authenticationCode] = await Promise.all([
303
- manager.getAuthenticationCode(),
304
- manager.clearAuthenticationCode(1, 'space')
305
- ]);
320
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('space', manager.peer(1))]);
306
321
 
307
- await manager.authenticateInvitation(1, 'space', authenticationCode);
308
- await manager.doneInvitation(1, 'space');
322
+ await manager.authenticateInvitation('space', authCode, manager.peer(1));
323
+ await manager.doneInvitation('space', manager.peer(1));
309
324
 
310
325
  await manager.openPanel(0, 'spaces');
311
326
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -324,14 +339,13 @@ test.describe('Invitations', () => {
324
339
  await manager.setConnectionState(0, ConnectionState.OFFLINE);
325
340
  await sleep(100);
326
341
  await manager.setConnectionState(0, ConnectionState.ONLINE);
327
- await manager.resetInvitation(1);
328
- await manager.invitationInputContinue(1, 'space');
329
- const [authenticationCode] = await Promise.all([
330
- manager.getAuthenticationCode(),
331
- manager.clearAuthenticationCode(1, 'space')
332
- ]);
333
- await manager.authenticateInvitation(1, 'space', authenticationCode);
334
- await manager.doneInvitation(1, 'space');
342
+ // TODO(wittjosiah): Requires attempting an action to discover the network failure.
343
+ await manager.authenticateInvitation('space', '00000', manager.peer(1));
344
+ await manager.resetInvitation(manager.peer(1));
345
+ await manager.invitationInputContinue('space', manager.peer(1));
346
+ const [authCode] = await Promise.all([manager.getAuthCode(), manager.clearAuthCode('space', manager.peer(1))]);
347
+ await manager.authenticateInvitation('space', authCode, manager.peer(1));
348
+ await manager.doneInvitation('space', manager.peer(1));
335
349
 
336
350
  await manager.openPanel(0, 'spaces');
337
351
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -348,20 +362,14 @@ test.describe('Invitations', () => {
348
362
  await manager.createIdentity(2);
349
363
  await manager.openPanel(1, 'join');
350
364
  await manager.openPanel(2, 'join');
351
- const [authenticationCode1] = await Promise.all([
352
- manager.getAuthenticationCode(),
353
- manager.acceptInvitation(1, 'space', invitation1)
354
- ]);
365
+ const [authCode1] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(1, 'space', invitation1)]);
355
366
  // Prevent auth code from being reused.
356
367
  await sleep(100);
357
- const [authenticationCode2] = await Promise.all([
358
- manager.getAuthenticationCode(),
359
- manager.acceptInvitation(2, 'space', invitation2)
360
- ]);
361
- await manager.authenticateInvitation(1, 'space', authenticationCode1);
362
- await manager.authenticateInvitation(2, 'space', authenticationCode2);
363
- await manager.doneInvitation(1, 'space');
364
- await manager.doneInvitation(2, 'space');
368
+ const [authCode2] = await Promise.all([manager.getAuthCode(), manager.acceptInvitation(2, 'space', invitation2)]);
369
+ await manager.authenticateInvitation('space', authCode1, manager.peer(1));
370
+ await manager.authenticateInvitation('space', authCode2, manager.peer(2));
371
+ await manager.doneInvitation('space', manager.peer(1));
372
+ await manager.doneInvitation('space', manager.peer(2));
365
373
 
366
374
  await manager.openPanel(0, 'spaces');
367
375
  expect(await manager.getSpaceName(0, 0)).to.equal(await manager.getSpaceName(1, 0));
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './shell-manager';