Skip to content

Commit

Permalink
Fix copy/delete/move
Browse files Browse the repository at this point in the history
  • Loading branch information
MrFlashAccount committed Aug 28, 2024
1 parent c12b705 commit a9d6989
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 559 deletions.
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 = 5_000) {
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
Loading

0 comments on commit a9d6989

Please sign in to comment.