Skip to content

Commit

Permalink
MC-1618: adding corpus admin query getSectionsWithSectionItems
Browse files Browse the repository at this point in the history
  • Loading branch information
katerinachinnappan committed Jan 22, 2025
1 parent b290d41 commit 318d9bc
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 64 deletions.
4 changes: 2 additions & 2 deletions servers/curated-corpus-api/schema-admin.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1257,9 +1257,9 @@ type Query {
getOpenGraphFields(url: Url!): OpenGraphFields

"""
Retrieves a Section with its associated SectionItems with the given external ID.
Retrieves a list of Sections with their corresponding SectionItems.
"""
getSectionWithSectionItems(externalId: ID!): Section
getSectionsWithSectionItems: [Section!]!
}

type Mutation {
Expand Down
4 changes: 2 additions & 2 deletions servers/curated-corpus-api/src/admin/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
} from '../../database/queries';
import { getOpenGraphFields } from './queries/OpenGraphFields';
import { hasTrustedDomain } from './queries/ApprovedItem/hasTrustedDomain';
import { getSectionWithSectionItems } from './queries/Section';
import { getSectionsWithSectionItems } from './queries/Section';
import { createOrUpdateSection } from './mutations/Section'
import { createSectionItem } from './mutations/SectionItem';

Expand Down Expand Up @@ -104,7 +104,7 @@ export const resolvers = {
getApprovedCorpusItemByUrl: getApprovedItemByUrl,
getScheduledSurfacesForUser: getScheduledSurfacesForUser,
getOpenGraphFields: getOpenGraphFields,
getSectionWithSectionItems: getSectionWithSectionItems,
getSectionsWithSectionItems: getSectionsWithSectionItems,
},
// Mutations that we need in the admin interface
Mutation: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ import {
createApprovedItemHelper,
} from '../../../../test/helpers';

import { GET_SECTION_WITH_SECTION_ITEMS } from '../sample-queries.gql';
import { GET_SECTIONS_WITH_SECTION_ITEMS } from '../sample-queries.gql';
import { MozillaAccessGroup } from 'content-common';
import { startServer } from '../../../../express';
import { IAdminContext } from '../../../context';

