mirror of
https://github.com/zoriya/flood.git
synced 2025-12-06 07:16:18 +00:00
server: tests: add tests for feed-monitor endpoints
This commit is contained in:
334
server/routes/api/feed-monitor.test.ts
Normal file
334
server/routes/api/feed-monitor.test.ts
Normal file
@@ -0,0 +1,334 @@
|
||||
import fs from 'fs';
|
||||
import supertest from 'supertest';
|
||||
|
||||
import app from '../../app';
|
||||
import {getAuthToken} from './auth';
|
||||
import {getTempPath} from '../../models/TemporaryStorage';
|
||||
|
||||
import type {AddFeedOptions, AddRuleOptions, ModifyFeedOptions} from '../../../shared/types/api/feed-monitor';
|
||||
import type {Feed, Rule} from '../../../shared/types/Feed';
|
||||
|
||||
const request = supertest(app);
|
||||
|
||||
const authToken = `jwt=${getAuthToken('_config')}`;
|
||||
|
||||
const feed: AddFeedOptions = {
|
||||
label: 'NYTimes',
|
||||
url: 'https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml',
|
||||
interval: 1,
|
||||
};
|
||||
|
||||
let addedFeed: Feed | null = null;
|
||||
|
||||
describe('GET /api/feed-monitor', () => {
|
||||
it('Expects nothing, yet. Verifies data structure.', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
const expectedResponse = {
|
||||
feeds: [],
|
||||
rules: [],
|
||||
};
|
||||
|
||||
expect(res.body).toStrictEqual(expectedResponse);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /api/feed-monitor/feeds', () => {
|
||||
it('Subscribes to a feed', (done) => {
|
||||
request
|
||||
.put('/api/feed-monitor/feeds')
|
||||
.send(feed)
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
const response: Feed = res.body;
|
||||
|
||||
expect(response).toMatchObject(feed);
|
||||
|
||||
expect(response._id).not.toBeNull();
|
||||
expect(typeof response._id).toBe('string');
|
||||
|
||||
addedFeed = response;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor to verify added feed', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
const expectedResponse = {
|
||||
feeds: [addedFeed],
|
||||
rules: [],
|
||||
};
|
||||
|
||||
expect(res.body).toStrictEqual(expectedResponse);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor/feeds to verify added feed', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor/feeds')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
expect(res.body).toStrictEqual([addedFeed]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PATCH /api/feed-monitor/feeds/{id}', () => {
|
||||
const modifyFeedOptions: ModifyFeedOptions = {
|
||||
label: 'Modified Feed',
|
||||
};
|
||||
|
||||
it('Modifies the added feed', (done) => {
|
||||
expect(addedFeed).not.toBe(null);
|
||||
if (addedFeed == null) return;
|
||||
|
||||
request
|
||||
.patch(`/api/feed-monitor/feeds/${addedFeed._id}`)
|
||||
.send(modifyFeedOptions)
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, _res) => {
|
||||
if (err) done(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor/feeds/{id} to verify modified feed', (done) => {
|
||||
expect(addedFeed).not.toBe(null);
|
||||
if (addedFeed == null) return;
|
||||
|
||||
request
|
||||
.get(`/api/feed-monitor/feeds/${addedFeed._id}`)
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
addedFeed = {...(addedFeed as Feed), ...modifyFeedOptions};
|
||||
|
||||
expect(res.body).toStrictEqual([addedFeed]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/feed-monitor/feeds/{id}/items', () => {
|
||||
it('Requests items of the feed', (done) => {
|
||||
expect(addedFeed).not.toBe(null);
|
||||
if (addedFeed == null) return;
|
||||
|
||||
request
|
||||
.get(`/api/feed-monitor/feeds/${addedFeed._id}/items`)
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
expect(Array.isArray(res.body)).toBe(true);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const tempDirectory = getTempPath('download');
|
||||
|
||||
fs.mkdirSync(tempDirectory, {recursive: true});
|
||||
|
||||
let addedRule: Rule;
|
||||
|
||||
describe('GET /api/feed-monitor/rules', () => {
|
||||
it('Expects nothing, verifies the response is an array', (done) => {
|
||||
request
|
||||
.get(`/api/feed-monitor/rules`)
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
expect(Array.isArray(res.body)).toBe(true);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /api/feed-monitor/rules', () => {
|
||||
const rule: AddRuleOptions = {
|
||||
label: 'Test rule',
|
||||
feedIDs: [''],
|
||||
match: '',
|
||||
exclude: '.*',
|
||||
destination: tempDirectory,
|
||||
tags: ['FeedItem'],
|
||||
startOnLoad: false,
|
||||
};
|
||||
|
||||
it('Adds an automation rule', (done) => {
|
||||
expect(addedFeed).not.toBe(null);
|
||||
if (addedFeed == null) return;
|
||||
rule.feedIDs = [addedFeed._id];
|
||||
|
||||
request
|
||||
.put('/api/feed-monitor/rules')
|
||||
.send(rule)
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
const response: Rule = res.body;
|
||||
|
||||
expect(response).toMatchObject(rule);
|
||||
|
||||
expect(response._id).not.toBeNull();
|
||||
expect(typeof response._id).toBe('string');
|
||||
|
||||
addedRule = response;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor to verify added rule', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
expect(res.body.rules).toStrictEqual([addedRule]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor/rules to verify added rule', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor/rules')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
expect(res.body).toStrictEqual([addedRule]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DELETE /api/feed-monitor/{id}', () => {
|
||||
it('Deletes the added feed', (done) => {
|
||||
expect(addedFeed).not.toBe(null);
|
||||
if (addedFeed == null) return;
|
||||
|
||||
request
|
||||
.delete(`/api/feed-monitor/${addedFeed._id}`)
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, _res) => {
|
||||
if (err) done(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Deletes the added rule', (done) => {
|
||||
request
|
||||
.delete(`/api/feed-monitor/${addedRule._id}`)
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, _res) => {
|
||||
if (err) done(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /api/feed-monitor to verify feed and rule are deleted', (done) => {
|
||||
request
|
||||
.get('/api/feed-monitor')
|
||||
.send()
|
||||
.set('Cookie', [authToken])
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
if (err) done(err);
|
||||
|
||||
const expectedResponse = {
|
||||
feeds: [],
|
||||
rules: [],
|
||||
};
|
||||
|
||||
expect(res.body).toStrictEqual(expectedResponse);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -50,18 +50,19 @@ router.delete<{id: string}>('/:id', (req, res) => {
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/feed-monitor/feeds
|
||||
* GET /api/feed-monitor/feeds/{id?}
|
||||
* @summary Gets subscribed feeds
|
||||
* @tags Feeds
|
||||
* @security User
|
||||
* @param id.path.optional - Unique ID of the feed subscription
|
||||
* @return {Array<Feed>}} 200 - success response - application/json
|
||||
* @return {Error} 500 - failure response - application/json
|
||||
*/
|
||||
router.get('/feeds', (req, res) => {
|
||||
router.get<{id?: string}>('/feeds/:id?', (req, res) => {
|
||||
const callback = ajaxUtil.getResponseFn(res);
|
||||
|
||||
req.services?.feedService
|
||||
.getFeeds()
|
||||
.getFeeds(req.params.id)
|
||||
.then((feeds) => {
|
||||
callback(feeds);
|
||||
})
|
||||
@@ -173,8 +174,8 @@ router.put<unknown, unknown, AddRuleOptions>('/rules', (req, res) => {
|
||||
|
||||
req.services?.feedService
|
||||
.addRule(req.body)
|
||||
.then(() => {
|
||||
callback(null);
|
||||
.then((rule) => {
|
||||
callback(rule);
|
||||
})
|
||||
.catch((error) => {
|
||||
callback(null, error);
|
||||
|
||||
@@ -84,11 +84,13 @@ class FeedService extends BaseService {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
// JSON.parse(JSON.stringify()) to remove undefined properties
|
||||
|
||||
modifiedFeedReader.stopReader();
|
||||
modifiedFeedReader.modify({feedLabel: label, url, interval});
|
||||
modifiedFeedReader.modify(JSON.parse(JSON.stringify({feedLabel: label, url, interval})));
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.db.update({_id: id}, {$set: {url, label, interval}}, {}, (err) => {
|
||||
this.db.update({_id: id}, {$set: JSON.parse(JSON.stringify({label, url, interval}))}, {}, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
@@ -160,9 +162,9 @@ class FeedService extends BaseService {
|
||||
});
|
||||
}
|
||||
|
||||
async getFeeds(): Promise<Array<Feed>> {
|
||||
async getFeeds(id?: string): Promise<Array<Feed>> {
|
||||
return new Promise<Array<Feed>>((resolve, reject) => {
|
||||
this.db.find({type: 'feed'}, (err: Error | null, feeds: Array<Feed>) => {
|
||||
this.db.find(id ? {_id: id} : {type: 'feed'}, (err: Error | null, feeds: Array<Feed>) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
|
||||
@@ -14,6 +14,5 @@
|
||||
},
|
||||
"outDir": "../dist"
|
||||
},
|
||||
"include": ["./**/*.ts", "../shared/**/*.ts", "../config.js", "../config.ts"],
|
||||
"exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"]
|
||||
"include": ["./**/*.ts", "../shared/**/*.ts", "../config.js", "../config.ts"]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export interface Feed {
|
||||
label: string;
|
||||
// URL of the feed.
|
||||
url: string;
|
||||
// Interval between checking the feed for new items.
|
||||
// Interval between checking the feed for new items. (in minutes)
|
||||
interval: number;
|
||||
// How many times rules have matched items of the feed.
|
||||
count?: number;
|
||||
|
||||
Reference in New Issue
Block a user