Skip to content

Commit

Permalink
Implement community board (flyer tests) [2/7] (#84)
Browse files Browse the repository at this point in the history
* Begin implementing FlyerRepo

- implemented basic FlyerRepo functions
- updated Flyer model to support uploading in app instead of through a google form

* Implement flyers for community board

- alphabetized imports and fields
- finished implementing flyers for community board

* Implement jest testing for flyers

- created jest unit testing for FlyerRepo
- created FlyerFactory to help with jest testing

* Remove isFiltered field from Flyer entity

- removed redundant isFiltered field from Flyer entity (already checked in microservice)
- updated FlyerRepo and jest testing to reflect changes

* Alphabetize imports and exports

- alphabetized imports and exports in FlyerRepo, flyer.test, and FlyerFactory

* Revert merge conflict changes

- reverted merge conflict changes (accept incoming when actually wanted to keep current)

* Address review comments

- alphabetize imports
- add unit test cases for FlyerRepo including searching for 0 flyers and maximum limit in response
- added unit test case for FlyerRepo.getTrendingFlyers

* Address review comments (Shungo)

- added spaces between test cases
  • Loading branch information
isaachan100 authored Apr 25, 2023
1 parent e012894 commit 34f1bd8
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/repos/FlyerRepo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import Filter from 'bad-words';
import Fuse from 'fuse.js';

import { ObjectId } from 'mongodb';

import { Flyer, FlyerModel } from '../entities/Flyer';
import {
DEFAULT_LIMIT,
DEFAULT_OFFSET,
FILTERED_WORDS,
MAX_NUM_DAYS_OF_TRENDING_ARTICLES,
} from '../common/constants';
import { Flyer, FlyerModel } from '../entities/Flyer';
import { OrganizationModel } from '../entities/Organization';

const { IS_FILTER_ACTIVE } = process.env;
Expand Down
66 changes: 66 additions & 0 deletions src/tests/data/FlyerFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable no-underscore-dangle */
import { _ } from 'underscore';
import { faker } from '@faker-js/faker';

import FactoryUtils from './FactoryUtils';
import { Flyer } from '../../entities/Flyer';
import OrganizationFactory from './OrganizationFactory';

class FlyerFactory {
public static async create(n: number): Promise<Flyer[]> {
/**
* Returns a list of n number of random Flyer objects
*
* @param n The number of desired random Flyer objects
* @returns A Promise of the list of n number of random Flyer objects
*/
return Promise.all(FactoryUtils.create(n, FlyerFactory.fake));
}

public static async createSpecific(
n: number,
newMappings: { [key: string]: any },
): Promise<Flyer[]> {
/**
* Returns a list of n number of random Flyer objects with specified
* fields values in newMappings
*
* @param n The number of desired random Flyer objects
* @param newMappings The specified values for Flyer parameters [key]
* @returns A Promise of the list of n number of random Flyer objects
*/
const arr = await FlyerFactory.create(n);
return arr.map((x) => {
const newDoc = x;
Object.entries(newMappings).forEach(([k, v]) => {
newDoc[k] = v;
});
return newDoc;
});
}

public static async fake(): Promise<Flyer> {
/**
* Returns a Flyer with random values in its instance variables
*
* @returns The Flyer object with random values in its instance variables
*/
const fakeFlyer = new Flyer();
const exampleOrg = await OrganizationFactory.getRandomOrganization();

fakeFlyer.date = faker.date.past();
fakeFlyer.imageURL = faker.image.cats();
fakeFlyer.description = faker.datatype.string();
fakeFlyer.location = faker.datatype.string();
fakeFlyer.organization = exampleOrg;
fakeFlyer.organizationSlug = exampleOrg.slug;
fakeFlyer.title = faker.commerce.productDescription();
fakeFlyer.isTrending = _.sample([true, false]);
fakeFlyer.nsfw = _.sample([true, false]);
fakeFlyer.shoutouts = _.random(0, 50);
fakeFlyer.trendiness = 0;

return fakeFlyer;
}
}
export default FlyerFactory;
206 changes: 206 additions & 0 deletions src/tests/flyer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable dot-notation */

import { faker } from '@faker-js/faker';
import { dbConnection, disconnectDB } from './data/TestingDBConnection';
import { DEFAULT_LIMIT } from '../common/constants';
import FactoryUtils from './data/FactoryUtils';
import FlyerFactory from './data/FlyerFactory';
import { FlyerModel } from '../entities/Flyer';
import FlyerRepo from '../repos/FlyerRepo';
import OrganizationFactory from './data/OrganizationFactory';
import OrganizationRepo from '../repos/OrganizationRepo';

beforeAll(async () => {
await dbConnection();
await OrganizationRepo.addOrganizationsToDB();
await FlyerModel.createCollection();
});

beforeEach(async () => {
await FlyerModel.deleteMany({});
});

afterAll(async () => {
FlyerModel.deleteMany({}).then(disconnectDB);
});

describe('getAllFlyer tests:', () => {
test('getAllFlyers - No flyers', async () => {
const getFlyersResponse = await FlyerRepo.getAllFlyers();
expect(getFlyersResponse).toHaveLength(0);
});

test('getAllFlyers - 5 flyers', async () => {
const flyers = await FlyerFactory.create(5);
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.getAllFlyers();
expect(getFlyersResponse).toHaveLength(5);
});

test('getAllFlyers limit 2', async () => {
const flyers = await FlyerFactory.create(3);
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.getAllFlyers(0, 2);
expect(getFlyersResponse).toHaveLength(2);
});

test('getAllFlyers - Sort by date desc, offset 2, limit 2', async () => {
const flyers = await FlyerFactory.create(5);
flyers.sort(FactoryUtils.compareByDate);
await FlyerModel.insertMany(flyers);

const flyerTitles = FactoryUtils.mapToValue(flyers.slice(2, 4), 'title'); // offset=2, limit=2

const getFlyersResponse = await FlyerRepo.getAllFlyers(2, 2);
const respTitles = FactoryUtils.mapToValue(getFlyersResponse, 'title');

expect(respTitles).toEqual(flyerTitles);
});
});

describe('getFlyer(s)ByID(s) tests:', () => {
test('getFlyerByID - 1 flyer', async () => {
const flyers = await FlyerFactory.create(1);
const insertOutput = await FlyerModel.insertMany(flyers);
const id = insertOutput[0]._id;

const getFlyersResponse = await FlyerRepo.getFlyerByID(id);
expect(getFlyersResponse.title).toEqual(flyers[0].title);
});

test('getFlyersByIDs - 3 flyers', async () => {
const flyers = await FlyerFactory.create(3);
const insertOutput = await FlyerModel.insertMany(flyers);
const ids = FactoryUtils.mapToValue(insertOutput, '_id');
const getFlyersResponse = await FlyerRepo.getFlyersByIDs(ids);

expect(FactoryUtils.mapToValue(getFlyersResponse, 'title')).toEqual(
FactoryUtils.mapToValue(flyers, 'title'),
);
});
});

describe('getFlyersByOrganizationSlug(s) tests', () => {
test('getFlyersByOrganizationSlug - 1 organization, 1 flyer', async () => {
const org = await OrganizationFactory.getRandomOrganization();
const flyers = await FlyerFactory.createSpecific(1, {
organizationSlug: org.slug,
organization: org,
});
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.getFlyersByOrganizationSlug(org.slug);
expect(getFlyersResponse[0].title).toEqual(flyers[0].title);
});

test('getFlyersByOrganizationSlug - 1 organization, 3 flyers', async () => {
const org = await OrganizationFactory.getRandomOrganization();
const flyers = (
await FlyerFactory.createSpecific(3, {
organizationSlug: org.slug,
organization: org,
})
).sort(FactoryUtils.compareByDate);

await FlyerModel.insertMany(flyers);
const getFlyersResponse = await FlyerRepo.getFlyersByOrganizationSlug(org.slug);

expect(FactoryUtils.mapToValue(getFlyersResponse, 'title')).toEqual(
FactoryUtils.mapToValue(flyers, 'title'),
);
});

test('getFlyersByOrganizationSlugs - many organizations, 5 flyers', async () => {
const flyers = (await FlyerFactory.create(3)).sort(FactoryUtils.compareByDate);

await FlyerModel.insertMany(flyers);
const getFlyersResponse = await FlyerRepo.getFlyersByOrganizationSlug(
FactoryUtils.mapToValue(flyers, 'organizationSlug'),
);

expect(FactoryUtils.mapToValue(getFlyersResponse, 'title')).toEqual(
FactoryUtils.mapToValue(flyers, 'title'),
);
});
});

describe('getFlyersAfterDate tests', () => {
test('getFlyersAfterDate - filter 1 flyer', async () => {
const today = new Date();
let flyers = await FlyerFactory.createSpecific(1, {
date: faker.date.recent(1), // 1 day ago
});
flyers = flyers.concat(
await FlyerFactory.createSpecific(1, {
date: faker.date.past(1, today.getDate() - 2), // 1 year ago
}),
);
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.getFlyersAfterDate(
faker.date.recent(2, today.getDate() - 1).toString(),
); // find flyers from after 2 days ago
expect(getFlyersResponse[0].title).toEqual(flyers[0].title);
});
});

describe('searchFlyer tests', () => {
test('searchFlyer - 1 flyer', async () => {
const flyers = await FlyerFactory.create(1);
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.searchFlyers(flyers[0].title);
expect(getFlyersResponse[0].title).toEqual(flyers[0].title);
});

test('searchFlyer - expect 0 flyers', async () => {
const flyers = await FlyerFactory.create(3);
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.searchFlyers(Math.random().toString().substr(3, 20));
expect(getFlyersResponse).toHaveLength(0);
});

test('searchFlyer - return at most limit number of flyers', async () => {
const flyers = await FlyerFactory.createSpecific(DEFAULT_LIMIT + 1, {
title: 'faker',
});
await FlyerModel.insertMany(flyers);

const getFlyersResponse = await FlyerRepo.searchFlyers('faker');
expect(getFlyersResponse).toHaveLength(DEFAULT_LIMIT);
});
});

describe('incrementShoutouts tests', () => {
test('incrementShoutouts - Shoutout 1 flyer', async () => {
const flyers = await FlyerFactory.create(1);
const oldShoutouts = flyers[0].shoutouts;
const insertOutput = await FlyerModel.insertMany(flyers);

await FlyerRepo.incrementShoutouts(insertOutput[0]._id);

const getFlyersResponse = await FlyerRepo.getFlyerByID(insertOutput[0]._id);
expect(getFlyersResponse.shoutouts).toEqual(oldShoutouts + 1);
});
});

describe('getTrending tests', () => {
test('getTrendingFlyers - get 5 trending flyers', async () => {
const trendingFlyers = await FlyerFactory.createSpecific(5, {
isTrending: true,
});
const notTrendingFlyers = await FlyerFactory.createSpecific(5, {
isTrending: false,
});
await FlyerModel.insertMany(trendingFlyers);
await FlyerModel.insertMany(notTrendingFlyers);

const getFlyersResponse = await FlyerRepo.getTrendingFlyers();
expect(getFlyersResponse).toHaveLength(5);
});
});

0 comments on commit 34f1bd8

Please sign in to comment.