describe('queries: Section (getSectionWithSectionItems)', () => {
describe('queries: Section (getSectionsWithSectionItems)', () => {
let app: Express.Application;
let db: PrismaClient;
let graphQLUrl: string;
let server: ApolloServer<IAdminContext>;
let section: Section;
let sectionItem: SectionItem;
let section1: Section;
let section2: Section;
let sectionItem1: SectionItem;
let sectionItem2: SectionItem;
let approvedItem: ApprovedItem;

const headers = {
Expand All @@ -50,70 +52,92 @@ describe('queries: Section (getSectionWithSectionItems)', () => {
});

beforeEach(async () => {
section = await createSectionHelper(db, {
section1 = await createSectionHelper(db, {
externalId: 'bcg-456',
createSource: ActivitySource.ML,
});
section2 = await createSectionHelper(db, {
externalId: 'xyz-123',
createSource: ActivitySource.ML,
});
});

afterEach(async () => {
await clearDb(db);
});

it('should retrieve a Section with no SectionItems', async () => {
it('should retrieve all Sections with no SectionItems', async () => {
const result = await request(app)
.post(graphQLUrl)
.set(headers)
.send({
query: print(GET_SECTION_WITH_SECTION_ITEMS),
variables: { externalId: section.externalId },
query: print(GET_SECTIONS_WITH_SECTION_ITEMS),
});

expect(result.body.errors).toBeUndefined();
expect(result.body.data).not.toBeNull();

expect(result.body.data?.getSectionWithSectionItems.externalId).toEqual('bcg-456');
expect(result.body.data?.getSectionWithSectionItems.sectionItems.length).toEqual(0);
// There should be 2 Sections in the array
expect(result.body.data?.getSectionsWithSectionItems.length).toEqual(2);

// Both Sections should not have any SectionItems
expect(result.body.data?.getSectionsWithSectionItems[0].sectionItems).toEqual([]);
expect(result.body.data?.getSectionsWithSectionItems[1].sectionItems).toEqual([]);
});

it('should retrieve a Section with its SectionItem', async () => {
// Create a SectionItem
it('should retrieve all Sections with their corresponding SectionItems', async () => {
// Create a few SectionItems
approvedItem = await createApprovedItemHelper(db, {
title: '10 Reasons You Should Quit Social Media',
});

sectionItem = await createSectionItemHelper(db, {
sectionItem1 = await createSectionItemHelper(db, {
approvedItemId: approvedItem.id,
sectionId: section.id,
sectionId: section1.id,
rank: 1
});

sectionItem2 = await createSectionItemHelper(db, {
approvedItemId: approvedItem.id,
sectionId: section2.id,
rank: 1
});

const result = await request(app)
.post(graphQLUrl)
.set(headers)
.send({
query: print(GET_SECTION_WITH_SECTION_ITEMS),
variables: { externalId: section.externalId },
query: print(GET_SECTIONS_WITH_SECTION_ITEMS),
});

expect(result.body.errors).toBeUndefined();
expect(result.body.data).not.toBeNull();

expect(result.body.data?.getSectionWithSectionItems.externalId).toEqual('bcg-456');
expect(result.body.data?.getSectionWithSectionItems.sectionItems.length).toEqual(1);
expect(result.body.data?.getSectionWithSectionItems.sectionItems[0].externalId).toEqual(sectionItem.externalId);
// All Sections should be returned
expect(result.body.data?.getSectionsWithSectionItems.length).toEqual(2);
expect(result.body.data?.getSectionsWithSectionItems[0].externalId).toEqual('bcg-456');
expect(result.body.data?.getSectionsWithSectionItems[1].externalId).toEqual('xyz-123');

// Each Section should have a SectionItem
expect(result.body.data?.getSectionsWithSectionItems[0].sectionItems.length).toEqual(1);
expect(result.body.data?.getSectionsWithSectionItems[0].sectionItems[0].externalId).toEqual(sectionItem1.externalId);

expect(result.body.data?.getSectionsWithSectionItems[1].sectionItems.length).toEqual(1);
expect(result.body.data?.getSectionsWithSectionItems[1].sectionItems[0].externalId).toEqual(sectionItem2.externalId);
});

it('should return null if Section externalId is not found', async () => {
it('should return an empty array if no Sections found', async () => {
// clear db
await clearDb(db);

const result = await request(app)
.post(graphQLUrl)
.set(headers)
.send({
query: print(GET_SECTION_WITH_SECTION_ITEMS),
variables: { externalId: 'fake-external-id' },
query: print(GET_SECTIONS_WITH_SECTION_ITEMS),
});

expect(result.body.errors).toBeUndefined();
expect(result.body.data?.getSectionWithSectionItems).toBeNull();
expect(result.body.data?.getSectionsWithSectionItems).toEqual([]);
});
});
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import { AuthenticationError } from '@pocket-tools/apollo-utils';

import {
getSectionWithSectionItems as dbGetSectionWithSectionItems
getSectionsWithSectionItems as dbGetSectionsWithSectionItems
} from '../../../../database/queries';
import { Section } from '../../../../database/types';
import { ACCESS_DENIED_ERROR } from '../../../../shared/types';
import { IAdminContext } from '../../../context';

/**
* Retrieve a Section with its SectionItems. Returns null if the Section
* externalId is not found.
* Retrieve all Sections with their SectionItems. Returns empty array if no Sections found.
*
* @param parent
* @param externalId
* @param context
*/
export async function getSectionWithSectionItems(
export async function getSectionsWithSectionItems(
parent,
args,
context: IAdminContext,
): Promise<Section | null> {
): Promise<Section[]> {
// Check if the user does not have the permissions to access this query
if (
!context.authenticatedUser.hasReadOnly &&
!context.authenticatedUser.canWriteToCorpus()
) {
throw new AuthenticationError(ACCESS_DENIED_ERROR);
}
return await dbGetSectionWithSectionItems(context.db, args.externalId);
return await dbGetSectionsWithSectionItems(context.db);
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ export const GET_OPEN_GRAPH_FIELDS = gql`
}
`;

export const GET_SECTION_WITH_SECTION_ITEMS = gql`
query GetSectionWithSectionItems($externalId: ID!){
getSectionWithSectionItems(externalId: $externalId) {
export const GET_SECTIONS_WITH_SECTION_ITEMS = gql`
query GetSectionsWithSectionItems{
getSectionsWithSectionItems {
...SectionData
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { PrismaClient, Section } from '.prisma/client';

import { client } from '../client';
import { clearDb, createApprovedItemHelper } from '../../test/helpers';
import { getSectionWithSectionItems } from './Section';
import { getSectionsWithSectionItems } from './Section';
import { createSectionHelper, createSectionItemHelper } from '../../test/helpers';

describe('Section', () => {
let db: PrismaClient;
let section: Section;
let section1: Section;
let section2: Section;

beforeAll(async () => {
db = client();
Expand All @@ -20,16 +21,20 @@ describe('Section', () => {

beforeEach(async () => {
await clearDb(db);
section = await createSectionHelper(db, {});
section1 = await createSectionHelper(db, {});
section2 = await createSectionHelper(db, {});
});

describe('getSectionWithSectionItems', () => {
it('should retrieve a Section', async () => {
const result = await getSectionWithSectionItems(db, section.externalId);
describe('getSectionsWithSectionItems', () => {
it('should retrieve all Sections', async () => {
const result = await getSectionsWithSectionItems(db);

expect(result.externalId).toEqual(section.externalId);
// There should be 2 Sections returned in the array
expect(result.length).toEqual(2);
expect(result[0].externalId).toEqual(section1.externalId);
expect(result[1].externalId).toEqual(section2.externalId);
});
it('should retrieve a Section with its SectionItems', async () => {
it('should retrieve all Sections with their corresponding SectionItems', async () => {
// create a few SectionItems
const approvedItem1 = await createApprovedItemHelper(db, {
title: 'Fake Item!',
Expand All @@ -39,26 +44,33 @@ describe('Section', () => {
});
const sectionItem1 = await createSectionItemHelper(db, {
approvedItemId: approvedItem1.id,
sectionId: section.id,
sectionId: section1.id,
rank: 1
});
const sectionItem2 = await createSectionItemHelper(db, {
approvedItemId: approvedItem2.id,
sectionId: section.id,
sectionId: section2.id,
rank: 2
});

const result = await getSectionWithSectionItems(db, section.externalId);
const result = await getSectionsWithSectionItems(db);

expect(result.externalId).toEqual(section.externalId);
expect(result.sectionItems.length).toEqual(2);
expect(result.sectionItems[0].externalId).toEqual(sectionItem1.externalId);
expect(result.sectionItems[1].externalId).toEqual(sectionItem2.externalId);
// There should be 2 Sections returned in the array
expect(result.length).toEqual(2);
// Each Section should have 1 SectionItem in the array
expect(result[0].sectionItems.length).toEqual(1);
expect(result[1].sectionItems.length).toEqual(1);
// Check for correct SectionItems
expect(result[0].sectionItems[0].externalId).toEqual(sectionItem1.externalId);
expect(result[1].sectionItems[0].externalId).toEqual(sectionItem2.externalId);
});
it('should return null if Section externalId not found', async () => {
const result = await getSectionWithSectionItems(db, 'fake-external-id');
it('should return an empty array if there are no Sections found', async () => {
// clear db
await clearDb(db);

expect(result).toBeNull()
const result = await getSectionsWithSectionItems(db);

expect(result).toEqual([]);
});
});
});
14 changes: 6 additions & 8 deletions servers/curated-corpus-api/src/database/queries/Section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import { PrismaClient } from '.prisma/client';
import { Section } from '../types';

/**
* This query retrieves a Section by externalId & its associated SectionItems.
* Returns null if externalId is not found in the database.
* This query retrieves all Sections & their associated SectionItems.
* Returns an empty array if no Sections are found.
*
* @param db
* @param externalId
* @param username
*/
export async function getSectionWithSectionItems(
export async function getSectionsWithSectionItems(
db: PrismaClient,
externalId: string,
): Promise<Section | null> {
return await db.section.findUnique({
where: {externalId},
): Promise<Section[]> {
const sections = await db.section.findMany({
include: {
sectionItems: {
include: {
Expand All @@ -29,4 +26,5 @@ export async function getSectionWithSectionItems(
}
}
});
return sections;
}
2 changes: 1 addition & 1 deletion servers/curated-corpus-api/src/database/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export {
getScheduledItems,
getItemsForScheduledSurface,
} from './ScheduledItem';
export { getSectionWithSectionItems } from './Section';
export { getSectionsWithSectionItems } from './Section';

0 comments on commit 318d9bc

Please sign in to comment.