@dxos/shell 0.6.13 → 0.6.14-main.2b6a0f3

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 (124) hide show
  1. package/dist/bundle/shell.mjs +12070 -15401
  2. package/dist/bundle/shell.mjs.map +1 -1
  3. package/dist/bundle/shell.umd.js +87 -94
  4. package/dist/bundle/shell.umd.js.map +1 -1
  5. package/dist/bundle/style.css +1 -1
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/react.mjs +551 -453
  8. package/dist/lib/browser/react.mjs.map +4 -4
  9. package/dist/lib/browser/testing/index.mjs +2 -7
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/types/src/components/CompoundButton/CompoundButton.stories.js +1 -1
  12. package/dist/types/src/components/CompoundButton/CompoundButton.stories.js.map +1 -1
  13. package/dist/types/src/components/IdentityList/SpaceMemberList.stories.d.ts +0 -3
  14. package/dist/types/src/components/IdentityList/SpaceMemberList.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/IdentityList/SpaceMemberList.stories.js +1 -2
  16. package/dist/types/src/components/IdentityList/SpaceMemberList.stories.js.map +1 -1
  17. package/dist/types/src/components/InvitationList/InvitationList.stories.d.ts +0 -3
  18. package/dist/types/src/components/InvitationList/InvitationList.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/InvitationList/InvitationList.stories.js +1 -2
  20. package/dist/types/src/components/InvitationList/InvitationList.stories.js.map +1 -1
  21. package/dist/types/src/components/Panel/Panel.stories.d.ts +0 -3
  22. package/dist/types/src/components/Panel/Panel.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Panel/Panel.stories.js +1 -2
  24. package/dist/types/src/components/Panel/Panel.stories.js.map +1 -1
  25. package/dist/types/src/components/Viewport/Viewport.stories.js +1 -1
  26. package/dist/types/src/components/Viewport/Viewport.stories.js.map +1 -1
  27. package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -1
  28. package/dist/types/src/composites/Shell/Shell.js +4 -3
  29. package/dist/types/src/composites/Shell/Shell.js.map +1 -1
  30. package/dist/types/src/composites/Shell/run-shell.js +1 -1
  31. package/dist/types/src/composites/Shell/run-shell.js.map +1 -1
  32. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +1 -1
  33. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
  34. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts.map +1 -1
  35. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js +7 -2
  36. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js.map +1 -1
  37. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +4 -4
  38. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
  39. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts +1 -1
  40. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts.map +1 -1
  41. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js +10 -108
  42. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js.map +1 -1
  43. package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.d.ts +8 -0
  44. package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.d.ts.map +1 -0
  45. package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.js +84 -0
  46. package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.js.map +1 -0
  47. package/dist/types/src/panels/IdentityPanel/useKubeAgentHandlers.d.ts +8 -0
  48. package/dist/types/src/panels/IdentityPanel/useKubeAgentHandlers.d.ts.map +1 -0
  49. package/dist/types/src/panels/IdentityPanel/useKubeAgentHandlers.js +119 -0
  50. package/dist/types/src/panels/IdentityPanel/useKubeAgentHandlers.js.map +1 -0
  51. package/dist/types/src/panels/JoinPanel/JoinPanel.d.ts.map +1 -1
  52. package/dist/types/src/panels/JoinPanel/JoinPanel.js +24 -16
  53. package/dist/types/src/panels/JoinPanel/JoinPanel.js.map +1 -1
  54. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.d.ts +3 -0
  55. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.d.ts.map +1 -1
  56. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js +3 -2
  57. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js.map +1 -1
  58. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts +7 -3
  59. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts.map +1 -1
  60. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  61. package/dist/types/src/panels/JoinPanel/joinMachine.js +2 -0
  62. package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
  63. package/dist/types/src/panels/JoinPanel/steps/InvitationAuthenticator.d.ts +3 -1
  64. package/dist/types/src/panels/JoinPanel/steps/InvitationAuthenticator.d.ts.map +1 -1
  65. package/dist/types/src/panels/JoinPanel/steps/InvitationAuthenticator.js +9 -6
  66. package/dist/types/src/panels/JoinPanel/steps/InvitationAuthenticator.js.map +1 -1
  67. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.d.ts.map +1 -1
  68. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js +8 -2
  69. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js.map +1 -1
  70. package/dist/types/src/panels/Panels.stories.js +1 -1
  71. package/dist/types/src/panels/Panels.stories.js.map +1 -1
  72. package/dist/types/src/panels/SpacePanel/SpacePanel.js +1 -1
  73. package/dist/types/src/panels/SpacePanel/SpacePanel.js.map +1 -1
  74. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js +1 -1
  75. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js.map +1 -1
  76. package/dist/types/src/panels/SpacePanel/SpacePanelProps.d.ts +4 -4
  77. package/dist/types/src/panels/SpacePanel/SpacePanelProps.d.ts.map +1 -1
  78. package/dist/types/src/playwright/invitations-manager.d.ts +1 -1
  79. package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
  80. package/dist/types/src/playwright/invitations-manager.js +4 -10
  81. package/dist/types/src/playwright/invitations-manager.js.map +1 -1
  82. package/dist/types/src/playwright/invitations.spec.js +31 -32
  83. package/dist/types/src/playwright/invitations.spec.js.map +1 -1
  84. package/dist/types/src/playwright/playwright.config.d.ts +2 -2
  85. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
  86. package/dist/types/src/playwright/playwright.config.js +12 -2
  87. package/dist/types/src/playwright/playwright.config.js.map +1 -1
  88. package/dist/types/src/testing/shell-manager.d.ts +1 -0
  89. package/dist/types/src/testing/shell-manager.d.ts.map +1 -1
  90. package/dist/types/src/testing/shell-manager.js +2 -7
  91. package/dist/types/src/testing/shell-manager.js.map +1 -1
  92. package/dist/types/src/translations/locales/en-US.d.ts +1 -0
  93. package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
  94. package/dist/types/src/translations/locales/en-US.js +4 -3
  95. package/dist/types/src/translations/locales/en-US.js.map +1 -1
  96. package/package.json +29 -27
  97. package/src/components/CompoundButton/CompoundButton.stories.tsx +1 -1
  98. package/src/components/IdentityList/SpaceMemberList.stories.tsx +1 -2
  99. package/src/components/InvitationList/InvitationList.stories.tsx +1 -2
  100. package/src/components/Panel/Panel.stories.tsx +1 -2
  101. package/src/components/Viewport/Viewport.stories.tsx +1 -1
  102. package/src/composites/Shell/Shell.tsx +4 -3
  103. package/src/composites/Shell/run-shell.tsx +1 -1
  104. package/src/panels/IdentityPanel/IdentityPanel.stories.tsx +7 -2
  105. package/src/panels/IdentityPanel/IdentityPanel.tsx +3 -3
  106. package/src/panels/IdentityPanel/IdentityPanelProps.ts +4 -4
  107. package/src/panels/IdentityPanel/useAgentHandlers.ts +9 -114
  108. package/src/panels/IdentityPanel/useEdgeAgentsHandlers.ts +96 -0
  109. package/src/panels/IdentityPanel/useKubeAgentHandlers.ts +128 -0
  110. package/src/panels/JoinPanel/JoinPanel.stories.tsx +3 -2
  111. package/src/panels/JoinPanel/JoinPanel.tsx +31 -9
  112. package/src/panels/JoinPanel/JoinPanelProps.ts +7 -3
  113. package/src/panels/JoinPanel/joinMachine.ts +2 -0
  114. package/src/panels/JoinPanel/steps/InvitationAuthenticator.tsx +29 -16
  115. package/src/panels/JoinPanel/steps/InvitationInput.tsx +9 -17
  116. package/src/panels/Panels.stories.tsx +1 -1
  117. package/src/panels/SpacePanel/SpacePanel.stories.tsx +1 -1
  118. package/src/panels/SpacePanel/SpacePanel.tsx +3 -3
  119. package/src/panels/SpacePanel/SpacePanelProps.ts +4 -4
  120. package/src/playwright/invitations-manager.ts +4 -8
  121. package/src/playwright/invitations.spec.ts +32 -33
  122. package/src/playwright/playwright.config.ts +13 -2
  123. package/src/testing/shell-manager.ts +4 -9
  124. package/src/translations/locales/en-US.ts +4 -3
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type cloneElement } from 'react';
5
+ import { type FC, type cloneElement } from 'react';
6
6
 
