Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust Refresh Interval in Assets table #10775

Merged
merged 22 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 97 additions & 46 deletions app/dashboard/e2e/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ export interface MockApi extends Awaited<ReturnType<typeof mockApiInternal>> {}
// eslint-disable-next-line no-restricted-syntax
export const mockApi: (params: MockParams) => Promise<MockApi> = mockApiInternal

/**
* Wait for a given number of milliseconds.
*/
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
function wait(ms: number = 0) {
return new Promise((resolve) => setTimeout(resolve, ms))
}

/** Add route handlers for the mock API to a page. */
// This syntax is required for Playwright to work properly.
// eslint-disable-next-line no-restricted-syntax
Expand Down Expand Up @@ -454,7 +462,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {

// === Endpoints returning arrays ===

await get(remoteBackendPaths.LIST_DIRECTORY_PATH + '*', (_route, request) => {
await get(remoteBackendPaths.LIST_DIRECTORY_PATH + '*', async (_route, request) => {
/** The type for the search query for this endpoint. */
interface Query {
/* eslint-disable @typescript-eslint/naming-convention */
Expand Down Expand Up @@ -504,33 +512,39 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
(a, b) => backend.ASSET_TYPE_ORDER[a.type] - backend.ASSET_TYPE_ORDER[b.type],
)
const json: remoteBackend.ListDirectoryResponseBody = { assets: filteredAssets }

await wait()

return json
})
await get(
remoteBackendPaths.LIST_FILES_PATH + '*',
() => ({ files: [] }) satisfies remoteBackend.ListFilesResponseBody,
)
await get(
remoteBackendPaths.LIST_PROJECTS_PATH + '*',
() => ({ projects: [] }) satisfies remoteBackend.ListProjectsResponseBody,
)
await get(
remoteBackendPaths.LIST_SECRETS_PATH + '*',
() => ({ secrets: [] }) satisfies remoteBackend.ListSecretsResponseBody,
)
await get(
remoteBackendPaths.LIST_TAGS_PATH + '*',
() => ({ tags: labels }) satisfies remoteBackend.ListTagsResponseBody,
)
await get(remoteBackendPaths.LIST_FILES_PATH + '*', async () => {
await wait()
return { files: [] } satisfies remoteBackend.ListFilesResponseBody
})
await get(remoteBackendPaths.LIST_PROJECTS_PATH + '*', async () => {
await wait()
return { projects: [] } satisfies remoteBackend.ListProjectsResponseBody
})
await get(remoteBackendPaths.LIST_SECRETS_PATH + '*', async () => {
await wait()
return { secrets: [] } satisfies remoteBackend.ListSecretsResponseBody
})
await get(remoteBackendPaths.LIST_TAGS_PATH + '*', async () => {
await wait()
return { tags: labels } satisfies remoteBackend.ListTagsResponseBody
})
await get(remoteBackendPaths.LIST_USERS_PATH + '*', async (route) => {
if (currentUser != null) {
await wait()
return { users } satisfies remoteBackend.ListUsersResponseBody
} else {
await route.fulfill({ status: HTTP_STATUS_BAD_REQUEST })
return
}
})
await get(remoteBackendPaths.LIST_USER_GROUPS_PATH + '*', async (route) => {
await wait()

await route.fulfill({ json: [] })
})
await get(remoteBackendPaths.LIST_VERSIONS_PATH + '*', (_route, request) => ({
Expand All @@ -553,29 +567,35 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {

// === Endpoints with dummy implementations ===

await get(remoteBackendPaths.getProjectDetailsPath(GLOB_PROJECT_ID), (_route, request) => {
const projectId = backend.ProjectId(request.url().match(/[/]projects[/]([^?/]+)/)?.[1] ?? '')
const project = assetMap.get(projectId)
if (!project?.projectState) {
throw new Error('Attempting to get a project that does not exist.')
} else {
return {
organizationId: defaultOrganizationId,
projectId: projectId,
name: 'example project name',
state: project.projectState,
packageName: 'Project_root',
// eslint-disable-next-line @typescript-eslint/naming-convention
ide_version: null,
// eslint-disable-next-line @typescript-eslint/naming-convention
engine_version: {
value: '2023.2.1-nightly.2023.9.29',
lifecycle: backend.VersionLifecycle.development,
},
address: backend.Address('ws://localhost/'),
} satisfies backend.ProjectRaw
}
})
await get(
remoteBackendPaths.getProjectDetailsPath(GLOB_PROJECT_ID),
async (_route, request) => {
const projectId = backend.ProjectId(
request.url().match(/[/]projects[/]([^?/]+)/)?.[1] ?? '',
)
const project = assetMap.get(projectId)
await wait()
if (!project?.projectState) {
throw new Error('Attempting to get a project that does not exist.')
} else {
return {
organizationId: defaultOrganizationId,
projectId: projectId,
name: 'example project name',
state: project.projectState,
packageName: 'Project_root',
// eslint-disable-next-line @typescript-eslint/naming-convention
ide_version: null,
// eslint-disable-next-line @typescript-eslint/naming-convention
engine_version: {
value: '2023.2.1-nightly.2023.9.29',
lifecycle: backend.VersionLifecycle.development,
},
address: backend.Address('ws://localhost/'),
} satisfies backend.ProjectRaw
}
},
)

// === Endpoints returning `void` ===

Expand All @@ -584,6 +604,9 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
interface Body {
readonly parentDirectoryId: backend.DirectoryId
}

await wait()

const assetId = request.url().match(/[/]assets[/]([^?/]+)/)?.[1]
// eslint-disable-next-line no-restricted-syntax
const asset = assetId != null ? assetMap.get(assetId as backend.AssetId) : null
Expand Down Expand Up @@ -622,20 +645,25 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
}
})
await get(remoteBackendPaths.INVITATION_PATH + '*', async (route) => {
await wait()
await route.fulfill({
json: { invitations: [] } satisfies backend.ListInvitationsResponseBody,
})
})
await post(remoteBackendPaths.INVITE_USER_PATH + '*', async (route) => {
await wait()
await route.fulfill()
})
await post(remoteBackendPaths.CREATE_PERMISSION_PATH + '*', async (route) => {
await wait()
await route.fulfill()
})
await delete_(remoteBackendPaths.deleteAssetPath(GLOB_ASSET_ID), async (route) => {
await wait()
await route.fulfill()
})
await post(remoteBackendPaths.closeProjectPath(GLOB_PROJECT_ID), async (route, request) => {
await wait()
const projectId = backend.ProjectId(request.url().match(/[/]projects[/]([^?/]+)/)?.[1] ?? '')
const project = assetMap.get(projectId)
if (project?.projectState) {
Expand All @@ -644,6 +672,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
await route.fulfill()
})
await post(remoteBackendPaths.openProjectPath(GLOB_PROJECT_ID), async (route, request) => {
await wait()
const projectId = backend.ProjectId(request.url().match(/[/]projects[/]([^?/]+)/)?.[1] ?? '')
const project = assetMap.get(projectId)
if (project?.projectState) {
Expand All @@ -652,15 +681,18 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
await route.fulfill()
})
await delete_(remoteBackendPaths.deleteTagPath(GLOB_TAG_ID), async (route) => {
await wait()
await route.fulfill()
})
await post(remoteBackendPaths.POST_LOG_EVENT_PATH, async (route) => {
await wait()
await route.fulfill()
})

// === Entity creation endpoints ===

await put(remoteBackendPaths.UPLOAD_USER_PICTURE_PATH + '*', async (route, request) => {
await wait()
const content = request.postData()
if (content != null) {
currentProfilePicture = content
Expand All @@ -671,6 +703,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
}
})
await put(remoteBackendPaths.UPLOAD_ORGANIZATION_PICTURE_PATH + '*', async (route, request) => {
await wait()
const content = request.postData()
if (content != null) {
currentOrganizationProfilePicture = content
Expand All @@ -680,7 +713,8 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
return
}
})
await post(remoteBackendPaths.UPLOAD_FILE_PATH + '*', (_route, request) => {
await post(remoteBackendPaths.UPLOAD_FILE_PATH + '*', async (_route, request) => {
await wait()
/** The type for the JSON request payload for this endpoint. */
interface SearchParams {
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand All @@ -700,6 +734,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
})

await post(remoteBackendPaths.CREATE_SECRET_PATH + '*', async (_route, request) => {
await wait()
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.CreateSecretRequestBody = await request.postDataJSON()
Expand All @@ -709,7 +744,8 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {

// === Other endpoints ===

await patch(remoteBackendPaths.updateAssetPath(GLOB_ASSET_ID), (_route, request) => {
await patch(remoteBackendPaths.updateAssetPath(GLOB_ASSET_ID), async (_route, request) => {
await wait()
const assetId = request.url().match(/[/]assets[/]([^?]+)/)?.[1] ?? ''
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand All @@ -724,6 +760,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
}
})
await patch(remoteBackendPaths.associateTagPath(GLOB_ASSET_ID), async (_route, request) => {
await wait()
const assetId = request.url().match(/[/]assets[/]([^/?]+)/)?.[1] ?? ''
/** The type for the JSON request payload for this endpoint. */
interface Body {
Expand All @@ -748,6 +785,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
return json
})
await put(remoteBackendPaths.updateDirectoryPath(GLOB_DIRECTORY_ID), async (route, request) => {
await wait()
const directoryId = request.url().match(/[/]directories[/]([^?]+)/)?.[1] ?? ''
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand All @@ -767,13 +805,15 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
}
})
await delete_(remoteBackendPaths.deleteAssetPath(GLOB_ASSET_ID), async (route, request) => {
await wait()
const assetId = request.url().match(/[/]assets[/]([^?]+)/)?.[1] ?? ''
// This could be an id for an arbitrary asset, but pretend it's a
// `DirectoryId` to make TypeScript happy.
deleteAsset(backend.DirectoryId(assetId))
await route.fulfill({ status: HTTP_STATUS_NO_CONTENT })
})
await patch(remoteBackendPaths.UNDO_DELETE_ASSET_PATH, async (route, request) => {
await wait()
/** The type for the JSON request payload for this endpoint. */
interface Body {
readonly assetId: backend.AssetId
Expand All @@ -785,6 +825,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
await route.fulfill({ status: HTTP_STATUS_NO_CONTENT })
})
await post(remoteBackendPaths.CREATE_USER_PATH + '*', async (route, request) => {
await wait()
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.CreateUserRequestBody = await request.postDataJSON()
Expand All @@ -806,15 +847,20 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
await route.fulfill({ json: currentUser })
})
await put(remoteBackendPaths.UPDATE_CURRENT_USER_PATH + '*', async (_route, request) => {
await wait()
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.UpdateUserRequestBody = await request.postDataJSON()
if (currentUser && body.username != null) {
currentUser = { ...currentUser, name: body.username }
}
})
await get(remoteBackendPaths.USERS_ME_PATH + '*', () => currentUser)
await get(remoteBackendPaths.USERS_ME_PATH + '*', async () => {
await wait()
return currentUser
})
await patch(remoteBackendPaths.UPDATE_ORGANIZATION_PATH + '*', async (route, request) => {
await wait()
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.UpdateOrganizationRequestBody = await request.postDataJSON()
Expand All @@ -833,18 +879,21 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
}
})
await get(remoteBackendPaths.GET_ORGANIZATION_PATH + '*', async (route) => {
await wait()
await route.fulfill({
json: currentOrganization,
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
status: currentOrganization == null ? 404 : 200,
})
})
await post(remoteBackendPaths.CREATE_TAG_PATH + '*', (route) => {
await post(remoteBackendPaths.CREATE_TAG_PATH + '*', async (route) => {
await wait()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.CreateTagRequestBody = route.request().postDataJSON()
return addLabel(body.value, body.color)
})
await post(remoteBackendPaths.CREATE_PROJECT_PATH + '*', (_route, request) => {
await post(remoteBackendPaths.CREATE_PROJECT_PATH + '*', async (_route, request) => {
await wait()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.CreateProjectRequestBody = request.postDataJSON()
const title = body.projectName
Expand Down Expand Up @@ -879,7 +928,8 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
})
return json
})
await post(remoteBackendPaths.CREATE_DIRECTORY_PATH + '*', (_route, request) => {
await post(remoteBackendPaths.CREATE_DIRECTORY_PATH + '*', async (_route, request) => {
await wait()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const body: backend.CreateDirectoryRequestBody = request.postDataJSON()
const title = body.title
Expand Down Expand Up @@ -910,6 +960,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
})

await page.route('*', async (route) => {
await wait()
if (!isOnline) {
await route.abort('connectionfailed')
}
Expand Down
12 changes: 7 additions & 5 deletions app/dashboard/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import * as inputBindingsModule from '#/configurations/inputBindings'
import AuthProvider, * as authProvider from '#/providers/AuthProvider'
import BackendProvider, { useLocalBackend } from '#/providers/BackendProvider'
import DriveProvider from '#/providers/DriveProvider'
import DevtoolsProvider from '#/providers/EnsoDevtoolsProvider'
import { useHttpClient } from '#/providers/HttpClientProvider'
import InputBindingsProvider from '#/providers/InputBindingsProvider'
import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider'
Expand Down Expand Up @@ -91,10 +90,11 @@ import * as appBaseUrl from '#/utilities/appBaseUrl'
import * as eventModule from '#/utilities/event'
import LocalStorage from '#/utilities/LocalStorage'
import * as object from '#/utilities/object'
import { Path } from '#/utilities/path'

import { useInitAuthService } from '#/authentication/service'
import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal'
import { Path } from '#/utilities/path'
import { FeatureFlagsProvider } from '#/providers/FeatureFlagsProvider'

// ============================
// === Global configuration ===
Expand Down Expand Up @@ -492,7 +492,7 @@ function AppRouter(props: AppRouterProps) {
)

return (
<DevtoolsProvider>
<FeatureFlagsProvider>
<RouterProvider navigate={navigate}>
<SessionProvider
saveAccessToken={authService?.cognito.saveAccessToken.bind(authService.cognito) ?? null}
Expand All @@ -517,7 +517,9 @@ function AppRouter(props: AppRouterProps) {
{routes}
{detect.IS_DEV_MODE && (
<suspense.Suspense>
<devtools.EnsoDevtools />
<errorBoundary.ErrorBoundary>
<devtools.EnsoDevtools />
</errorBoundary.ErrorBoundary>
</suspense.Suspense>
)}
</errorBoundary.ErrorBoundary>
Expand All @@ -527,7 +529,7 @@ function AppRouter(props: AppRouterProps) {
</BackendProvider>
</SessionProvider>
</RouterProvider>
</DevtoolsProvider>
</FeatureFlagsProvider>
)
}

Expand Down
Loading
Loading