integration tests for graphQL schemas

This commit is contained in:
Chegele 2023-08-01 20:08:21 -04:00
parent 1c738b6b02
commit f83eac3ccc
9 changed files with 1359 additions and 594 deletions

1642
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
"@nestjs/core": "^10.0.0",
"@nestjs/graphql": "^12.0.1",
"@nestjs/platform-express": "^10.0.0",
"apollo-server-core": "^3.12.0",
"graphql": "^16.6.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",

View File

@ -2,8 +2,9 @@ import { Edge } from "../graph.interface";
import { Citation } from "./citation";
import { Member } from "../member/member";
import { Post } from "../post/post";
import { ApolloTestServer } from "../../../../util/apollo-test-server";
describe('Reputation Service Citation', () => {
describe('Rep Service Citation - Unit Tests', () => {
let testingPostA: Post;
let testingPostB: Post;
@ -23,6 +24,12 @@ describe('Reputation Service Citation', () => {
testingCitation = new Citation("testingCitation", testingPostA, testingPostB, 10);
});
afterAll(() => {
Member.clear();
Post.clear();
Citation.clear();
});
it('should be able to get all citations', () => {
const citations = Citation.getAllCitations();
expect(citations.length).toBe(1);
@ -98,4 +105,85 @@ describe('Reputation Service Citation', () => {
expect(edge.getAdjacent(testingPostB)).toBe(testingPostA);
});
});
describe ('Rep Service Citation - Integration Tests', () => {
let testServer: ApolloTestServer;
let createUser1 = `createMember(id: "testingUser1") { id }`;
let createUser2 = `createMember(id: "testingUser2") { id }`;
let createPost1 = `createPost(id: "testingPost1", title: "Test Post 1", content: "Test Content 1", authorId: "testingUser1") { id }`;
let createPost2 = `createPost(id: "testingPost2", title: "Test Post 2", content: "Test Content 2", authorId: "testingUser2") { id }`;
let createCitation = `createCitation(citationId: "testingCitation1", sourcePostId: "testingPost1", citedPostId: "testingPost2", impact: 10) { id }`;
beforeEach(async () => {
testServer = new ApolloTestServer();
await testServer.init();
await testServer.executeMutation(createUser1);
await testServer.executeMutation(createUser2);
await testServer.executeMutation(createPost1);
await testServer.executeMutation(createPost2);
await testServer.executeMutation(createCitation);
});
afterAll(async () => {
await testServer.close();
});
it('should be able to query all citations', async () => {
const query = `citations { id }`;
const response = await testServer.executeQuery(query);
expect(response.data.citations.length).toBe(1);
});
it('should be able to query a specific citation', async () => {
const query = `citation(id: "testingCitation1") { id }`;
const response = await testServer.executeQuery(query);
expect(response.data.citation.id).toBe("testingCitation1");
});
it('should include all required fields and cascade through types', async () => {
const query = `citation(id: "testingCitation1") { id, directional, impact,
sourcePost { id, title, authors { id, reputation, ledger { balance }} },}`;
const response = await testServer.executeQuery(query);
const citation = response.data.citation;
const citationFields = ["id", "directional", "impact", "sourcePost"];
for (const field of citationFields) expect(response.data.citation[field]).toBeDefined();
const post = citation.sourcePost;
const postFields = ["id", "title", "authors"];
for (const field of postFields) expect(post[field]).toBeDefined();
const member = post.authors[0];
const memberFields = ["id", "reputation", "ledger"];
for (const field of memberFields) expect(member[field]).toBeDefined();
});
it('should be able to query the adjacent post on a citation', async () => {
const query = `adjacentPost(citationId: "testingCitation1", postId: "testingPost1") { id }`;
const response = await testServer.executeQuery(query);
expect(response.data.adjacentPost.id).toBe("testingPost2");
});
it('should be able to query the sign of citations', async () => {
const positive = await testServer.executeQuery(`isPositive(citationId: "testingCitation1")`);
const negative = await testServer.executeQuery(`isNegative(citationId: "testingCitation1")`);
const neutral = await testServer.executeQuery(`isNeutral(citationId: "testingCitation1")`);
expect(positive.data.isPositive).toBe(true);
expect(negative.data.isNegative).toBe(false);
expect(neutral.data.isNeutral).toBe(false);
});
it('should be able to create a new citation', async () => {
const query = `createCitation(citationId: "newCitation", sourcePostId: "testingPost1", citedPostId: "testingPost2", impact: -10) { id }`;
const response = await testServer.executeMutation(query);
expect(response.data.createCitation.id).toBe("newCitation");
});
});
describe ('Rep Service Citation - E2E Tests', () => {
});

View File

@ -14,6 +14,10 @@ export class Citation implements Edge {
return Citation.localStore.get(id);
}
public static clear() {
Citation.localStore.clear();
}
private _id: string;
private _directional: boolean;
private _sourcePost: Post;

View File

@ -1,6 +1,7 @@
import { Member } from "./member";
import { ApolloTestServer } from "../../../../util/apollo-test-server";
describe('Reputation Service Member', () => {
describe('Rep Service Member - Unit Tests', () => {
let testMemberA: Member;
let testMemberB: Member;
@ -10,6 +11,10 @@ describe('Reputation Service Member', () => {
testMemberB = new Member("testMemberB");
});
afterAll(() => {
Member.clear();
});
it('should be able to get all members', () => {
const members = Member.getAllMembers();
expect(members.length).toBe(2);
@ -68,3 +73,70 @@ describe('Reputation Service Member', () => {
});
});
describe('Rep Service Member - Integration Tests', () => {
let testServer: ApolloTestServer;
let createUser1 = `createMember(id: "testingUser1") { id }`;
let createUser2 = `createMember(id: "testingUser2") { id }`;
let createPost1 = `createPost(id: "testingPost1", title: "Test Post 1", content: "Test Content 1", authorId: "testingUser1") { id }`;
beforeEach(async () => {
testServer = new ApolloTestServer();
await testServer.init();
await testServer.executeMutation(createUser1);
await testServer.executeMutation(createUser2);
await testServer.executeMutation(createPost1);
});
afterAll(async () => {
await testServer.close();
});
it('should be able to query all members', async () => {
const query = `members { id }`;
const response = await testServer.executeQuery(query);
expect(response.data.members.length).toBe(2);
});
it('should be able to query a specific member', async () => {
const query = `member(id: "testingUser1") { id }`;
const response = await testServer.executeQuery(query);
expect(response.data.member.id).toBe("testingUser1");
});
it('should include all required fields', async () => {
const query = `member(id: "testingUser1") { id, reputation, ledger { balance } }`;
const response = await testServer.executeQuery(query);
const member = response.data.member;
const memberFields = ["id", "reputation", "ledger"];
for (const field of memberFields) expect(member[field]).toBeDefined();
});
it('should be able to query the ledger from members', async () => {
const query = `member(id: "testingUser1") { ledger { timestamp, type, postId, citationId, change, balance } }`;
const response = await testServer.executeQuery(query);
const ledger = response.data.member.ledger;
const ledgerFields = ["timestamp", "type", "postId", "citationId", "change", "balance"];
//TODO: for (const field of ledgerFields) expect(ledger[0][field]).toBeDefined();
// Currently not using the form to propagate any reputation
});
it('should be able to query the reputation from members', async () => {
const query = `member(id: "testingUser1") { reputation }`;
const response = await testServer.executeQuery(query);
expect(response.data.member.reputation).toBe(0);
});
it('should be able to create a new member', async () => {
const query = `createMember(id: "testingUser3") { id }`;
const response = await testServer.executeMutation(query);
expect(response.data.createMember.id).toBe("testingUser3");
});
});
describe('Rep Service Member - E2E Tests', () => {
});

View File

@ -21,6 +21,10 @@ export class Member {
return Member.localStore.get(id);
}
public static clear() {
Member.localStore.clear();
}
private _id: string;
private _reputation: number;
private _ledger: LedgerEntry[];

View File

@ -2,8 +2,9 @@ import { Vertex } from "../graph.interface";
import { Citation } from "../citation/citation";
import { Member } from "../member/member";
import { Post } from "./post";
import { ApolloTestServer } from "../../../../util/apollo-test-server";
describe('Reputation Service Post', () => {
describe('Rep Service Post - Unit Tests', () => {
let testingPostA: Post;
let testingPostB: Post;
@ -26,6 +27,12 @@ describe('Reputation Service Post', () => {
testingPostA.setCitation(testingCitation, 300);
});
afterAll(() => {
Member.clear();
Post.clear();
Citation.clear();
});
it('should be able to get all posts', () => {
const posts = Post.getAllPosts();
expect(posts.length).toBe(2);
@ -159,4 +166,73 @@ describe('Reputation Service Post', () => {
expect(post?.citationsWeightTotal).toBe(300);
});
});
describe('Rep Service Post - Integration Tests', () => {
let testServer: ApolloTestServer;
let createUser1 = `createMember(id: "testingUser1") { id }`;
let createUser2 = `createMember(id: "testingUser2") { id }`;
let createPost1 = `createPost(id: "testingPost1", title: "Test Post 1", content: "Test Content 1", authorId: "testingUser1") { id }`;
let createPost2 = `createPost(id: "testingPost2", title: "Test Post 2", content: "Test Content 2", authorId: "testingUser2") { id }`;
let createCitation = `createCitation(citationId: "testingCitation1", sourcePostId: "testingPost1", citedPostId: "testingPost2", impact: 10) { id }`;
beforeEach(async () => {
testServer = new ApolloTestServer();
await testServer.init();
await testServer.executeMutation(createUser1);
await testServer.executeMutation(createUser2);
await testServer.executeMutation(createPost1);
await testServer.executeMutation(createPost2);
await testServer.executeMutation(createCitation);
});
afterAll(async () => {
await testServer.close();
});
it('should be able to get all posts', async () => {
const query = `posts { id }`;
const result = await testServer.executeQuery(query);
expect(result.data.posts.length).toBe(2);
});
it('should be able to get a specific post', async () => {
const query = `post(id: "testingPost1") { id }`;
const result = await testServer.executeQuery(query);
expect(result.data.post.id).toBe("testingPost1");
});
it('should include all required fields and cascade through types', async () => {
//TODO: Add test for all fields
});
it('should be able to get the weight of an author within a post', async () => {
const query = `authorWeight(postId: "testingPost1", authorId: "testingUser1")`;
const result = await testServer.executeQuery(query);
expect(result.data.authorWeight).toBe(1000);
});
it('should be able to create a new post', async () => {
const mutation = `createPost(id: "testingPost3", title: "Test Post 3", content: "Test Content 3", authorId: "testingUser1") { id }`;
const result = await testServer.executeMutation(mutation);
expect(result.data.createPost.id).toBe("testingPost3");
});
it('should be able to add an author to a post', async () => {
const mutation = `setAuthor(postId: "testingPost1", authorId: "testingUser2", weight: 500)`;
const result = await testServer.executeMutation(mutation);
expect(result.data.setAuthor).toBe(true);
});
it('should be able to add a citation to a post', async () => {
//TODO: Add test for adding a citation
});
});
describe('Rep Service Post - E2E Tests', () => {
});

View File

@ -26,6 +26,10 @@ export class Post implements Vertex {
return Post.localStore.get(id);
}
public static clear() {
Post.localStore.clear();
}
public static serialize(post: Post, pretty: boolean = true) {
const postProperties = {
id: post.id,

View File

@ -0,0 +1,56 @@
import { getApolloServer } from '@nestjs/apollo';
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { AppModule } from "../app.module";
import { ApolloServer, BaseContext } from "@apollo/server";
import { DocumentNode } from 'graphql';
import { gql } from 'apollo-server-core';
export class ApolloTestServer {
private app: INestApplication;
private apolloServer: ApolloServer<BaseContext>;
constructor() { }
public async init() {
const testingModule = Test.createTestingModule({imports: [AppModule]});
const fixture = await testingModule.compile();
this.app = fixture.createNestApplication();
await this.app.init();
this.apolloServer = getApolloServer(this.app);
}
public async close() {
await this.app.close();
}
public query(queryString: string) {
const query = "query Query {" + queryString + "}";
return gql`${query}`;
}
public mutation(queryString: string) {
const query = "mutation Mutation {" + queryString + "}";
return gql`${query}`;
}
public async executeQuery(query: DocumentNode | string) {
if (typeof query === 'string') query = this.query(query);
const result: any = await this.apolloServer.executeOperation({query});
return {
data: result?.body?.singleResult?.data || null,
errors: result?.body?.singleResult?.errors || null,
}
}
public async executeMutation(query: DocumentNode | string) {
if (typeof query === 'string') query = this.mutation(query);
const result: any = await this.apolloServer.executeOperation({query});
return {
data: result?.body?.singleResult?.data || null,
errors: result?.body?.singleResult?.errors || null,
}
}
}