feat: test comments, issues and mentions

This commit is contained in:
Aravinth Manivannan 2023-09-18 20:28:09 +05:30
parent 506aaaf16d
commit fa48c720b7
Signed by: realaravinth
GPG key ID: F8F50389936984FF
2 changed files with 143 additions and 23 deletions

View file

@ -3,6 +3,9 @@ import authtoken from "../secrets/user1-accesstoken.json";
const token = authtoken["sha1"]; const token = authtoken["sha1"];
const username = authtoken["login"]; const username = authtoken["login"];
const repo = authtoken["repo"];
const api = new Forgejo("http://localhost:3000", "owner_user");
api.setTokenAuth(token);
test("use authentication without setting it ", () => { test("use authentication without setting it ", () => {
const api = new Forgejo("http://localhost:3000", "owner_user"); const api = new Forgejo("http://localhost:3000", "owner_user");
@ -15,9 +18,50 @@ test("use authentication without setting it ", () => {
}); });
test("verify /user API ", async () => { test("verify /user API ", async () => {
const api = new Forgejo("http://localhost:3000", "owner_user");
api.setTokenAuth(token);
let user = await api.getUser(); let user = await api.getUser();
console.log(user);
expect(user["login"]).toBe(username); expect(user["login"]).toBe(username);
}); });
test("notifications API ", async () => {
let notifications = await api.getNotifications();
expect(notifications.length).toBe(5);
expect(await api.getNumUnreadNotifications()).toBe(5);
let notification = await api.getNotificationThread(notifications[0].id);
expect(notification).toEqual(notifications[0]);
});
test("issue API ", async () => {
let notifications = await api.getNotifications();
let issue = await api.getIssue(username, repo, 1);
expect(notifications[0].subject.type).toEqual("Issue");
expect(issue.title).toEqual(notifications[0].subject.title);
expect(issue.lazy_comments_data).toBeUndefined();
expect(issue.created_at instanceof Date).toBe(true);
expect(issue.updated_at instanceof Date).toBe(true);
if (issue.closed_at) {
// TODO: add issue closing functionality in integration/forgejo.py and verify this
expect(issue.closed_at instanceof Date).toBe(true);
}
// expect(typeof(issue.created_at)).toBe('Date');
});
test("comments API ", async () => {
let notifications = await api.getNotifications();
let issue = await api.getIssue(username, repo, 1);
issue = await api.getCommentsForIssue(issue);
expect(issue.lazy_comments_data.length).toBe(2);
issue.lazy_comments_data?.forEach((comment) => {
expect(comment.created_at instanceof Date).toBe(true);
expect(comment.updated_at instanceof Date).toBe(true);
});
});
test("mentions in issue", async () => {
expect(await api.findMentionsInIssue(username, repo, 1)).toBe(true);
expect(await api.findMentionsInIssue(username, repo, 2)).toBe(true);
expect(await api.findMentionsInIssue(username, repo, 3)).toBe(true);
expect(await api.findMentionsInIssue(username, repo, 4)).toBe(true);
expect(await api.findMentionsInIssue(username, repo, 5)).toBe(false);
});

View file

@ -3,6 +3,10 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
import Auth from "./auth"; import Auth from "./auth";
import User from "./spec/user";
import Notification from "./spec/notification";
import Issue from "./spec/issue";
import Comment from "./spec/comments";
class Forgejo { class Forgejo {
url: URL; url: URL;
@ -16,7 +20,6 @@ class Forgejo {
*/ */
constructor(url: string, username: string) { constructor(url: string, username: string) {
this.url = new URL(url); this.url = new URL(url);
console.log(this.url.toString());
this.username = username; this.username = username;
} }
@ -43,69 +46,85 @@ class Forgejo {
/** /**
* Get logged in user * Get logged in user
*/ */
async getUser() { async getUser(): Promise<User> {
this.url.pathname = "/api/v1/user"; this.url.pathname = "/api/v1/user";
console.log(this.url.toString());
let res = await fetch(this.url, { let res = await fetch(this.url, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
headers: this.getTokenAuthHeader(), headers: this.getTokenAuthHeader(),
}); });
console.log(`got res: ${res}`);
return await res.json(); return await res.json();
} }
/** /**
* Get all notifications * Get all notifications
*/ */
async getNotifications() { async getNotifications(): Promise<Array<Notification>> {
this.url.pathname = "/api/v1/notifications"; this.url.pathname = "/api/v1/notifications";
let res = await fetch(this.url); let res = await fetch(this.url, {
method: "GET",
credentials: "include",
headers: this.getTokenAuthHeader(),
});
return await res.json(); return await res.json();
} }
/** /**
* Get number of unread notifications * Get number of unread notifications
*/ */
async getNumUnreadNotifications() { async getNumUnreadNotifications(): Promise<number> {
this.url.pathname = "/api/v1/notifications/new"; this.url.pathname = "/api/v1/notifications/new";
let res = await fetch(this.url); let res = await fetch(this.url, {
return await res.json()["new"]; method: "GET",
credentials: "include",
headers: this.getTokenAuthHeader(),
});
let data = await res.json();
return data["new"];
} }
/** /**
* Get Notification Thread * Get Notification Thread
* @param {number} id - The ID of a notification thread * @param {number} id - The ID of a notification thread
*/ */
async getNotificationThread(id: number) { async getNotificationThread(id: number): Promise<Notification> {
this.url.pathname = `/api/v1/notifications/threads/${id}`; this.url.pathname = `/api/v1/notifications/threads/${id}`;
let res = await fetch(this.url); let res = await fetch(this.url, {
method: "GET",
credentials: "include",
headers: this.getTokenAuthHeader(),
});
return await res.json(); return await res.json();
} }
/** /**
* Get the time at which the issue was last read * Get the time at which the issue was last read
*/ */
lastReadTime(issue: number): number { lastReadTime(issue: Issue): Date {
return 10120123; // TODO: return last read UNIX epoch time from storage. If unread, return 0 return new Date("01/01/01"); // TODO: return last read time from storage. If unread, return 0
} }
/** /**
* Check if logged in user is mentioned in the issue * Check if logged in user is mentioned in the issue
*/ */
async findMentionsInIssue(owner: string, repo: string, id: number) { async findMentionsInIssue(owner: string, repo: string, id: number) {
let issue = this.getIssue(owner, repo, id); let issue = await this.getIssue(owner, repo, id);
issue = await this.getCommentsForIssue(issue);
let unreadTime = this.lastReadTime(issue); let unreadTime = this.lastReadTime(issue);
const mentionUtil = (str: string): boolean => str.includes(this.username); const mentionUtil = (str: string): boolean => {
return str.includes(this.username);
};
const items = []; const items = [];
if (issue.created > unreadTime) { if (new Date(issue.created_at) > unreadTime) {
items.push(issue.title); items.push(issue.title);
items.push(issue.body); items.push(issue.body);
} }
issue.commentsData.forEach((comment) => { issue.lazy_comments_data.forEach((comment) => {
if (comment.created_at > unreadTime) { if (comment.created_at > unreadTime) {
items.push(comment.body); items.push(comment.body);
return; return;
@ -118,12 +137,14 @@ class Forgejo {
} }
}); });
let mention = false;
items.forEach((item) => { items.forEach((item) => {
if (mentionUtil(item)) { if (mentionUtil(item)) {
return true; mention = true;
return;
} }
}); });
return false; return mention;
} }
/** /**
@ -151,7 +172,62 @@ class Forgejo {
* @param {str} repo - The name of the repository * @param {str} repo - The name of the repository
* @param {number} id - The ID of an issue * @param {number} id - The ID of an issue
*/ */
async getIssue(owner: string, repo: string, id: number) {} async getIssue(owner: string, repo: string, id: number): Promise<Issue> {
this.url.pathname = `/api/v1/repos/${owner}/${repo}/issues/${id}`;
let res = await fetch(this.url, {
method: "GET",
credentials: "include",
headers: this.getTokenAuthHeader(),
});
let issue = await res.json();
if (typeof issue.created_at === "string") {
issue.created_at = new Date(issue.created_at);
}
if (issue.updated_at) {
if (typeof issue.updated_at === "string") {
issue.updated_at = new Date(issue.updated_at);
}
}
if (issue.closed_at) {
if (typeof issue.closed_at === "string") {
issue.closed_at = new Date(issue.closed_at);
}
}
return issue;
}
async getCommentsForIssue(issue: Issue): Promise<Issue> {
// TODO: check if issue.number != issue.id causes problems. I'm assuming
// Issue.number is the local repository issue ID and issue.id is DB ID
this.url.pathname = `/api/v1/repos/${issue.repository.owner}/${issue.repository.name}/issues/${issue.number}/comments`;
let res = await fetch(this.url, {
method: "GET",
credentials: "include",
headers: this.getTokenAuthHeader(),
});
let c: Array<Comment> = await res.json();
c = c.map((comment) => {
if (typeof comment.created_at === "string") {
comment.created_at = new Date(comment.created_at);
}
if (comment.updated_at) {
if (typeof comment.updated_at === "string") {
comment.updated_at = new Date(comment.updated_at);
}
}
return comment;
});
issue.lazy_comments_data = c;
return issue;
}
} }
export default Forgejo; export default Forgejo;