7
7
  import type { Identity } from '@dxos/react-client/halo';
8
8
  import type { Invitation, AuthenticatingInvitationObservable, InvitationResult } from '@dxos/react-client/invitations';
@@ -55,6 +55,10 @@ export type JoinPanelImplProps = Pick<
55
55
  Halo: Invitation.State;
56
56
  Space: Invitation.State;
57
57
  }>;
58
+ invitationAuthMethods?: Partial<{
59
+ Halo: Invitation.AuthMethod;
60
+ Space: Invitation.AuthMethod;
61
+ }>;
58
62
  succeededKeys?: Partial<{
59
63
  Halo: Set<string>;
60
64
  Space: Set<string>;
@@ -71,8 +75,8 @@ export type JoinPanelImplProps = Pick<
71
75
  onSpaceInvitationAuthenticate?: (authCode: string) => Promise<void> | undefined;
72
76
  onConfirmResetStorage?: () => Promise<void>;
73
77
  onCancelResetStorage?: () => void;
74
- IdentityInput?: React.FC<IdentityInputProps>;
75
- ConfirmReset?: React.FC<ConfirmResetProps>;
78
+ IdentityInput?: FC<IdentityInputProps>;
79
+ ConfirmReset?: FC<ConfirmResetProps>;
76
80
  };
