Skip to content

Commit

Permalink
feat: support additional atlas fields on backend (#410) (#412)
Browse files Browse the repository at this point in the history
  • Loading branch information
hunterckx authored Aug 14, 2024
1 parent 55b7711 commit 95ee0fd
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 4 deletions.
55 changes: 55 additions & 0 deletions __tests__/api-atlases-create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ jest.mock("../app/services/cellxgene");
jest.mock("../app/utils/pg-app-connect-config");

const NEW_ATLAS_DATA: NewAtlasData = {
cellxgeneAtlasCollection: "7a223dd3-a422-4f4b-a437-90b9a3b00ba8",
codeLinks: [{ url: "https://example.com/new-atlas-foo" }],
description: "foo bar baz baz foo bar",
highlights: "bar foo baz baz baz foo",
integrationLead: [],
network: "eye",
shortName: "test",
Expand Down Expand Up @@ -260,6 +263,51 @@ describe("/api/atlases/create", () => {
).toEqual(400);
});

it("returns error 400 when cellxgene id is not a uuid", async () => {
expect(
(
await doCreateTest(
USER_CONTENT_ADMIN,
{
...NEW_ATLAS_DATA,
cellxgeneAtlasCollection: "not-a-uuid",
},
true
)
)._getStatusCode()
).toEqual(400);
});

it("returns error 400 when link url is not a url", async () => {
expect(
(
await doCreateTest(
USER_CONTENT_ADMIN,
{
...NEW_ATLAS_DATA,
codeLinks: [{ url: "not-a-url" }],
},
true
)
)._getStatusCode()
).toEqual(400);
});

it("returns error 400 when highlights are too long", async () => {
expect(
(
await doCreateTest(
USER_CONTENT_ADMIN,
{
...NEW_ATLAS_DATA,
highlights: "x".repeat(10001),
},
true
)
)._getStatusCode()
).toEqual(400);
});

it("creates and returns atlas entry with no integration leads", async () => {
await testSuccessfulCreate(NEW_ATLAS_DATA);
});
Expand Down Expand Up @@ -291,9 +339,16 @@ async function testSuccessfulCreate(atlasData: NewAtlasData): Promise<void> {
expect(newAtlasFromDb.target_completion).toEqual(
atlasData.targetCompletion ? new Date(atlasData.targetCompletion) : null
);
expect(newAtlasFromDb.overview.cellxgeneAtlasCollection).toEqual(
atlasData.cellxgeneAtlasCollection ?? null
);
expect(newAtlasFromDb.overview.codeLinks).toEqual(atlasData.codeLinks ?? []);
expect(newAtlasFromDb.overview.description).toEqual(
atlasData.description ?? ""
);
expect(newAtlasFromDb.overview.highlights).toEqual(
atlasData.highlights ?? ""
);
expect(newAtlasFromDb.overview.integrationLead).toEqual(
atlasData.integrationLead
);
Expand Down
17 changes: 13 additions & 4 deletions __tests__/api-atlases-id.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ const ATLAS_DRAFT_EDIT: AtlasEditData = {
wave: "3",
};

const ATLAS_PUBLIC_EDIT_NO_TARGET_COMPLETION: AtlasEditData = {
const ATLAS_PUBLIC_EDIT_NO_TARGET_COMPLETION_OR_CELLXGENE: AtlasEditData = {
codeLinks: ATLAS_DRAFT.codeLinks,
description: ATLAS_DRAFT.description,
highlights: ATLAS_DRAFT.highlights,
integrationLead: ATLAS_DRAFT.integrationLead,
network: ATLAS_DRAFT.network,
shortName: ATLAS_DRAFT.shortName,
Expand All @@ -92,6 +94,8 @@ const ATLAS_PUBLIC_EDIT_NO_TARGET_COMPLETION: AtlasEditData = {
};

const ATLAS_WITH_MISC_SOURCE_STUDIES_EDIT: AtlasEditData = {
cellxgeneAtlasCollection:
ATLAS_WITH_MISC_SOURCE_STUDIES.cellxgeneAtlasCollection,
integrationLead: ATLAS_WITH_MISC_SOURCE_STUDIES.integrationLead,
network: ATLAS_WITH_MISC_SOURCE_STUDIES.network,
shortName: ATLAS_WITH_MISC_SOURCE_STUDIES.shortName,
Expand Down Expand Up @@ -388,16 +392,16 @@ describe(TEST_ROUTE, () => {
await testSuccessfulEdit(ATLAS_DRAFT, ATLAS_DRAFT_EDIT, 2);
});

it("PUT updates and returns atlas entry with target completion removed", async () => {
it("PUT updates and returns atlas entry with target completion and CELLxGENE collection removed", async () => {
const updatedAtlas = await testSuccessfulEdit(
ATLAS_PUBLIC,
ATLAS_PUBLIC_EDIT_NO_TARGET_COMPLETION,
ATLAS_PUBLIC_EDIT_NO_TARGET_COMPLETION_OR_CELLXGENE,
0
);
expect(updatedAtlas.target_completion).toBeNull();
});

it("PUT updates and returns atlas entry with description removed", async () => {
it("PUT updates and returns atlas entry with description, code links, and highlights removed", async () => {
const updatedAtlas = await testSuccessfulEdit(
ATLAS_WITH_MISC_SOURCE_STUDIES,
ATLAS_WITH_MISC_SOURCE_STUDIES_EDIT,
Expand Down Expand Up @@ -430,7 +434,12 @@ async function testSuccessfulEdit(

const updatedOverview = updatedAtlasFromDb.overview;

expect(updatedOverview.cellxgeneAtlasCollection).toEqual(
editData.cellxgeneAtlasCollection ?? null
);
expect(updatedOverview.codeLinks).toEqual(editData.codeLinks ?? []);
expect(updatedOverview.description).toEqual(editData.description ?? "");
expect(updatedOverview.highlights).toEqual(editData.highlights ?? "");
expect(updatedOverview.integrationLead).toEqual(editData.integrationLead);
expect(updatedOverview.network).toEqual(editData.network);
expect(updatedOverview.shortName).toEqual(editData.shortName);
Expand Down
14 changes: 14 additions & 0 deletions app/apis/catalog/hca-atlas-tracker/common/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ export type APIValue = (typeof API)[APIKey];

export interface HCAAtlasTrackerListAtlas {
bioNetwork: NetworkKey;
cellxgeneAtlasCollection: string | null;
codeLinks: LinkInfo[];
completedTaskCount: number;
componentAtlasCount: number;
description: string;
highlights: string;
id: string;
integrationLeadEmail: IntegrationLead["email"][];
integrationLeadName: IntegrationLead["name"][];
Expand All @@ -27,9 +30,12 @@ export interface HCAAtlasTrackerListAtlas {

export interface HCAAtlasTrackerAtlas {
bioNetwork: NetworkKey;
cellxgeneAtlasCollection: string | null;
codeLinks: LinkInfo[];
completedTaskCount: number;
componentAtlasCount: number;
description: string;
highlights: string;
id: string;
integrationLead: IntegrationLead[];
publication: {
Expand Down Expand Up @@ -217,8 +223,11 @@ export interface HCAAtlasTrackerDBAtlasWithComponentAtlases
}

export interface HCAAtlasTrackerDBAtlasOverview {
cellxgeneAtlasCollection: string | null;
codeLinks: LinkInfo[];
completedTaskCount: number;
description: string;
highlights: string;
integrationLead: IntegrationLead[];
network: NetworkKey;
shortName: string;
Expand Down Expand Up @@ -455,6 +464,11 @@ export interface IntegrationLead {
name: string;
}

export interface LinkInfo {
label?: string;
url: string;
}

export type SourceDatasetId = string;

export type SourceStudyId = string;
Expand Down
8 changes: 8 additions & 0 deletions app/apis/catalog/hca-atlas-tracker/common/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ import { ROLE } from "./entities";
* Schema for data used to create a new atlas.
*/
export const newAtlasSchema = object({
cellxgeneAtlasCollection: string().uuid().nullable(),
codeLinks: array().of(
object({
label: string(),
url: string().url().required(),
}).required()
),
description: string().max(10000),
highlights: string().max(10000),
integrationLead: array()
.of(
object({
Expand Down
6 changes: 6 additions & 0 deletions app/apis/catalog/hca-atlas-tracker/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ export function atlasInputMapper(
): HCAAtlasTrackerListAtlas {
return {
bioNetwork: apiAtlas.bioNetwork,
cellxgeneAtlasCollection: apiAtlas.cellxgeneAtlasCollection,
codeLinks: apiAtlas.codeLinks,
completedTaskCount: apiAtlas.completedTaskCount,
componentAtlasCount: apiAtlas.componentAtlasCount,
description: apiAtlas.description,
highlights: apiAtlas.highlights,
id: apiAtlas.id,
integrationLeadEmail: apiAtlas.integrationLead.map(({ email }) => email),
integrationLeadName: apiAtlas.integrationLead.map(({ name }) => name),
Expand All @@ -68,9 +71,12 @@ export function dbAtlasToApiAtlas(
): HCAAtlasTrackerAtlas {
return {
bioNetwork: dbAtlas.overview.network,
cellxgeneAtlasCollection: dbAtlas.overview.cellxgeneAtlasCollection,
codeLinks: dbAtlas.overview.codeLinks,
completedTaskCount: dbAtlas.overview.completedTaskCount,
componentAtlasCount: dbAtlas.component_atlas_count,
description: dbAtlas.overview.description,
highlights: dbAtlas.overview.highlights,
id: dbAtlas.id,
integrationLead: dbAtlas.overview.integrationLead,
publication: {
Expand Down
3 changes: 3 additions & 0 deletions app/services/atlases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ export async function atlasInputDataToDbData(
): Promise<AtlasInputDbData> {
return {
overviewData: {
cellxgeneAtlasCollection: inputData.cellxgeneAtlasCollection ?? null,
codeLinks: inputData.codeLinks ?? [],
description: inputData.description ?? "",
highlights: inputData.highlights ?? "",
integrationLead: inputData.integrationLead,
network: inputData.network,
shortName: inputData.shortName,
Expand Down
13 changes: 13 additions & 0 deletions migrations/1723321794859_atlas-highlights-code-cellxgene.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { MigrationBuilder } from "node-pg-migrate";

export function up(pgm: MigrationBuilder): void {
pgm.sql(
`UPDATE hat.atlases SET overview=overview||'{"cellxgeneAtlasCollection":null,"codeLinks":[],"highlights":""}'`
);
}

export function down(pgm: MigrationBuilder): void {
pgm.sql(
`UPDATE hat.atlases SET overview=overview-'cellxgeneAtlasCollection'-'codeLinks'-'highlights'`
);
}
20 changes: 20 additions & 0 deletions testing/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1537,7 +1537,10 @@ export const INTEGRATION_LEAD_BAZ_BAZ = {
};

export const ATLAS_DRAFT: TestAtlas = {
cellxgeneAtlasCollection: null,
codeLinks: [],
description: "bar baz baz foo baz",
highlights: "",
id: ATLAS_ID_DRAFT,
integrationLead: [
{
Expand All @@ -1562,7 +1565,10 @@ export const ATLAS_DRAFT: TestAtlas = {
};

export const ATLAS_PUBLIC: TestAtlas = {
cellxgeneAtlasCollection: "354564bb-52cb-4dea-8e2e-d3d707ca3b87",
codeLinks: [{ label: "foo", url: "https://example.com/atlas-public-foo" }],
description: "foo foo bar bar foo",
highlights: "bar foo baz foo foo bar baz",
id: ATLAS_ID_PUBLIC,
integrationLead: [
{
Expand All @@ -1584,7 +1590,10 @@ export const ATLAS_PUBLIC: TestAtlas = {
};

export const ATLAS_WITH_IL: TestAtlas = {
cellxgeneAtlasCollection: null,
codeLinks: [],
description: "foo baz bar baz foo baz",
highlights: "",
id: "798b563d-16ff-438a-8e15-77be05b1f8ec",
integrationLead: [INTEGRATION_LEAD_BAZ],
network: "heart",
Expand All @@ -1596,7 +1605,12 @@ export const ATLAS_WITH_IL: TestAtlas = {
};

export const ATLAS_WITH_MISC_SOURCE_STUDIES: TestAtlas = {
cellxgeneAtlasCollection: "5aa910ee-23d7-419e-b2a4-8362dc058426",
codeLinks: [
{ url: "https://example.com/atlas-with-misc-source-studies-foo" },
],
description: "bar foo bar bar foo baz",
highlights: "foo foo foo foo bar foo bar",
id: ATLAS_ID_WITH_MISC_SOURCE_STUDIES,
integrationLead: [INTEGRATION_LEAD_BAZ_BAZ],
network: "adipose",
Expand All @@ -1623,7 +1637,10 @@ export const ATLAS_WITH_MISC_SOURCE_STUDIES: TestAtlas = {
};

export const ATLAS_WITH_SOURCE_STUDY_VALIDATIONS_A: TestAtlas = {
cellxgeneAtlasCollection: null,
codeLinks: [],
description: "foo baz baz bar foo bar",
highlights: "",
id: "7ce0814d-606c-475b-942a-0f72ff8c5c0b",
integrationLead: [],
network: "organoid",
Expand All @@ -1641,7 +1658,10 @@ export const ATLAS_WITH_SOURCE_STUDY_VALIDATIONS_A: TestAtlas = {
};

export const ATLAS_WITH_SOURCE_STUDY_VALIDATIONS_B: TestAtlas = {
cellxgeneAtlasCollection: null,
codeLinks: [],
description: "baz foo baz foo bar bar foo",
highlights: "",
id: "9766683a-3c8d-4ec8-b8b5-3fceb8fe0d31",
integrationLead: [],
network: "gut",
Expand Down
4 changes: 4 additions & 0 deletions testing/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
DOI_STATUS,
HCAAtlasTrackerDBUnpublishedSourceStudyInfo,
IntegrationLead,
LinkInfo,
NetworkKey,
PublicationInfo,
ROLE,
Expand All @@ -20,7 +21,10 @@ export interface TestUser {
}

export interface TestAtlas {
cellxgeneAtlasCollection: string | null;
codeLinks: LinkInfo[];
description: string;
highlights: string;
id: string;
integrationLead: IntegrationLead[];
network: NetworkKey;
Expand Down
8 changes: 8 additions & 0 deletions testing/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ export function makeTestAtlasOverview(
atlas: TestAtlas
): HCAAtlasTrackerDBAtlasOverview {
return {
cellxgeneAtlasCollection: atlas.cellxgeneAtlasCollection,
codeLinks: atlas.codeLinks,
completedTaskCount: 0,
description: atlas.description,
highlights: atlas.highlights,
integrationLead: atlas.integrationLead,
network: atlas.network,
shortName: atlas.shortName,
Expand Down Expand Up @@ -258,7 +261,12 @@ export function expectApiAtlasToMatchTest(
apiAtlas: HCAAtlasTrackerAtlas,
testAtlas: TestAtlas
): void {
expect(apiAtlas.cellxgeneAtlasCollection).toEqual(
testAtlas.cellxgeneAtlasCollection
);
expect(apiAtlas.codeLinks).toEqual(testAtlas.codeLinks);
expect(apiAtlas.description).toEqual(testAtlas.description);
expect(apiAtlas.highlights).toEqual(testAtlas.highlights);
expect(apiAtlas.id).toEqual(testAtlas.id);
expect(apiAtlas.integrationLead).toEqual(testAtlas.integrationLead);
expect(apiAtlas.bioNetwork).toEqual(testAtlas.network);
Expand Down

0 comments on commit 95ee0fd

Please sign in to comment.