From 24b02b841e0a4df7fb9575d68132bcdbb4c45759 Mon Sep 17 00:00:00 2001 From: Chegele Date: Tue, 18 Jul 2023 20:21:59 -0400 Subject: [PATCH] Forum unit tests --- .../reputation/components/forum.spec.ts | 175 ++++++++++++++++++ src/services/reputation/components/forum.ts | 68 +++++-- 2 files changed, 225 insertions(+), 18 deletions(-) create mode 100644 src/services/reputation/components/forum.spec.ts diff --git a/src/services/reputation/components/forum.spec.ts b/src/services/reputation/components/forum.spec.ts new file mode 100644 index 0000000..c3357bc --- /dev/null +++ b/src/services/reputation/components/forum.spec.ts @@ -0,0 +1,175 @@ + +import { Vertex } from '../graph/vertex'; +import { Edge } from '../graph/edge'; +import { Citation } from './citation'; +import { Forum } from './forum'; +import { Member } from './member'; +import { Post } from './post'; + +function implementsVertex(obj: Object) { + return "id" in obj && "data" in obj && "citations" in obj; +} + +function implementsEdge(obj: Object) { + const properties = ["id", "directional", "parentVertex", "childVertex", "getAdjacent"]; + for (const property of properties) if (!(property in obj)) return false; + return true; +} + +describe('Reputation Service Forum', () => { + + let testingForum: Forum; + let testingPostA: Post; + let testingPostB: Post; + let testingCitation: Citation; + + const TEST_AUTHOR_A = new Member("testAuthorA"); + const TEST_TITLE_A = "The Hitchhiker's Guide to the Galaxy"; + const TEST_CONTENT_A = "The ships hung in the sky in much the same way that bricks don't."; + + const TEST_AUTHOR_B = new Member("testAuthorB"); + const TEST_TITLE_B = "The Restaurant at the End of the Universe"; + const TEST_CONTENT_B = "The story so far: In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."; + + beforeEach(() => { + testingPostA = new Post("testingPostA", TEST_TITLE_A, TEST_CONTENT_A, TEST_AUTHOR_A); + testingPostB = new Post("testingPostB", TEST_TITLE_B, TEST_CONTENT_B, TEST_AUTHOR_B); + testingCitation = new Citation("testingCitation", testingPostA, testingPostB, 10); + testingForum = new Forum( + {}, + [testingPostA, testingPostB], + [testingCitation], + [TEST_AUTHOR_A, TEST_AUTHOR_B] + ); + }); + + it('should be able to get all posts', () => { + const posts = testingForum.getAllPosts(); + expect(posts.length).toBe(2); + expect(posts[0]).toBe(testingPostA); + expect(posts[1]).toBe(testingPostB); + }); + + it('should be able to get a post by id', () => { + const post = testingForum.getPost("testingPostA"); + expect(post).toBe(testingPostA); + }); + + it('should be able to add a post', () => { + const newPost = new Post("newPost", "newTitle", "newContent", TEST_AUTHOR_A); + testingForum.addPost(newPost); + expect(testingForum.getPost("newPost")).toBe(newPost); + }); + + it('should be able to delete a post', () => { + testingForum.deletePost(testingPostA); + expect(testingForum.getPost("testingPostA")).toBeUndefined(); + }); + + it('should be able to get all citations', () => { + const citations = testingForum.getAllCitations(); + expect(citations.length).toBe(1); + expect(citations[0]).toBe(testingCitation); + }); + + it('should be able to get a citation by id', () => { + const citation = testingForum.getCitation("testingCitation"); + expect(citation).toBe(testingCitation); + }); + + it('should be able to add a citation', () => { + const newCitation = new Citation("newCitation", testingPostA, testingPostB, 10); + testingForum.addCitation(newCitation); + expect(testingForum.getCitation("newCitation")).toBe(newCitation); + }); + + it('should be able to delete a citation', () => { + testingForum.deleteCitation(testingCitation); + expect(testingForum.getCitation("testingCitation")).toBeUndefined(); + }); + + it('should be able to get all members', () => { + const members = testingForum.getAllMembers(); + expect(members.length).toBe(2); + expect(members[0]).toBe(TEST_AUTHOR_A); + expect(members[1]).toBe(TEST_AUTHOR_B); + }); + + it('should be able to get a member by id', () => { + const member = testingForum.getMember("testAuthorA"); + expect(member).toBe(TEST_AUTHOR_A); + }); + + it('should be able to add a member', () => { + const newMember = new Member("newMember"); + testingForum.addMember(newMember); + expect(testingForum.getMember("newMember")).toBe(newMember); + }); + + it('should be able to delete a member', () => { + testingForum.deleteMember(TEST_AUTHOR_A); + expect(testingForum.getMember("testAuthorA")).toBeUndefined(); + }); + + it('should be able to get all posts as vertices', () => { + const vertices = testingForum.getAllVertices(); + const vertex = vertices[0]; + expect(vertices.length).toBe(2); + expect(implementsVertex(vertex)).toBe(true); + }); + + it('should be able to get a post as a vertex by id', () => { + const vertex = testingForum.getVertex("testingPostA"); + expect(vertex).toBe(testingPostA); + expect(implementsVertex(vertex)).toBe(true); + }); + + it('should be able to add a post as a vertex', () => { + const newPost = new Post("newPost", "newTitle", "newContent", TEST_AUTHOR_A); + testingForum.addVertex(newPost); + expect(testingForum.getVertex("newPost")).toBe(newPost); + }); + + it('should be able to delete a post as a vertex', () => { + testingForum.deleteVertex(testingPostA); + expect(testingForum.getVertex("testingPostA")).toBeUndefined(); + }); + + it('should be able to get all citations as edges', () => { + const edges = testingForum.getAllEdges(); + const edge = edges[0]; + expect(edges.length).toBe(1); + expect(implementsEdge(edge)).toBe(true); + }); + + it('should be able to get a citation as an edge by id', () => { + const edge = testingForum.getEdge("testingCitation"); + expect(edge).toBe(testingCitation); + expect(implementsEdge(edge)).toBe(true); + }); + + it('should be able to add a citation as an edge', () => { + const newCitation = new Citation("newCitation", testingPostA, testingPostB, 10); + testingForum.addEdge(newCitation); + expect(testingForum.getEdge("newCitation")).toBe(newCitation); + }); + + it('should be able to delete a citation as an edge', () => { + testingForum.deleteEdge(testingCitation); + expect(testingForum.getEdge("testingCitation")).toBeUndefined(); + }); + + it('should be able to get the branch of a post', () => { + //TODO: implement + }); + + it('should be able to asses the reputation impact of a post', () => { + //TODO: implement + }); + + it('should be able to propagate reputation rewarded through a post', () => { + //TODO: implement + }); + + +}); \ No newline at end of file diff --git a/src/services/reputation/components/forum.ts b/src/services/reputation/components/forum.ts index f9b81d9..56749bc 100644 --- a/src/services/reputation/components/forum.ts +++ b/src/services/reputation/components/forum.ts @@ -1,15 +1,20 @@ import { Edge, Graph, Vertex } from "../graph.interface"; import { Citation } from "./citation"; -import { Member } from "./member"; +import { LedgerEntry, Member } from "./member"; import { Post } from "./post"; -export default class Forum implements Graph { +export class Forum implements Graph { private posts = new Map(); private citations = new Map(); private members = new Map(); + private ledger = new Map(); - constructor(posts: Post[], citations: Citation[], members: Member[]) { + //TODO: Need to define the forum parameters + public params = {}; + + constructor(params: object, posts: Post[], citations: Citation[], members: Member[]) { + this.params = params; posts.forEach(post => this.posts.set(post.id, post)); citations.forEach(citation => this.citations.set(citation.id, citation)); members.forEach(member => this.members.set(member.id, member)); @@ -41,13 +46,9 @@ export default class Forum implements Graph { } public deletePost(post: string | Post) { - if (typeof post === "string") this.posts.delete(post); - else for (const [key, val] of this.posts.entries()) { - if (val === post) { - this.posts.delete(key); - break; - } - } + if (typeof post === "string") post = this.posts.get(post); + for (const citation of post.citations) this.deleteCitation(citation); + this.posts.delete(post.id); } public getAllCitations() { @@ -59,17 +60,48 @@ export default class Forum implements Graph { } public addCitation(citation: Citation) { + citation.sourcePost.setCitation(citation); + citation.citedPost.setCitation(citation); this.citations.set(citation.id, citation); } public deleteCitation(citation: string | Citation) { - if (typeof citation === "string") this.citations.delete(citation); - else for (const [key, val] of this.citations.entries()) { - if (val === citation) { - this.citations.delete(key); - break; - } - } + if (typeof citation === "string") citation = this.citations.get(citation); + this.citations.delete(citation.id); + citation.sourcePost.removeCitation(citation); + citation.citedPost.removeCitation(citation); } -} \ No newline at end of file + public getAllMembers() { + return Array.from(this.members.values()); + } + + public getMember(id: string) { + return this.members.get(id); + } + + public addMember(member: Member) { + this.members.set(member.id, member); + } + + public deleteMember(member: string | Member) { + if (typeof member === "string") member = this.members.get(member); + this.members.delete(member.id); + } + + //TODO: Need to define this function + public getBranch(post: Post, depth: number, direction: 'predecessor' | 'successor') { + + } + + //TODO: Need to define this function + public assesPostImpact(post: Post, depth: number = 1) { + + } + + //TODO: Need to define this function + public propagateReputation(post: Post) { + + } + +} \ No newline at end of file