77
81
 
78
82
  export interface IdentityAction {
@@ -316,6 +316,7 @@ const joinMachine = createMachine<JoinMachineContext, JoinEvent>(
316
316
  { target: 'acceptingSpaceInvitation', actions: 'log' },
317
317
  ],
318
318
  },
319
+ // TODO(wittjosiah): Remove.
319
320
  choosingIdentity: {
320
321
  initial: 'unknownAuthMethod',
321
322
  states: {
@@ -343,6 +344,7 @@ const joinMachine = createMachine<JoinMachineContext, JoinEvent>(
343
344
  deselectAuthMethod: { target: '.choosingAuthMethod', actions: 'log' },
344
345
  },
345
346
  },
347
+ // TODO(wittjosiah): Factor out to a machine handling recovery and device invitations.
346
348
  resettingIdentity: {},
347
349
  acceptingSpaceInvitation: acceptingInvitationTemplate('Space', '#join.finishingJoiningSpace'),
348
350
  finishingJoiningSpace: {
@@ -4,7 +4,9 @@
4
4
 
5
5
  import React, { type ChangeEvent, useState } from 'react';
6
6
 
7
+ import { Invitation } from '@dxos/react-client/invitations';
7
8
  import { Input, useTranslation } from '@dxos/react-ui';
9
+ import { descriptionText } from '@dxos/react-ui-theme';
8
10
  import { hexToEmoji } from '@dxos/util';
9
11
 
10
12
  import { Actions, Action, Emoji, StepHeading, Label } from '../../../components';
@@ -14,6 +16,7 @@ const pinLength = 6;
14
16
 
15
17
  export interface InvitationAuthenticatorProps extends JoinStepProps {
16
18
  Kind: 'Space' | 'Halo';
19
+ authMethod?: Invitation.AuthMethod;
17
20
  failed?: boolean;
18
21
  pending?: boolean;
19
22
  invitationId?: string;
@@ -24,6 +27,7 @@ export interface InvitationAuthenticatorProps extends JoinStepProps {
24
27
  export const InvitationAuthenticator = ({
25
28
  failed,
26
29
  Kind,
30
+ authMethod,
27
31
  active,
28
32
  pending,
29
33
  invitationId,
@@ -51,22 +55,31 @@ export const InvitationAuthenticator = ({
51
55
  })}
52
56
  >
53
57
  <Input.Label asChild>
54
- <StepHeading>{t('auth code input label')}</StepHeading>
58
+ {authMethod === Invitation.AuthMethod.SHARED_SECRET ? (
59
+ <StepHeading>{t('auth code input label')}</StepHeading>
60
+ ) : (
61
+ <>
62
+ <StepHeading className={descriptionText}>{t('authenticating label')}</StepHeading>
63
+ <div role='none' className='grow' />
64
+ </>
65
+ )}
55
66
  </Input.Label>
56
- <Input.PinInput
57
- {...{
58
- disabled,
59
- length: pinLength,
60
- onChange,
61
- inputMode: 'numeric',
62
- autoComplete: 'off',
63
- pattern: '\\d*',
64
- 'data-autofocus': `connecting${Kind}Invitation inputting${Kind}VerificationCode authenticationFailing${Kind}VerificationCode authenticating${Kind}VerificationCode`,
65
- 'data-prevent-ios-autofocus': true,
66
- 'data-testid': `${invitationType}-auth-code-input`,
67
- 'data-1p-ignore': true,
68
- }}
69
- />
67
+ {authMethod === Invitation.AuthMethod.SHARED_SECRET && (
68
+ <Input.PinInput
69
+ {...{
70
+ disabled,
71
+ length: pinLength,
72
+ onChange,
73
+ inputMode: 'numeric',
74
+ autoComplete: 'off',
75
+ pattern: '\\d*',
76
+ 'data-autofocus': `connecting${Kind}Invitation inputting${Kind}VerificationCode authenticationFailing${Kind}VerificationCode authenticating${Kind}VerificationCode`,
77
+ 'data-prevent-ios-autofocus': true,
78
+ 'data-testid': `${invitationType}-auth-code-input`,
79
+ 'data-1p-ignore': true,
80
+ }}
81
+ />
82
+ )}
70
83
  {failed && (
71
84
  <Input.DescriptionAndValidation classNames='text-center'>
72
85
  <Input.Validation>{t('failed to authenticate message')}</Input.Validation>
@@ -74,7 +87,7 @@ export const InvitationAuthenticator = ({
74
87
  )}
75
88
  </Input.Root>
76
89
 
77
- {invitationId && (
90
+ {invitationId && authMethod === Invitation.AuthMethod.SHARED_SECRET && (
78
91
  <>
79
92
  <Label>{t('auth other device emoji message')}</Label>
80
93
  <div className='flex justify-center'>
@@ -78,25 +78,17 @@ export const InvitationInput = (props: InvitationInputProps) => {
78
78
  />
79
79
  </div>
80
80
  <Actions>
81
- {Kind === 'Halo' ? (
82
- <Action
83
- variant='ghost'
84
- disabled={disabled}
85
- onClick={() => send({ type: 'deselectAuthMethod' })}
86
- data-testid={`${Kind.toLowerCase()}-invitation-input-back`}
87
- >
88
- {t('back label')}
89
- </Action>
90
- ) : exitActionParent ? (
91
- cloneElement(exitActionParent, {}, exitAction)
92
- ) : doneActionParent ? (
93
- cloneElement(doneActionParent, {}, exitAction)
94
- ) : (
95
- exitAction
96
- )}
81
+ {/* TODO(wittjosiah): This disables returning to deprecated identity creation flow. */}
82
+ {Kind === 'Halo'
83
+ ? null
84
+ : exitActionParent
85
+ ? cloneElement(exitActionParent, {}, exitAction)
86
+ : doneActionParent
87
+ ? cloneElement(doneActionParent, {}, exitAction)
88
+ : exitAction}
97
89
  <Action
98
90
  variant='primary'
99
- disabled={disabled}
91
+ disabled={disabled || inputValue.trim().length === 0}
100
92
  onClick={handleNext}
101
93
  data-testid={`${Kind.toLowerCase()}-invitation-input-continue`}
102
94
  >
@@ -53,7 +53,7 @@ export const Default = (props: any) => {
53
53
  Default.parameters = { layout: 'fullscreen' };
54
54
 
55
55
  export default {
56
- title: 'react-shell/All',
56
+ title: 'sdk/react-shell/All',
57
57
  decorators: [withTheme],
58
58
  component: StoryRow,
59
59
  parameters: { chromatic: { disableSnapshot: false }, translations: [osTranslations] },
@@ -28,7 +28,7 @@ const noOpProps: SpacePanelImplProps = {
28
28
  };
29
29
 
30
30
  export default {
31
- title: 'react-shell/SpacePanel',
31
+ title: 'sdk/react-shell/SpacePanel',
32
32
  component: SpacePanelImpl,
33
33
  decorators: [withTheme],
34
34
  parameters: { chromatic: { disableSnapshot: false } },
@@ -8,7 +8,7 @@ import React, { useEffect, useMemo } from 'react';
8
8
  import { log } from '@dxos/log';
9
9
  import { useInvitationStatus } from '@dxos/react-client/invitations';
10
10
  import type { CancellableInvitationObservable } from '@dxos/react-client/invitations';
11
- import { DensityProvider, useId, useTranslation } from '@dxos/react-ui';
11
+ import { useId, useTranslation } from '@dxos/react-ui';
12
12
 
13
13
  import { type SpacePanelHeadingProps, type SpacePanelImplProps, type SpacePanelProps } from './SpacePanelProps';
14
14
  import { useSpaceMachine } from './spaceMachine';
@@ -46,7 +46,7 @@ export const SpacePanelImpl = (props: SpacePanelImplProps) => {
46
46
  } = props;
47
47
 
48
48
  return (
49
- <DensityProvider density='fine'>
49
+ <>
50
50
  <SpacePanelHeading {...rest} {...{ titleId, space }} />
51
51
  <Viewport.Root activeView={activeView}>
52
52
  <Viewport.Views>
@@ -62,7 +62,7 @@ export const SpacePanelImpl = (props: SpacePanelImplProps) => {
62
62
  </Viewport.View>
63
63
  </Viewport.Views>
64
64
  </Viewport.Root>
65
- </DensityProvider>
65
+ </>
66
66
  );
67
67
  };
68
68
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type cloneElement } from 'react';
5
+ import { type FC, type cloneElement } from 'react';
6
6
  import { type SingleOrArray, type Event } from 'xstate';
7
7
 
8
8
  import { type Space } from '@dxos/react-client/echo';
@@ -23,9 +23,9 @@ export type SpacePanelImplProps = {
23
23
  authCode?: string;
24
24
  onDone?: () => void;
25
25
  doneActionParent?: Parameters<typeof cloneElement>[0];
26
- DoneAction?: React.FC;
27
- SpaceManager?: React.FC<SpaceManagerProps>;
28
- InvitationManager?: React.FC<InvitationManagerProps>;
26
+ DoneAction?: FC;
27
+ SpaceManager?: FC<SpaceManagerProps>;
28
+ InvitationManager?: FC<InvitationManagerProps>;
29
29
  };
30
30
 
31
31
  export type SpacePanelProps = Pick<SpacePanelImplProps, 'space'> &
@@ -2,14 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import type { Browser, ConsoleMessage } from '@playwright/test';
6
- import { expect } from 'chai';
7
- import waitForExpect from 'wait-for-expect';
5
+ import { expect, type Browser, type ConsoleMessage } from '@playwright/test';
8
6
 
9
7
  import { Trigger } from '@dxos/async';
10
8
  import { type Invitation } from '@dxos/react-client/invitations';
11
9
  import { ConnectionState } from '@dxos/react-client/mesh';
12
- import { setupPage } from '@dxos/test/playwright';
10
+ import { setupPage } from '@dxos/test-utils/playwright';
13
11
 
14
12
  import { ScopedShellManager } from '../testing';
15
13
 
@@ -35,11 +33,11 @@ export class InvitationsManager extends ScopedShellManager {
35
33
 
36
34
  const { page } = await setupPage(this._browser, {
37
35
  url: storybookUrl('invitations--default'),
38
- waitFor: (page) => page.getByTestId('invitations.identity-header').first().isVisible(),
39
36
  });
40
37
 
41
38
  this.page = page;
42
39
  this.page.on('console', (message) => this._onConsoleMessage(message));
40
+ await this.page.getByTestId('invitations.identity-header').first().waitFor({ state: 'visible' });
43
41
  this._initialized = true;
44
42
  }
45
43
 
@@ -119,9 +117,7 @@ export class InvitationsManager extends ScopedShellManager {
119
117
  const createIdentity = this.peer(id).getByTestId('invitations.create-identity');
120
118
  // TODO(wittjosiah): Clicking on buttons wrapped in tooltips is flaky in webkit playwright.
121
119
  await createIdentity.click();
122
- await waitForExpect(async () => {
123
- expect(await createIdentity.isDisabled()).to.be.true;
124
- });
120
+ await expect(createIdentity).toBeDisabled();
125
121
  }
126
122
 
127
123
  async createSpace(id: number) {
@@ -2,8 +2,7 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import { test } from '@playwright/test';
6
- import { expect } from 'chai';
5
+ import { expect, test } from '@playwright/test';
7
6
 
8
7
  import { sleep } from '@dxos/async';
9
8
  import { Invitation } from '@dxos/react-client/invitations';
@@ -47,7 +46,7 @@ test.describe('Invitations', () => {
47
46
  await manager.authenticateInvitation('device', authCode, manager.peer(1));
48
47
  await manager.doneInvitation('device', manager.peer(1));
49
48
 
50
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
49
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
51
50
  });
52
51
 
53
52
  test('no auth method', async () => {
@@ -59,7 +58,7 @@ test.describe('Invitations', () => {
59
58
  await manager.acceptInvitation(1, 'device', invitation);
60
59
  await manager.doneInvitation('device', manager.peer(1));
61
60
 
62
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
61
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
63
62
  });
64
63
 
65
64
  test('invalid & retry auth code', async () => {
@@ -75,7 +74,7 @@ test.describe('Invitations', () => {
75
74
  await manager.authenticateInvitation('device', authCode, manager.peer(1));
76
75
  await manager.doneInvitation('device', manager.peer(1));
77
76
 
78
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
77
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
79
78
  });
80
79
 
81
80
  // TODO(wittjosiah): Remove? This seems to invalidate the invitation now.
@@ -94,7 +93,7 @@ test.describe('Invitations', () => {
94
93
  await manager.clearAuthCode('device', manager.peer(1));
95
94
  await manager.authenticateInvitation('device', '000003', manager.peer(1));
96
95
 
97
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
96
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
98
97
 
99
98
  await manager.resetInvitation(manager.peer(1));
100
99
  await manager.invitationInputContinue('device', manager.peer(1));
@@ -102,7 +101,7 @@ test.describe('Invitations', () => {
102
101
  await manager.authenticateInvitation('device', authCode, manager.peer(1));
103
102
  await manager.doneInvitation('device', manager.peer(1));
104
103
 
105
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
104
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
106
105
  });
107
106
 
108
107
  test('invitation timeout', async () => {
@@ -113,7 +112,7 @@ test.describe('Invitations', () => {
113
112
  await manager.openPanel(1, 'identity');
114
113
  await manager.acceptInvitation(1, 'device', invitation);
115
114
 
116
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
115
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
117
116
  });
118
117
 
119
118
  // TODO(thure): This is skipped because the UI no longer affords cancelling device invitations, consider removing.
@@ -125,10 +124,10 @@ test.describe('Invitations', () => {
125
124
 
126
125
  await manager.openPanel(1, 'identity');
127
126
  await manager.acceptInvitation(1, 'device', invitation);
128
- expect(await manager.readyToAuthenticate('device', manager.peer(1))).to.be.true;
127
+ expect(await manager.readyToAuthenticate('device', manager.peer(1))).toBe(true);
129
128
  await manager.cancelInvitation('device', 'host', manager.peer(0));
130
129
 
131
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
130
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
132
131
  });
133
132
 
134
133
  // TODO(wittjosiah): Remove? This seems to invalidate the invitation now.
@@ -147,7 +146,7 @@ test.describe('Invitations', () => {
147
146
  await manager.authenticateInvitation('device', authCode, manager.peer(1));
148
147
  await manager.doneInvitation('device', manager.peer(1));
149
148
 
150
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
149
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
151
150
  });
152
151
 
153
152
  // TODO(thure): The design no longer affords signalling an identity’s network status. Remove or adjust test, or adjust design.
@@ -159,18 +158,18 @@ test.describe('Invitations', () => {
159
158
 
160
159
  await manager.openPanel(1, 'identity');
161
160
  await manager.acceptInvitation(1, 'device', invitation);
162
- expect(await manager.readyToAuthenticate('device', manager.peer(1))).to.be.true;
161
+ expect(await manager.readyToAuthenticate('device', manager.peer(1))).toBe(true);
163
162
  await manager.toggleNetworkStatus(0);
164
- expect(await manager.getNetworkStatus(0)).to.equal(ConnectionState.OFFLINE);
163
+ expect(await manager.getNetworkStatus(0)).toEqual(ConnectionState.OFFLINE);
165
164
  await manager.toggleNetworkStatus(0);
166
- expect(await manager.getNetworkStatus(0)).to.equal(ConnectionState.ONLINE);
165
+ expect(await manager.getNetworkStatus(0)).toEqual(ConnectionState.ONLINE);
167
166
  await manager.resetInvitation(manager.peer(1));
168
167
  await manager.invitationInputContinue('device', manager.peer(1));
169
168
  await manager.clearAuthCode('device', manager.peer(1));
170
169
  await manager.authenticateInvitation('device', authCode, manager.peer(1));
171
170
  await manager.doneInvitation('device', manager.peer(1));
172
171
 
173
- expect(await manager.getDisplayName(0)).to.equal(await manager.getDisplayName(1));
172
+ expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
174
173
  });
175
174
  });
176
175
 
@@ -190,7 +189,7 @@ test.describe('Invitations', () => {
190
189
  await manager.doneInvitation('space', manager.peer(1));
191
190
 
192
191
  await manager.openPanel(0, 'spaces');
193
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
192
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
194
193
  });
195
194
 
196
195
  test('already joined', async () => {
@@ -209,7 +208,7 @@ test.describe('Invitations', () => {
209
208
  await manager.acceptInvitation(1, 'space', invitation2);
210
209
  await manager.doneInvitation('space', manager.peer(1));
211
210
 
212
- expect(await manager.getSpaceMembersCount(0)).to.equal(2);
211
+ expect(await manager.getSpaceMembersCount(0)).toEqual(2);
213
212
  });
214
213
 
215
214
  test('no auth method', async () => {
@@ -224,7 +223,7 @@ test.describe('Invitations', () => {
224
223
  await manager.doneInvitation('space', manager.peer(1));
225
224
 
226
225
  await manager.openPanel(0, 'spaces');
227
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
226
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
228
227
  });
229
228
 
230
229
  test('invalid & retry auth code', async () => {
@@ -239,14 +238,14 @@ test.describe('Invitations', () => {
239
238
  await manager.acceptInvitation(1, 'space', invitation);
240
239
  await manager.authenticateInvitation('space', '000000', manager.peer(1));
241
240
 
242
- expect(await manager.authenticatorIsVisible('space', manager.peer(1))).to.be.true;
241
+ expect(await manager.authenticatorIsVisible('space', manager.peer(1))).toBe(true);
243
242
 
244
243
  await manager.clearAuthCode('space', manager.peer(1));
245
244
  await manager.authenticateInvitation('space', authCode, manager.peer(1));
246
245
  await manager.doneInvitation('space', manager.peer(1));
247
246
 
248
247
  await manager.openPanel(0, 'spaces');
249
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
248
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
250
249
  });
251
250
 
252
251
  // TODO(wittjosiah): Remove? This seems to invalidate the invitation now.
@@ -267,7 +266,7 @@ test.describe('Invitations', () => {
267
266
  await manager.clearAuthCode('space', manager.peer(1));
268
267
  await manager.authenticateInvitation('space', '000003', manager.peer(1));
269
268
 
270
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
269
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
271
270
 
272
271
  await manager.resetInvitation(manager.peer(1));
273
272
  await manager.invitationInputContinue('space', manager.peer(1));
@@ -276,7 +275,7 @@ test.describe('Invitations', () => {
276
275
  await manager.doneInvitation('space', manager.peer(1));
277
276
 
278
277
  await manager.openPanel(0, 'spaces');
279
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
278
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
280
279
  });
281
280
 
282
281
  test('invitation timeout', async () => {
@@ -289,7 +288,7 @@ test.describe('Invitations', () => {
289
288
  await manager.openPanel(1, 'join');
290
289
  await manager.acceptInvitation(1, 'space', invitation);
291
290
 
292
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
291
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
293
292
  });
294
293
 
295
294
  // TODO(wittjosiah): Cancel not propagating.
@@ -302,10 +301,10 @@ test.describe('Invitations', () => {
302
301
  await manager.createIdentity(1);
303
302
  await manager.openPanel(1, 'join');
304
303
  await manager.acceptInvitation(1, 'space', invitation);
305
- expect(await manager.readyToAuthenticate('space', manager.peer(1))).to.be.true;
304
+ expect(await manager.readyToAuthenticate('space', manager.peer(1))).toBe(true);
306
305
  await manager.cancelInvitation('space', 'host', manager.peer(0));
307
306
 
308
- expect(await manager.invitationFailed(manager.peer(1))).to.be.true;
307
+ expect(await manager.invitationFailed(manager.peer(1))).toBe(true);
309
308
  });
310
309
 
311
310
  // TODO(wittjosiah): Remove? This seems to invalidate the invitation now.
@@ -327,7 +326,7 @@ test.describe('Invitations', () => {
327
326
  await manager.doneInvitation('space', manager.peer(1));
328
327
 
329
328
  await manager.openPanel(0, 'spaces');
330
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
329
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
331
330
  });
332
331
 
333
332
  // TODO(thure): The design no longer affords signalling an identity’s network status. Remove or adjust test, or adjust design.
@@ -341,11 +340,11 @@ test.describe('Invitations', () => {
341
340
  await manager.createIdentity(1);
342
341
  await manager.openPanel(1, 'join');
343
342
  await manager.acceptInvitation(1, 'space', invitation);
344
- expect(await manager.readyToAuthenticate('space', manager.peer(1))).to.be.true;
343
+ expect(await manager.readyToAuthenticate('space', manager.peer(1))).toBe(true);
345
344
  await manager.toggleNetworkStatus(0);
346
- expect(await manager.getNetworkStatus(0)).to.equal(ConnectionState.OFFLINE);
345
+ expect(await manager.getNetworkStatus(0)).toEqual(ConnectionState.OFFLINE);
347
346
  await manager.toggleNetworkStatus(0);
348
- expect(await manager.getNetworkStatus(0)).to.equal(ConnectionState.ONLINE);
347
+ expect(await manager.getNetworkStatus(0)).toEqual(ConnectionState.ONLINE);
349
348
  await manager.resetInvitation(manager.peer(1));
350
349
  await manager.invitationInputContinue('space', manager.peer(1));
351
350
  await manager.clearAuthCode('space', manager.peer(1));
@@ -353,7 +352,7 @@ test.describe('Invitations', () => {
353
352
  await manager.doneInvitation('space', manager.peer(1));
354
353
 
355
354
  await manager.openPanel(0, 'spaces');
356
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
355
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
357
356
  });
358
357
 
359
358
  test('multiple concurrent invitations', async () => {
@@ -385,9 +384,9 @@ test.describe('Invitations', () => {
385
384
  await manager.doneInvitation('space', manager.peer(2));
386
385
 
387
386
  await manager.openPanel(0, 'spaces');
388
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(1, 1));
389
- expect(await manager.getSpaceName(0, 1)).to.equal(await manager.getSpaceName(2, 1));
390
- expect(await manager.getSpaceName(1, 1)).to.equal(await manager.getSpaceName(2, 1));
387
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
388
+ expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(2, 1));
389
+ expect(await manager.getSpaceName(1, 1)).toEqual(await manager.getSpaceName(2, 1));
391
390
  });
392
391
  });
393
392
  });
@@ -2,6 +2,17 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { defaultPlaywrightConfig } from '@dxos/test/playwright';
5
+ import { nxE2EPreset } from '@nx/playwright/preset';
6
+ import { defineConfig } from '@playwright/test';
6
7
 
7
- export default defaultPlaywrightConfig;
8
+ import { e2ePreset } from '@dxos/test-utils/playwright';
9
+
10
+ export default defineConfig({
11
+ ...nxE2EPreset(__filename, { testDir: __dirname }),
12
+ ...e2ePreset(__dirname),
13
+ webServer: {
14
+ command: 'pnpm -w nx storybook-e2e stories',
15
+ port: 9009,
16
+ reuseExistingServer: !process.env.CI,
17
+ },
18
+ });
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import type { ConsoleMessage, Dialog, Page } from '@playwright/test';
5
+ import type { ConsoleMessage, Page } from '@playwright/test';
6
6
 
7
7
  import { sleep, Trigger } from '@dxos/async';
8
8
 
@@ -60,13 +60,6 @@ export class ShellManager extends ScopedShellManager {
60
60
  }
61
61
 
62
62
  async resetDevice() {
63
- const handleDialog = async (dialog: Dialog) => {
64
- if (dialog.type() === 'confirm') {
65
- await dialog.accept();
66
- }
67
- };
68
- this.page.on('dialog', handleDialog);
69
-
70
63
  await this.shell.getByTestId('device-list-item-current.options').click();
71
64
  await this.shell.getByTestId('device-list-item-current.reset').click();
72
65
  await this.shell.getByTestId('reset-storage.reset-identity-input').fill(CONFIRM_INPUT);
@@ -78,6 +71,9 @@ export class ShellManager extends ScopedShellManager {
78
71
  await this.shell.getByTestId('device-list-item-current.join-existing').click();
79
72
  await this.shell.getByTestId('join-new-identity.reset-identity-input').fill(CONFIRM_INPUT);
80
73
  await this.shell.getByTestId('join-new-identity.reset-identity-confirm').click();
74
+ }
75
+
76
+ async acceptDeviceInvitation(invitationCode: string) {
81
77
  await this.inputInvitation('device', invitationCode, this.shell);
82
78
  }
83
79
 
@@ -114,7 +110,6 @@ export class ShellManager extends ScopedShellManager {
114
110
  // Wait for focus to shift before typing.
115
111
  await sleep(1500);
116
112
  await this.authenticateInvitation('space', authCode, this.shell);
117
- await this.doneInvitation('space', this.shell);
118
113
  }
119
114
 
120
115
  private async _onConsoleMessage(message: ConsoleMessage) {
@@ -34,7 +34,7 @@ export const os = {
34
34
  'recover identity input label': 'Type or paste your seed phrase',
35
35
  'failed to create identity message': 'Failed to create an identity.',
36
36
  'failed to recover identity message': 'Failed to recover an identity from the provided seed phrase.',
37
- 'failed to authenticate message': 'Incorrect PIN.',
37
+ 'failed to authenticate message': 'Incorrect code.',
38
38
  'identity added label': 'Created identity & added to this device:',
39
39
  'join space as identity heading': '<part>as </part><part><icon/><label>{{labelValue}}</label></part>',
40
40
  'error status label': 'Failed',
@@ -42,8 +42,8 @@ export const os = {
42
42
  'cancelled status label': 'Cancelled',
43
43
  'init status label': 'Ready to connect',
44
44
  'connecting status label': 'Connecting…',
45
- 'connected status label': 'Enter confirmation PIN',
46
- 'authenticating status label': 'Enter confirmation PIN',
45
+ 'connected status label': 'Enter authentication code',
46
+ 'authenticating status label': 'Enter authentication code',
47
47
  'success status label': 'Success',
48
48
  'cancel label': 'Cancel',
49
49
  'done label': 'Done',
@@ -152,4 +152,5 @@ export const os = {
152
152
  'agent requested label': 'Agent requested',
153
153
  'agent requested description':
154
154
  'The agent service is creating an agent for you. Once the agent connects, it will display in the devices list.',
155
+ 'authenticating label': 'Authenticating…',
155
156
  };