feat(AppActions): add drop down menu on open to give the user the option to choose which url to open to
This commit is contained in:
parent
633baf24d0
commit
8a871a35f3
15 changed files with 712 additions and 56 deletions
|
@ -30,7 +30,8 @@ test('user can install and uninstall app', async ({ page, context }) => {
|
|||
await expect(page.getByText('Running')).toBeVisible({ timeout: 60000 });
|
||||
await expect(page.getByText('App installed successfully')).toBeVisible();
|
||||
|
||||
const [newPage] = await Promise.all([context.waitForEvent('page'), await page.getByTestId('app-details').getByRole('button', { name: 'Open' }).click()]);
|
||||
await page.getByTestId('app-details').getByRole('button', { name: 'Open' }).click();
|
||||
const [newPage] = await Promise.all([context.waitForEvent('page'), await page.getByRole('menuitem', { name: 'localhost:8000' }).click()]);
|
||||
|
||||
await newPage.waitForLoadState();
|
||||
await expect(newPage.getByText('Hello World')).toBeVisible();
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"@otplib/plugin-crypto": "^12.0.1",
|
||||
"@otplib/plugin-thirty-two": "^12.0.1",
|
||||
"@radix-ui/react-dialog": "^1.0.3",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-select": "^1.2.1",
|
||||
"@radix-ui/react-switch": "^1.0.2",
|
||||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
|
@ -87,8 +88,8 @@
|
|||
"devDependencies": {
|
||||
"@babel/core": "^7.21.8",
|
||||
"@faker-js/faker": "^8.0.1",
|
||||
"@testing-library/dom": "^9.3.0",
|
||||
"@playwright/test": "^1.32.3",
|
||||
"@testing-library/dom": "^9.3.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
|
|
492
pnpm-lock.yaml
generated
492
pnpm-lock.yaml
generated
|
@ -16,6 +16,9 @@ dependencies:
|
|||
'@radix-ui/react-dialog':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-dropdown-menu':
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-select':
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
|
@ -1062,6 +1065,10 @@ packages:
|
|||
resolution: {integrity: sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==}
|
||||
dev: false
|
||||
|
||||
/@floating-ui/core@1.2.6:
|
||||
resolution: {integrity: sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg==}
|
||||
dev: false
|
||||
|
||||
/@floating-ui/dom@0.5.4:
|
||||
resolution: {integrity: sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==}
|
||||
dependencies:
|
||||
|
@ -1074,6 +1081,12 @@ packages:
|
|||
'@floating-ui/core': 1.2.1
|
||||
dev: false
|
||||
|
||||
/@floating-ui/dom@1.2.9:
|
||||
resolution: {integrity: sha512-sosQxsqgxMNkV3C+3UqTS6LxP7isRLwX8WMepp843Rb3/b0Wz8+MdUkxJksByip3C2WwLugLHN1b4ibn//zKwQ==}
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.2.6
|
||||
dev: false
|
||||
|
||||
/@floating-ui/react-dom@0.7.2(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg==}
|
||||
peerDependencies:
|
||||
|
@ -1088,6 +1101,17 @@ packages:
|
|||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/@floating-ui/react-dom@2.0.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Ke0oU3SeuABC2C4OFu2mSAwHIP5WUiV98O9YWoHV4Q5aT6E9k06DV0Khi5uYspR8xmmBk08t8ZDcz3TR3ARkEg==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.2.9
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@formatjs/ecma402-abstract@1.11.4:
|
||||
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
|
||||
dependencies:
|
||||
|
@ -1640,6 +1664,12 @@ packages:
|
|||
'@babel/runtime': 7.20.13
|
||||
dev: false
|
||||
|
||||
/@radix-ui/primitive@1.0.1:
|
||||
resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-arrow@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA==}
|
||||
peerDependencies:
|
||||
|
@ -1652,6 +1682,27 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-collection@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-s8WdQQ6wNXpaxdZ308KSr8fEWGrg4un8i4r/w7fhiS4ElRNjk5rRcl0/C6TANG2LvLOGIxtzo/jAg6Qf73TEBw==}
|
||||
peerDependencies:
|
||||
|
@ -1667,6 +1718,30 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-compose-refs@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==}
|
||||
peerDependencies:
|
||||
|
@ -1676,6 +1751,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-context@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==}
|
||||
peerDependencies:
|
||||
|
@ -1685,6 +1774,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-context@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-dialog@1.0.3(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-owNhq36kNPqC2/a+zJRioPg6HHnTn5B/sh/NjTY8r4W9g1L5VJlrzZIVcBr7R9Mg8iLjVmh6MGgMlfoVf/WO/A==}
|
||||
peerDependencies:
|
||||
|
@ -1721,6 +1824,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-direction@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-dismissable-layer@1.0.3(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-nXZOvFjOuHS1ovumntGV7NNoLaEp9JEvTht3MBjP44NSW5hUKj/8OnfN3+8WmB+CEhN44XaGhpHoSsUIEl5P7Q==}
|
||||
peerDependencies:
|
||||
|
@ -1737,6 +1854,58 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-dropdown-menu@2.0.5(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-xdOrZzOTocqqkCkYo8yRPCib5OkTkqN7lqNCdxwPOdE466DOaNl4N8PkUIlsXthQvW5Wwkd+aEmWpfWlBoDPEw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-id': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-menu': 2.0.5(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-focus-guards@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ==}
|
||||
peerDependencies:
|
||||
|
@ -1746,6 +1915,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-focus-scope@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-spwXlNTfeIprt+kaEWE/qYuYT3ZAqJiAGjN/JgdvgVDTu8yc+HuX+WOWXrKliKnLnwck0F6JDkqIERncnih+4A==}
|
||||
peerDependencies:
|
||||
|
@ -1760,6 +1943,29 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-id@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==}
|
||||
peerDependencies:
|
||||
|
@ -1770,6 +1976,59 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-id@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-menu@2.0.5(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Gw4f9pwdH+w5w+49k0gLjN0PfRDHvxmAgG16AbyJZ7zhwZ6PBHKtWohvnSwfusfnK3L68dpBREHpVkj8wEM7ZA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-id': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-popper': 1.1.2(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
aria-hidden: 1.2.3
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-remove-scroll: 2.5.5(@types/react@18.2.7)(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-popper@1.1.1(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-keYDcdMPNMjSC8zTsZ8wezUMiWM9Yj14wtF3s0PTIs9srnEPC9Kt2Gny1T3T81mmSeyDjZxsD9N5WCwNNb712w==}
|
||||
peerDependencies:
|
||||
|
@ -1793,6 +2052,36 @@ packages:
|
|||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@floating-ui/react-dom': 2.0.0(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-size': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/rect': 1.0.1
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-portal@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==}
|
||||
peerDependencies:
|
||||
|
@ -1805,6 +2094,27 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-presence@1.0.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==}
|
||||
peerDependencies:
|
||||
|
@ -1818,6 +2128,28 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-primitive@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==}
|
||||
peerDependencies:
|
||||
|
@ -1830,6 +2162,27 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-roving-focus@1.0.3(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-stjCkIoMe6h+1fWtXlA6cRfikdBzCLp3SnVk7c48cv/uy3DTGoXhN76YaOYUJuy3aEDvDIKwKR5KSmvrtPvQPQ==}
|
||||
peerDependencies:
|
||||
|
@ -1850,6 +2203,35 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-id': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
'@types/react-dom': 18.2.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-select@1.2.1(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-GULRMITaOHNj79BZvQs3iZO0+f2IgI8g5HDhMi7Bnc13t7IlG86NFtOCfTLme4PNZdEtU+no+oGgcl6IFiphpQ==}
|
||||
peerDependencies:
|
||||
|
@ -1894,6 +2276,21 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-slot@1.0.2(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-switch@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-BcG/LKehxt36NXG0wPnoCitIfSMtU9Xo7BmythYA1PAMLtsMvW7kALfBzmduQoHTWcKr0AVcFyh0gChBUp9TiQ==}
|
||||
peerDependencies:
|
||||
|
@ -1940,6 +2337,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-controllable-state@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==}
|
||||
peerDependencies:
|
||||
|
@ -1950,6 +2361,21 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-escape-keydown@1.0.2(react@18.2.0):
|
||||
resolution: {integrity: sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA==}
|
||||
peerDependencies:
|
||||
|
@ -1960,6 +2386,21 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-layout-effect@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==}
|
||||
peerDependencies:
|
||||
|
@ -1969,6 +2410,20 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-previous@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-RG2K8z/K7InnOKpq6YLDmT49HGjNmrK+fr82UCVKT2sW0GYfVnYp4wZWBooT/EYfQ5faA9uIjvsuMMhH61rheg==}
|
||||
peerDependencies:
|
||||
|
@ -1988,6 +2443,21 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-rect@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/rect': 1.0.1
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-size@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg==}
|
||||
peerDependencies:
|
||||
|
@ -1998,6 +2468,21 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-size@1.0.1(@types/react@18.2.7)(react@18.2.0):
|
||||
resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.7)(react@18.2.0)
|
||||
'@types/react': 18.2.7
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-visually-hidden@1.0.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-qirnJxtYn73HEk1rXL12/mXnu2rwsNHDID10th2JGtdK25T9wX+mxRmGt7iPSahw512GbZOc0syZX1nLQGoEOg==}
|
||||
peerDependencies:
|
||||
|
@ -2016,6 +2501,12 @@ packages:
|
|||
'@babel/runtime': 7.20.13
|
||||
dev: false
|
||||
|
||||
/@radix-ui/rect@1.0.1:
|
||||
resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
dev: false
|
||||
|
||||
/@redis/bloom@1.2.0(@redis/client@1.5.7):
|
||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
||||
peerDependencies:
|
||||
|
@ -2579,7 +3070,6 @@ packages:
|
|||
resolution: {integrity: sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==}
|
||||
dependencies:
|
||||
'@types/react': 18.2.7
|
||||
dev: true
|
||||
|
||||
/@types/react-transition-group@4.4.5:
|
||||
resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==}
|
||||
|
|
4
src/@types/next.d.ts
vendored
4
src/@types/next.d.ts
vendored
|
@ -11,7 +11,9 @@ type SessionContent = {
|
|||
};
|
||||
|
||||
declare module 'express-session' {
|
||||
export type SessionData = SessionContent;
|
||||
interface SessionData extends SessionContent {
|
||||
userId?: number;
|
||||
}
|
||||
}
|
||||
|
||||
interface ExtendedGetServerSidePropsContext<Params, Preview> extends GetServerSidePropsContext<Params, Preview> {
|
||||
|
|
|
@ -144,6 +144,7 @@
|
|||
"link": "Link",
|
||||
"website": "Website",
|
||||
"supported-arch": "Supported architectures",
|
||||
"choose-open-method": "Choose open method",
|
||||
"categories": {
|
||||
"data": "Data",
|
||||
"network": "Network",
|
||||
|
|
|
@ -1,24 +1,28 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import React from 'react';
|
||||
import { AppActions } from './AppActions';
|
||||
import { cleanup, fireEvent, render, screen } from '../../../../../../tests/test-utils';
|
||||
import { cleanup, fireEvent, render, screen, waitFor, userEvent } from '../../../../../../tests/test-utils';
|
||||
import { AppInfo } from '../../../../core/types';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
describe('Test: AppActions', () => {
|
||||
const app = {
|
||||
name: 'My App',
|
||||
form_fields: [],
|
||||
exposable: [],
|
||||
id: 'test',
|
||||
info: {
|
||||
port: 3000,
|
||||
id: 'test',
|
||||
name: 'My App',
|
||||
form_fields: [],
|
||||
exposable: [],
|
||||
},
|
||||
} as unknown as AppInfo;
|
||||
|
||||
it('should call the callbacks when buttons are clicked', () => {
|
||||
// arrange
|
||||
const onStart = jest.fn();
|
||||
const onRemove = jest.fn();
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="stopped" info={app} onStart={onStart} onUninstall={onRemove} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="stopped" app={app} onStart={onStart} onUninstall={onRemove} />);
|
||||
|
||||
// act
|
||||
const startButton = screen.getByRole('button', { name: 'Start' });
|
||||
|
@ -33,8 +37,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is running', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="running" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="running" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Stop' })).toBeInTheDocument();
|
||||
|
@ -44,8 +48,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is starting', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="starting" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="starting" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
||||
|
@ -54,8 +58,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is stopping', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="stopping" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="stopping" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
||||
|
@ -64,8 +68,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is removing', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="uninstalling" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="uninstalling" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
||||
|
@ -74,8 +78,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is installing', () => {
|
||||
// arrange
|
||||
// @ts-ignore
|
||||
render(<AppActions status="installing" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="installing" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
||||
|
@ -84,8 +88,8 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is updating', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="updating" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="updating" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
|
||||
|
@ -94,10 +98,96 @@ describe('Test: AppActions', () => {
|
|||
|
||||
it('should render the correct buttons when app status is missing', () => {
|
||||
// arrange
|
||||
// @ts-expect-error
|
||||
render(<AppActions status="missing" info={app} />);
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="missing" app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Install' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render update button if app is running and has an update available', () => {
|
||||
// arrange
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="running" updateAvailable app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Update' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render update button if app is stopped and has an update available', () => {
|
||||
// arrange
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions status="stopped" updateAvailable app={app} />);
|
||||
|
||||
// assert
|
||||
expect(screen.getByRole('button', { name: 'Update' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render domain button if app is running and has a domain', async () => {
|
||||
// arrange
|
||||
const appWithDomain = {
|
||||
...app,
|
||||
exposed: true,
|
||||
domain: 'myapp.example.com',
|
||||
};
|
||||
const openFn = jest.fn();
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions onOpen={openFn} status="running" app={appWithDomain} />);
|
||||
|
||||
// act
|
||||
const openButton = screen.getByRole('button', { name: 'Open' });
|
||||
userEvent.type(openButton, '{arrowdown}');
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/myapp.example.com/)).toBeInTheDocument();
|
||||
});
|
||||
const domainButton = screen.getByText(/myapp.example.com/);
|
||||
|
||||
// assert
|
||||
userEvent.click(domainButton);
|
||||
await waitFor(() => {
|
||||
expect(openFn).toHaveBeenCalledWith('domain');
|
||||
});
|
||||
});
|
||||
|
||||
it('should render local_domain open button', async () => {
|
||||
// arrange
|
||||
const openFn = jest.fn();
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions localDomain="tipi.lan" onOpen={openFn} status="running" app={app} />);
|
||||
|
||||
// act
|
||||
const openButton = screen.getByRole('button', { name: 'Open' });
|
||||
userEvent.type(openButton, '{arrowdown}');
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/test.tipi.lan/)).toBeInTheDocument();
|
||||
});
|
||||
const localButton = screen.getByText(/test.tipi.lan/);
|
||||
|
||||
// assert
|
||||
userEvent.click(localButton);
|
||||
await waitFor(() => {
|
||||
expect(openFn).toHaveBeenCalledWith('local_domain');
|
||||
});
|
||||
});
|
||||
|
||||
it('should render local open button', async () => {
|
||||
// arrange
|
||||
const openFn = jest.fn();
|
||||
// @ts-expect-error - we don't need to pass all props for this test
|
||||
render(<AppActions localUrl="http://localhost:3000" onOpen={openFn} status="running" app={app} />);
|
||||
|
||||
// act
|
||||
const openButton = screen.getByRole('button', { name: 'Open' });
|
||||
userEvent.type(openButton, '{arrowdown}');
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/localhost:3000/)).toBeInTheDocument();
|
||||
});
|
||||
const localButton = screen.getByText(/localhost:3000/);
|
||||
|
||||
// assert
|
||||
userEvent.click(localButton);
|
||||
await waitFor(() => {
|
||||
expect(openFn).toHaveBeenCalledWith('local');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
import { Icon, IconDownload, IconExternalLink, IconPlayerPause, IconPlayerPlay, IconSettings, IconTrash, IconX } from '@tabler/icons-react';
|
||||
import { Icon, IconDownload, IconExternalLink, IconLock, IconLockOff, IconPlayerPause, IconPlayerPlay, IconSettings, IconTrash, IconX } from '@tabler/icons-react';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import type { AppStatus } from '@/server/db/schema';
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/DropdownMenu';
|
||||
import { Button } from '../../../../components/ui/Button';
|
||||
import { AppInfo } from '../../../../core/types';
|
||||
import { AppWithInfo } from '../../../../core/types';
|
||||
|
||||
interface IProps {
|
||||
info: AppInfo;
|
||||
app: AppWithInfo;
|
||||
status?: AppStatus;
|
||||
updateAvailable: boolean;
|
||||
localDomain?: string;
|
||||
onInstall: () => void;
|
||||
onUninstall: () => void;
|
||||
onStart: () => void;
|
||||
onStop: () => void;
|
||||
onOpen: () => void;
|
||||
onOpen: (url: OpenType) => void;
|
||||
onUpdate: () => void;
|
||||
onUpdateSettings: () => void;
|
||||
onCancel: () => void;
|
||||
|
@ -23,7 +25,7 @@ interface IProps {
|
|||
|
||||
interface BtnProps {
|
||||
IconComponent?: Icon;
|
||||
onClick: () => void;
|
||||
onClick?: () => void;
|
||||
width?: number | null;
|
||||
title?: string;
|
||||
color?: string;
|
||||
|
@ -43,7 +45,10 @@ const ActionButton: React.FC<BtnProps> = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const AppActions: React.FC<IProps> = ({ info, status, onInstall, onUninstall, onStart, onStop, onOpen, onUpdate, onCancel, updateAvailable, onUpdateSettings }) => {
|
||||
type OpenType = 'local' | 'domain' | 'local_domain';
|
||||
|
||||
export const AppActions: React.FC<IProps> = ({ app, status, localDomain, onInstall, onUninstall, onStart, onStop, onOpen, onUpdate, onCancel, updateAvailable, onUpdateSettings }) => {
|
||||
const { info } = app;
|
||||
const t = useTranslations('apps.app-details');
|
||||
const hasSettings = Object.keys(info.form_fields).length > 0 || info.exposable;
|
||||
|
||||
|
@ -53,12 +58,41 @@ export const AppActions: React.FC<IProps> = ({ info, status, onInstall, onUninst
|
|||
const RemoveButton = <ActionButton key="remove" IconComponent={IconTrash} onClick={onUninstall} title={t('actions.remove')} color="danger" />;
|
||||
const SettingsButton = <ActionButton key="settings" IconComponent={IconSettings} onClick={onUpdateSettings} title={t('actions.settings')} />;
|
||||
const StopButton = <ActionButton key="stop" IconComponent={IconPlayerPause} onClick={onStop} title={t('actions.stop')} color="danger" />;
|
||||
const OpenButton = <ActionButton key="open" IconComponent={IconExternalLink} onClick={onOpen} title={t('actions.open')} />;
|
||||
const LoadingButtion = <ActionButton key="loading" loading onClick={() => null} color="success" title={t('actions.loading')} />;
|
||||
const LoadingButtion = <ActionButton key="loading" loading color="success" title={t('actions.loading')} />;
|
||||
const CancelButton = <ActionButton key="cancel" IconComponent={IconX} onClick={onCancel} title={t('actions.cancel')} />;
|
||||
const InstallButton = <ActionButton key="install" onClick={onInstall} title={t('actions.install')} color="success" />;
|
||||
const UpdateButton = <ActionButton key="update" IconComponent={IconDownload} onClick={onUpdate} width={null} title={t('actions.update')} color="success" />;
|
||||
|
||||
const OpenButton = (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button width={140} className={clsx('me-2 px-4 mt-2')}>
|
||||
{t('actions.open')}
|
||||
<IconExternalLink className="ms-1" size={14} />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuLabel>{t('choose-open-method')}</DropdownMenuLabel>
|
||||
<DropdownMenuGroup>
|
||||
{app.exposed && app.domain && (
|
||||
<DropdownMenuItem onClick={() => onOpen('domain')}>
|
||||
<IconLock className="text-green me-2" size={16} />
|
||||
{app.domain}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={() => onOpen('local_domain')}>
|
||||
<IconLock className="text-muted me-2" size={16} />
|
||||
{app.id}.{localDomain}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onOpen('local')}>
|
||||
<IconLockOff className="text-muted me-2" size={16} />
|
||||
{window.location.hostname}:{app.info.port}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
|
||||
switch (status) {
|
||||
case 'stopped':
|
||||
buttons.push(StartButton, RemoveButton);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { fireEvent, render, screen, waitFor } from '../../../../../../tests/test-utils';
|
||||
import { fireEvent, render, screen, userEvent, waitFor } from '../../../../../../tests/test-utils';
|
||||
import { createAppEntity } from '../../../../mocks/fixtures/app.fixtures';
|
||||
import { getTRPCMock, getTRPCMockError } from '../../../../mocks/getTrpcMock';
|
||||
import { server } from '../../../../mocks/server';
|
||||
|
@ -86,10 +86,19 @@ describe('Test: AppDetailsContainer', () => {
|
|||
|
||||
// Act
|
||||
const openButton = screen.getByRole('button', { name: 'Open' });
|
||||
openButton.click();
|
||||
userEvent.type(openButton, '{arrowdown}');
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/localhost:/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const openButtonItem = screen.getByText(/localhost:/);
|
||||
userEvent.click(openButtonItem);
|
||||
|
||||
// Assert
|
||||
expect(spy).toHaveBeenCalledWith(`http://localhost:${app.info.port}`, '_blank', 'noreferrer');
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalledWith(`http://localhost:${app.info.port}`, '_blank', 'noreferrer');
|
||||
});
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
it('should open with https when app info has https set to true', async () => {
|
||||
|
@ -100,10 +109,20 @@ describe('Test: AppDetailsContainer', () => {
|
|||
|
||||
// Act
|
||||
const openButton = screen.getByRole('button', { name: 'Open' });
|
||||
openButton.click();
|
||||
userEvent.type(openButton, '{arrowdown}');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/localhost:/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const openButtonItem = screen.getByText(/localhost:/);
|
||||
userEvent.click(openButtonItem);
|
||||
|
||||
// Assert
|
||||
expect(spy).toHaveBeenCalledWith(`https://localhost:${app.info.port}`, '_blank', 'noreferrer');
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalledWith(`https://localhost:${app.info.port}`, '_blank', 'noreferrer');
|
||||
});
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import { castAppConfig } from '../../helpers/castAppConfig';
|
|||
interface IProps {
|
||||
app: AppRouterOutput['getApp'];
|
||||
}
|
||||
type OpenType = 'local' | 'domain' | 'local_domain';
|
||||
|
||||
export const AppDetailsContainer: React.FC<IProps> = ({ app }) => {
|
||||
const t = useTranslations();
|
||||
|
@ -29,6 +30,8 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app }) => {
|
|||
const updateDisclosure = useDisclosure();
|
||||
const updateSettingsDisclosure = useDisclosure();
|
||||
|
||||
const getSettings = trpc.system.getSettings.useQuery();
|
||||
|
||||
const utils = trpc.useContext();
|
||||
|
||||
const invalidate = () => {
|
||||
|
@ -135,15 +138,26 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app }) => {
|
|||
update.mutate({ id: app.id });
|
||||
};
|
||||
|
||||
const handleOpen = () => {
|
||||
const handleOpen = (type: OpenType) => {
|
||||
let url = '';
|
||||
const { https } = app.info;
|
||||
const protocol = https ? 'https' : 'http';
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
// Current domain
|
||||
const domain = window.location.hostname;
|
||||
window.open(`${protocol}://${domain}:${app.info.port}${app.info.url_suffix || ''}`, '_blank', 'noreferrer');
|
||||
url = `${protocol}://${domain}:${app.info.port}${app.info.url_suffix || ''}`;
|
||||
}
|
||||
|
||||
if (type === 'domain' && app.domain) {
|
||||
url = `https://${app.domain}${app.info.url_suffix || ''}`;
|
||||
}
|
||||
|
||||
if (type === 'local_domain') {
|
||||
url = `https://${app.id}.${getSettings.data?.localDomain}`;
|
||||
}
|
||||
|
||||
window.open(url, '_blank', 'noreferrer');
|
||||
};
|
||||
|
||||
const newVersion = [app?.latestDockerVersion ? `${app?.latestDockerVersion}` : '', `(${String(app?.latestVersion)})`].join(' ');
|
||||
|
@ -170,14 +184,10 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app }) => {
|
|||
<span className="mt-1 me-1">{t('apps.app-details.version')}: </span>
|
||||
<span className="badge bg-gray mt-2">{app.info.version}</span>
|
||||
</div>
|
||||
{app.domain && (
|
||||
<a target="_blank" rel="noreferrer" className="mt-1" href={`https://${app.domain}`}>
|
||||
https://{app.domain}
|
||||
</a>
|
||||
)}
|
||||
<span className="mt-1 text-muted text-center mb-2">{app.info.short_desc}</span>
|
||||
<div className="mb-1">{app.status !== 'missing' && <AppStatus status={app.status} />}</div>
|
||||
<AppActions
|
||||
localDomain={getSettings.data?.localDomain}
|
||||
updateAvailable={updateAvailable}
|
||||
onUpdate={updateDisclosure.open}
|
||||
onUpdateSettings={updateSettingsDisclosure.open}
|
||||
|
@ -187,7 +197,7 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app }) => {
|
|||
onInstall={installDisclosure.open}
|
||||
onOpen={handleOpen}
|
||||
onStart={handleStartSubmit}
|
||||
info={app.info}
|
||||
app={app}
|
||||
status={app.status}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -56,10 +56,10 @@ describe('Test: SettingsForm', () => {
|
|||
// arrange
|
||||
render(<SettingsForm onSubmit={jest.fn()} />);
|
||||
const submitButton = screen.getByRole('button', { name: 'Save' });
|
||||
const dnsIpInput = screen.getByLabelText('DNS IP');
|
||||
const domainInput = screen.getByLabelText('Domain name');
|
||||
const internalIpInput = screen.getByLabelText('Internal IP');
|
||||
const appsRepoUrlInput = screen.getByLabelText('Apps repo URL');
|
||||
const dnsIpInput = screen.getByRole('textbox', { name: 'dnsIp' });
|
||||
const domainInput = screen.getByRole('textbox', { name: 'domain' });
|
||||
const internalIpInput = screen.getByRole('textbox', { name: 'internalIp' });
|
||||
const appsRepoUrlInput = screen.getByRole('textbox', { name: 'appsRepoUrl' });
|
||||
|
||||
// act
|
||||
fireEvent.change(dnsIpInput, { target: { value: 'invalid ip' } });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable global-require */
|
||||
import express, { Request } from 'express';
|
||||
import express from 'express';
|
||||
import { parse } from 'url';
|
||||
|
||||
import type { NextServer } from 'next/dist/server/next';
|
||||
|
@ -44,7 +44,7 @@ nextApp.prepare().then(async () => {
|
|||
|
||||
app.use('/certificate', async (req, res) => {
|
||||
const userId = req.session?.userId;
|
||||
const user = await authService.getUserById(userId);
|
||||
const user = await authService.getUserById(userId as number);
|
||||
|
||||
if (user?.operator) {
|
||||
res.setHeader('Content-Dispositon', 'attachment; filename=cert.pem');
|
||||
|
|
|
@ -40,7 +40,7 @@ describe('Install app', () => {
|
|||
const envFile = fs.readFileSync(`/app/storage/app-data/${appConfig.id}/app.env`).toString();
|
||||
|
||||
// assert
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nTEST_FIELD=test\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nAPP_ID=${appConfig.id}\nTEST_FIELD=test\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
});
|
||||
|
||||
it('Should add app in database', async () => {
|
||||
|
@ -336,7 +336,7 @@ describe('Start app', () => {
|
|||
const envFile = fs.readFileSync(`/app/storage/app-data/${appConfig.id}/app.env`).toString();
|
||||
|
||||
// assert
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nTEST_FIELD=test\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nAPP_ID=${appConfig.id}\nTEST_FIELD=test\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
});
|
||||
|
||||
it('Should throw if start script fails', async () => {
|
||||
|
@ -395,7 +395,7 @@ describe('Update app config', () => {
|
|||
const envFile = fs.readFileSync(`/app/storage/app-data/${appConfig.id}/app.env`).toString();
|
||||
|
||||
// assert
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nTEST_FIELD=${word}\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
expect(envFile.trim()).toBe(`TEST=test\nAPP_PORT=${appConfig.port}\nAPP_ID=${appConfig.id}\nTEST_FIELD=${word}\nAPP_DOMAIN=localhost:${appConfig.port}`);
|
||||
});
|
||||
|
||||
it('Should throw if required field is missing', async () => {
|
||||
|
|
|
@ -185,7 +185,7 @@ export class AppServiceClass {
|
|||
*
|
||||
* @param {string} id - The ID of the app to update.
|
||||
* @param {object} form - The new configuration of the app.
|
||||
* @param {boolean} [exposed=false] - If the app should be exposed or not.
|
||||
* @param {boolean} [exposed] - If the app should be exposed or not.
|
||||
* @param {string} [domain] - The domain for the app if exposed is true.
|
||||
*/
|
||||
public updateAppConfig = async (id: string, form: Record<string, string>, exposed?: boolean, domain?: string) => {
|
||||
|
|
|
@ -18,6 +18,8 @@ class ResizeObserver {
|
|||
observe() {}
|
||||
|
||||
unobserve() {}
|
||||
|
||||
disconnect() {}
|
||||
}
|
||||
|
||||
// Mock localStorage
|
||||
|
@ -41,6 +43,8 @@ const localStorageMock = (() => {
|
|||
|
||||
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
|
||||
Object.defineProperty(window, 'ResizeObserver', { value: ResizeObserver });
|
||||
Object.defineProperty(window, 'MutationObserver', { value: ResizeObserver });
|
||||
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
value: () => {
|
||||
return {
|
||||
|
|
|
@ -2,9 +2,12 @@ import React, { FC, ReactElement } from 'react';
|
|||
import { render, RenderOptions, renderHook } from '@testing-library/react';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
import { NextIntlProvider } from 'next-intl';
|
||||
import ue from '@testing-library/user-event';
|
||||
import { TRPCTestClientProvider } from './TRPCTestClientProvider';
|
||||
import messages from '../src/client/messages/en.json';
|
||||
|
||||
const userEvent = ue.setup();
|
||||
|
||||
const AllTheProviders: FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
<NextIntlProvider locale="en" messages={messages}>
|
||||
<TRPCTestClientProvider>
|
||||
|
@ -20,3 +23,4 @@ const customRenderHook = (callback: () => any, options?: Omit<RenderOptions, 'wr
|
|||
export * from '@testing-library/react';
|
||||
export { customRender as render };
|
||||
export { customRenderHook as renderHook };
|
||||
export { userEvent };
|
||||
|
|
Loading…
Add table
Reference in a new issue